128 lines
3.1 KiB
Go
128 lines
3.1 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
|
|
"github.com/alexedwards/argon2id"
|
|
|
|
"gitea.theedgeofrage.com/TheEdgeOfRage/ytrssil-api/db"
|
|
"gitea.theedgeofrage.com/TheEdgeOfRage/ytrssil-api/feedparser"
|
|
"gitea.theedgeofrage.com/TheEdgeOfRage/ytrssil-api/lib/log"
|
|
"gitea.theedgeofrage.com/TheEdgeOfRage/ytrssil-api/models"
|
|
)
|
|
|
|
type Handler interface {
|
|
CreateUser(ctx context.Context, user models.User) error
|
|
SubscribeToChannel(ctx context.Context, username string, channelID string) error
|
|
GetNewVideos(ctx context.Context, username string) ([]models.Video, error)
|
|
FetchVideos(ctx context.Context) error
|
|
}
|
|
|
|
type handler struct {
|
|
log log.Logger
|
|
db db.DB
|
|
}
|
|
|
|
func New(log log.Logger, db db.DB) *handler {
|
|
return &handler{log: log, db: db}
|
|
}
|
|
|
|
func (h *handler) CreateUser(ctx context.Context, user models.User) error {
|
|
hashedPassword, err := argon2id.CreateHash(user.Password, argon2id.DefaultParams)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Password = hashedPassword
|
|
|
|
return h.db.CreateUser(ctx, user)
|
|
}
|
|
|
|
func (h *handler) SubscribeToChannel(ctx context.Context, username string, channelID string) error {
|
|
parsedChannel, err := feedparser.Parse(h.log, channelID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
channel := models.Channel{
|
|
ID: channelID,
|
|
Name: parsedChannel.Name,
|
|
}
|
|
|
|
err = h.db.CreateChannel(ctx, channel)
|
|
if !errors.Is(err, db.ErrChannelExists) {
|
|
return err
|
|
}
|
|
|
|
return h.db.SubscribeUserToChannel(ctx, username, channelID)
|
|
}
|
|
|
|
func (h *handler) GetNewVideos(ctx context.Context, username string) ([]models.Video, error) {
|
|
return h.db.GetNewVideos(ctx, username)
|
|
}
|
|
|
|
func (h *handler) addVideoToAllSubscribers(ctx context.Context, channelID string, videoID string) error {
|
|
subs, err := h.db.GetChannelSubscribers(ctx, channelID)
|
|
if err != nil {
|
|
h.log.Log("level", "ERROR", "call", "db.GetChannelSubscribers", "err", err)
|
|
return err
|
|
}
|
|
|
|
for _, sub := range subs {
|
|
err = h.db.AddVideoToUser(ctx, sub, videoID)
|
|
if err != nil {
|
|
h.log.Log("level", "ERROR", "call", "db.AddVideoToUser", "err", err)
|
|
continue
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *handler) fetchVideosForChannel(ctx context.Context, channelID string, parsedChannel *feedparser.Channel) {
|
|
for _, parsedVideo := range parsedChannel.Videos {
|
|
date, err := parsedVideo.Published.Parse()
|
|
if err != nil {
|
|
h.log.Log("level", "WARNING", "call", "feedparser.Parse", "err", err)
|
|
continue
|
|
}
|
|
|
|
id := strings.Split(parsedVideo.ID, ":")[2]
|
|
video := models.Video{
|
|
ID: id,
|
|
Title: parsedVideo.Title,
|
|
PublishedTime: date,
|
|
}
|
|
err = h.db.CreateVideo(ctx, video, channelID)
|
|
if err != nil {
|
|
if !errors.Is(err, db.ErrVideoExists) {
|
|
h.log.Log("level", "WARNING", "call", "db.CreateVideo", "err", err)
|
|
}
|
|
continue
|
|
}
|
|
err = h.addVideoToAllSubscribers(ctx, channelID, id)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
func (h *handler) FetchVideos(ctx context.Context) error {
|
|
channels, err := h.db.ListChannels(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, channel := range channels {
|
|
parsedChannel, err := feedparser.Parse(h.log, channel.ID)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
h.fetchVideosForChannel(ctx, channel.ID, parsedChannel)
|
|
}
|
|
|
|
return nil
|
|
}
|