promodj/parser.go
2021-08-14 09:59:41 +05:00

121 lines
2.5 KiB
Go

package main
import (
"bytes"
"fmt"
"net/url"
"strings"
"github.com/PuerkitoBio/goquery"
)
// Genre represents track information
type TrackInfo struct {
Title string
Url string
}
// Genre represents genre information
type Genre struct {
Name string
Code string
}
// Genres holds cached list of available genres
var Genres []Genre
func UpdateGenres() error {
var err error
Genres, err = updateGenreList()
if err != nil {
return fmt.Errorf("get genres list failed: %w", err)
}
return nil
}
func updateGenreList() ([]Genre, error) {
url := "https://promodj.com/music"
doc, err := goquery.NewDocument(url)
if err != nil {
return nil, err
}
var genres []Genre
doc.Find("div.styles_tagcloud > a").Each(func(i int, s *goquery.Selection) {
genres = append(genres, Genre{s.Text(), strings.TrimPrefix(s.AttrOr("href", ""), "/music/")})
})
return genres, nil
}
// tracksByGenre возвращает список треков по указанному жанру
func tracksByGenre(genre string) ([]TrackInfo, error) {
var result []TrackInfo
for i := 1; i <= 50; i++ {
url := fmt.Sprintf("https://promodj.com/music/%s?download=1&page=%d", genre, i)
doc, err := goquery.NewDocument(url)
if err != nil {
return nil, err
}
doc.Find("div.title > a.invert").Each(
func(n int, s *goquery.Selection) {
href, exists := s.Attr("href")
if !exists {
return
}
fields := strings.Split(href, "/")
if len(fields) != 7 {
return
}
fileUrl := fmt.Sprintf("https://promodj.com/download/%s/%s.mp3", fields[5], fields[6])
result = append(result, TrackInfo{s.Text(), fileUrl})
})
}
result = removeDuplicate(result)
return result, nil
}
// tracksToM3u возвращает байты M3U-плейлиста, сгенерированного по указанному
// списку треков
func tracksToM3u(host string, tracks []TrackInfo) []byte {
b := new(bytes.Buffer)
b.Write([]byte{0xEF, 0xBB, 0xBF})
fmt.Fprint(b, "#EXTM3U\n")
for _, track := range tracks {
fmt.Fprintf(b, "#EXTINF:-1,%s\n", track.Title)
u, _ := url.Parse(fmt.Sprintf("https://%s/stream", host))
q := make(url.Values)
q.Add("url", track.Url)
u.RawQuery = q.Encode()
fmt.Fprintf(b, "%s\n", u.String())
}
return b.Bytes()
}
func removeDuplicate(strSlice []TrackInfo) []TrackInfo {
allKeys := make(map[string]bool)
list := []TrackInfo{}
for _, item := range strSlice {
if _, value := allKeys[item.Url]; !value {
allKeys[item.Url] = true
list = append(list, item)
}
}
return list
}