You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
synctv/internal/cache/alist.go

151 lines
3.6 KiB
Go

2 years ago
package cache
import (
"context"
"errors"
"time"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/vendor"
"github.com/synctv-org/vendors/api/alist"
"github.com/zijiren233/gencontainer/refreshcache"
)
type AlistUserCache = refreshcache.RefreshCache[*AlistUserCacheData, struct{}]
2 years ago
type AlistUserCacheData struct {
Host string
Token string
Backend string
2 years ago
}
func NewAlistUserCache(userID string) *AlistUserCache {
f := AlistAuthorizationCacheWithUserIDInitFunc(userID)
return refreshcache.NewRefreshCache(func(ctx context.Context, args ...struct{}) (*AlistUserCacheData, error) {
return f(ctx)
}, 0)
}
func AlistAuthorizationCacheWithUserIDInitFunc(userID string) func(ctx context.Context, args ...struct{}) (*AlistUserCacheData, error) {
return func(ctx context.Context, args ...struct{}) (*AlistUserCacheData, error) {
v, err := db.GetAlistVendor(userID)
if err != nil {
return nil, err
2 years ago
}
return AlistAuthorizationCacheWithConfigInitFunc(ctx, v)
}
2 years ago
}
func AlistAuthorizationCacheWithConfigInitFunc(ctx context.Context, v *model.AlistVendor) (*AlistUserCacheData, error) {
cli := vendor.LoadAlistClient(v.Backend)
if v.Username == "" {
_, err := cli.Me(ctx, &alist.MeReq{
Host: v.Host,
})
if err != nil {
return nil, err
}
return &AlistUserCacheData{
Host: v.Host,
Backend: v.Backend,
}, nil
} else {
resp, err := cli.Login(ctx, &alist.LoginReq{
Host: v.Host,
Username: v.Username,
Password: string(v.HashedPassword),
Hashed: true,
})
if err != nil {
return nil, err
2 years ago
}
return &AlistUserCacheData{
Host: v.Host,
Token: resp.Token,
Backend: v.Backend,
}, nil
2 years ago
}
}
type AlistMovieCache = refreshcache.RefreshCache[*AlistMovieCacheData, *AlistUserCache]
2 years ago
func NewAlistMovieCache(movie *model.Movie) *AlistMovieCache {
return refreshcache.NewRefreshCache(NewAlistMovieCacheInitFunc(movie), time.Hour)
2 years ago
}
type AlistMovieCacheData struct {
URLs []struct {
URL string
Name string
}
2 years ago
}
func NewAlistMovieCacheInitFunc(movie *model.Movie) func(ctx context.Context, args ...*AlistUserCache) (*AlistMovieCacheData, error) {
return func(ctx context.Context, args ...*AlistUserCache) (*AlistMovieCacheData, error) {
if len(args) == 0 {
return nil, errors.New("need alist user cache")
}
aucd, err := args[0].Get(ctx)
2 years ago
if err != nil {
return nil, err
}
if aucd.Host == "" {
return nil, errors.New("not bind alist vendor")
}
cli := vendor.LoadAlistClient(movie.Base.VendorInfo.Backend)
2 years ago
fg, err := cli.FsGet(ctx, &alist.FsGetReq{
Host: aucd.Host,
Token: aucd.Token,
Path: movie.Base.VendorInfo.Alist.Path,
Password: movie.Base.VendorInfo.Alist.Password,
})
if err != nil {
return nil, err
}
if fg.IsDir {
return nil, errors.New("path is dir")
}
cache := &AlistMovieCacheData{
URLs: []struct {
URL string
Name string
}{
{
URL: fg.RawUrl,
},
},
2 years ago
}
if fg.Provider == "AliyundriveOpen" {
fo, err := cli.FsOther(ctx, &alist.FsOtherReq{
Host: aucd.Host,
Token: aucd.Token,
2 years ago
Path: movie.Base.VendorInfo.Alist.Path,
Password: movie.Base.VendorInfo.Alist.Password,
Method: "video_preview",
})
if err != nil {
return nil, err
}
cache.URLs = make([]struct {
URL string
Name string
}, len(fo.VideoPreviewPlayInfo.LiveTranscodingTaskList))
for i, v := range fo.VideoPreviewPlayInfo.LiveTranscodingTaskList {
cache.URLs[i] = struct {
URL string
Name string
}{
URL: v.Url,
Name: v.TemplateId,
}
}
2 years ago
}
return cache, nil
}
}