Compare commits

...

4 Commits

17 changed files with 364 additions and 424 deletions

1
.gitignore vendored
View File

@ -11,6 +11,7 @@ server
*.so
*.dylib
collector
newsbot.db
# Test binary, built with `go test -c`
*.test

View File

@ -11,7 +11,7 @@ import (
"git.jamestombleson.com/jtom38/newsbot-api/docs"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/handler/v1"
v1 "git.jamestombleson.com/jtom38/newsbot-api/internal/handler/v1"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/cron"
)
@ -44,7 +44,7 @@ func main() {
queries := database.New(db)
c := cron.NewScheduler(ctx)
c := cron.NewScheduler(ctx, db)
c.Start()
server := v1.NewServer(ctx, queries, configs, db)

View File

@ -0,0 +1,220 @@
package cron
import (
"log"
"time"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/input"
)
func (c *Cron) CollectRssPosts() {
log.Println("Starting ")
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorRss)
if err != nil {
log.Println(err)
}
for sourceIndex, source := range sources {
if !source.Enabled {
continue
}
rssClient := input.NewRssClient(source)
articles, err := rssClient.GetArticles()
if err != nil {
log.Println(err)
}
for _, article := range articles {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url)
if err == nil {
continue
}
rowsCreated, err := c.repo.Articles.CreateFromEntity(*c.ctx, article)
if err != nil {
log.Println(err)
}
if rowsCreated != 1 {
log.Println("Got back the wrong number of rows")
}
}
if sourceIndex != len(sources) {
time.Sleep(time.Second * 30)
}
}
}
func (c *Cron) CollectRedditPosts() {
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorReddit)
if err != nil {
log.Printf("[Reddit] No sources found to query - %v\r", err)
}
for _, source := range sources {
if !source.Enabled {
continue
}
log.Printf("[Reddit] Checking '%v'...", source.DisplayName)
rc := input.NewRedditClient(source)
raw, err := rc.GetContent()
if err != nil {
log.Println(err)
}
redditArticles := rc.ConvertToArticles(raw)
for _, article := range redditArticles {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url)
if err == nil {
continue
}
rowsAdded, err := c.repo.Articles.CreateFromEntity(*c.ctx, article)
if err != nil {
log.Printf("Failed to add a new reddit article to the database: %s", err)
}
if rowsAdded != 1 {
log.Printf("no error came back when data was added to the database but the expected row count is wrong")
}
}
}
log.Print("[Reddit] Done!")
}
func (c *Cron) CollectYoutubePosts() {
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorYoutube)
if err != nil {
log.Printf("[Youtube] No sources found to query - %v\r", err)
}
for sourceIndex, source := range sources {
if !source.Enabled {
continue
}
log.Printf("[YouTube] Checking '%v'...", source.DisplayName)
yc := input.NewYoutubeClient(source)
raw, err := yc.GetContent()
if err != nil {
log.Println(err)
}
for _, article := range raw {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url)
if err == nil {
continue
}
rowsAdded, err := c.repo.Articles.CreateFromEntity(*c.ctx, article)
if err != nil {
log.Printf("Failed to add a new youtube article to the database: %s", err)
}
if rowsAdded != 1 {
log.Printf("no error came back when data was added to the database but the expected row count is wrong")
}
}
if sourceIndex != len(sources) {
time.Sleep(time.Second * 30)
}
}
log.Print("[YouTube] Done!")
}
func (c *Cron) CollectFfxivPosts() {
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorFfxiv)
if err != nil {
log.Printf("[FFXIV] No sources found to query - %v\r", err)
}
for sourceIndex, source := range sources {
if !source.Enabled {
continue
}
fc := input.NewFFXIVClient(source)
items, err := fc.CheckSource()
if err != nil {
log.Println(err)
}
for _, article := range items {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url)
if err == nil {
continue
}
rowsAdded, err := c.repo.Articles.CreateFromEntity(*c.ctx, article)
if err != nil {
log.Printf("Failed to add a new FFXIV article to the database: %s", err)
}
if rowsAdded != 1 {
log.Printf("no error came back when data was added to the database but the expected row count is wrong")
}
}
if sourceIndex != len(sources) {
time.Sleep(time.Second * 30)
}
}
log.Printf("[FFXIV Done!]")
}
func (c *Cron) CollectTwitchPosts() {
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorTwitch)
if err != nil {
log.Printf("[Twitch] No sources found to query - %v\r", err)
}
tc, err := input.NewTwitchClient()
if err != nil {
log.Println(err)
return
}
err = tc.Login()
if err != nil {
log.Println(err)
}
for sourceIndex, source := range sources {
if !source.Enabled {
continue
}
log.Printf("[Twitch] Checking '%v'...", source.DisplayName)
tc.ReplaceSourceRecord(source)
items, err := tc.GetContent()
if err != nil {
log.Println(err)
}
for _, article := range items {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url)
if err == nil {
continue
}
rowsAdded, err := c.repo.Articles.CreateFromEntity(*c.ctx, article)
if err != nil {
log.Printf("Failed to add a new Twitch article to the database: %s", err)
}
if rowsAdded != 1 {
log.Printf("no error came back when data was added to the database but the expected row count is wrong")
}
}
if sourceIndex != len(sources) {
time.Sleep(time.Second * 30)
}
}
log.Print("[Twitch] Done!")
}

