commit 3d25058496a7014bd785dc8c047d75244f3818fd Author: CDN18 Date: Sun Aug 11 09:50:31 2024 +0800 feat: sync diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e7dab73 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module lrc-cli + +go 1.22.6 diff --git a/main.go b/main.go new file mode 100644 index 0000000..f4b22ba --- /dev/null +++ b/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "os" +) + +func main() { + // parse args + if len(os.Args) < 2 { + fmt.Println(USAGE) + return + } + switch os.Args[1] { + case "sync": + syncLyrics(os.Args[2:]) + case "help": + fmt.Println(USAGE) + default: + fmt.Println("Unknown command") + fmt.Println(USAGE) + } +} diff --git a/model.go b/model.go new file mode 100644 index 0000000..ae4a6f2 --- /dev/null +++ b/model.go @@ -0,0 +1,14 @@ +package main + +type Lyrics struct { + Metadata map[string]string + Timeline []string + Content []string +} + +const USAGE = `Usage: lyc-cli [command] [options] +Commands: + sync Synchronize timeline of two lyrics files + help Show help` + +const SYNC_USAGE = `Usage: lyc-cli sync ` diff --git a/util.go b/util.go new file mode 100644 index 0000000..88aa0bf --- /dev/null +++ b/util.go @@ -0,0 +1,131 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "regexp" + "strings" +) + +func parseLyrics(filePath string) (Lyrics, error) { + file, err := os.Open(filePath) + if err != nil { + return Lyrics{}, err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + lyrics := Lyrics{ + Metadata: make(map[string]string), + } + timeLineRegex := regexp.MustCompile(`\[((\d+:)?\d+:\d+(\.\d+)?)\]`) + tagRegex := regexp.MustCompile(`\[(\w+):(.+)\]`) + + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "[") && strings.Contains(line, "]") { + if timeLineRegex.MatchString(line) { + // Timeline Tag + time := timeLineRegex.FindString(line) + lyrics.Timeline = append(lyrics.Timeline, time) + // Content + content := timeLineRegex.ReplaceAllString(line, "") + lyrics.Content = append(lyrics.Content, strings.TrimSpace(content)) + } else { + // Metadata + matches := tagRegex.FindStringSubmatch(line) + if len(matches) == 3 { + lyrics.Metadata[matches[1]] = strings.TrimSpace(matches[2]) + } + } + } + } + + if err := scanner.Err(); err != nil { + return Lyrics{}, err + } + + return lyrics, nil +} + +func syncLyrics(args []string) { + if len(args) < 2 { + fmt.Println(SYNC_USAGE) + return + } + + sourceFile := args[0] + targetFile := args[1] + + sourceLyrics, err := parseLyrics(sourceFile) + if err != nil { + fmt.Println("Error parsing source lyrics file:", err) + return + } + + targetLyrics, err := parseLyrics(targetFile) + if err != nil { + fmt.Println("Error parsing target lyrics file:", err) + return + } + + // Sync timeline + if len(sourceLyrics.Timeline) != len(targetLyrics.Timeline) { + fmt.Println("Warning: Timeline length mismatch") + return + } + minLength := len(sourceLyrics.Timeline) + if len(targetLyrics.Timeline) < minLength { + minLength = len(targetLyrics.Timeline) + } + + for i := 0; i < minLength; i++ { + targetLyrics.Timeline[i] = sourceLyrics.Timeline[i] + } + + // save to target, name it as "_synced.lrc" + targetFileName := strings.TrimSuffix(targetFile, ".lrc") + "_synced.lrc" + err = saveLyrics(targetFileName, targetLyrics) + if err != nil { + fmt.Println("Error saving synced lyrics file:", err) + return + } +} + +// func printLyricsInfo(lyrics Lyrics) { +// fmt.Println("Metadata:") +// for key, value := range lyrics.Metadata { +// fmt.Printf("%s: %s\n", key, value) +// } + +// fmt.Println("\nTimeline:") +// for _, time := range lyrics.Timeline { +// fmt.Println(time) +// } + +// fmt.Println("\nLyrics Content:") +// for _, content := range lyrics.Content { +// fmt.Println(content) +// } +// } + +func saveLyrics(filePath string, lyrics Lyrics) error { + file, err := os.Create(filePath) + if err != nil { + return err + } + defer file.Close() + + // Write metadata + for key, value := range lyrics.Metadata { + fmt.Fprintf(file, "[%s: %s]\n", key, value) + } + + // Write timeline and content + for i := 0; i < len(lyrics.Timeline); i++ { + fmt.Fprintf(file, "%s %s\n", lyrics.Timeline[i], lyrics.Content[i]) + } + + return nil +}