mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Use Feed model
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -46,18 +44,10 @@ const (
|
||||
DefaultQuality = QualityHigh
|
||||
)
|
||||
|
||||
type Feed struct {
|
||||
Id int64 `json:"id"`
|
||||
HashId string `json:"hash_id"` // Short human readable feed id for users
|
||||
UserId string `json:"user_id"` // Patreon user id
|
||||
ItemId string `json:"item_id"`
|
||||
Provider Provider `json:"provider"` // Youtube or Vimeo
|
||||
LinkType LinkType `json:"link_type"` // Either group, channel or user
|
||||
PageSize int `json:"page_size"` // The number of episodes to return
|
||||
Format Format `json:"format"`
|
||||
Quality Quality `json:"quality"`
|
||||
FeatureLevel int `json:"feature_level"` // Available features
|
||||
LastAccess time.Time `json:"last_access"`
|
||||
type Metadata struct {
|
||||
Provider Provider `json:"provider"`
|
||||
Format Format `json:"format"`
|
||||
Quality Quality `json:"quality"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
itunes "github.com/mxpv/podcast"
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -12,7 +13,7 @@ const (
|
||||
defaultCategory = "TV & Film"
|
||||
)
|
||||
|
||||
func makeEnclosure(feed *api.Feed, id string, lengthInBytes int64) (string, itunes.EnclosureType, int64) {
|
||||
func makeEnclosure(feed *model.Feed, id string, lengthInBytes int64) (string, itunes.EnclosureType, int64) {
|
||||
ext := "mp4"
|
||||
contentType := itunes.MP4
|
||||
if feed.Format == api.FormatAudio {
|
||||
@@ -20,6 +21,6 @@ func makeEnclosure(feed *api.Feed, id string, lengthInBytes int64) (string, itun
|
||||
contentType = itunes.M4A
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("https://podsync.net/download/%s/%s.%s", feed.HashId, id, ext)
|
||||
url := fmt.Sprintf("https://podsync.net/download/%s/%s.%s", feed.HashID, id, ext)
|
||||
return url, contentType, lengthInBytes
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
itunes "github.com/mxpv/podcast"
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/silentsokolov/go-vimeo"
|
||||
"golang.org/x/net/context"
|
||||
@@ -32,8 +33,8 @@ func (v *VimeoBuilder) selectImage(p *vimeo.Pictures, q api.Quality) string {
|
||||
}
|
||||
}
|
||||
|
||||
func (v *VimeoBuilder) queryChannel(feed *api.Feed) (*itunes.Podcast, error) {
|
||||
channelId := feed.ItemId
|
||||
func (v *VimeoBuilder) queryChannel(feed *model.Feed) (*itunes.Podcast, error) {
|
||||
channelId := feed.ItemID
|
||||
|
||||
ch, resp, err := v.client.Channels.Get(channelId)
|
||||
if err != nil {
|
||||
@@ -54,8 +55,8 @@ func (v *VimeoBuilder) queryChannel(feed *api.Feed) (*itunes.Podcast, error) {
|
||||
return &podcast, nil
|
||||
}
|
||||
|
||||
func (v *VimeoBuilder) queryGroup(feed *api.Feed) (*itunes.Podcast, error) {
|
||||
groupId := feed.ItemId
|
||||
func (v *VimeoBuilder) queryGroup(feed *model.Feed) (*itunes.Podcast, error) {
|
||||
groupId := feed.ItemID
|
||||
|
||||
gr, resp, err := v.client.Groups.Get(groupId)
|
||||
if err != nil {
|
||||
@@ -76,8 +77,8 @@ func (v *VimeoBuilder) queryGroup(feed *api.Feed) (*itunes.Podcast, error) {
|
||||
return &podcast, nil
|
||||
}
|
||||
|
||||
func (v *VimeoBuilder) queryUser(feed *api.Feed) (*itunes.Podcast, error) {
|
||||
userId := feed.ItemId
|
||||
func (v *VimeoBuilder) queryUser(feed *model.Feed) (*itunes.Podcast, error) {
|
||||
userId := feed.ItemID
|
||||
|
||||
user, resp, err := v.client.Users.Get(userId)
|
||||
if err != nil {
|
||||
@@ -105,7 +106,7 @@ func (v *VimeoBuilder) getVideoSize(video *vimeo.Video) int64 {
|
||||
|
||||
type getVideosFunc func(id string, opt *vimeo.ListVideoOptions) ([]*vimeo.Video, *vimeo.Response, error)
|
||||
|
||||
func (v *VimeoBuilder) queryVideos(getVideos getVideosFunc, podcast *itunes.Podcast, feed *api.Feed) error {
|
||||
func (v *VimeoBuilder) queryVideos(getVideos getVideosFunc, podcast *itunes.Podcast, feed *model.Feed) error {
|
||||
opt := vimeo.ListVideoOptions{}
|
||||
opt.Page = 1
|
||||
opt.PerPage = vimeoDefaultPageSize
|
||||
@@ -113,7 +114,7 @@ func (v *VimeoBuilder) queryVideos(getVideos getVideosFunc, podcast *itunes.Podc
|
||||
added := 0
|
||||
|
||||
for {
|
||||
videos, response, err := getVideos(feed.ItemId, &opt)
|
||||
videos, response, err := getVideos(feed.ItemID, &opt)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to query videos (error %d %s)", response.StatusCode, response.Status)
|
||||
}
|
||||
@@ -152,7 +153,7 @@ func (v *VimeoBuilder) queryVideos(getVideos getVideosFunc, podcast *itunes.Podc
|
||||
}
|
||||
}
|
||||
|
||||
func (v *VimeoBuilder) Build(feed *api.Feed) (podcast *itunes.Podcast, err error) {
|
||||
func (v *VimeoBuilder) Build(feed *model.Feed) (podcast *itunes.Podcast, err error) {
|
||||
if feed.LinkType == api.LinkTypeChannel {
|
||||
if podcast, err = v.queryChannel(feed); err == nil {
|
||||
err = v.queryVideos(v.client.Channels.ListVideo, podcast, feed)
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
itunes "github.com/mxpv/podcast"
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -18,7 +19,7 @@ func TestQueryVimeoChannel(t *testing.T) {
|
||||
builder, err := NewVimeoBuilder(context.Background(), vimeoKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
podcast, err := builder.queryChannel(&api.Feed{ItemId: "staffpicks", Quality: api.QualityHigh})
|
||||
podcast, err := builder.queryChannel(&model.Feed{ItemID: "staffpicks", Quality: api.QualityHigh})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "https://vimeo.com/channels/staffpicks", podcast.Link)
|
||||
@@ -33,7 +34,7 @@ func TestQueryVimeoGroup(t *testing.T) {
|
||||
builder, err := NewVimeoBuilder(context.Background(), vimeoKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
podcast, err := builder.queryGroup(&api.Feed{ItemId: "motion", Quality: api.QualityHigh})
|
||||
podcast, err := builder.queryGroup(&model.Feed{ItemID: "motion", Quality: api.QualityHigh})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "https://vimeo.com/groups/motion", podcast.Link)
|
||||
@@ -48,7 +49,7 @@ func TestQueryVimeoUser(t *testing.T) {
|
||||
builder, err := NewVimeoBuilder(context.Background(), vimeoKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
podcast, err := builder.queryUser(&api.Feed{ItemId: "motionarray", Quality: api.QualityHigh})
|
||||
podcast, err := builder.queryUser(&model.Feed{ItemID: "motionarray", Quality: api.QualityHigh})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "https://vimeo.com/motionarray", podcast.Link)
|
||||
@@ -63,7 +64,7 @@ func TestQueryVimeoVideos(t *testing.T) {
|
||||
|
||||
feed := &itunes.Podcast{}
|
||||
|
||||
err = builder.queryVideos(builder.client.Channels.ListVideo, feed, &api.Feed{ItemId: "staffpicks"})
|
||||
err = builder.queryVideos(builder.client.Channels.ListVideo, feed, &model.Feed{ItemID: "staffpicks"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, vimeoDefaultPageSize, len(feed.Items))
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/BrianHicks/finch/duration"
|
||||
itunes "github.com/mxpv/podcast"
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/api/youtube/v3"
|
||||
)
|
||||
@@ -130,11 +131,11 @@ func (yt *YouTubeBuilder) selectThumbnail(snippet *youtube.ThumbnailDetails, qua
|
||||
// Cost:
|
||||
// - 5 units for channel or user
|
||||
// - 3 units for playlist
|
||||
func (yt *YouTubeBuilder) queryFeed(feed *api.Feed) (*itunes.Podcast, string, error) {
|
||||
func (yt *YouTubeBuilder) queryFeed(feed *model.Feed) (*itunes.Podcast, string, error) {
|
||||
now := time.Now()
|
||||
|
||||
if feed.LinkType == api.LinkTypeChannel || feed.LinkType == api.LinkTypeUser {
|
||||
channel, err := yt.listChannels(feed.LinkType, feed.ItemId)
|
||||
channel, err := yt.listChannels(feed.LinkType, feed.ItemID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -166,7 +167,7 @@ func (yt *YouTubeBuilder) queryFeed(feed *api.Feed) (*itunes.Podcast, string, er
|
||||
}
|
||||
|
||||
if feed.LinkType == api.LinkTypePlaylist {
|
||||
playlist, err := yt.listPlaylists(feed.ItemId, "")
|
||||
playlist, err := yt.listPlaylists(feed.ItemID, "")
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -197,7 +198,7 @@ func (yt *YouTubeBuilder) queryFeed(feed *api.Feed) (*itunes.Podcast, string, er
|
||||
|
||||
// Video size information requires 1 additional call for each video (1 feed = 50 videos = 50 calls),
|
||||
// which is too expensive, so get approximated size depending on duration and definition params
|
||||
func (yt *YouTubeBuilder) getSize(duration int64, feed *api.Feed) int64 {
|
||||
func (yt *YouTubeBuilder) getSize(duration int64, feed *model.Feed) int64 {
|
||||
if feed.Format == api.FormatAudio {
|
||||
if feed.Quality == api.QualityHigh {
|
||||
return highAudioBytesPerSecond * duration
|
||||
@@ -215,7 +216,7 @@ func (yt *YouTubeBuilder) getSize(duration int64, feed *api.Feed) int64 {
|
||||
|
||||
// Cost: 5 units (call: 1, snippet: 2, contentDetails: 2)
|
||||
// See https://developers.google.com/youtube/v3/docs/videos/list#part
|
||||
func (yt *YouTubeBuilder) queryVideoDescriptions(playlistItems map[string]*youtube.PlaylistItemSnippet, feed *api.Feed, podcast *itunes.Podcast) error {
|
||||
func (yt *YouTubeBuilder) queryVideoDescriptions(playlistItems map[string]*youtube.PlaylistItemSnippet, feed *model.Feed, podcast *itunes.Podcast) error {
|
||||
// Make the list of video ids
|
||||
ids := make([]string, 0, len(playlistItems))
|
||||
for _, s := range playlistItems {
|
||||
@@ -290,7 +291,7 @@ func (yt *YouTubeBuilder) queryVideoDescriptions(playlistItems map[string]*youtu
|
||||
}
|
||||
|
||||
// Cost: (3 units + 5 units) * X pages = 8 units per page
|
||||
func (yt *YouTubeBuilder) queryItems(itemId string, feed *api.Feed, podcast *itunes.Podcast) error {
|
||||
func (yt *YouTubeBuilder) queryItems(itemId string, feed *model.Feed, podcast *itunes.Podcast) error {
|
||||
pageToken := ""
|
||||
count := 0
|
||||
|
||||
@@ -322,7 +323,7 @@ func (yt *YouTubeBuilder) queryItems(itemId string, feed *api.Feed, podcast *itu
|
||||
}
|
||||
}
|
||||
|
||||
func (yt *YouTubeBuilder) Build(feed *api.Feed) (*itunes.Podcast, error) {
|
||||
func (yt *YouTubeBuilder) Build(feed *model.Feed) (*itunes.Podcast, error) {
|
||||
|
||||
// Query general information about feed (title, description, lang, etc)
|
||||
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
itunes "github.com/mxpv/podcast"
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -14,16 +15,16 @@ const (
|
||||
)
|
||||
|
||||
type idService interface {
|
||||
Generate(feed *api.Feed) (string, error)
|
||||
Generate(feed *model.Feed) (string, error)
|
||||
}
|
||||
|
||||
type storageService interface {
|
||||
CreateFeed(feed *api.Feed) error
|
||||
GetFeed(hashId string) (*api.Feed, error)
|
||||
CreateFeed(feed *model.Feed) error
|
||||
GetFeed(hashId string) (*model.Feed, error)
|
||||
}
|
||||
|
||||
type builder interface {
|
||||
Build(feed *api.Feed) (podcast *itunes.Podcast, err error)
|
||||
Build(feed *model.Feed) (podcast *itunes.Podcast, err error)
|
||||
}
|
||||
|
||||
type service struct {
|
||||
@@ -52,7 +53,7 @@ func (s *service) CreateFeed(req *api.CreateFeedRequest, identity *api.Identity)
|
||||
feed.LastAccess = time.Now().UTC()
|
||||
|
||||
if identity.FeatureLevel > 0 {
|
||||
feed.UserId = identity.UserId
|
||||
feed.UserID = identity.UserId
|
||||
feed.Quality = req.Quality
|
||||
feed.Format = req.Format
|
||||
feed.FeatureLevel = identity.FeatureLevel
|
||||
@@ -68,7 +69,7 @@ func (s *service) CreateFeed(req *api.CreateFeedRequest, identity *api.Identity)
|
||||
return "", errors.Wrap(err, "failed to generate id for feed")
|
||||
}
|
||||
|
||||
feed.HashId = hashId
|
||||
feed.HashID = hashId
|
||||
|
||||
// Save to database
|
||||
if err := s.storage.CreateFeed(feed); err != nil {
|
||||
@@ -79,7 +80,7 @@ func (s *service) CreateFeed(req *api.CreateFeedRequest, identity *api.Identity)
|
||||
}
|
||||
|
||||
func (s *service) GetFeed(hashId string) (*itunes.Podcast, error) {
|
||||
feed, err := s.GetMetadata(hashId)
|
||||
feed, err := s.storage.GetFeed(hashId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -92,24 +93,36 @@ func (s *service) GetFeed(hashId string) (*itunes.Podcast, error) {
|
||||
return builder.Build(feed)
|
||||
}
|
||||
|
||||
func (s *service) GetMetadata(hashId string) (*api.Feed, error) {
|
||||
return s.storage.GetFeed(hashId)
|
||||
func (s *service) GetMetadata(hashId string) (*api.Metadata, error) {
|
||||
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
|
||||
}
|
||||
|
||||
type feedOption func(*service)
|
||||
|
||||
//noinspection GoExportedFuncWithUnexportedType
|
||||
func WithStorage(storage storageService) feedOption {
|
||||
return func(service *service) {
|
||||
service.storage = storage
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection GoExportedFuncWithUnexportedType
|
||||
func WithIdGen(id idService) feedOption {
|
||||
return func(service *service) {
|
||||
service.id = id
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection GoExportedFuncWithUnexportedType
|
||||
func WithBuilder(provider api.Provider, builder builder) feedOption {
|
||||
return func(service *service) {
|
||||
service.builders[provider] = builder
|
||||
|
@@ -6,7 +6,7 @@ package feeds
|
||||
import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
podcast "github.com/mxpv/podcast"
|
||||
api "github.com/mxpv/podsync/pkg/api"
|
||||
model "github.com/mxpv/podsync/pkg/model"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
@@ -34,7 +34,7 @@ func (_m *MockidService) EXPECT() *MockidServiceMockRecorder {
|
||||
}
|
||||
|
||||
// Generate mocks base method
|
||||
func (_m *MockidService) Generate(feed *api.Feed) (string, error) {
|
||||
func (_m *MockidService) Generate(feed *model.Feed) (string, error) {
|
||||
ret := _m.ctrl.Call(_m, "Generate", feed)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
@@ -70,7 +70,7 @@ func (_m *MockstorageService) EXPECT() *MockstorageServiceMockRecorder {
|
||||
}
|
||||
|
||||
// CreateFeed mocks base method
|
||||
func (_m *MockstorageService) CreateFeed(feed *api.Feed) error {
|
||||
func (_m *MockstorageService) CreateFeed(feed *model.Feed) error {
|
||||
ret := _m.ctrl.Call(_m, "CreateFeed", feed)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
@@ -82,9 +82,9 @@ func (_mr *MockstorageServiceMockRecorder) CreateFeed(arg0 interface{}) *gomock.
|
||||
}
|
||||
|
||||
// GetFeed mocks base method
|
||||
func (_m *MockstorageService) GetFeed(hashId string) (*api.Feed, error) {
|
||||
func (_m *MockstorageService) GetFeed(hashId string) (*model.Feed, error) {
|
||||
ret := _m.ctrl.Call(_m, "GetFeed", hashId)
|
||||
ret0, _ := ret[0].(*api.Feed)
|
||||
ret0, _ := ret[0].(*model.Feed)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
@@ -118,7 +118,7 @@ func (_m *Mockbuilder) EXPECT() *MockbuilderMockRecorder {
|
||||
}
|
||||
|
||||
// Build mocks base method
|
||||
func (_m *Mockbuilder) Build(feed *api.Feed) (*podcast.Podcast, error) {
|
||||
func (_m *Mockbuilder) Build(feed *model.Feed) (*podcast.Podcast, error) {
|
||||
ret := _m.ctrl.Call(_m, "Build", feed)
|
||||
ret0, _ := ret[0].(*podcast.Podcast)
|
||||
ret1, _ := ret[1].(error)
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -42,7 +43,7 @@ func TestService_GetFeed(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
feed := &api.Feed{Provider: api.ProviderYoutube}
|
||||
feed := &model.Feed{Provider: api.ProviderYoutube}
|
||||
|
||||
storage := NewMockstorageService(ctrl)
|
||||
storage.EXPECT().GetFeed("123").Times(1).Return(feed, nil)
|
||||
@@ -64,7 +65,7 @@ func TestService_GetMetadata(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
|
||||
storage := NewMockstorageService(ctrl)
|
||||
storage.EXPECT().GetFeed("123").Times(1).Return(&api.Feed{}, nil)
|
||||
storage.EXPECT().GetFeed("123").Times(1).Return(&model.Feed{}, nil)
|
||||
|
||||
s := service{storage: storage}
|
||||
_, err := s.GetMetadata("123")
|
||||
|
@@ -5,10 +5,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func parseURL(link string) (*api.Feed, error) {
|
||||
func parseURL(link string) (*model.Feed, error) {
|
||||
if !strings.HasPrefix(link, "http") {
|
||||
link = "https://" + link
|
||||
}
|
||||
@@ -19,7 +20,7 @@ func parseURL(link string) (*api.Feed, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
feed := &api.Feed{}
|
||||
feed := &model.Feed{}
|
||||
|
||||
if strings.HasSuffix(parsed.Host, "youtube.com") {
|
||||
kind, id, err := parseYoutubeURL(parsed)
|
||||
@@ -29,7 +30,7 @@ func parseURL(link string) (*api.Feed, error) {
|
||||
|
||||
feed.Provider = api.ProviderYoutube
|
||||
feed.LinkType = kind
|
||||
feed.ItemId = id
|
||||
feed.ItemID = id
|
||||
|
||||
return feed, nil
|
||||
}
|
||||
@@ -42,7 +43,7 @@ func parseURL(link string) (*api.Feed, error) {
|
||||
|
||||
feed.Provider = api.ProviderVimeo
|
||||
feed.LinkType = kind
|
||||
feed.ItemId = id
|
||||
feed.ItemID = id
|
||||
|
||||
return feed, nil
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ const (
|
||||
type feedService interface {
|
||||
CreateFeed(req *api.CreateFeedRequest, identity *api.Identity) (string, error)
|
||||
GetFeed(hashId string) (*itunes.Podcast, error)
|
||||
GetMetadata(hashId string) (*api.Feed, error)
|
||||
GetMetadata(hashId string) (*api.Metadata, error)
|
||||
}
|
||||
|
||||
type patreonService interface {
|
||||
|
@@ -61,9 +61,9 @@ func (_mr *MockfeedServiceMockRecorder) GetFeed(arg0 interface{}) *gomock.Call {
|
||||
}
|
||||
|
||||
// GetMetadata mocks base method
|
||||
func (_m *MockfeedService) GetMetadata(hashId string) (*api.Feed, error) {
|
||||
func (_m *MockfeedService) GetMetadata(hashId string) (*api.Metadata, error) {
|
||||
ret := _m.ctrl.Call(_m, "GetMetadata", hashId)
|
||||
ret0, _ := ret[0].(*api.Feed)
|
||||
ret0, _ := ret[0].(*api.Metadata)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@@ -116,7 +116,7 @@ func TestGetMetadata(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
|
||||
feed := NewMockfeedService(ctrl)
|
||||
feed.EXPECT().GetMetadata("123").Times(1).Return(&api.Feed{}, nil)
|
||||
feed.EXPECT().GetMetadata("123").Times(1).Return(&api.Metadata{}, nil)
|
||||
|
||||
srv := httptest.NewServer(New(feed, nil, cfg))
|
||||
defer srv.Close()
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"hash/fnv"
|
||||
"time"
|
||||
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/ventu-io/go-shortid"
|
||||
)
|
||||
|
||||
@@ -18,7 +18,7 @@ func hashString(s string) int {
|
||||
return int(h.Sum32())
|
||||
}
|
||||
|
||||
func (h *hashId) Generate(feed *api.Feed) (string, error) {
|
||||
func (h *hashId) Generate(feed *model.Feed) (string, error) {
|
||||
return h.sid.Generate()
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/proxy"
|
||||
"github.com/go-pg/pg"
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ type PgStorage struct {
|
||||
db *pg.DB
|
||||
}
|
||||
|
||||
func (p *PgStorage) CreateFeed(feed *api.Feed) error {
|
||||
func (p *PgStorage) CreateFeed(feed *model.Feed) error {
|
||||
feed.LastAccess = time.Now().UTC()
|
||||
_, err := p.db.Model(feed).OnConflict("DO NOTHING").Insert()
|
||||
if err != nil {
|
||||
@@ -30,10 +30,10 @@ func (p *PgStorage) CreateFeed(feed *api.Feed) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PgStorage) GetFeed(hashId string) (*api.Feed, error) {
|
||||
func (p *PgStorage) GetFeed(hashId string) (*model.Feed, error) {
|
||||
lastAccess := time.Now().UTC()
|
||||
|
||||
feed := &api.Feed{}
|
||||
feed := &model.Feed{}
|
||||
_, err := p.db.Model(feed).
|
||||
Set("last_access = ?", lastAccess).
|
||||
Where("hash_id = ?", hashId).
|
||||
|
@@ -21,7 +21,7 @@ END
|
||||
$$;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS feeds (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
feed_id BIGSERIAL PRIMARY KEY,
|
||||
hash_id VARCHAR(12) NOT NULL CHECK (hash_id <> '') UNIQUE,
|
||||
user_id VARCHAR(32) NULL,
|
||||
item_id VARCHAR(32) NOT NULL CHECK (item_id <> ''),
|
||||
|
@@ -4,29 +4,30 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPgStorage_CreateFeed(t *testing.T) {
|
||||
feed := &api.Feed{
|
||||
HashId: "xyz",
|
||||
feed := &model.Feed{
|
||||
HashID: "xyz",
|
||||
Provider: api.ProviderYoutube,
|
||||
LinkType: api.LinkTypeChannel,
|
||||
ItemId: "123",
|
||||
ItemID: "123",
|
||||
}
|
||||
|
||||
client := createClient(t)
|
||||
err := client.CreateFeed(feed)
|
||||
require.NoError(t, err)
|
||||
require.True(t, feed.Id > 0)
|
||||
require.True(t, feed.FeedID > 0)
|
||||
}
|
||||
|
||||
func TestPgStorage_CreateFeedWithDuplicate(t *testing.T) {
|
||||
feed := &api.Feed{
|
||||
HashId: "123",
|
||||
feed := &model.Feed{
|
||||
HashID: "123",
|
||||
Provider: api.ProviderYoutube,
|
||||
LinkType: api.LinkTypeChannel,
|
||||
ItemId: "123",
|
||||
ItemID: "123",
|
||||
}
|
||||
|
||||
client := createClient(t)
|
||||
@@ -34,7 +35,7 @@ func TestPgStorage_CreateFeedWithDuplicate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensure 1 record
|
||||
count, err := client.db.Model(&api.Feed{}).Count()
|
||||
count, err := client.db.Model(&model.Feed{}).Count()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, count)
|
||||
|
||||
@@ -43,18 +44,18 @@ func TestPgStorage_CreateFeedWithDuplicate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check no duplicates inserted
|
||||
count, err = client.db.Model(&api.Feed{}).Count()
|
||||
count, err = client.db.Model(&model.Feed{}).Count()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, count)
|
||||
}
|
||||
|
||||
func TestPgStorage_GetFeed(t *testing.T) {
|
||||
feed := &api.Feed{
|
||||
HashId: "xyz",
|
||||
UserId: "123",
|
||||
feed := &model.Feed{
|
||||
HashID: "xyz",
|
||||
UserID: "123",
|
||||
Provider: api.ProviderYoutube,
|
||||
LinkType: api.LinkTypeChannel,
|
||||
ItemId: "123",
|
||||
ItemID: "123",
|
||||
}
|
||||
|
||||
client := createClient(t)
|
||||
@@ -62,16 +63,16 @@ func TestPgStorage_GetFeed(t *testing.T) {
|
||||
|
||||
out, err := client.GetFeed("xyz")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, feed.Id, out.Id)
|
||||
require.Equal(t, feed.FeedID, out.FeedID)
|
||||
}
|
||||
|
||||
func TestPgStorage_UpdateLastAccess(t *testing.T) {
|
||||
feed := &api.Feed{
|
||||
HashId: "xyz",
|
||||
UserId: "123",
|
||||
feed := &model.Feed{
|
||||
HashID: "xyz",
|
||||
UserID: "123",
|
||||
Provider: api.ProviderYoutube,
|
||||
LinkType: api.LinkTypeChannel,
|
||||
ItemId: "123",
|
||||
ItemID: "123",
|
||||
}
|
||||
|
||||
client := createClient(t)
|
||||
@@ -84,11 +85,11 @@ func TestPgStorage_UpdateLastAccess(t *testing.T) {
|
||||
last, err := client.GetFeed("xyz")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEmpty(t, last.HashId)
|
||||
require.NotEmpty(t, last.UserId)
|
||||
require.NotEmpty(t, last.HashID)
|
||||
require.NotEmpty(t, last.UserID)
|
||||
require.NotEmpty(t, last.Provider)
|
||||
require.NotEmpty(t, last.LinkType)
|
||||
require.NotEmpty(t, last.ItemId)
|
||||
require.NotEmpty(t, last.ItemID)
|
||||
|
||||
require.True(t, last.LastAccess.UnixNano() > lastAccess.UnixNano())
|
||||
}
|
||||
@@ -99,7 +100,7 @@ func createClient(t *testing.T) *PgStorage {
|
||||
pg, err := NewPgStorage(&PgConfig{ConnectionUrl: TestDatabaseConnectionUrl})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = pg.db.Model(&api.Feed{}).Where("1=1").Delete()
|
||||
_, err = pg.db.Model(&model.Feed{}).Where("1=1").Delete()
|
||||
require.NoError(t, err)
|
||||
|
||||
return pg
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -55,7 +56,7 @@ func (r *RedisStorage) parseFormat(m map[string]string) (api.Format, api.Quality
|
||||
return "", "", fmt.Errorf("unsupported formmat %s", quality)
|
||||
}
|
||||
|
||||
func (r *RedisStorage) GetFeed(hashId string) (*api.Feed, error) {
|
||||
func (r *RedisStorage) GetFeed(hashId string) (*model.Feed, error) {
|
||||
result, err := r.client.HGetAll(hashId).Result()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to query feed with id %s", hashId)
|
||||
@@ -70,11 +71,11 @@ func (r *RedisStorage) GetFeed(hashId string) (*api.Feed, error) {
|
||||
return nil, errors.Wrap(err, "failed query update feed")
|
||||
}
|
||||
|
||||
feed := &api.Feed{
|
||||
feed := &model.Feed{
|
||||
PageSize: api.DefaultPageSize,
|
||||
Quality: api.DefaultQuality,
|
||||
Format: api.DefaultFormat,
|
||||
HashId: hashId,
|
||||
HashID: hashId,
|
||||
LastAccess: time.Now().UTC(),
|
||||
}
|
||||
|
||||
@@ -122,12 +123,12 @@ func (r *RedisStorage) GetFeed(hashId string) (*api.Feed, error) {
|
||||
return nil, errors.New("failed to unpack item id")
|
||||
}
|
||||
|
||||
feed.ItemId = id
|
||||
feed.ItemID = id
|
||||
|
||||
// Fetch user id
|
||||
patreonId, ok := m["patreonid"]
|
||||
if ok {
|
||||
feed.UserId = patreonId
|
||||
feed.UserID = patreonId
|
||||
}
|
||||
|
||||
// Unpack page size
|
||||
@@ -153,12 +154,12 @@ func (r *RedisStorage) GetFeed(hashId string) (*api.Feed, error) {
|
||||
return feed, nil
|
||||
}
|
||||
|
||||
func (r *RedisStorage) CreateFeed(feed *api.Feed) error {
|
||||
func (r *RedisStorage) CreateFeed(feed *model.Feed) error {
|
||||
fields := map[string]interface{}{
|
||||
"provider": string(feed.Provider),
|
||||
"type": string(feed.LinkType),
|
||||
"id": feed.ItemId,
|
||||
"patreonid": feed.UserId,
|
||||
"id": feed.ItemID,
|
||||
"patreonid": feed.UserID,
|
||||
"pagesize": feed.PageSize,
|
||||
}
|
||||
|
||||
@@ -180,11 +181,11 @@ func (r *RedisStorage) CreateFeed(feed *api.Feed) error {
|
||||
|
||||
}
|
||||
|
||||
if err := r.client.HMSet(feed.HashId, fields).Err(); err != nil {
|
||||
if err := r.client.HMSet(feed.HashID, fields).Err(); err != nil {
|
||||
return errors.Wrap(err, "failed to save feed")
|
||||
}
|
||||
|
||||
return r.client.Expire(feed.HashId, expiration).Err()
|
||||
return r.client.Expire(feed.HashID, expiration).Err()
|
||||
}
|
||||
|
||||
func (r *RedisStorage) keys() ([]string, error) {
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mxpv/podsync/pkg/api"
|
||||
"github.com/mxpv/podsync/pkg/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -37,12 +38,12 @@ func TestRedisStorage_CreateFeed(t *testing.T) {
|
||||
|
||||
hashId := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
|
||||
|
||||
err := client.CreateFeed(&api.Feed{
|
||||
HashId: hashId,
|
||||
UserId: "321",
|
||||
err := client.CreateFeed(&model.Feed{
|
||||
HashID: hashId,
|
||||
UserID: "321",
|
||||
Provider: api.ProviderYoutube,
|
||||
LinkType: api.LinkTypeChannel,
|
||||
ItemId: "123",
|
||||
ItemID: "123",
|
||||
PageSize: 45,
|
||||
Quality: api.QualityLow,
|
||||
Format: api.FormatAudio,
|
||||
@@ -53,11 +54,11 @@ func TestRedisStorage_CreateFeed(t *testing.T) {
|
||||
feed, err := client.GetFeed(hashId)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, hashId, feed.HashId)
|
||||
require.Equal(t, "321", feed.UserId)
|
||||
require.Equal(t, hashId, feed.HashID)
|
||||
require.Equal(t, "321", feed.UserID)
|
||||
require.Equal(t, api.ProviderYoutube, feed.Provider)
|
||||
require.Equal(t, api.LinkTypeChannel, feed.LinkType)
|
||||
require.Equal(t, "123", feed.ItemId)
|
||||
require.Equal(t, "123", feed.ItemID)
|
||||
require.Equal(t, 45, feed.PageSize)
|
||||
require.Equal(t, api.QualityLow, feed.Quality)
|
||||
require.Equal(t, api.FormatAudio, feed.Format)
|
||||
|
Reference in New Issue
Block a user