Add basic CLI tool to print results
parent
7a34955318
commit
8c42ea05be
|
@ -6,6 +6,7 @@ import (
|
|||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/ollien/gobbler/categorize/match"
|
||||
"github.com/ollien/gobbler/categorize/tv"
|
||||
)
|
||||
|
||||
|
@ -35,7 +36,9 @@ func newCategorizerForFS(libraryFs fs.FS) Categorizer {
|
|||
// (though the season folder need not exist)
|
||||
func (c Categorizer) CategorizeFile(filename string) (tv.Location, error) {
|
||||
showFolder, err := c.findShowFolder(filename)
|
||||
if err != nil {
|
||||
if errors.Is(err, tv.ErrNotTvShow) {
|
||||
return tv.Location{}, match.ErrNoMatches
|
||||
} else if err != nil {
|
||||
return tv.Location{}, fmt.Errorf("could not find show folder for categorization: %w", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,14 +7,14 @@ import (
|
|||
"github.com/ollien/gobbler/categorize/match"
|
||||
)
|
||||
|
||||
var errNotTvShow = errors.New("no tv-like information found in show name")
|
||||
var ErrNotTvShow = errors.New("no tv-like information found in show name")
|
||||
|
||||
// FindShowFolder finds the show that the given filename likey belongs to, among the given show folders.
|
||||
// Returns errNotTvShow if no match can be found
|
||||
// Returns ErrNotTvShow if no match can be found
|
||||
func FindShowFolder(filename string, showFolders []string) (string, error) {
|
||||
possibleShowName, err := extractShowName(filename)
|
||||
if err != nil {
|
||||
return "", errNotTvShow
|
||||
return "", ErrNotTvShow
|
||||
}
|
||||
|
||||
return matchToFolder(possibleShowName, showFolders)
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ollien/gobbler/categorize"
|
||||
"github.com/ollien/gobbler/categorize/match"
|
||||
"github.com/ollien/gobbler/categorize/tv"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type fileLocationMap = map[string]tv.Location
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Fprintln(os.Stderr, "Usage: ./gobbler sourceFolder libraryFolder")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
sourceFolder, libraryFolder := os.Args[1], os.Args[2]
|
||||
|
||||
sourceFolderContents, err := getDirEntries(sourceFolder)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
categorizer, err := categorize.NewCategorizer(libraryFolder)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
locations := performCategorization(categorizer, sourceFolderContents)
|
||||
prettyPrintLocations(locations)
|
||||
|
||||
numSkipped := len(sourceFolderContents) - len(locations)
|
||||
fmt.Fprintf(os.Stderr, "%d items not categorized\n", numSkipped)
|
||||
}
|
||||
|
||||
func getDirEntries(path string) ([]string, error) {
|
||||
fd, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer fd.Close()
|
||||
|
||||
return fd.Readdirnames(-1)
|
||||
}
|
||||
|
||||
// performCategorization categorizes the given files through the given categorizer, converting them to a map of
|
||||
// filename to Locations
|
||||
func performCategorization(categorizer categorize.Categorizer, sourceFolderContents []string) fileLocationMap {
|
||||
locations := map[string]tv.Location{}
|
||||
for _, entry := range sourceFolderContents {
|
||||
location, err := categorizer.CategorizeFile(entry)
|
||||
if errors.Is(err, match.ErrNoMatches) {
|
||||
continue
|
||||
} else if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to categorize '%s':\n\t%s\n", entry, err)
|
||||
continue
|
||||
}
|
||||
|
||||
locations[entry] = location
|
||||
}
|
||||
|
||||
return locations
|
||||
}
|
||||
|
||||
func prettyPrintLocations(locations fileLocationMap) {
|
||||
for filename, location := range locations {
|
||||
color.New(color.FgGreen, color.Bold).Println(filename)
|
||||
seasonString := "Season"
|
||||
if len(location.Seasons()) > 1 {
|
||||
seasonString = "Seasons"
|
||||
}
|
||||
|
||||
fmt.Printf(" ├── %s\n", location.MediaTitle())
|
||||
fmt.Printf(" └── %s %s\n", seasonString, joinIntsGramatically(location.Seasons()))
|
||||
}
|
||||
}
|
||||
|
||||
// joinIntsGramatically joins a seqwuence of ints as a comma separated list of strings, compelte with "and" and
|
||||
// oxford comma (e.g. "1, 2, 3, 4, and 5")
|
||||
func joinIntsGramatically(nums []int) string {
|
||||
if len(nums) == 0 {
|
||||
return ""
|
||||
} else if len(nums) == 1 {
|
||||
return strconv.Itoa(nums[0])
|
||||
}
|
||||
|
||||
numStrings := make([]string, len(nums))
|
||||
for i, num := range nums {
|
||||
numStrings[i] = strconv.Itoa(num)
|
||||
}
|
||||
|
||||
joined := strings.Join(numStrings[:len(numStrings)-1], ", ")
|
||||
|
||||
return joined + ", and " + numStrings[len(numStrings)-1]
|
||||
}
|
5
go.mod
5
go.mod
|
@ -3,6 +3,7 @@ module github.com/ollien/gobbler
|
|||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
github.com/agnivade/levenshtein v1.1.1
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
)
|
||||
|
|
11
go.sum
11
go.sum
|
@ -1,13 +1,21 @@
|
|||
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
|
||||
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
github.com/bevacqua/fuzzysearch v1.0.2 h1:23dOu/69YB8gzAIc2vk4eWtY2lg8YgCcTMQwg2QVyvA=
|
||||
github.com/bevacqua/fuzzysearch v1.0.2/go.mod h1:Pjn0r0ohRYG/5PnkllhikX34r67ITFOdCM32/uJnxl4=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
|
||||
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/lithammer/fuzzysearch v1.1.2 h1:ePUtm14xKxbpCxozcFbIDRtvANxnVnE+RKpJUqkr2gA=
|
||||
github.com/lithammer/fuzzysearch v1.1.2/go.mod h1:v6tYW/9kpfV6LNcweXdSjQsfCku/1M/oObmSox1fzP8=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
|
||||
|
@ -16,6 +24,9 @@ github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
||||
|
|
Loading…
Reference in New Issue