Skip to content

Commit

Permalink
Merge pull request #35 from raitonoberu/local
Browse files Browse the repository at this point in the history
Local lyrics source
  • Loading branch information
raitonoberu authored Jan 6, 2024
2 parents 2949519 + c9b0894 commit 580c2cc
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sptlrx/player"
"sptlrx/pool"
"sptlrx/services/hosted"
"sptlrx/services/local"
"sptlrx/services/spotify"
"sptlrx/ui"
"strings"
Expand Down Expand Up @@ -139,6 +140,9 @@ func loadPlayer(conf *config.Config) (player.Player, error) {
}

func loadProvider(conf *config.Config, player player.Player) (lyrics.Provider, error) {
if conf.Local.Folder != "" {
return local.New(conf.Local.Folder)
}
if conf.Cookie == "" {
return hosted.New(conf.Host), nil
}
Expand Down
4 changes: 4 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ type Config struct {
Browser struct {
Port int `default:"8974" yaml:"port"`
} `yaml:"browser"`

Local struct {
Folder string `yaml:"folder"`
} `yaml:"local"`
}

func New() *Config {
Expand Down
128 changes: 128 additions & 0 deletions services/local/local.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package local

import (
"bufio"
"io"
"io/fs"
"os"
"path/filepath"
"sptlrx/lyrics"
"strconv"
"strings"
)

var replacer = strings.NewReplacer(
"_", " ", "-", " ",
",", "", ".", "",
"!", "", "?", "",
"(", "", ")", "",
"[", "", "]", "",
)

type file struct {
Path string
NameParts []string
}

func New(folder string) (*Client, error) {
index, err := createIndex(folder)
if err != nil {
return nil, err
}
return &Client{index: index}, nil
}

// Client implements lyrics.Provider
type Client struct {
index []*file
}

func (c *Client) Lyrics(id, query string) ([]lyrics.Line, error) {
f := c.findFile(query)
if f == nil {
return nil, nil
}

reader, err := os.Open(f.Path)
if err != nil {
return nil, err
}
defer reader.Close()

return parseLrcFile(reader), nil
}

func (c *Client) findFile(query string) *file {
parts := splitString(query)

var best *file
var maxScore int
for _, f := range c.index {
var score int
for _, part := range parts {
for _, namePart := range f.NameParts {
if namePart == part {
score++
break
}
}
}
if score > maxScore {
maxScore = score
best = f
if score == len(parts) {
break
}
}
}
return best
}

func createIndex(folder string) ([]*file, error) {
index := []*file{}

return index, filepath.WalkDir(folder, func(path string, d fs.DirEntry, err error) error {
if d.IsDir() || !strings.HasSuffix(d.Name(), ".lrc") {
return nil
}
name := strings.TrimSuffix(d.Name(), ".lrc")
parts := splitString(name)

index = append(index, &file{
Path: path,
NameParts: parts,
})
return nil
})
}

func splitString(s string) []string {
s = strings.ToLower(s)
s = replacer.Replace(s)
return strings.Fields(s)
}

func parseLrcFile(reader io.Reader) []lyrics.Line {
result := []lyrics.Line{}
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
if !strings.HasPrefix(line, "[") || len(line) < 10 {
continue
}
result = append(result, parseLrcLine(line))
}
return result
}

func parseLrcLine(line string) lyrics.Line {
// [00:00.00]text -> {"time": 0, "words": "text"}
h, _ := strconv.Atoi(line[1:3])
m, _ := strconv.Atoi(line[4:6])
s, _ := strconv.Atoi(line[7:9])

return lyrics.Line{
Time: h*60*1000 + m*1000 + s*10,
Words: line[10:],
}
}

0 comments on commit 580c2cc

Please sign in to comment.