/******************************************************************************* * Copyright 2022 Stefan Majewsky * SPDX-License-Identifier: GPL-3.0-only * Refer to the file "LICENSE" for details. *******************************************************************************/ package main import ( "fmt" "os" "path/filepath" "regexp" "strconv" "strings" ) type ScanResult struct { //episode date Day int Month int Year int //files discovered AudioFileNames []string //parts extracted from the shownotes Title string AuthorNames string Description string //parts extracted from the chaptermarks ChapterMarks []ChapterMark } type ChapterMark struct { StartTime string Title string URL string } func Scan() (result ScanResult) { //determine episode date by finding shownotes file names, err := filepath.Glob("shownotes-pentaradio-*.txt") must(err) if len(names) == 0 { fail("no files found: shownotes-pentaradio-*.txt") } if len(names) > 1 { fail("multiple files found: shownotes-pentaradio-*.txt") } match := regexp.MustCompile(`^shownotes-pentaradio-(\d{4})-(\d{2})-(\d{2})\.txt$`).FindStringSubmatch(names[0]) if match == nil { fail("cannot extract date from file name: %s", names[0]) } //validate episode date result.Year, _ = strconv.Atoi(match[1]) if result.Year < 2000 || result.Year > 2999 { fail("invalid year in filename: %s", names[0]) } result.Month, _ = strconv.Atoi(match[2]) if result.Month < 1 || result.Month > 12 { fail("invalid month in filename: %s", names[0]) } result.Day, _ = strconv.Atoi(match[3]) if result.Day < 1 || result.Day > 31 { fail("invalid day in filename: %s", names[0]) } //parse input files result.ParseShownotes() result.ParseChapterMarks() //collect audio files pattern := fmt.Sprintf("pentaradio-%04d-%02d-%02d.*", result.Year, result.Month, result.Day) result.AudioFileNames, err = filepath.Glob(pattern) must(err) if len(names) == 0 { fail("no files found: %s", pattern) } return } var monthWords = []string{ "Null", "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember", } func (scan ScanResult) ShowNotesFile() string { return fmt.Sprintf("shownotes-pentaradio-%04d-%02d-%02d.txt", scan.Year, scan.Month, scan.Day) } func (scan *ScanResult) ParseShownotes() { buf, err := os.ReadFile(scan.ShowNotesFile()) must(err) expectedTitle := fmt.Sprintf("Pentaradio vom %d. %s %d", scan.Day, monthWords[scan.Month], scan.Year) shownotesRx := regexp.MustCompile( fmt.Sprintf(`^# %s\n`, expectedTitle) + //header line `# Titel: "(.*)"\n\n` + //episode title `Mit (.*)\.\n\n` + //author names `((?s:.*?))\n\n##\s`, //short description (everything up until the first

) ) match := shownotesRx.FindStringSubmatch(string(buf)) if match == nil { fail("shownotes do not match expected format: /%s/", shownotesRx.String()) } scan.Title = match[1] scan.AuthorNames = match[2] scan.Description = match[3] } func (scan ScanResult) ChapterMarksFile() string { return fmt.Sprintf("chapter-pentaradio-%04d-%02d-%02d.dat", scan.Year, scan.Month, scan.Day) } func (scan *ScanResult) ParseChapterMarks() { buf, err := os.ReadFile(scan.ChapterMarksFile()) must(err) lineRx := regexp.MustCompile(`^(\d\d:\d\d:\d\d.\d\d\d) (\S.*?\S)(?: <(https?://.*)>)?$`) for _, line := range strings.Split(string(buf), "\n") { if strings.TrimSpace(line) == "" { continue } match := lineRx.FindStringSubmatch(line) if match == nil { fail("invalid format for chapter mark: %s", line) } scan.ChapterMarks = append(scan.ChapterMarks, ChapterMark{ StartTime: match[1], Title: match[2], URL: match[3], }) } }