View File

@ -19,7 +19,7 @@ func TestRssPullsCorrectly(t *testing.T) {
ctx := context.Background()
db := services.NewRepositoryService(conn)
rowsCreated, err := db.Sources.Create(ctx, domain.SourceCollectorRss, "Gitea - Newsbot.api", "https://git.jamestombleson.com/jtom38/newsbot-api.rss", "rss,gitea,newsbot.api",true)
rowsCreated, err := db.Sources.Create(ctx, domain.SourceCollectorRss, "Gitea - Newsbot.api", "https://git.jamestombleson.com/jtom38/newsbot-api.rss", "rss,gitea,newsbot.api", true)
if err != nil {
t.Error(err)
t.FailNow()
@ -31,7 +31,7 @@ func TestRssPullsCorrectly(t *testing.T) {
}
client := cron.NewScheduler(ctx, conn)
client.CheckRssSources()
client.CollectRssPosts()
articles, err := db.Articles.ListByPage(ctx, 0, 100)
if err != nil {

View File

@ -1,59 +0,0 @@
package cron
import (
"log"
"time"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/input"
)
func (c *Cron) CheckRssSources() {
log.Println("Starting ")
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorRss)
if err != nil {
log.Println(err)
}
for sourceIndex, source := range sources {
if !source.Enabled {
continue
}
rssClient := input.NewRssClient(source)
articles, err := rssClient.GetArticles()
if err != nil {
log.Println(err)
}
for _, article := range articles {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url)
if err == nil {
continue
}
rowsCreated, err := c.repo.Articles.CreateFromEntity(*c.ctx, article)
if err != nil {
log.Println(err)
}
if rowsCreated != 1 {
log.Println("Got back the wrong number of rows")
}
}
if sourceIndex != len(sources) {
time.Sleep(time.Second * 30)
}
}
}
func (c *Cron) ListAllSourceRecords(sourceType string) ([]domain.SourceEntity, error) {
var records []domain.SourceEntity
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, sourceType)
if err != nil {
return records, err
}
return sources, nil
}

View File

