diff --git a/add_feed.go b/add_feed.go index 17ae5d4..eaa37c0 100644 --- a/add_feed.go +++ b/add_feed.go @@ -102,6 +102,11 @@ func addFeedExtensionToDB(ctx context.Context, feed *gofeed.Feed, newFeed db.Fee } func addFeedAuthors(ctx context.Context, feed *gofeed.Feed, newFeed db.Feed) { + if feed.Authors == nil { + log.Printf("No authors to add to database") + return + } + // Add authors to the database for _, author := range feed.Authors { _, err := DB.CreateFeedAuthor(ctx, db.CreateFeedAuthorParams{ @@ -113,7 +118,30 @@ func addFeedAuthors(ctx context.Context, feed *gofeed.Feed, newFeed db.Feed) { }) if err != nil { log.Printf("Error adding author %s (%s) to database: %s", author.Name, author.Email, err) + continue } log.Printf("Author %s (%s) added to database", author.Name, author.Email) } } + +func addFeedImages(ctx context.Context, feed *gofeed.Feed, newFeed db.Feed) { + if feed.Image == nil { + log.Printf("No image to add to database") + return + } + + // TODO: Download the image and store it on the server + _, err := DB.CreateFeedImage(ctx, db.CreateFeedImageParams{ + CreatedAt: pgtype.Timestamptz{Time: time.Now(), Valid: true}, + UpdatedAt: pgtype.Timestamptz{Time: time.Now(), Valid: true}, + DeletedAt: pgtype.Timestamptz{Valid: false}, + Url: pgtype.Text{String: feed.Image.URL, Valid: feed.Image.URL != ""}, + Title: pgtype.Text{String: feed.Image.Title, Valid: feed.Image.Title != ""}, + FeedID: newFeed.ID, + }) + if err != nil { + log.Printf("Error adding image to database: %s", err) + return + } + log.Printf("Image added to database: %s", feed.Image.URL) +} diff --git a/add_item.go b/add_item.go index 0dcafbb..a296770 100644 --- a/add_item.go +++ b/add_item.go @@ -24,6 +24,11 @@ func addItemToDB(item *gofeed.Item, ctx context.Context, newFeed db.Feed) { // Add authors to the database addItemAuthors(ctx, item, newItem) + // Add images to the database + if item.Image != nil { + addItemImages(ctx, item, newItem) + } + log.Printf("Item added to database") } @@ -84,7 +89,6 @@ func addItemExtensionToDB(ctx context.Context, item *gofeed.Item, newItem db.Ite fmt.Println("Error marshalling extension attributes:", err) attrsCustom = []byte("{}") } - log.Printf("Extension attributes: %s", attrsCustom) } childrenCustom := []byte("{}") @@ -95,7 +99,6 @@ func addItemExtensionToDB(ctx context.Context, item *gofeed.Item, newItem db.Ite fmt.Println("Error marshalling extension children:", err) childrenCustom = []byte("{}") } - log.Printf("Extension children: %s", childrenCustom) } _, err := DB.CreateItemExtension(ctx, db.CreateItemExtensionParams{ @@ -111,6 +114,7 @@ func addItemExtensionToDB(ctx context.Context, item *gofeed.Item, newItem db.Ite if err != nil { log.Printf("Error adding extension to database: %s", err) + continue } log.Printf("Extension added to database") @@ -132,7 +136,24 @@ func addItemAuthors(ctx context.Context, item *gofeed.Item, newItem db.Item) { if err != nil { log.Printf("Error adding author %s (%s) to database: %s", author.Name, author.Email, err) + continue } log.Printf("Author %s (%s) added to database", author.Name, author.Email) } } + +func addItemImages(ctx context.Context, item *gofeed.Item, newItem db.Item) { + _, err := DB.CreateItemImage(ctx, db.CreateItemImageParams{ + CreatedAt: pgtype.Timestamptz{Time: time.Now(), Valid: true}, + UpdatedAt: pgtype.Timestamptz{Time: time.Now(), Valid: true}, + DeletedAt: pgtype.Timestamptz{Valid: false}, + Url: pgtype.Text{String: item.Image.URL, Valid: item.Image.URL != ""}, + Title: pgtype.Text{String: item.Image.Title, Valid: item.Image.Title != ""}, + ItemID: newItem.ID, + }) + if err != nil { + log.Printf("Error adding image to database: %s", err) + return + } + log.Printf("Image added to database: %s", item.Image.URL) +} diff --git a/db/feeds.sql.go b/db/feeds.sql.go index bba965d..94aea86 100644 --- a/db/feeds.sql.go +++ b/db/feeds.sql.go @@ -265,6 +265,53 @@ func (q *Queries) CreateFeedExtension(ctx context.Context, arg CreateFeedExtensi return i, err } +const createFeedImage = `-- name: CreateFeedImage :one +INSERT INTO + feed_images ( + created_at, + updated_at, + deleted_at, + "url", + title, + feed_id + ) +VALUES + ($1, $2, $3, $4, $5, $6) +RETURNING + id, created_at, updated_at, deleted_at, url, title, feed_id +` + +type CreateFeedImageParams struct { + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` + DeletedAt pgtype.Timestamptz `json:"deleted_at"` + Url pgtype.Text `json:"url"` + Title pgtype.Text `json:"title"` + FeedID int64 `json:"feed_id"` +} + +func (q *Queries) CreateFeedImage(ctx context.Context, arg CreateFeedImageParams) (FeedImage, error) { + row := q.db.QueryRow(ctx, createFeedImage, + arg.CreatedAt, + arg.UpdatedAt, + arg.DeletedAt, + arg.Url, + arg.Title, + arg.FeedID, + ) + var i FeedImage + err := row.Scan( + &i.ID, + &i.CreatedAt, + &i.UpdatedAt, + &i.DeletedAt, + &i.Url, + &i.Title, + &i.FeedID, + ) + return i, err +} + const createItem = `-- name: CreateItem :one INSERT INTO items ( @@ -471,6 +518,53 @@ func (q *Queries) CreateItemExtension(ctx context.Context, arg CreateItemExtensi return i, err } +const createItemImage = `-- name: CreateItemImage :one +INSERT INTO + item_images ( + created_at, + updated_at, + deleted_at, + "url", + title, + item_id + ) +VALUES + ($1, $2, $3, $4, $5, $6) +RETURNING + id, created_at, updated_at, deleted_at, url, title, item_id +` + +type CreateItemImageParams struct { + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` + DeletedAt pgtype.Timestamptz `json:"deleted_at"` + Url pgtype.Text `json:"url"` + Title pgtype.Text `json:"title"` + ItemID int64 `json:"item_id"` +} + +func (q *Queries) CreateItemImage(ctx context.Context, arg CreateItemImageParams) (ItemImage, error) { + row := q.db.QueryRow(ctx, createItemImage, + arg.CreatedAt, + arg.UpdatedAt, + arg.DeletedAt, + arg.Url, + arg.Title, + arg.ItemID, + ) + var i ItemImage + err := row.Scan( + &i.ID, + &i.CreatedAt, + &i.UpdatedAt, + &i.DeletedAt, + &i.Url, + &i.Title, + &i.ItemID, + ) + return i, err +} + const getFeed = `-- name: GetFeed :one SELECT id, url, created_at, updated_at, deleted_at, title, description, link, feed_link, links, updated, updated_parsed, published, published_parsed, language, copyright, generator, categories, custom, feed_type, feed_version @@ -609,6 +703,55 @@ func (q *Queries) GetFeedExtensions(ctx context.Context, arg GetFeedExtensionsPa return items, nil } +const getFeedImages = `-- name: GetFeedImages :many +SELECT + id, created_at, updated_at, deleted_at, url, title, feed_id +FROM + feed_images +WHERE + feed_id = $1 +ORDER BY + created_at DESC +LIMIT + $2 +OFFSET + $3 +` + +type GetFeedImagesParams struct { + FeedID int64 `json:"feed_id"` + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` +} + +func (q *Queries) GetFeedImages(ctx context.Context, arg GetFeedImagesParams) ([]FeedImage, error) { + rows, err := q.db.Query(ctx, getFeedImages, arg.FeedID, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + items := []FeedImage{} + for rows.Next() { + var i FeedImage + if err := rows.Scan( + &i.ID, + &i.CreatedAt, + &i.UpdatedAt, + &i.DeletedAt, + &i.Url, + &i.Title, + &i.FeedID, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const getFeeds = `-- name: GetFeeds :many SELECT id, url, created_at, updated_at, deleted_at, title, description, link, feed_link, links, updated, updated_parsed, published, published_parsed, language, copyright, generator, categories, custom, feed_type, feed_version @@ -803,6 +946,55 @@ func (q *Queries) GetItemExtensions(ctx context.Context, arg GetItemExtensionsPa return items, nil } +const getItemImages = `-- name: GetItemImages :many +SELECT + id, created_at, updated_at, deleted_at, url, title, item_id +FROM + item_images +WHERE + item_id = $1 +ORDER BY + created_at DESC +LIMIT + $2 +OFFSET + $3 +` + +type GetItemImagesParams struct { + ItemID int64 `json:"item_id"` + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` +} + +func (q *Queries) GetItemImages(ctx context.Context, arg GetItemImagesParams) ([]ItemImage, error) { + rows, err := q.db.Query(ctx, getItemImages, arg.ItemID, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + items := []ItemImage{} + for rows.Next() { + var i ItemImage + if err := rows.Scan( + &i.ID, + &i.CreatedAt, + &i.UpdatedAt, + &i.DeletedAt, + &i.Url, + &i.Title, + &i.ItemID, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const getItems = `-- name: GetItems :many SELECT id, created_at, updated_at, deleted_at, title, description, content, link, links, updated, updated_parsed, published, published_parsed, guid, categories, custom, feed_id diff --git a/feeds.go b/feeds.go index 469d3c5..bb14492 100644 --- a/feeds.go +++ b/feeds.go @@ -36,11 +36,19 @@ func AddFeedToDB(feedURL string) error { } // Add extensions to the database + log.Printf("Adding extensions to the database") addFeedExtensionToDB(ctx, feed, newFeed) // Add authors to the database + log.Printf("Adding authors to the database") addFeedAuthors(ctx, feed, newFeed) - fmt.Println(feed.Title) + // TODO: Add categories to the database + + // Add images to the database + log.Printf("Adding images to the database") + addFeedImages(ctx, feed, newFeed) + + log.Printf("Feed added to database") return nil } diff --git a/handlers.go b/handlers.go index 74ea764..4bd171d 100644 --- a/handlers.go +++ b/handlers.go @@ -83,6 +83,19 @@ func FeedsHandler(w http.ResponseWriter, _ *http.Request) { fb.WriteString("
  • Value: " + ext.Value.String + "
  • ") } } + + images, err := DB.GetFeedImages(context.Background(), db.GetFeedImagesParams{ + FeedID: feed.ID, + Limit: 100, + }) + if err != nil { + http.Error(w, "Error getting images", http.StatusInternalServerError) + return + } + for _, image := range images { + fb.WriteString("
  • \"Feed
  • ") + } + fb.WriteString("") fb.WriteString("" + feed.Url + "") fb.WriteString("") @@ -363,8 +376,21 @@ func FeedHandler(w http.ResponseWriter, r *http.Request) { fb.WriteString("
  • Children: " + string(ext.Children) + "
  • ") } fb.WriteString("") - } + + // Get images for the item + images, err := DB.GetItemImages(context.Background(), db.GetItemImagesParams{ + ItemID: item.ID, + Limit: 100, + }) + if err != nil { + http.Error(w, "Error getting images", http.StatusInternalServerError) + return + } + for _, image := range images { + fb.WriteString("
  • \"Feed
  • ") + } + fb.WriteString("") fb.WriteString("