dischord/extractor/youtube/providers.go

103 lines
2.3 KiB
Go
Raw Normal View History

2022-09-20 00:54:22 +02:00
package youtube
import (
"git.nobrain.org/r4/dischord/extractor"
"errors"
"net/url"
)
func init() {
extractor.AddExtractor("youtube", &Extractor{})
extractor.AddSearcher("youtube-search", &Searcher{})
extractor.AddSuggestor("youtube-search-suggestions", &Suggestor{})
}
type matchType int
const (
matchTypeNone matchType = iota
matchTypeVideo
matchTypePlaylist
)
var (
ErrInvalidInput = errors.New("invalid input")
)
func matches(requireDirectPlaylistUrl bool, input string) matchType {
u, err := url.Parse(input)
if err != nil {
return matchTypeNone
}
if u.Scheme != "http" && u.Scheme != "https" {
return matchTypeNone
}
q, err := url.ParseQuery(u.RawQuery)
if err != nil {
return matchTypeNone
}
switch u.Host {
case "www.youtube.com", "youtube.com":
if u.Path != "/watch" && u.Path != "/playlist" {
return matchTypeNone
}
if q.Has("list") && (!requireDirectPlaylistUrl || u.Path == "/playlist") {
return matchTypePlaylist
}
return matchTypeVideo
case "youtu.be":
return matchTypeVideo
default:
return matchTypeNone
}
}
type Extractor struct {
decryptor decryptor
}
func (e *Extractor) DefaultConfig() extractor.ProviderConfig {
return extractor.ProviderConfig{
"require-direct-playlist-url": false,
}
}
func (e *Extractor) Matches(cfg extractor.ProviderConfig, input string) bool {
return matches(cfg["require-direct-playlist-url"].(bool), input) != matchTypeNone
}
func (e *Extractor) Extract(cfg extractor.ProviderConfig, input string) ([]extractor.Data, error) {
switch matches(cfg["require-direct-playlist-url"].(bool), input) {
case matchTypeVideo:
d, err := getVideo(&e.decryptor, input)
if err != nil {
return nil, err
}
return []extractor.Data{d}, nil
case matchTypePlaylist:
return getPlaylist(input)
}
return nil, ErrInvalidInput
}
type Searcher struct{}
func (s *Searcher) DefaultConfig() extractor.ProviderConfig {
return extractor.ProviderConfig{}
}
func (s *Searcher) Search(cfg extractor.ProviderConfig, input string) ([]extractor.Data, error) {
return getSearch(input)
}
type Suggestor struct{}
func (s *Suggestor) DefaultConfig() extractor.ProviderConfig {
return extractor.ProviderConfig{}
}
func (s *Suggestor) Suggest(cfg extractor.ProviderConfig, input string) ([]string, error) {
return getSearchSuggestions(input)
}