Add support for images

This commit is contained in:
Joakim Hellsén 2024-02-18 00:27:00 +01:00
commit fb37a9ee88
7 changed files with 336 additions and 4 deletions

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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

View file

@ -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
}

View file

@ -83,6 +83,19 @@ func FeedsHandler(w http.ResponseWriter, _ *http.Request) {
fb.WriteString("<li>Value: " + ext.Value.String + "</li>")
}
}
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("<li><img src=\"" + image.Url.String + "\" alt=\"Feed Image\" width=\"256\"></li>")
}
fb.WriteString("</ul>")
fb.WriteString("<a href=\"/feed/" + strconv.FormatInt(feed.ID, 10) + "\">" + feed.Url + "</a>")
fb.WriteString("</li>")
@ -363,8 +376,21 @@ func FeedHandler(w http.ResponseWriter, r *http.Request) {
fb.WriteString("<li>Children: " + string(ext.Children) + "</li>")
}
fb.WriteString("</ul>")
}
// 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("<li><img src=\"" + image.Url.String + "\" alt=\"Feed Image\" width=\"256\"></li>")
}
fb.WriteString("</ul>")
fb.WriteString("<ul>")
if item.Published.Valid {

View file

@ -46,7 +46,6 @@ var FunMsg = []string{
"In the vacuum of space, let equality fill the void.",
"From Big Bang to the heat death of the universe, solidarity is eternal.",
"In dark times, should the stars also go out?",
"One day I will return to your side.",
"Un Jour Je Serai de Retour Prés de Toi",
"You should build Space Communism — precisely *because* it's impossible.",
"She thinks you are an idiot, sire.",

View file

@ -263,3 +263,61 @@ LIMIT
$2
OFFSET
$3;
-- 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
*;
-- 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
*;
-- name: GetFeedImages :many
SELECT
*
FROM
feed_images
WHERE
feed_id = $1
ORDER BY
created_at DESC
LIMIT
$2
OFFSET
$3;
-- name: GetItemImages :many
SELECT
*
FROM
item_images
WHERE
item_id = $1
ORDER BY
created_at DESC
LIMIT
$2
OFFSET
$3;