1
0
mirror of https://github.com/mxpv/podsync.git synced 2024-05-11 05:55:04 +00:00

192 lines
4.8 KiB
Go
Raw Normal View History

2017-08-05 13:48:53 -07:00
package builders
import (
"net/http"
"strconv"
itunes "github.com/mxpv/podcast"
2017-08-19 16:58:23 -07:00
"github.com/mxpv/podsync/pkg/api"
2017-11-03 16:04:33 -07:00
"github.com/mxpv/podsync/pkg/model"
2017-08-05 13:48:53 -07:00
"github.com/pkg/errors"
"github.com/silentsokolov/go-vimeo"
"golang.org/x/net/context"
"golang.org/x/oauth2"
)
const (
vimeoDefaultPageSize = 50
)
type VimeoBuilder struct {
client *vimeo.Client
}
2017-08-10 15:23:07 -07:00
func (v *VimeoBuilder) selectImage(p *vimeo.Pictures, q api.Quality) string {
2017-08-25 16:41:58 -07:00
if p == nil || len(p.Sizes) == 0 {
2017-08-05 13:48:53 -07:00
return ""
}
2017-11-03 15:04:33 -07:00
if q == api.QualityLow {
2017-08-05 13:48:53 -07:00
return p.Sizes[0].Link
} else {
return p.Sizes[len(p.Sizes)-1].Link
}
}
2017-11-03 16:04:33 -07:00
func (v *VimeoBuilder) queryChannel(feed *model.Feed) (*itunes.Podcast, error) {
channelId := feed.ItemID
2017-08-13 14:50:59 -07:00
2017-08-05 13:48:53 -07:00
ch, resp, err := v.client.Channels.Get(channelId)
if err != nil {
2017-08-25 16:41:58 -07:00
if resp.StatusCode == http.StatusNotFound {
return nil, api.ErrNotFound
}
2017-08-05 13:48:53 -07:00
2017-08-25 16:41:58 -07:00
return nil, errors.Wrapf(err, "failed to query channel with channelId %s", channelId)
2017-08-05 13:48:53 -07:00
}
podcast := itunes.New(ch.Name, ch.Link, ch.Description, &ch.CreatedTime, nil)
podcast.Generator = podsyncGenerator
podcast.AddSubTitle(ch.Name)
podcast.AddImage(v.selectImage(ch.Pictures, feed.Quality))
podcast.AddCategory(defaultCategory, nil)
podcast.IAuthor = ch.User.Name
return &podcast, nil
}
2017-11-03 16:04:33 -07:00
func (v *VimeoBuilder) queryGroup(feed *model.Feed) (*itunes.Podcast, error) {
groupId := feed.ItemID
2017-08-13 14:50:59 -07:00
2017-08-05 13:48:53 -07:00
gr, resp, err := v.client.Groups.Get(groupId)
if err != nil {
2017-08-25 16:41:58 -07:00
if resp.StatusCode == http.StatusNotFound {
return nil, api.ErrNotFound
}
2017-08-05 13:48:53 -07:00
2017-08-25 16:41:58 -07:00
return nil, errors.Wrapf(err, "failed to query group with id %s", groupId)
2017-08-05 13:48:53 -07:00
}
podcast := itunes.New(gr.Name, gr.Link, gr.Description, &gr.CreatedTime, nil)
podcast.Generator = podsyncGenerator
podcast.AddSubTitle(gr.Name)
podcast.AddImage(v.selectImage(gr.Pictures, feed.Quality))
podcast.AddCategory(defaultCategory, nil)
podcast.IAuthor = gr.User.Name
return &podcast, nil
}
2017-11-03 16:04:33 -07:00
func (v *VimeoBuilder) queryUser(feed *model.Feed) (*itunes.Podcast, error) {
userId := feed.ItemID
2017-08-13 14:50:59 -07:00
2017-08-05 13:48:53 -07:00
user, resp, err := v.client.Users.Get(userId)
if err != nil {
2017-08-25 16:41:58 -07:00
if resp.StatusCode == http.StatusNotFound {
return nil, api.ErrNotFound
}
2017-08-05 13:48:53 -07:00
2017-08-25 16:41:58 -07:00
return nil, errors.Wrapf(err, "failed to query user with id %s", userId)
2017-08-05 13:48:53 -07:00
}
podcast := itunes.New(user.Name, user.Link, user.Bio, &user.CreatedTime, nil)
podcast.Generator = podsyncGenerator
podcast.AddSubTitle(user.Name)
podcast.AddImage(v.selectImage(user.Pictures, feed.Quality))
podcast.AddCategory(defaultCategory, nil)
podcast.IAuthor = user.Name
return &podcast, nil
}
func (v *VimeoBuilder) getVideoSize(video *vimeo.Video) int64 {
// Very approximate video file size
return int64(float64(video.Duration*video.Width*video.Height) * 0.38848958333)
}
2017-08-13 14:50:59 -07:00
type getVideosFunc func(id string, opt *vimeo.ListVideoOptions) ([]*vimeo.Video, *vimeo.Response, error)
2017-08-05 13:48:53 -07:00
2017-11-03 16:04:33 -07:00
func (v *VimeoBuilder) queryVideos(getVideos getVideosFunc, podcast *itunes.Podcast, feed *model.Feed) error {
2017-08-05 13:48:53 -07:00
opt := vimeo.ListVideoOptions{}
opt.Page = 1
opt.PerPage = vimeoDefaultPageSize
added := 0
for {
2017-11-03 16:04:33 -07:00
videos, response, err := getVideos(feed.ItemID, &opt)
2017-08-05 13:48:53 -07:00
if err != nil {
2017-08-25 16:41:58 -07:00
return errors.Wrapf(err, "failed to query videos (error %d %s)", response.StatusCode, response.Status)
2017-08-05 13:48:53 -07:00
}
for _, video := range videos {
item := itunes.Item{}
item.GUID = strconv.Itoa(video.GetID())
item.Link = video.Link
item.Title = video.Name
item.Description = video.Description
if item.Description == "" {
item.Description = " " // Videos can be without description, workaround for AddItem
}
item.AddDuration(int64(video.Duration))
item.AddPubDate(&video.CreatedTime)
item.AddImage(v.selectImage(video.Pictures, feed.Quality))
size := v.getVideoSize(video)
item.AddEnclosure(makeEnclosure(feed, item.GUID, size))
_, err = podcast.AddItem(item)
if err != nil {
2017-08-25 16:41:58 -07:00
return errors.Wrapf(err, "failed to add episode %s (%s)", item.GUID, item.Title)
2017-08-05 13:48:53 -07:00
}
added++
}
if added >= feed.PageSize || response.NextPage == "" {
return nil
}
opt.Page++
}
}
2017-11-03 16:04:33 -07:00
func (v *VimeoBuilder) Build(feed *model.Feed) (podcast *itunes.Podcast, err error) {
2017-11-03 15:04:33 -07:00
if feed.LinkType == api.LinkTypeChannel {
2017-08-13 14:50:59 -07:00
if podcast, err = v.queryChannel(feed); err == nil {
err = v.queryVideos(v.client.Channels.ListVideo, podcast, feed)
}
return
2017-08-05 13:48:53 -07:00
}
2017-11-03 15:04:33 -07:00
if feed.LinkType == api.LinkTypeGroup {
2017-08-13 14:50:59 -07:00
if podcast, err = v.queryGroup(feed); err == nil {
err = v.queryVideos(v.client.Groups.ListVideo, podcast, feed)
2017-08-05 13:48:53 -07:00
}
2017-08-13 14:50:59 -07:00
return
}
2017-11-03 15:04:33 -07:00
if feed.LinkType == api.LinkTypeUser {
2017-08-13 14:50:59 -07:00
if podcast, err = v.queryUser(feed); err == nil {
err = v.queryVideos(v.client.Users.ListVideo, podcast, feed)
2017-08-05 13:48:53 -07:00
}
2017-08-13 14:50:59 -07:00
return
2017-08-05 13:48:53 -07:00
}
2017-08-13 14:50:59 -07:00
err = errors.New("unsupported feed type")
2017-08-05 13:48:53 -07:00
return
}
func NewVimeoBuilder(ctx context.Context, token string) (*VimeoBuilder, error) {
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
tc := oauth2.NewClient(ctx, ts)
client := vimeo.NewClient(tc)
return &VimeoBuilder{client}, nil
}