Skip to content

Commit 071940b

Browse files
committed
v2.0.2: support for playlists
1 parent bcf5e8c commit 071940b

2 files changed

Lines changed: 80 additions & 20 deletions

File tree

gobalt.go

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ import (
2020
)
2121

2222
var (
23-
CobaltApi = "https://cobalt-backend.canine.tools" //Override this value to use your own cobalt instance. See https://instances.hyper.lol/ for alternatives from the main instance.
24-
Client = http.Client{Timeout: 10 * time.Second} //This allows you to modify the HTTP Client used in requests. This Client will be re-used.
25-
useragent = fmt.Sprintf("gobalt/2.0.1 (+https://github.com/lostdusty/gobalt/v2; go/%v; %v/%v)", runtime.Version(), runtime.GOOS, runtime.GOARCH)
23+
CobaltApi = "https://cobalt-backend.canine.tools" //Override this value to use your own cobalt instance. See https://instances.hyper.lol/ for alternatives from the main instance.
24+
Client = http.Client{
25+
Timeout: 10 * time.Second,
26+
} //This allows you to modify the HTTP Client used in requests. This Client will be re-used.
27+
useragent = fmt.Sprintf("gobalt/2.0.2 (+https://github.com/lostdusty/gobalt/v2; go/%v; %v/%v)", runtime.Version(), runtime.GOOS, runtime.GOARCH)
2628
)
2729

2830
// ServerInfo is the struct used in the function CobaltServerInfo(). It contains two sub-structs: Cobalt and Git
@@ -52,24 +54,21 @@ type CobaltGitInformation struct {
5254
// This function is called before Run() to check if the cobalt server used is reachable.
5355
// If you can't contact the main server, try using another instance using GetCobaltinstances().
5456
func CobaltServerInfo(api string) (*ServerInfo, error) {
57+
if !strings.HasPrefix(api, "http") {
58+
api = "http://" + api
59+
}
5560
//Parse url before testing, sanity check
5661
parseApiUrl, err := url.Parse(api)
5762
if err != nil {
58-
return nil, fmt.Errorf("net/url failed to parse provided url, check it and try again (details: %v)", err)
63+
return nil, fmt.Errorf("net/url failed to parse provided url, check it and try again (details: %v, url: %v)", err, api)
5964
}
6065

6166
if parseApiUrl.Scheme == "" {
6267
parseApiUrl.Scheme = "https"
6368
}
6469

6570
//Check if the server is reachable
66-
req, err := http.NewRequest(http.MethodGet, parseApiUrl.String(), nil)
67-
req.Header.Add("User-Agent", useragent)
68-
if err != nil {
69-
return nil, err
70-
}
71-
72-
res, err := Client.Do(req)
71+
res, err := genericHttpRequest(parseApiUrl.String(), http.MethodGet, nil)
7372
if err != nil {
7473
return nil, err
7574
}
@@ -293,13 +292,7 @@ type Services struct {
293292

294293
// GetCobaltInstances makes a request to instances.hyper.lol and returns a list of all online cobalt instances.
295294
func GetCobaltInstances() ([]CobaltInstance, error) {
296-
req, err := http.NewRequest(http.MethodGet, "https://instances.hyper.lol/instances.json", nil)
297-
req.Header.Add("User-Agent", useragent)
298-
if err != nil {
299-
return nil, err
300-
}
301-
302-
res, err := Client.Do(req)
295+
res, err := genericHttpRequest("https://instances.hyper.lol/instances.json", http.MethodGet, nil)
303296
if err != nil {
304297
return nil, err
305298
}
@@ -313,7 +306,7 @@ func GetCobaltInstances() ([]CobaltInstance, error) {
313306
var listOfCobaltInstances []CobaltInstance
314307
err = json.Unmarshal(jsonbody, &listOfCobaltInstances)
315308
if err != nil {
316-
return nil, fmt.Errorf("json err? %v", err)
309+
return nil, err
317310
}
318311

319312
parseModernInstances := make([]CobaltInstance, 0)
@@ -335,7 +328,7 @@ type MediaInfo struct {
335328

336329
// ProcessMedia(url) attempts to fetch the file size, mime type and name.
337330
func ProcessMedia(url string) (*MediaInfo, error) {
338-
req, err := http.Head(url)
331+
req, err := genericHttpRequest(url, http.MethodHead, nil)
339332
if err != nil {
340333
return nil, err
341334
}
@@ -359,3 +352,56 @@ func ProcessMedia(url string) (*MediaInfo, error) {
359352
Type: req.Header.Get("Content-Type"),
360353
}, nil
361354
}
355+
356+
// This slice will contain urls of Youtube videos
357+
type Playlist []string
358+
359+
// Function GetYoutubePlaylist(string) gets an Youtube playlist has parameter, and returns a slice []Playlist with the urls of the playlist.
360+
func GetYoutubePlaylist(playlist string) (Playlist, error) {
361+
//Parse param url
362+
newYoutubePlaylistUrl, err := url.Parse(playlist)
363+
if err != nil {
364+
return nil, err
365+
}
366+
if !strings.HasSuffix(newYoutubePlaylistUrl.Host, "youtube.com") || newYoutubePlaylistUrl.Path != "/playlist" {
367+
return nil, errors.New("non youtube playlist url provided")
368+
}
369+
370+
getUrls, err := genericHttpRequest(fmt.Sprintf("https://playlist.kwiatekmiki.pl/api/getvideos?url=%v", newYoutubePlaylistUrl.String()), http.MethodGet, nil)
371+
if err != nil {
372+
return nil, err
373+
}
374+
if getUrls.StatusCode != 200 {
375+
return nil, fmt.Errorf("%v", getUrls.Status)
376+
}
377+
378+
unmarshalBody, err := io.ReadAll(getUrls.Body)
379+
if err != nil {
380+
return nil, err
381+
}
382+
383+
var list Playlist
384+
err = json.Unmarshal(unmarshalBody, &list)
385+
if err != nil {
386+
return nil, err
387+
}
388+
389+
return list, nil
390+
}
391+
392+
// Function to do generic, less complex http requests, to avoid code repetitions. Internal use of the library only.
393+
func genericHttpRequest(url, method string, body io.Reader) (*http.Response, error) {
394+
request, err := http.NewRequest(method, url, body)
395+
request.Header.Add("User-Agent", useragent)
396+
397+
if err != nil {
398+
return nil, err
399+
}
400+
401+
response, err := Client.Do(request)
402+
if err != nil {
403+
return nil, err
404+
}
405+
406+
return response, nil
407+
}

gobalt_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,17 @@ func TestMediaParsing(t *testing.T) {
5959
t.Logf("name %v | size %v bytes | mime %v", d.Filename, n.Size, n.Type)
6060

6161
}
62+
63+
func TestPlaylistGet(t *testing.T) {
64+
a, err := GetYoutubePlaylist("https://youtube.com/playlist?list=PLDKxz_KUEUfMDTqDgv4eHuZq1u_SQtRiu&si=a-f1kK5lSGFRJO8z")
65+
if err != nil {
66+
t.Fatalf("failed to get playlist: %v", err)
67+
}
68+
if a[0] != "https://youtu.be/gYygotHLyjo" {
69+
t.Fatalf("got unexpected link: %v, instead of https://youtu.be/gYygotHLyjo", a[0])
70+
}
71+
t.Log("Urls of the playlist:")
72+
for _, v := range a {
73+
t.Log(v)
74+
}
75+
}

0 commit comments

Comments
 (0)