From 96886f9f091adeb0dfc54a0988d575935c68304e Mon Sep 17 00:00:00 2001 From: zhangshan Date: Wed, 6 Jan 2021 18:07:01 +0800 Subject: [PATCH] add track.song api --- .gitignore | 1 + app/temp.go | 59 ------------ app/temp_test.go | 35 ------- config.example.toml | 14 +-- lastfm/auth.go | 2 +- lastfm/lastfm.go | 96 -------------------- lastfm/lastfm_test.go | 7 +- lastfm/scrobble.go | 103 +++++++++++++++++++++ lastfm/track_love.go | 31 +++++++ main.go | 102 ++------------------- xiami/song.go | 38 ++++++++ xiami/song_test.go | 13 +++ xiami/xiami.go | 207 ------------------------------------------ xiami/xiami_test.go | 32 ------- xiami_test.go | 22 ----- 15 files changed, 200 insertions(+), 562 deletions(-) delete mode 100644 app/temp.go delete mode 100644 app/temp_test.go create mode 100644 lastfm/scrobble.go create mode 100644 lastfm/track_love.go create mode 100644 xiami/song.go create mode 100644 xiami/song_test.go delete mode 100644 xiami/xiami.go delete mode 100644 xiami/xiami_test.go delete mode 100644 xiami_test.go diff --git a/.gitignore b/.gitignore index daa3045..042d207 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ config.toml log/* go.sum +xiami/song.json diff --git a/app/temp.go b/app/temp.go deleted file mode 100644 index 53f3489..0000000 --- a/app/temp.go +++ /dev/null @@ -1,59 +0,0 @@ -package app - -import ( - "bufio" - "encoding/json" - "errors" - "fmt" - "log" - "os" - - "xiamiToLastfm/xiami" -) - -var file = "temp.txt" - -// If program quit before messages in channel completely processed, -// the messages will be saved to a temp file, and processed next time when the program start. -func TempStore(playedChan chan xiami.Track) error { - fmt.Println("unsent xiami tracks exist, saving to a temp file.") - f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0666) - if err != nil { - return errors.New("temp file create failed") - } - defer f.Close() - - n := len(playedChan) - for i := 0; i < n; i++ { - t := <-playedChan - a, _ := json.Marshal(t) - f.Write(a) - f.WriteString("\n") - } - log.Println("Temp file created: ", file) - return nil -} - -// While program start, if a temp file detected and successful loaded, -// the messages will be added to the channel and processed soon. -func TempRead(playedChan chan xiami.Track) error { - f, err := os.OpenFile(file, os.O_RDONLY, 0666) - if err != nil { - return errors.New("temp file not found") - } - - fmt.Println("previous unsent xiami tracks detected, will send to server later.") - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - var t xiami.Track - json.Unmarshal(scanner.Bytes(), &t) - playedChan <- t - } - f.Close() - - os.Remove(file) - log.Println("Temp file removed: ", file) - return nil - -} diff --git a/app/temp_test.go b/app/temp_test.go deleted file mode 100644 index 2ab9082..0000000 --- a/app/temp_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package app - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "xiamiToLastfm/xiami" -) - -func TestTempStore(t *testing.T) { - playedChan := make(chan xiami.Track, 10) - defer close(playedChan) - track := xiami.Track{ - Title: "自己顕示欲", - Album: "TVアニメ『ID-0』オリジナルサウンドトラック", - Artist: "服部隆之", - Timestamp: 1523328000, - } - playedChan <- track - track = xiami.Track{ - Title: "仕事", - Album: "TVアニメ『ID-0』オリジナルサウンドトラック", - Artist: "服部隆之", - Timestamp: 1523327819, - } - playedChan <- track - assert.True(t, TempStore(playedChan) == nil) -} - -func TestTempRead(t *testing.T) { - playedChan := make(chan xiami.Track, 10) - defer close(playedChan) - assert.True(t, TempRead(playedChan) == nil) - assert.Equal(t, 2, len(playedChan)) -} diff --git a/config.example.toml b/config.example.toml index 0256f41..9a730b1 100644 --- a/config.example.toml +++ b/config.example.toml @@ -17,16 +17,4 @@ title = "Xiami and Last.fm Example" recording = "/recording" [xiami] - domain = "http://www.xiami.com" - spm = "" - user_id = 0 - checked_at = 0 - - [xiami.cookie] - _unsign_token = "" - _xiamitoken = "" - member_auth = "" - x5sec = "" - - [xiami.url] - recent = "/space/charts-recent/u/" + file = "xiami/song.json" diff --git a/lastfm/auth.go b/lastfm/auth.go index 551fa98..90a0f7b 100644 --- a/lastfm/auth.go +++ b/lastfm/auth.go @@ -141,7 +141,7 @@ func authPage() string { // Session keys have an infinite lifetime by default func session() error { v := url.Values{} - v.Set("method", "auth.session") + v.Set("method", "auth.getSession") v.Set("api_key", apiKey) v.Set("token", token) sig := signature(&v) diff --git a/lastfm/lastfm.go b/lastfm/lastfm.go index 666a15a..a0096c0 100644 --- a/lastfm/lastfm.go +++ b/lastfm/lastfm.go @@ -7,11 +7,7 @@ import ( "io/ioutil" "log" "net/http" - "net/url" "os" - - "xiamiToLastfm/musicbrainz" - "xiamiToLastfm/xiami" ) // QuitChan: an empty channel used to signal main channel to stop. @@ -20,98 +16,6 @@ var ( QuitChan chan struct{} ) -// https://www.last.fm/api/show/track.scrobble -type ScrobbleParams struct { - Artist []string `json:"artist,omitempty"` - Track []string `json:"track,omitempty"` - Timestamp []string `json:"timestamp,omitempty"` - Album []string `json:"album,omitempty"` - TrackNumber []string `json:"trackNumber,omitempty"` - Mbid []string `json:"mbid,omitempty"` //The MusicBrainz Track ID - AlbumArtist []string `json:"albumArtist,omitempty"` - DurationInSeconds []string `json:"duration,omitempty"` - ApiKey string `json:"api_key"` - ApiSig string `json:"api_sig"` - Sk string `json:"sk"` - Format string `json:"format"` - Method string `json:"method"` -} - -// Send scrobble info to last.fm server -// https://www.last.fm/api/show/track.scrobble -func Scrobble(xm xiami.Track) error { - log.Println("lastfm.Scrobble playedChan track: ", xm) - - v := url.Values{} - v.Set("artist[0]", xm.Artist) - v.Set("album[0]", xm.Album) - v.Set("track[0]", xm.Title) - - if mbid, ok := musicbrainz.MbID(xm.Title, xm.Artist, xm.Album); ok { - v.Set("mbid[0]", string(mbid)) - } - - v.Set("timestamp[0]", fmt.Sprint(xm.Timestamp)) - v.Set("method", "track.scrobble") - v.Set("sk", sk) - v.Set("api_key", apiKey) - sig := signature(&v) - v.Set("api_sig", sig) - v.Set("format", "json") - - respData, err := postRequest(v.Encode()) - if err != nil { - //if failed, insert back to channel - return err - } - - accepted, ignored := scrobbleResponse(respData) - log.Printf("last.fm: Scrobble succese: accepted - %d, ignored - %d\n", accepted, ignored) - fmt.Printf("scrobbled:\t %s - %s \n", xm.Title, xm.Artist) - - return nil -} - -func scrobbleResponse(data []byte) (accepted, ignored int) { - type response struct { - Data struct { - Msg struct { - Accepted int `json:"accepted"` - Ignored int `json:"ignored"` - } `json:"@attr"` - } `json:"scrobbles"` - } - - var resp response - json.Unmarshal(data, &resp) - return resp.Data.Msg.Accepted, resp.Data.Msg.Ignored -} - -// Update nowplaying -// https://www.last.fm/api/show/track.updateNowPlaying -func UpdateNowPlaying(xm xiami.Track) error { - log.Println("last.fm: nowPlayingChan track: ", xm) - - v := url.Values{} - v.Set("method", "track.updateNowPlaying") - v.Set("sk", sk) - v.Set("api_key", apiKey) - v.Set("artist", xm.Artist) - v.Set("album", xm.Album) - v.Set("track", xm.Title) - sig := signature(&v) - v.Set("api_sig", sig) - v.Set("format", "json") - - if _, err := postRequest(v.Encode()); err != nil { - //if failed, as discard. - return err - } - - fmt.Printf("updated:\t %s - %s \n", xm.Title, xm.Artist) - return nil -} - func getRequest(url string) ([]byte, error) { log.Println("last.fm: getRequest url: ", url) res, err := http.Get(url) diff --git a/lastfm/lastfm_test.go b/lastfm/lastfm_test.go index f57798b..f6b58d8 100644 --- a/lastfm/lastfm_test.go +++ b/lastfm/lastfm_test.go @@ -135,7 +135,7 @@ func TestStartScrobble(t *testing.T) { } playedChan <- track - assert.Equal(t, nil, Scrobble(playedChan)) + assert.Equal(t, nil, Scrobble(track)) } func TestUpdateNowPlaying(t *testing.T) { @@ -149,7 +149,7 @@ func TestUpdateNowPlaying(t *testing.T) { Timestamp: 1523328000, } nowPlayingChan <- track - assert.Equal(t, nil, UpdateNowPlaying(nowPlayingChan)) + assert.Equal(t, nil, UpdateNowPlaying(track)) } func TestRenderScrobbleResp(t *testing.T) { @@ -180,7 +180,8 @@ func TestHandleError(t *testing.T) { } func TestGetSession(t *testing.T) { - session() + err := session() + assert.Nil(t, err) } func init() { diff --git a/lastfm/scrobble.go b/lastfm/scrobble.go new file mode 100644 index 0000000..f4cd620 --- /dev/null +++ b/lastfm/scrobble.go @@ -0,0 +1,103 @@ +package lastfm + +import ( + "encoding/json" + "fmt" + "log" + "net/url" + + "xiamiToLastfm/musicbrainz" + "xiamiToLastfm/xiami" +) + +// https://www.last.fm/api/show/track.scrobble +type ScrobbleParams struct { + Artist []string `json:"artist,omitempty"` + Track []string `json:"track,omitempty"` + Timestamp []string `json:"timestamp,omitempty"` + Album []string `json:"album,omitempty"` + TrackNumber []string `json:"trackNumber,omitempty"` + Mbid []string `json:"mbid,omitempty"` //The MusicBrainz Track ID + AlbumArtist []string `json:"albumArtist,omitempty"` + DurationInSeconds []string `json:"duration,omitempty"` + ApiKey string `json:"api_key"` + ApiSig string `json:"api_sig"` + Sk string `json:"sk"` + Format string `json:"format"` + Method string `json:"method"` +} + +// Send scrobble info to last.fm server +// https://www.last.fm/api/show/track.scrobble +func Scrobble(xm xiami.Track) error { + log.Println("lastfm.Scrobble playedChan track: ", xm) + + v := url.Values{} + v.Set("artist[0]", xm.Artist) + v.Set("album[0]", xm.Album) + v.Set("track[0]", xm.Title) + + if mbid, ok := musicbrainz.MbID(xm.Title, xm.Artist, xm.Album); ok { + v.Set("mbid[0]", string(mbid)) + } + + v.Set("timestamp[0]", fmt.Sprint(xm.Timestamp)) + v.Set("method", "track.scrobble") + v.Set("sk", sk) + v.Set("api_key", apiKey) + sig := signature(&v) + v.Set("api_sig", sig) + v.Set("format", "json") + + respData, err := postRequest(v.Encode()) + if err != nil { + //if failed, insert back to channel + return err + } + + accepted, ignored := scrobbleResponse(respData) + log.Printf("last.fm: Scrobble succese: accepted - %d, ignored - %d\n", accepted, ignored) + fmt.Printf("scrobbled:\t %s - %s \n", xm.Title, xm.Artist) + + return nil +} + +func scrobbleResponse(data []byte) (accepted, ignored int) { + type response struct { + Data struct { + Msg struct { + Accepted int `json:"accepted"` + Ignored int `json:"ignored"` + } `json:"@attr"` + } `json:"scrobbles"` + } + + var resp response + json.Unmarshal(data, &resp) + return resp.Data.Msg.Accepted, resp.Data.Msg.Ignored +} + +// Update nowplaying +// https://www.last.fm/api/show/track.updateNowPlaying +func UpdateNowPlaying(xm xiami.Track) error { + log.Println("last.fm: nowPlayingChan track: ", xm) + + v := url.Values{} + v.Set("method", "track.updateNowPlaying") + v.Set("sk", sk) + v.Set("api_key", apiKey) + v.Set("artist", xm.Artist) + v.Set("album", xm.Album) + v.Set("track", xm.Title) + sig := signature(&v) + v.Set("api_sig", sig) + v.Set("format", "json") + + if _, err := postRequest(v.Encode()); err != nil { + //if failed, as discard. + return err + } + + fmt.Printf("updated:\t %s - %s \n", xm.Title, xm.Artist) + return nil +} diff --git a/lastfm/track_love.go b/lastfm/track_love.go new file mode 100644 index 0000000..7e3c34c --- /dev/null +++ b/lastfm/track_love.go @@ -0,0 +1,31 @@ +package lastfm + +import ( + "fmt" + "log" + "net/url" + + "xiamiToLastfm/xiami" +) + +func TrackLove(xm *xiami.Track) error { + log.Println("lastfm.track.love track: ", xm) + + v := url.Values{} + v.Set("artist", xm.Artist) + v.Set("track", xm.Title) + v.Set("method", "track.love") + v.Set("sk", sk) + v.Set("api_key", apiKey) + sig := signature(&v) + v.Set("api_sig", sig) + v.Set("format", "json") + + if _, err := postRequest(v.Encode()); err != nil { + //if failed, insert back to channel + return err + } + + fmt.Printf("loved:\t %s - %s \n", xm.Title, xm.Artist) + return nil +} diff --git a/main.go b/main.go index 132e91c..9e2de74 100644 --- a/main.go +++ b/main.go @@ -2,21 +2,14 @@ package main import ( "flag" - "fmt" "log" - "os" - "os/signal" - "syscall" - "time" - "github.com/spf13/viper" "xiamiToLastfm/app" "xiamiToLastfm/lastfm" "xiamiToLastfm/xiami" ) var debug bool -var frequency = time.Minute var config string func main() { @@ -25,110 +18,31 @@ func main() { } prepare() - delayStart() run() } func run() { - ticker := time.NewTicker(frequency) - - fmt.Println("start scrobbling...") - nowPlayingChan := make(chan xiami.Track) - playedChan := make(chan xiami.Track, 10) - - quitChan := make(chan struct{}) - lastfm.QuitChan = quitChan - stop(quitChan) - - go func() { - if err := app.TempRead(playedChan); err != nil { - log.Println(err) - } - - for { - select { - case xm := <-nowPlayingChan: - if err := lastfm.UpdateNowPlaying(xm); err != nil { - fmt.Println("last.fm: updateNowPlaying sent failed.") - log.Println("last.fm: ", err) - } - case xm := <-playedChan: - if err := lastfm.Scrobble(xm); err != nil { - playedChan <- xm - fmt.Println("last.fm: scrobble sent failed. Try again in 5 seconds.") - log.Println("last.fm: ", err) - time.Sleep(time.Second * 5) - } - //write the execute time while channel's empty. To avoid duplicate request to last.fm. - if len(playedChan) < 1 { - viper.Set("xiami.checked_at", time.Now().Truncate(time.Minute).Unix()) - viper.WriteConfig() - } - case <-quitChan: - return - } - } - }() - - for { - select { - case <-ticker.C: - xiami.Tracks(nowPlayingChan, playedChan) - case <-quitChan: - ticker.Stop() + data, err := xiami.ReadFile() + if err != nil { + panic(err) + } - close(nowPlayingChan) - windUp(playedChan) - close(playedChan) - return + for _, track := range data.Data { + if err := lastfm.TrackLove(track); err != nil { + log.Println("") } } + } func init() { flag.BoolVar(&debug, "d", false, "debug mode, will export logs to file") - minute := flag.Uint64("m", 1, "how often to check the xiami page. unit: minute") flag.StringVar(&config, "c", "config.toml", "config name and path") flag.Parse() - frequency *= time.Duration(*minute) - app.InitConfig(config) } func prepare() { - xiami.Init() lastfm.Auth() } - -// delayStart will delay the program a few seconds and start at exact next minute, -// to ensure time calculated from xiami page will be relatively accurate. -func delayStart() { - now := time.Now() - start := now.Truncate(time.Minute).Add(time.Minute) - fmt.Println("will start at", start.Format("2006-01-02 15:04:05")) - - sleep := start.UnixNano() - now.UnixNano() - time.Sleep(time.Duration(sleep)) -} - -// Detect Ctrl+C keyboard interruption and set quit signal to quitChan. -func stop(quit chan struct{}) { - c := make(chan os.Signal, 2) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - go func() { - <-c - fmt.Println("\r- Ctrl+C pressed in Terminal") - close(quit) - fmt.Println("Stopped.") - }() -} - -// Before the program quit, if scrobble play chan is not empty, save to a temp file. -func windUp(playedChan chan xiami.Track) { - if len(playedChan) > 0 { - if err := app.TempStore(playedChan); err != nil { - log.Println(err) - } - } -} diff --git a/xiami/song.go b/xiami/song.go new file mode 100644 index 0000000..8ca041f --- /dev/null +++ b/xiami/song.go @@ -0,0 +1,38 @@ +package xiami + +import ( + "encoding/json" + "io/ioutil" + "os" + + "github.com/spf13/viper" +) + +type Track struct { + Title string `json:"songName"` + Artist string `json:"singers"` + Album string `json:"albumName"` + Alias string `json:"translation"` + Timestamp int64 `json:"-"` +} + +type SongData struct { + Data []*Track `json:"data"` +} + +func ReadFile() (*SongData, error) { + r, err := os.Open(viper.GetString("xiami.file")) + + if err != nil { + return nil, err + } + defer r.Close() + b, _ := ioutil.ReadAll(r) + + data := new(SongData) + if err := json.Unmarshal(b, data); err != nil { + return nil, err + } + + return data, nil +} diff --git a/xiami/song_test.go b/xiami/song_test.go new file mode 100644 index 0000000..2d346e2 --- /dev/null +++ b/xiami/song_test.go @@ -0,0 +1,13 @@ +package xiami + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestReadFile(t *testing.T) { + data, err := ReadFile() + assert.Nil(t, err) + t.Log(data.Data[0]) +} diff --git a/xiami/xiami.go b/xiami/xiami.go deleted file mode 100644 index 544eaf6..0000000 --- a/xiami/xiami.go +++ /dev/null @@ -1,207 +0,0 @@ -package xiami - -import ( - "bufio" - "fmt" - "log" - "net/http" - "net/url" - "os" - "strconv" - "strings" - "time" - - "github.com/PuerkitoBio/goquery" - "github.com/spf13/viper" -) - -const ( - typeNowPlaying = iota + 1 - typePlayed -) - -var ( - domain, spm string - userId int -) - -type Track struct { - Title, Artist, Album string - Timestamp int64 -} - -// Get xiami user id from user's profile page url -func Init() { - if checkConfig() { - return - } - fmt.Println("Press Enter xiami profile page url") - profileUrl, _ := bufio.NewReader(os.Stdin).ReadString('\n') - - parseUrl(profileUrl) - return -} - -func checkConfig() bool { - domain = viper.GetString("xiami.domain") - userId = viper.GetInt("xiami.user_id") - spm = viper.GetString("xiami.spm") - if userId > 0 && spm != "" { - return true - } - return false -} - -// parseUrl and save to config -func parseUrl(rawUrl string) (userId, spm string) { - u, _ := url.Parse(rawUrl) - spm = u.Query().Get("spm") - spm = strings.TrimRight(spm, "\n") - - s := strings.Split(u.Path, "/") - userId = s[2] - - viper.Set("xiami.user_id", userId) - viper.Set("xiami.spm", spm) - viper.WriteConfig() - - return userId, spm -} - -// Access user's recent track page. -func Tracks(playingChan, playedChan chan Track) error { - recentUri := viper.GetString("xiami.url.recent") - lastCheckAt := viper.GetInt64("xiami.checked_at") - - recentUrl, _ := url.Parse(domain) - recentUrl.Path += recentUri + fmt.Sprint(userId) - - doc, err := document(recentUrl) - if err != nil || doc == nil { - log.Println("xiami.Tracks:", err) - return err - } - - // Find the track list - doc.Find(".track_list tr").Each(func(i int, s *goquery.Selection) { - trackTime := s.Find(".track_time").Text() - timeStamp, scrobbleType, ok := parseTime(trackTime) - - // compare with last record check time, if before, means scrobbles are up to date. - if !ok || timeStamp < lastCheckAt { - return - } - - title, _ := s.Find(".song_name a").Attr("title") - trackUrl, _ := s.Find(".song_name a").Attr("href") - - //find record's artist and album from its' detail page, as artist and album are required. - artist, album, ok := album(trackUrl) - time.Sleep(2 * time.Second) - - if !ok { - log.Println("xiami.album fetch failed") - return - } - - t := Track{Title: title, Artist: artist, Album: album, Timestamp: timeStamp} - - switch scrobbleType { - case typeNowPlaying: - playingChan <- t - fmt.Printf("nowPlaying:\t %s - %s 《%s》 \n", title, artist, album) - log.Println("xiami.Tracks: playingChan <- t ", t) - case typePlayed: - playedChan <- t - fmt.Printf("listened [%d]:\t %s - %s 《%s》 \n", i, title, artist, album) - log.Println("xiami.Tracks: playedChan <- t ", t) - default: - log.Println("xiami.Tracks: switch default") - } - }) - log.Println("xiami.Tracks returned.") - return nil -} - -// if time before 1 hour, then exact time cannot be calculated, abort -func parseTime(s string) (t int64, srbType int, ok bool) { - //播放完毕可以同步 - if strings.HasSuffix(s, "分钟前") { - minutes, _ := strconv.Atoi(strings.TrimSuffix(s, "分钟前")) - duration := - time.Minute * time.Duration(minutes) - t := time.Now().Add(duration) - return t.Truncate(time.Minute).Unix(), typePlayed, true - } - - //正在播放 - if strings.HasSuffix(s, "刚刚") || strings.HasSuffix(s, "秒前") { - return time.Now().Unix(), typeNowPlaying, true - } - return 0, 0, false -} - -func album(uri string) (artist, album string, ok bool) { - songUrl, _ := url.Parse(domain) - songUrl.Path += uri - - doc, err := document(songUrl) - if err != nil { - log.Println("xiami.album:", err) - return "", "", false - } - if doc == nil { - return "", "", false - } - - var info []string - doc.Find("#albums_info tr").Each(func(i int, s *goquery.Selection) { - // For each item found, get the artist and title - title, _ := s.Find("a").Attr("title") - info = append(info, title) - }) - - if len(info) < 2 { - return "", "", false - } - - return info[1], info[0], true -} - -func document(u *url.URL) (*goquery.Document, error) { - v := url.Values{} - v.Set("spm", spm) - u.RawQuery = v.Encode() - - log.Println("xiami.document url:", u) - - req, err := http.NewRequest("GET", u.String(), nil) - addCookies(req) - client := new(http.Client) - res, err := client.Do(req) - - if err != nil { - log.Println("xiami.document Fatal: ", err) - return nil, err - } - defer res.Body.Close() - - if res.StatusCode != 200 { - return nil, fmt.Errorf("status code error: '%s' on %s", res.Status, u) - } - - // Load the HTML document - doc, err := goquery.NewDocumentFromReader(res.Body) - if err != nil { - return nil, err - } - return doc, nil -} -func addCookies(req *http.Request) { - keys := viper.AllSettings() - xm := keys["xiami"].(map[string]interface{}) - cookies := xm["cookie"].(map[string]interface{}) - for k, v := range cookies { - req.AddCookie(&http.Cookie{Name: k, Value: v.(string)}) - log.Printf("xiami.addCookie %s:%s \n", k, v) - } -} diff --git a/xiami/xiami_test.go b/xiami/xiami_test.go deleted file mode 100644 index cd6ae8d..0000000 --- a/xiami/xiami_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package xiami - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestParseUrl(t *testing.T) { - url := "http://www.xiami.com/u/37185?spm=a1z1s.6928797.1561534497.2.dETWvH" - userId, spm := parseUrl(url) - - assert.Equal(t, "37185", userId) - assert.Equal(t, "a1z1s.6928797.1561534497.2.dETWvH", spm) -} - -func TestParseTime(t *testing.T) { - test := "1分钟前" - timestamp, _, _ := parseTime(test) - now := time.Now().Truncate(time.Minute).Unix() - var expected int64 = 60 - assert.Equal(t, expected, now-timestamp) -} - -func TestGetAlbum(t *testing.T) { - url := "https://www.xiami.com/song/mSJtnV7aa77?spm=a1z1s.6626017.0.0.nGwy1E" - artist, album, ok := album(url) - assert.True(t, ok) - assert.Equal(t, "川井憲次", artist) - assert.Equal(t, "NHKスペシャル「人体 神秘の巨大ネットワーク」オリジナル・サウンドトラック", album) -} diff --git a/xiami_test.go b/xiami_test.go deleted file mode 100644 index 45e47d3..0000000 --- a/xiami_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "testing" - - "xiamiToLastfm/app" - "xiamiToLastfm/xiami" -) - -func TestGetTracks(t *testing.T) { - app.InitConfig("config.toml") - xiami.Init() - - nowPlayingChan := make(chan xiami.Track) - playedChan := make(chan xiami.Track, 5) - defer func() { - close(nowPlayingChan) - close(playedChan) - }() - - xiami.Tracks(nowPlayingChan, playedChan) -}