-
Notifications
You must be signed in to change notification settings - Fork 2
/
tv_episode_guess.go
111 lines (92 loc) · 3.1 KB
/
tv_episode_guess.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package main
import (
"errors"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/xrash/smetrics"
)
type GuessEpisode struct {
Season int
Episode int
Name string
}
/// From a tv episode eg 'Some TV Show - Episode Name.vob' it looks up tmdb, finds the closest episode name, and
/// renames to eg 'Seinfeld S09E03 The Serenity Now.Seinfeld - Serenity.vob.remove if correct'
/// Returns an error if it can't figure anything out.
func tvEpisodeGuess(folder string, file string, paths Paths, config Config) error {
s := strings.Split(file, "-")
if len(s) < 2 {
return errors.New("Unrecognised file naming, expected eg 'Some show - Episode name.vob'")
}
showTitleFromFile := strings.TrimSpace(s[0])
episodeTitleFromFile := strings.TrimSpace(s[1])
if showTitleFromFile == "" {
return errors.New("Missing show name before the dash")
}
if episodeTitleFromFile == "" {
return errors.New("Missing episode name after the dash")
}
// Search for the id.
log.Println("Searching for series for title", showTitleFromFile)
seriesId := tvdbSearchForSeries(showTitleFromFile)
if seriesId == "" {
log.Println("Could not find TV show for", showTitleFromFile)
return errors.New("Series search")
}
// Get show details.
log.Println("Fetching series details for series id", seriesId)
series, seriesErr := tvdbSeriesDetails(seriesId)
if seriesErr != nil {
log.Println("Could not get TV show metadata for", showTitleFromFile)
return seriesErr
}
allEpisodes := make([]GuessEpisode, 0)
// Find all seasons.
for _, sparseSeason := range series.Seasons {
log.Println("Looking up details for season: ", sparseSeason.Season)
fatSeason, seasonErr := tvdbSeasonDetails(seriesId, sparseSeason.TVDBID, sparseSeason.Season)
if seasonErr != nil {
log.Println("Could not get season metadata for", showTitleFromFile)
return seasonErr
}
for _, episode := range fatSeason.Episodes {
guess := GuessEpisode{
Season: episode.SeasonNumber,
Episode: episode.Episode,
Name: episode.Name,
}
allEpisodes = append(allEpisodes, guess)
}
}
// Any episodes?
if len(allEpisodes) == 0 {
return errors.New("No episodes found")
}
// Find the closest.
closestDistance := 99999
var closestGuess *GuessEpisode
for _, ep := range allEpisodes {
thisDistance := smetrics.WagnerFischer(
strings.ToLower(ep.Name),
strings.ToLower(episodeTitleFromFile),
1, 3, 2)
log.Println("Comparing", episodeTitleFromFile, "to", ep.Name, "distance =", thisDistance)
if thisDistance < closestDistance {
closestDistance = thisDistance
epCopy := ep // Without this, the memory for 'ep' is overwritten next loop iteration.
closestGuess = &epCopy
}
}
if closestGuess == nil {
return errors.New("No guesses found")
}
// Rename it and succeed.
sxex := fmt.Sprintf("S%02dE%02d", closestGuess.Season, closestGuess.Episode)
newName := series.Name + " " + sxex + " " + closestGuess.Name + "." + file + ".remove if correct"
os.Rename(filepath.Join(folder, file), filepath.Join(folder, newName))
log.Println("Guessed a file. You can remove the 'remove if correct' if you're happy with the guess.")
return nil
}