-
Notifications
You must be signed in to change notification settings - Fork 1
/
musixmatch.go
109 lines (94 loc) · 3.06 KB
/
musixmatch.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
package main
import (
"encoding/json"
"errors"
"io"
"log"
"net/http"
"net/url"
"github.com/valyala/fastjson"
)
const URL = "https://apic-desktop.musixmatch.com/ws/1.1/macro.subtitles.get"
type Musixmatch struct {
Token string
}
func (mx Musixmatch) findLyrics(track Track) (Song, error) {
song := Song{}
baseURL, _ := url.Parse(URL)
params := url.Values{
"format": {"json"},
"namespace": {"lyrics_richsynched"},
"subtitle_format": {"mxm"},
"app_id": {"web-desktop-app-v1.0"},
"usertoken": {mx.Token},
"q_album": {track.AlbumName},
"q_artist": {track.ArtistName},
"q_artists": {track.ArtistName},
"q_track": {track.TrackName},
"track_spotify_id": {""},
"q_duration": {""},
"f_subtitle_length": {""},
}
baseURL.RawQuery = params.Encode()
// log.Println(baseURL.String())
client := http.Client{}
req, err := http.NewRequest("GET", baseURL.String(), nil)
if err != nil {
return song, err
}
req.Header = http.Header{
"authority": {"apic-desktop.musixmatch.com"},
"cookie": {"x-mxm-token-guid="},
}
res, err := client.Do(req)
if err != nil {
return song, err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return song, err
}
var p fastjson.Parser
v, err := p.Parse(string(body))
if err != nil {
return song, err
}
if v.GetInt("message", "header", "status_code") == 401 && string(v.GetStringBytes("message", "header", "hint")) == "renew" {
return song, errors.New("invalid token")
}
mtg := v.Get("message", "body", "macro_calls", "matcher.track.get", "message")
tlg := v.Get("message", "body", "macro_calls", "track.lyrics.get", "message")
tsg := v.Get("message", "body", "macro_calls", "track.subtitles.get", "message")
switch mtg.GetInt("header", "status_code") {
case 200:
if err := json.Unmarshal(mtg.Get("body", "track").MarshalTo(nil), &song.Track); err != nil {
return song, err
}
case 401:
return song, errors.New("too many request. increase the cooldown time and try again in a few minutes")
case 404:
return song, errors.New("no results found")
default:
return song, errors.New("unknown error")
}
if song.Track.HasSubtitles == 1 {
if err := json.Unmarshal(tsg.GetStringBytes("body", "subtitle_list", "0", "subtitle", "subtitle_body"), &song.Subtitles.Lines); err != nil {
return song, err
}
} else {
log.Println("no synced lyrics found")
if song.Track.HasLyrics == 1 {
if tlg.GetInt("body", "lyrics", "restrited") == 1 {
return song, errors.New("restricted lyrics")
}
if err := json.Unmarshal(tlg.Get("body", "lyrics").MarshalTo(nil), &song.Lyrics); err != nil {
return song, err
}
} else if song.Track.Instrumental == 1 {
log.Println("song is instrumental")
} else {
return song, errors.New("no lyrics found")
}
}
return song, nil
}