2017-08-13 14:50:59 -07:00
|
|
|
package feeds
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
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-13 14:50:59 -07:00
|
|
|
"github.com/pkg/errors"
|
2017-11-03 17:19:44 -07:00
|
|
|
"github.com/ventu-io/go-shortid"
|
2017-08-13 14:50:59 -07:00
|
|
|
)
|
|
|
|
|
2017-08-20 18:35:47 -07:00
|
|
|
const (
|
|
|
|
maxPageSize = 150
|
|
|
|
)
|
|
|
|
|
2017-11-02 18:03:44 -07:00
|
|
|
type storageService interface {
|
2017-11-03 16:04:33 -07:00
|
|
|
CreateFeed(feed *model.Feed) error
|
|
|
|
GetFeed(hashId string) (*model.Feed, error)
|
2017-11-02 18:03:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
type builder interface {
|
2017-11-03 16:04:33 -07:00
|
|
|
Build(feed *model.Feed) (podcast *itunes.Podcast, err error)
|
2017-11-02 18:03:44 -07:00
|
|
|
}
|
|
|
|
|
2017-11-03 17:19:44 -07:00
|
|
|
type Service struct {
|
|
|
|
sid *shortid.Shortid
|
2017-11-02 18:03:44 -07:00
|
|
|
storage storageService
|
2017-08-13 14:50:59 -07:00
|
|
|
builders map[api.Provider]builder
|
|
|
|
}
|
|
|
|
|
2017-11-03 17:19:44 -07:00
|
|
|
func (s Service) CreateFeed(req *api.CreateFeedRequest, identity *api.Identity) (string, error) {
|
2017-08-13 17:12:35 -07:00
|
|
|
feed, err := parseURL(req.URL)
|
2017-08-13 14:50:59 -07:00
|
|
|
if err != nil {
|
|
|
|
return "", errors.Wrapf(err, "failed to create feed for URL: %s", req.URL)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure builder exists for this provider
|
|
|
|
_, ok := s.builders[feed.Provider]
|
|
|
|
if !ok {
|
|
|
|
return "", fmt.Errorf("failed to get builder for URL: %s", req.URL)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set default fields
|
|
|
|
feed.PageSize = api.DefaultPageSize
|
2017-11-03 15:04:33 -07:00
|
|
|
feed.Format = api.FormatVideo
|
|
|
|
feed.Quality = api.QualityHigh
|
2017-08-13 14:50:59 -07:00
|
|
|
feed.FeatureLevel = api.DefaultFeatures
|
|
|
|
feed.LastAccess = time.Now().UTC()
|
|
|
|
|
2017-08-20 18:35:47 -07:00
|
|
|
if identity.FeatureLevel > 0 {
|
2017-11-03 16:04:33 -07:00
|
|
|
feed.UserID = identity.UserId
|
2017-08-20 18:35:47 -07:00
|
|
|
feed.Quality = req.Quality
|
|
|
|
feed.Format = req.Format
|
|
|
|
feed.FeatureLevel = identity.FeatureLevel
|
|
|
|
feed.PageSize = req.PageSize
|
|
|
|
if feed.PageSize > maxPageSize {
|
|
|
|
feed.PageSize = maxPageSize
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-13 14:50:59 -07:00
|
|
|
// Generate short id
|
2017-11-03 17:19:44 -07:00
|
|
|
hashId, err := s.sid.Generate()
|
2017-08-13 14:50:59 -07:00
|
|
|
if err != nil {
|
|
|
|
return "", errors.Wrap(err, "failed to generate id for feed")
|
|
|
|
}
|
|
|
|
|
2017-11-03 16:04:33 -07:00
|
|
|
feed.HashID = hashId
|
2017-08-13 14:50:59 -07:00
|
|
|
|
|
|
|
// Save to database
|
|
|
|
if err := s.storage.CreateFeed(feed); err != nil {
|
|
|
|
return "", errors.Wrap(err, "failed to save feed to database")
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashId, nil
|
|
|
|
}
|
|
|
|
|
2017-11-03 17:19:44 -07:00
|
|
|
func (s Service) GetFeed(hashId string) (*itunes.Podcast, error) {
|
2017-11-03 16:04:33 -07:00
|
|
|
feed, err := s.storage.GetFeed(hashId)
|
2017-08-13 14:50:59 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
builder, ok := s.builders[feed.Provider]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.Wrapf(err, "failed to get builder for feed: %s", hashId)
|
|
|
|
}
|
|
|
|
|
|
|
|
return builder.Build(feed)
|
|
|
|
}
|
|
|
|
|
2017-11-03 17:19:44 -07:00
|
|
|
func (s Service) GetMetadata(hashId string) (*api.Metadata, error) {
|
2017-11-03 16:04:33 -07:00
|
|
|
feed, err := s.storage.GetFeed(hashId)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &api.Metadata{
|
|
|
|
Provider: feed.Provider,
|
|
|
|
Format: feed.Format,
|
|
|
|
Quality: feed.Quality,
|
|
|
|
}, nil
|
2017-08-13 14:50:59 -07:00
|
|
|
}
|
2017-08-13 17:39:30 -07:00
|
|
|
|
2017-11-03 17:19:44 -07:00
|
|
|
type feedOption func(*Service)
|
2017-08-13 17:39:30 -07:00
|
|
|
|
2017-11-03 16:04:33 -07:00
|
|
|
//noinspection GoExportedFuncWithUnexportedType
|
2017-11-02 18:03:44 -07:00
|
|
|
func WithStorage(storage storageService) feedOption {
|
2017-11-03 17:19:44 -07:00
|
|
|
return func(service *Service) {
|
2017-08-13 17:39:30 -07:00
|
|
|
service.storage = storage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-03 16:04:33 -07:00
|
|
|
//noinspection GoExportedFuncWithUnexportedType
|
2017-08-13 17:39:30 -07:00
|
|
|
func WithBuilder(provider api.Provider, builder builder) feedOption {
|
2017-11-03 17:19:44 -07:00
|
|
|
return func(service *Service) {
|
2017-08-13 17:39:30 -07:00
|
|
|
service.builders[provider] = builder
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-03 17:19:44 -07:00
|
|
|
func NewFeedService(opts ...feedOption) (*Service, error) {
|
|
|
|
sid, err := shortid.New(1, shortid.DefaultABC, uint64(time.Now().UnixNano()))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
svc := &Service{
|
|
|
|
sid: sid,
|
|
|
|
builders: make(map[api.Provider]builder),
|
|
|
|
}
|
2017-08-13 17:39:30 -07:00
|
|
|
|
|
|
|
for _, fn := range opts {
|
|
|
|
fn(svc)
|
|
|
|
}
|
|
|
|
|
2017-11-03 17:19:44 -07:00
|
|
|
return svc, nil
|
2017-08-13 17:39:30 -07:00
|
|
|
}
|