1
0
mirror of https://github.com/mxpv/podsync.git synced 2024-05-11 05:55:04 +00:00
2021-10-09 17:14:35 -07:00

189 lines
3.9 KiB
Go
Executable File

package builder
import (
"net/url"
"strings"
"github.com/pkg/errors"
"github.com/mxpv/podsync/pkg/model"
)
func ParseURL(link string) (model.Info, error) {
parsed, err := parseURL(link)
if err != nil {
return model.Info{}, err
}
info := model.Info{}
if strings.HasSuffix(parsed.Host, "youtube.com") {
kind, id, err := parseYoutubeURL(parsed)
if err != nil {
return model.Info{}, err
}
info.Provider = model.ProviderYoutube
info.LinkType = kind
info.ItemID = id
return info, nil
}
if strings.HasSuffix(parsed.Host, "vimeo.com") {
kind, id, err := parseVimeoURL(parsed)
if err != nil {
return model.Info{}, err
}
info.Provider = model.ProviderVimeo
info.LinkType = kind
info.ItemID = id
return info, nil
}
if strings.HasSuffix(parsed.Host, "soundcloud.com") {
kind, id, err := parseSoundcloudURL(parsed)
if err != nil {
return model.Info{}, err
}
info.Provider = model.ProviderSoundcloud
info.LinkType = kind
info.ItemID = id
return info, nil
}
return model.Info{}, errors.New("unsupported URL host")
}
func parseURL(link string) (*url.URL, error) {
if !strings.HasPrefix(link, "http") {
link = "https://" + link
}
parsed, err := url.Parse(link)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse url: %s", link)
}
return parsed, nil
}
func parseYoutubeURL(parsed *url.URL) (model.Type, string, error) {
path := parsed.EscapedPath()
// https://www.youtube.com/playlist?list=PLCB9F975ECF01953C
// https://www.youtube.com/watch?v=rbCbho7aLYw&list=PLMpEfaKcGjpWEgNtdnsvLX6LzQL0UC0EM
if strings.HasPrefix(path, "/playlist") || strings.HasPrefix(path, "/watch") {
kind := model.TypePlaylist
id := parsed.Query().Get("list")
if id != "" {
return kind, id, nil
}
return "", "", errors.New("invalid playlist link")
}
// - https://www.youtube.com/channel/UC5XPnUk8Vvv_pWslhwom6Og
// - https://www.youtube.com/channel/UCrlakW-ewUT8sOod6Wmzyow/videos
if strings.HasPrefix(path, "/channel") {
kind := model.TypeChannel
parts := strings.Split(parsed.EscapedPath(), "/")
if len(parts) <= 2 {
return "", "", errors.New("invalid youtube channel link")
}
id := parts[2]
if id == "" {
return "", "", errors.New("invalid id")
}
return kind, id, nil
}
// - https://www.youtube.com/user/fxigr1
if strings.HasPrefix(path, "/user") {
kind := model.TypeUser
parts := strings.Split(parsed.EscapedPath(), "/")
if len(parts) <= 2 {
return "", "", errors.New("invalid user link")
}
id := parts[2]
if id == "" {
return "", "", errors.New("invalid id")
}
return kind, id, nil
}
return "", "", errors.New("unsupported link format")
}
func parseVimeoURL(parsed *url.URL) (model.Type, string, error) {
parts := strings.Split(parsed.EscapedPath(), "/")
if len(parts) <= 1 {
return "", "", errors.New("invalid vimeo link path")
}
var kind model.Type
switch parts[1] {
case "groups":
kind = model.TypeGroup
case "channels":
kind = model.TypeChannel
default:
kind = model.TypeUser
}
if kind == model.TypeGroup || kind == model.TypeChannel {
if len(parts) <= 2 {
return "", "", errors.New("invalid channel link")
}
id := parts[2]
if id == "" {
return "", "", errors.New("invalid id")
}
return kind, id, nil
}
if kind == model.TypeUser {
id := parts[1]
if id == "" {
return "", "", errors.New("invalid id")
}
return kind, id, nil
}
return "", "", errors.New("unsupported link format")
}
func parseSoundcloudURL(parsed *url.URL) (model.Type, string, error) {
parts := strings.Split(parsed.EscapedPath(), "/")
if len(parts) <= 3 {
return "", "", errors.New("invald soundcloud link path")
}
var kind model.Type
// - https://soundcloud.com/user/sets/example-set
switch parts[2] {
case "sets":
kind = model.TypePlaylist
default:
return "", "", errors.New("invalid soundcloud url, missing sets")
}
id := parts[3]
return kind, id, nil
}