@ -3,102 +3,37 @@ package cron
import (
"context"
"database/sql"
"fmt"
"log"
"time"
"github.com/google/uuid"
_ "github.com/lib/pq"
"github.com/robfig/cron/v3"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/input"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/output"
)
type Cron struct {
Db *database.Queries
ctx *context.Context
timer *cron.Cron
repo services.RepositoryService
}
func openDatabase() (*database.Queries, error) {
_env := services.NewConfig()
connString := _env.GetConfig(services.Sql_Connection_String)
if connString == "" {
panic("Connection String is null!")
}
db, err := sql.Open("postgres", connString)
if err != nil {
panic(err)
}
queries := database.New(db)
return queries, err
}
func NewScheduler(ctx context.Context) *Cron {
func NewScheduler(ctx context.Context, conn *sql.DB) *Cron {
c := &Cron{
ctx: &ctx,
ctx: &ctx,
repo: services.NewRepositoryService(conn),
}
timer := cron.New()
queries, err := openDatabase()
if err != nil {
panic(err)
}
c.Db = queries
//timer.AddFunc("*/5 * * * *", func() { go CheckCache() })
//features := services.GetEnvConfig()
features := services.NewConfig()
timer.AddFunc("5 * * * *", c.CheckRssSources)
//if features.RedditEnabled {
// timer.AddFunc("5 1-23 * * *", func() { go c.CheckReddit() })
// log.Print("[Input] Reddit backend was enabled")
// //go c.CheckReddit()
//}
res, _ := features.GetFeature(services.FEATURE_ENABLE_REDDIT_BACKEND)
if res {
timer.AddFunc("5 1-23 * * *", func() { go c.CheckReddit() })
log.Print("[Input] Reddit backend was enabled")
//go c.CheckReddit()
}
//if features.YoutubeEnabled {
// timer.AddFunc("10 1-23 * * *", func() { go c.CheckYoutube() })
// log.Print("[Input] YouTube backend was enabled")
//}
res, _ = features.GetFeature(services.FEATURE_ENABLE_YOUTUBE_BACKEND)
if res {
timer.AddFunc("10 1-23 * * *", func() { go c.CheckYoutube() })
log.Print("[Input] YouTube backend was enabled")
}
//if features.FfxivEnabled {
// timer.AddFunc("5 5,10,15,20 * * *", func() { go c.CheckFfxiv() })
// log.Print("[Input] FFXIV backend was enabled")
//}
res, _ = features.GetFeature(services.FEATURE_ENABLE_FFXIV_BACKEND)
if res {
timer.AddFunc("5 5,10,15,20 * * *", func() { go c.CheckFfxiv() })
log.Print("[Input] FFXIV backend was enabled")
}
//if features.TwitchEnabled {
// timer.AddFunc("15 1-23 * * *", func() { go c.CheckTwitch() })
// log.Print("[Input] Twitch backend was enabled")
//}
res, _ = features.GetFeature(services.FEATURE_ENABLE_TWITCH_BACKEND)
if res {
timer.AddFunc("15 1-23 * * *", func() { go c.CheckTwitch() })
log.Print("[Input] Twitch backend was enabled")
}
timer.AddFunc("*/5 * * * *", func() { go c.CheckDiscordQueue() })
log.Print("[Output] Discord Output was enabled")
timer.AddFunc("5 * * * *", c.CollectRssPosts)
//timer.AddFunc("5 1-23 * * *", c.CollectRedditPosts)
//timer.AddFunc("10 1-23 * * *", c.CheckYoutube)
//timer.AddFunc("5 5,10,15,20 * * *", c.CheckFfxiv)
//timer.AddFunc("15 1-23 * * *", c.CheckTwitch)
//timer.AddFunc("*/5 * * * *", c.CheckDiscordQueue)
c.timer = timer
return c
@ -112,105 +47,8 @@ func (c *Cron) Stop() {
c.timer.Stop()
}
// This is the main entry point to query all the reddit services
func (c *Cron) CheckReddit() {
sources, err := c.Db.ListSourcesBySource(*c.ctx, "reddit")
if err != nil {
log.Printf("[Reddit] No sources found to query - %v\r", err)
}
for _, source := range sources {
if !source.Enabled {
continue
}
log.Printf("[Reddit] Checking '%v'...", source.Name)
rc := input.NewRedditClient(source)
raw, err := rc.GetContent()
if err != nil {
log.Println(err)
}
redditArticles := rc.ConvertToArticles(raw)
c.checkPosts(redditArticles, "Reddit")
}
log.Print("[Reddit] Done!")
}
func (c *Cron) CheckYoutube() {
// Add call to the db to request youtube sources.
sources, err := c.Db.ListSourcesBySource(*c.ctx, "youtube")
if err != nil {
log.Printf("[Youtube] No sources found to query - %v\r", err)
}
for _, source := range sources {
if !source.Enabled {
continue
}
log.Printf("[YouTube] Checking '%v'...", source.Name)
yc := input.NewYoutubeClient(source)
raw, err := yc.GetContent()
if err != nil {
log.Println(err)
}
c.checkPosts(raw, "YouTube")
}
log.Print("[YouTube] Done!")
}
func (c *Cron) CheckFfxiv() {
sources, err := c.Db.ListSourcesBySource(*c.ctx, "ffxiv")
if err != nil {
log.Printf("[FFXIV] No sources found to query - %v\r", err)
}
for _, source := range sources {
if !source.Enabled {
continue
}
fc := input.NewFFXIVClient(source)
items, err := fc.CheckSource()
if err != nil {
log.Println(err)
}
c.checkPosts(items, "FFXIV")
}
log.Printf("[FFXIV Done!]")
}
func (c *Cron) CheckTwitch() error {
sources, err := c.Db.ListSourcesBySource(*c.ctx, "twitch")
if err != nil {
log.Printf("[Twitch] No sources found to query - %v\r", err)
}
tc, err := input.NewTwitchClient()
if err != nil {
return err
}
err = tc.Login()
if err != nil {
return err
}
for _, source := range sources {
if !source.Enabled {
continue
}
log.Printf("[Twitch] Checking '%v'...", source.Name)
tc.ReplaceSourceRecord(source)
items, err := tc.GetContent()
if err != nil {
log.Println(err)
}
c.checkPosts(items, "Twitch")
}
log.Print("[Twitch] Done!")
return nil
}
func (c *Cron) CheckDiscordQueue() error {
/*
func (c *Cron) CheckDiscordQueue() {
// Get items from the table
queueItems, err := c.Db.ListDiscordQueueItems(*c.ctx, 50)
if err != nil {
@ -279,55 +117,15 @@ func (c *Cron) CheckDiscordQueue() error {
return nil
}
*/
func (c *Cron) checkPosts(posts []database.Article, sourceName string) error {
for _, item := range posts {
_, err := c.Db.GetArticleByUrl(*c.ctx, item.Url)
if err != nil {
id := uuid.New()
err := c.postArticle(id, item)
if err != nil {
return fmt.Errorf("[%v] Failed to post article - %v - %v.\r", sourceName, item.Url, err)
}
err = c.addToDiscordQueue(id)
if err != nil {
return err
}
}
}
time.Sleep(30 * time.Second)
return nil
}
func (c *Cron) postArticle(id uuid.UUID, item database.Article) error {
err := c.Db.CreateArticle(*c.ctx, database.CreateArticleParams{
ID: id,
Sourceid: item.Sourceid,
Tags: item.Tags,
Title: item.Title,
Url: item.Url,
Pubdate: item.Pubdate,
Video: item.Video,
Videoheight: item.Videoheight,
Videowidth: item.Videowidth,
Thumbnail: item.Thumbnail,
Description: item.Description,
Authorname: item.Authorname,
Authorimage: item.Authorimage,
})
return err
}
func (c *Cron) addToDiscordQueue(Id uuid.UUID) error {
err := c.Db.CreateDiscordQueue(*c.ctx, database.CreateDiscordQueueParams{
ID: uuid.New(),
Articleid: Id,
})
if err != nil {
return err
}
return nil
}
//func (c *Cron) addToDiscordQueue(Id uuid.UUID) error {
// err := c.Db.CreateDiscordQueue(*c.ctx, database.CreateDiscordQueueParams{
// ID: uuid.New(),
// Articleid: Id,
// })
// if err != nil {
// return err
// }
// return nil
//}

View File

@ -1,12 +1,12 @@
package cron_test
import (
"context"
"testing"
"database/sql"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/cron"
"github.com/pressly/goose/v3"
)
/*
func TestInvokeTwitch(t *testing.T) {
}
@ -15,7 +15,7 @@ func TestInvokeTwitch(t *testing.T) {
func TestCheckReddit(t *testing.T) {
ctx := context.Background()
c := cron.NewScheduler(ctx)
c.CheckReddit()
c.Col()
}
func TestCheckYouTube(t *testing.T) {
@ -32,6 +32,7 @@ func TestCheckTwitch(t *testing.T) {
t.Error(err)
}
}
*/
func setupInMemoryDb() (*sql.DB, error) {
db, err := sql.Open("sqlite", ":memory:")

View File

@ -1,7 +1,6 @@
package input
import (
"database/sql"
"errors"
"log"
"net/http"
@ -13,7 +12,7 @@ import (
"github.com/go-rod/rod/lib/launcher"
"github.com/google/uuid"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/cache"
)
@ -25,7 +24,7 @@ const (
)
type FFXIVClient struct {
record database.Source
record domain.SourceEntity
//SourceID uint
//Url string
//Region string
@ -33,15 +32,15 @@ type FFXIVClient struct {
cacheGroup string
}
func NewFFXIVClient(Record database.Source) FFXIVClient {
func NewFFXIVClient(Record domain.SourceEntity) FFXIVClient {
return FFXIVClient{
record: Record,
cacheGroup: "ffxiv",
}
}
func (fc *FFXIVClient) CheckSource() ([]database.Article, error) {
var articles []database.Article
func (fc *FFXIVClient) CheckSource() ([]domain.ArticleEntity, error) {
var articles []domain.ArticleEntity
parser := fc.GetBrowser()
defer parser.Close()
@ -97,18 +96,16 @@ func (fc *FFXIVClient) CheckSource() ([]database.Article, error) {
return articles, err
}
article := database.Article{
Sourceid: fc.record.ID,
Tags: tags,
Title: title,
Url: link,
Pubdate: pubDate,
Videoheight: 0,
Videowidth: 0,
Thumbnail: thumb,
Description: description,
Authorname: sql.NullString{String: authorName},
Authorimage: sql.NullString{String: authorImage},
article := domain.ArticleEntity{
SourceID: fc.record.ID,
Tags: tags,
Title: title,
Url: link,
PubDate: pubDate,
Thumbnail: thumb,
Description: description,
AuthorName: authorName,
AuthorImageUrl: authorImage,
}
log.Printf("Collected '%v' from '%v'", article.Title, article.Url)

View File

@ -3,18 +3,16 @@ package input_test
import (
"testing"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
ffxiv "git.jamestombleson.com/jtom38/newsbot-api/internal/services/input"
"github.com/google/uuid"
)
var FFXIVRecord database.Source = database.Source{
ID: uuid.New(),
Site: "ffxiv",
Name: "Final Fantasy XIV - NA",
Source: "ffxiv",
Url: "https://na.finalfantasyxiv.com/lodestone/",
Tags: "ffxiv, final, fantasy, xiv, na, lodestone",
var FFXIVRecord domain.SourceEntity = domain.SourceEntity{
ID: 9999,
DisplayName: "Final Fantasy XIV - NA",
Source: domain.SourceCollectorFfxiv,
Url: "https://na.finalfantasyxiv.com/lodestone/",
Tags: "ffxiv, final, fantasy, xiv, na, lodestone",
}
func TestFfxivGetParser(t *testing.T) {

View File

@ -1,7 +1,6 @@
package input
import (
"database/sql"
"encoding/json"
"errors"
"fmt"
@ -9,7 +8,6 @@ import (
"strings"
"time"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"github.com/go-rod/rod"
@ -18,7 +16,7 @@ import (
type RedditClient struct {
config RedditConfig
record database.Source
record domain.SourceEntity
}
type RedditConfig struct {
@ -27,7 +25,7 @@ type RedditConfig struct {
PullNSFW string
}
func NewRedditClient(Record database.Source) *RedditClient {
func NewRedditClient(Record domain.SourceEntity) *RedditClient {
rc := RedditClient{
record: Record,
}
@ -71,7 +69,7 @@ func (rc *RedditClient) GetContent() (domain.RedditJsonContent, error) {
// TODO Wire this to support the config options
Url := fmt.Sprintf("%v.json", rc.record.Url)
log.Printf("[Reddit] Collecting results on '%v'", rc.record.Name)
log.Printf("[Reddit] Collecting results on '%v'", rc.record.DisplayName)
content, err := getHttpContent(Url)
if err != nil {
@ -88,10 +86,10 @@ func (rc *RedditClient) GetContent() (domain.RedditJsonContent, error) {
return items, nil
}
func (rc *RedditClient) ConvertToArticles(items domain.RedditJsonContent) []database.Article {
var redditArticles []database.Article
func (rc *RedditClient) ConvertToArticles(items domain.RedditJsonContent) []domain.ArticleEntity {
var redditArticles []domain.ArticleEntity
for _, item := range items.Data.Children {
var article database.Article
var article domain.ArticleEntity
article, err := rc.convertToArticle(item.Data)
if err != nil {
log.Printf("[Reddit] %v", err)
@ -104,8 +102,8 @@ func (rc *RedditClient) ConvertToArticles(items domain.RedditJsonContent) []data
// ConvertToArticle() will take the reddit model struct and convert them over to Article structs.
// This data can be passed to the database.
func (rc *RedditClient) convertToArticle(source domain.RedditPost) (database.Article, error) {
var item database.Article
func (rc *RedditClient) convertToArticle(source domain.RedditPost) (domain.ArticleEntity, error) {
var item domain.ArticleEntity
if source.Content == "" && source.Url != "" {
item = rc.convertPicturePost(source)
@ -131,65 +129,57 @@ func (rc *RedditClient) convertToArticle(source domain.RedditPost) (database.Art
return item, nil
}
func (rc *RedditClient) convertPicturePost(source domain.RedditPost) database.Article {
var item = database.Article{
Sourceid: rc.record.ID,
Title: source.Title,
Tags: fmt.Sprintf("%v", rc.record.Tags),
Url: fmt.Sprintf("https://www.reddit.com%v", source.Permalink),
Pubdate: time.Now(),
Video: sql.NullString{String: "null"},
Videoheight: 0,
Videowidth: 0,
Thumbnail: source.Thumbnail,
Description: source.Content,
Authorname: sql.NullString{String: source.Author},
Authorimage: sql.NullString{String: "null"},
func (rc *RedditClient) convertPicturePost(source domain.RedditPost) domain.ArticleEntity {
var item = domain.ArticleEntity{
SourceID: rc.record.ID,
Title: source.Title,
Tags: fmt.Sprintf("%v", rc.record.Tags),
Url: fmt.Sprintf("https://www.reddit.com%v", source.Permalink),
PubDate: time.Now(),
IsVideo: false,
Thumbnail: source.Thumbnail,
Description: source.Content,
AuthorName: source.Author,
AuthorImageUrl: "null",
}
return item
}
func (rc *RedditClient) convertTextPost(source domain.RedditPost) database.Article {
var item = database.Article{
Sourceid: rc.record.ID,
func (rc *RedditClient) convertTextPost(source domain.RedditPost) domain.ArticleEntity {
var item = domain.ArticleEntity{
SourceID: rc.record.ID,
Tags: "a",
Title: source.Title,
Pubdate: time.Now(),
Videoheight: 0,
Videowidth: 0,
PubDate: time.Now(),
Url: fmt.Sprintf("https://www.reddit.com%v", source.Permalink),
Authorname: sql.NullString{String: source.Author},
AuthorName: source.Author,
Description: source.Content,
}
return item
}
func (rc *RedditClient) convertVideoPost(source domain.RedditPost) database.Article {
var item = database.Article{
Sourceid: rc.record.ID,
func (rc *RedditClient) convertVideoPost(source domain.RedditPost) domain.ArticleEntity {
var item = domain.ArticleEntity{
SourceID: rc.record.ID,
Tags: "a",
Title: source.Title,
Pubdate: time.Now(),
PubDate: time.Now(),
Url: fmt.Sprintf("https://www.reddit.com%v", source.Permalink),
Videoheight: 0,
Videowidth: 0,
Authorname: sql.NullString{String: source.Author},
AuthorName: source.Author,
Description: source.Media.RedditVideo.FallBackUrl,
}
return item
}
// This post is nothing more then a redirect to another location.
func (rc *RedditClient) convertRedirectPost(source domain.RedditPost) database.Article {
var item = database.Article{
Sourceid: rc.record.ID,
func (rc *RedditClient) convertRedirectPost(source domain.RedditPost) domain.ArticleEntity {
var item = domain.ArticleEntity{
SourceID: rc.record.ID,
Tags: "a",
Title: source.Title,
Pubdate: time.Now(),
PubDate: time.Now(),
Url: fmt.Sprintf("https://www.reddit.com%v", source.Permalink),
Videoheight: 0,
Videowidth: 0,
Authorname: sql.NullString{String: source.Author},
AuthorName: source.Author,
Description: source.UrlOverriddenByDest,
}
return item

View File

@ -3,18 +3,16 @@ package input_test
import (
"testing"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/input"
"github.com/google/uuid"
)
var RedditRecord database.Source = database.Source{
ID: uuid.New(),
Name: "dadjokes",
Source: "reddit",
Site: "reddit",
Url: "https://reddit.com/r/dadjokes",
Tags: "reddit, dadjokes",
var RedditRecord domain.SourceEntity = domain.SourceEntity{
ID: 9999,
DisplayName: "dadjokes",
Source: domain.SourceCollectorRss,
Url: "https://reddit.com/r/dadjokes",
Tags: "reddit, dadjokes",
}
func TestGetContent(t *testing.T) {

View File

@ -8,9 +8,10 @@ import (
)
var rssRecord = domain.SourceEntity{
ID: 1,
ID: 1,
DisplayName: "ArsTechnica",
Url: "https://feeds.arstechnica.com/arstechnica/index",
Url: "https://feeds.arstechnica.com/arstechnica/index",
Source: domain.SourceCollectorRss,
}
func TestRssClientConstructor(t *testing.T) {

View File

@ -1,19 +1,18 @@
package input
import (
"database/sql"
"errors"
"fmt"
"strings"
"time"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"github.com/nicklaw5/helix/v2"
)
type TwitchClient struct {
SourceRecord database.Source
SourceRecord domain.SourceEntity
// config
monitorClips string
@ -72,7 +71,7 @@ func initTwitchApi(ClientId string, ClientSecret string) (helix.Client, error) {
}
// This will let you replace the bound source record to keep the same session alive.
func (tc *TwitchClient) ReplaceSourceRecord(source database.Source) {
func (tc *TwitchClient) ReplaceSourceRecord(source domain.SourceEntity) {
tc.SourceRecord = source
}
@ -87,8 +86,8 @@ func (tc *TwitchClient) Login() error {
return nil
}
func (tc *TwitchClient) GetContent() ([]database.Article, error) {
var items []database.Article
func (tc *TwitchClient) GetContent() ([]domain.ArticleEntity, error) {
var items []domain.ArticleEntity
user, err := tc.GetUserDetails()
if err != nil {
@ -101,31 +100,31 @@ func (tc *TwitchClient) GetContent() ([]database.Article, error) {
}
for _, video := range posts {
var article database.Article
var article domain.ArticleEntity
AuthorName, err := tc.ExtractAuthor(video)
if err != nil {
return items, err
}
article.Authorname = sql.NullString{String: AuthorName}
article.AuthorName = AuthorName
Authorimage, err := tc.ExtractAuthorImage(user)
if err != nil {
return items, err
}
article.Authorimage = sql.NullString{String: Authorimage}
article.AuthorImageUrl = Authorimage
article.Description, err = tc.ExtractDescription(video)
if err != nil {
return items, err
}
article.Pubdate, err = tc.ExtractPubDate(video)
article.PubDate, err = tc.ExtractPubDate(video)
if err != nil {
return items, err
}
article.Sourceid = tc.SourceRecord.ID
article.SourceID = tc.SourceRecord.ID
article.Tags, err = tc.ExtractTags(video, user)
if err != nil {
return items, err
@ -156,7 +155,7 @@ func (tc *TwitchClient) GetUserDetails() (helix.User, error) {
var blank helix.User
users, err := tc.api.GetUsers(&helix.UsersParams{
Logins: []string{tc.SourceRecord.Name},
Logins: []string{tc.SourceRecord.DisplayName},
})
if err != nil {
return blank, err

View File

@ -4,21 +4,20 @@ import (
"log"
"testing"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/input"
"github.com/google/uuid"
)
var TwitchSourceRecord = database.Source{
ID: uuid.New(),
Name: "nintendo",
Source: "Twitch",
var TwitchSourceRecord = domain.SourceEntity{
ID: 9999,
DisplayName: "nintendo",
Source: domain.SourceCollectorTwitch,
}
var TwitchInvalidRecord = database.Source{
ID: uuid.New(),
Name: "EvilNintendo",
Source: "Twitch",
var TwitchInvalidRecord = domain.SourceEntity{
ID: 9999,
DisplayName: "EvilNintendo",
Source: domain.SourceCollectorTwitch,
}
func TestTwitchLogin(t *testing.T) {

View File

@ -1,7 +1,6 @@
package input
import (
"database/sql"
"errors"
"fmt"
"log"
@ -12,11 +11,11 @@ import (
"github.com/go-rod/rod/lib/launcher"
"github.com/mmcdole/gofeed"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
)
type YoutubeClient struct {
record database.Source
record domain.SourceEntity
// internal variables at time of collection
channelID string
@ -37,7 +36,7 @@ var (
const YOUTUBE_FEED_URL string = "https://www.youtube.com/feeds/videos.xml?channel_id="
func NewYoutubeClient(Record database.Source) YoutubeClient {
func NewYoutubeClient(Record domain.SourceEntity) YoutubeClient {
yc := YoutubeClient{
record: Record,
cacheGroup: "youtube",
@ -46,8 +45,8 @@ func NewYoutubeClient(Record database.Source) YoutubeClient {
}
// CheckSource will go and run all the commands needed to process a source.
func (yc *YoutubeClient) GetContent() ([]database.Article, error) {
var items []database.Article
func (yc *YoutubeClient) GetContent() ([]domain.ArticleEntity, error) {
var items []domain.ArticleEntity
docParser, err := yc.GetParser(yc.record.Url)
if err != nil {
return items, err
@ -247,7 +246,7 @@ func (yc *YoutubeClient) CheckUriCache(uri *string) bool {
return false
}
func (yc *YoutubeClient) ConvertToArticle(item *gofeed.Item) database.Article {
func (yc *YoutubeClient) ConvertToArticle(item *gofeed.Item) domain.ArticleEntity {
parser, err := yc.GetParser(item.Link)
if err != nil {
log.Printf("[YouTube] Unable to process %v, submit this link as an issue.\n", item.Link)
@ -265,16 +264,16 @@ func (yc *YoutubeClient) ConvertToArticle(item *gofeed.Item) database.Article {
log.Printf("[YouTube] %v", msg)
}
var article = database.Article{
Sourceid: yc.record.ID,
Tags: tags,
Title: item.Title,
Url: item.Link,
Pubdate: *item.PublishedParsed,
Thumbnail: thumb,
Description: item.Description,
Authorname: sql.NullString{String: item.Author.Name},
Authorimage: sql.NullString{String: yc.avatarUri},
var article = domain.ArticleEntity{
SourceID: yc.record.ID,
Tags: tags,
Title: item.Title,
Url: item.Link,
PubDate: *item.PublishedParsed,
Thumbnail: thumb,
Description: item.Description,
AuthorName: item.Author.Name,
AuthorImageUrl: yc.avatarUri,
}
return article
}

View File

@ -3,17 +3,15 @@ package input_test
import (
"testing"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/input"
"github.com/google/uuid"
)
var YouTubeRecord database.Source = database.Source{
ID: uuid.New(),
Name: "dadjokes",
Source: "reddit",
Site: "reddit",
Url: "https://youtube.com/gamegrumps",
var YouTubeRecord = domain.SourceEntity{
ID: 9999,
DisplayName: "dadjokes",
Source: domain.SourceCollectorReddit,
Url: "https://youtube.com/gamegrumps",
}
func TestGetPageParser(t *testing.T) {

View File

@ -4,8 +4,8 @@ help: ## Shows this help command
build: ## builds the application with the current go runtime
~/go/bin/swag f
~/go/bin/swag i
go build .
~/go/bin/swag init -g cmd/server.go
go build cmd/server.go
docker-build: ## Generates the docker image
docker build -t "newsbot.collector.api" .