81 lines
1.6 KiB
Go
81 lines
1.6 KiB
Go
|
package ytlinkprov
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"github.com/lrstanley/go-ytdlp"
|
||
|
)
|
||
|
|
||
|
type CacheLinkProv struct {
|
||
|
cache map[string]TimedLink
|
||
|
cacheWindow time.Duration
|
||
|
ytInstall ytdlp.ResolvedInstall
|
||
|
}
|
||
|
|
||
|
type TimedLink struct {
|
||
|
Link string
|
||
|
Time time.Time
|
||
|
}
|
||
|
|
||
|
func NewCachedLinkProvider(expiration time.Duration) (*CacheLinkProv, error) {
|
||
|
p := new(CacheLinkProv)
|
||
|
p.cache = make(map[string]TimedLink)
|
||
|
p.cacheWindow = expiration
|
||
|
ctx := context.Background()
|
||
|
ytInstall, err := ytdlp.Install(
|
||
|
ctx,
|
||
|
&ytdlp.InstallOptions{
|
||
|
AllowVersionMismatch: true,
|
||
|
},
|
||
|
)
|
||
|
if err != nil {
|
||
|
return p, err
|
||
|
}
|
||
|
p.ytInstall = *ytInstall
|
||
|
|
||
|
return p, nil
|
||
|
}
|
||
|
|
||
|
func (c *CacheLinkProv) GetLink(id string) (link string, err error) {
|
||
|
|
||
|
cc, ok := c.cache[id]
|
||
|
if ok && c.validCache(cc) {
|
||
|
return cc.Link, nil
|
||
|
}
|
||
|
link, err = getRemoteLink(id)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
t_now := time.Now().UTC()
|
||
|
c.cache[id] = TimedLink{
|
||
|
Link: link,
|
||
|
Time: t_now,
|
||
|
}
|
||
|
|
||
|
// INFO: This is a vary, vary slow leak
|
||
|
|
||
|
return link, nil
|
||
|
}
|
||
|
|
||
|
func (c *CacheLinkProv) validCache(l TimedLink) bool {
|
||
|
t_exp := time.Now().UTC().Add(c.cacheWindow)
|
||
|
if t_exp.Before(l.Time) {
|
||
|
// expired
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
|
||
|
}
|
||
|
|
||
|
func getRemoteLink(id string) (string, error) {
|
||
|
vidUrl := fmt.Sprintf("https://youtube.com/watch?v=%s", id)
|
||
|
ytCmd := ytdlp.New().ExtractAudio().GetURL()
|
||
|
ytRes, err := ytCmd.Run(context.Background(), vidUrl)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
return ytRes.Stdout, nil
|
||
|
}
|