140 lines
3.8 KiB
Go
Raw Normal View History

2022-07-29 03:34:55 -05:00
package main
import (
_ "embed"
"encoding/json"
"fmt"
"html/template"
"math"
"os"
"time"
"github.com/confusedpolarbear/intro_skipper_verifier/structs"
)
//go:embed report.html
var reportTemplate []byte
func compareReports(oldReportPath, newReportPath, destination string) {
start := time.Now()
// Populate the destination filename if none was provided
if destination == "" {
destination = fmt.Sprintf("report-%d.html", start.Unix())
}
// Open the report for writing
f, err := os.OpenFile(destination, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
panic(err)
} else {
defer f.Close()
}
fmt.Printf("Started at: %s\n", start.Format(time.RFC1123))
fmt.Printf("First report: %s\n", oldReportPath)
fmt.Printf("Second report: %s\n", newReportPath)
fmt.Printf("Destination: %s\n\n", destination)
// Unmarshal both reports
oldReport, newReport := unmarshalReport(oldReportPath), unmarshalReport(newReportPath)
fmt.Println("[+] Comparing reports")
// Setup a function map with helper functions to use in the template
tmp := template.New("report")
funcs := make(template.FuncMap)
funcs["printTime"] = func(t time.Time) string {
return t.Format(time.RFC1123)
}
funcs["printDuration"] = func(d time.Duration) string {
return d.Round(time.Second).String()
}
funcs["printAnalysisSettings"] = func(pc structs.PluginConfiguration) string {
return pc.AnalysisSettings()
}
funcs["printIntroductionReqs"] = func(pc structs.PluginConfiguration) string {
return pc.IntroductionRequirements()
}
funcs["sortShows"] = templateSortShows
funcs["sortSeasons"] = templateSortSeason
funcs["compareEpisodes"] = templateCompareEpisodes
tmp.Funcs(funcs)
// Load the template or panic
report := template.Must(tmp.Parse(string(reportTemplate)))
err = report.Execute(f,
structs.TemplateReportData{
OldReport: oldReport,
NewReport: newReport,
})
if err != nil {
panic(err)
}
// Log success
fmt.Printf("[+] Reports successfully compared in %s\n", time.Since(start).Round(time.Millisecond))
}
func unmarshalReport(path string) structs.Report {
// Read the provided report
contents, err := os.ReadFile(path)
if err != nil {
panic(err)
}
// Unmarshal
var report structs.Report
if err := json.Unmarshal(contents, &report); err != nil {
panic(err)
}
// Setup maps and template data for later use
report.Path = path
report.Shows = make(map[string]structs.Seasons)
report.IntroMap = make(map[string]structs.Intro)
// Sort episodes by show and season
for _, intro := range report.Intros {
// Round the duration to the nearest second to avoid showing 8 decimal places in the report
intro.Duration = float32(math.Round(float64(intro.Duration)))
// Pretty print the intro start and end times
intro.FormattedStart = (time.Duration(intro.IntroStart) * time.Second).String()
intro.FormattedEnd = (time.Duration(intro.IntroEnd) * time.Second).String()
2022-07-29 03:34:55 -05:00
show, season := intro.Series, intro.Season
// If this show hasn't been seen before, allocate space for it
if _, ok := report.Shows[show]; !ok {
report.Shows[show] = make(structs.Seasons)
}
// Store this intro in the season of this show
episodes := report.Shows[show][season]
episodes = append(episodes, intro)
report.Shows[show][season] = episodes
// Store a reference to this intro in a lookup table
report.IntroMap[intro.EpisodeId] = intro
}
// Print report info
fmt.Printf("Report %s:\n", path)
fmt.Printf("Generated with Jellyfin %s running on %s\n", report.ServerInfo.Version, report.ServerInfo.OperatingSystem)
fmt.Printf("Analysis settings: %s\n", report.PluginConfig.AnalysisSettings())
fmt.Printf("Introduction reqs: %s\n", report.PluginConfig.IntroductionRequirements())
fmt.Printf("Episodes analyzed: %d\n", len(report.Intros))
fmt.Println()
return report
}