Add patching with basic linking

This could be cleaned up a bit, and only handles the single episode, non-directory case. It will need to be extended
master
Nick Krichevsky 2021-09-09 23:45:25 -04:00
parent f21ae2e502
commit 29951882f4
1 changed files with 72 additions and 13 deletions

View File

@ -1,14 +1,25 @@
package main
import (
"errors"
"fmt"
"io"
"os"
"path"
"strconv"
"strings"
"github.com/fatih/color"
)
type categorizationInputChoice int
const (
inputChoiceYes categorizationInputChoice = iota
inputChoiceNo
inputChoiceStop
)
func main() {
if len(os.Args) != 3 {
fmt.Fprintln(os.Stderr, "Usage: ./gobbler sourceFolder libraryFolder")
@ -17,39 +28,87 @@ func main() {
sourceFolder, libraryFolder := os.Args[1], os.Args[2]
locations := []fileLocation{}
categorizationStats, err := categorizeFolder(sourceFolder, libraryFolder, func(res categorizationResult) bool {
if res.err != nil {
fmt.Fprintln(os.Stderr, res.err)
} else {
locations = append(locations, res.location)
}
inputChoice := promptForCategorizationChoice(res.location)
if inputChoice == inputChoiceStop {
return false
} else if inputChoice != inputChoiceYes {
return true
}
if !res.location.location.IsFullyResolved() {
fmt.Fprintln(os.Stderr, "multi-season linking entries not yet supported")
return true
}
// we know the error will be nil if we've done the fully resolved check
relativeOutPath, _ := res.location.location.Path()
err := os.Link(
path.Join(sourceFolder, res.location.filename),
path.Join(libraryFolder, relativeOutPath, res.location.filename),
)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to link: %s\n", err)
}
return true
})
if err != nil {
// TODO: print something nicer than a panic
panic(err)
}
prettyPrintLocations(locations)
fmt.Fprintf(os.Stderr, "%d items not categorized\n", categorizationStats.filesSkipped)
}
func prettyPrintLocations(fileLocations []fileLocation) {
for _, fl := range fileLocations {
filename, location := fl.filename, fl.location
color.New(color.FgGreen, color.Bold).Println(filename)
seasonString := "Season"
if len(location.Seasons()) > 1 {
seasonString = "Seasons"
func promptForCategorizationChoice(fl fileLocation) categorizationInputChoice {
prettyPrintLocation(fl)
return collectCategorizationInput()
}
func collectCategorizationInput() categorizationInputChoice {
for {
color.New(color.FgBlue).Print("Link to destination? [y/n/d]? ")
var input string
_, err := fmt.Scanln(&input)
if errors.Is(err, io.EOF) {
continue
} else if err != nil {
panic(err)
}
fmt.Printf(" ├── %s\n", location.MediaTitle())
fmt.Printf(" └── %s %s\n", seasonString, joinIntsGramatically(location.Seasons()))
switch strings.ToLower(input) {
case "y":
return inputChoiceYes
case "n":
return inputChoiceNo
case "d":
return inputChoiceStop
default:
// TODO: Print a more helpful message
fmt.Fprintf(os.Stderr, "Invalid input - please enter y, n, or d")
}
}
}
func prettyPrintLocation(fl fileLocation) {
filename, location := fl.filename, fl.location
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 {