Items will now be added when adding feed, add /feed/{id} and improve SQL

This commit is contained in:
Joakim Hellsén 2024-02-17 04:50:23 +01:00
commit 99cd70165e
14 changed files with 807 additions and 282 deletions

View file

@ -11,7 +11,7 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
const CountFeeds = `-- name: CountFeeds :one const countFeeds = `-- name: CountFeeds :one
SELECT SELECT
COUNT(*) COUNT(*)
FROM FROM
@ -19,13 +19,27 @@ FROM
` `
func (q *Queries) CountFeeds(ctx context.Context) (int64, error) { func (q *Queries) CountFeeds(ctx context.Context) (int64, error) {
row := q.db.QueryRow(ctx, CountFeeds) row := q.db.QueryRow(ctx, countFeeds)
var count int64 var count int64
err := row.Scan(&count) err := row.Scan(&count)
return count, err return count, err
} }
const CreateFeed = `-- name: CreateFeed :one const countItems = `-- name: CountItems :one
SELECT
COUNT(*)
FROM
items
`
func (q *Queries) CountItems(ctx context.Context) (int64, error) {
row := q.db.QueryRow(ctx, countItems)
var count int64
err := row.Scan(&count)
return count, err
}
const createFeed = `-- name: CreateFeed :one
INSERT INTO INSERT INTO
feeds ( feeds (
"url", "url",
@ -76,18 +90,18 @@ VALUES
type CreateFeedParams struct { type CreateFeedParams struct {
Url string `json:"url"` Url string `json:"url"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Title pgtype.Text `json:"title"` Title pgtype.Text `json:"title"`
Description pgtype.Text `json:"description"` Description pgtype.Text `json:"description"`
Link pgtype.Text `json:"link"` Link pgtype.Text `json:"link"`
FeedLink pgtype.Text `json:"feed_link"` FeedLink pgtype.Text `json:"feed_link"`
Links []string `json:"links"` Links []string `json:"links"`
Updated pgtype.Text `json:"updated"` Updated pgtype.Text `json:"updated"`
UpdatedParsed pgtype.Timestamp `json:"updated_parsed"` UpdatedParsed pgtype.Timestamptz `json:"updated_parsed"`
Published pgtype.Text `json:"published"` Published pgtype.Text `json:"published"`
PublishedParsed pgtype.Timestamp `json:"published_parsed"` PublishedParsed pgtype.Timestamptz `json:"published_parsed"`
Language pgtype.Text `json:"language"` Language pgtype.Text `json:"language"`
Copyright pgtype.Text `json:"copyright"` Copyright pgtype.Text `json:"copyright"`
Generator pgtype.Text `json:"generator"` Generator pgtype.Text `json:"generator"`
@ -98,7 +112,7 @@ type CreateFeedParams struct {
} }
func (q *Queries) CreateFeed(ctx context.Context, arg CreateFeedParams) (Feed, error) { func (q *Queries) CreateFeed(ctx context.Context, arg CreateFeedParams) (Feed, error) {
row := q.db.QueryRow(ctx, CreateFeed, row := q.db.QueryRow(ctx, createFeed,
arg.Url, arg.Url,
arg.CreatedAt, arg.CreatedAt,
arg.UpdatedAt, arg.UpdatedAt,
@ -146,3 +160,292 @@ func (q *Queries) CreateFeed(ctx context.Context, arg CreateFeedParams) (Feed, e
) )
return i, err return i, err
} }
const createItem = `-- name: CreateItem :one
INSERT INTO
items (
created_at,
updated_at,
deleted_at,
title,
"description",
content,
link,
links,
updated,
updated_parsed,
published,
published_parsed,
"guid",
categories,
custom,
feed_id
)
VALUES
(
$1,
$2,
$3,
$4,
$5,
$6,
$7,
$8,
$9,
$10,
$11,
$12,
$13,
$14,
$15,
$16
) RETURNING id, created_at, updated_at, deleted_at, title, description, content, link, links, updated, updated_parsed, published, published_parsed, guid, categories, custom, feed_id
`
type CreateItemParams struct {
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Title pgtype.Text `json:"title"`
Description pgtype.Text `json:"description"`
Content pgtype.Text `json:"content"`
Link pgtype.Text `json:"link"`
Links []string `json:"links"`
Updated pgtype.Text `json:"updated"`
UpdatedParsed pgtype.Timestamp `json:"updated_parsed"`
Published pgtype.Text `json:"published"`
PublishedParsed pgtype.Timestamp `json:"published_parsed"`
Guid pgtype.Text `json:"guid"`
Categories []string `json:"categories"`
Custom []byte `json:"custom"`
FeedID int64 `json:"feed_id"`
}
func (q *Queries) CreateItem(ctx context.Context, arg CreateItemParams) (Item, error) {
row := q.db.QueryRow(ctx, createItem,
arg.CreatedAt,
arg.UpdatedAt,
arg.DeletedAt,
arg.Title,
arg.Description,
arg.Content,
arg.Link,
arg.Links,
arg.Updated,
arg.UpdatedParsed,
arg.Published,
arg.PublishedParsed,
arg.Guid,
arg.Categories,
arg.Custom,
arg.FeedID,
)
var i Item
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Title,
&i.Description,
&i.Content,
&i.Link,
&i.Links,
&i.Updated,
&i.UpdatedParsed,
&i.Published,
&i.PublishedParsed,
&i.Guid,
&i.Categories,
&i.Custom,
&i.FeedID,
)
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
FROM
feeds
WHERE
id = $1
`
func (q *Queries) GetFeed(ctx context.Context, id int64) (Feed, error) {
row := q.db.QueryRow(ctx, getFeed, id)
var i Feed
err := row.Scan(
&i.ID,
&i.Url,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Title,
&i.Description,
&i.Link,
&i.FeedLink,
&i.Links,
&i.Updated,
&i.UpdatedParsed,
&i.Published,
&i.PublishedParsed,
&i.Language,
&i.Copyright,
&i.Generator,
&i.Categories,
&i.Custom,
&i.FeedType,
&i.FeedVersion,
)
return i, err
}
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
FROM
feeds
ORDER BY
created_at DESC
LIMIT $1
OFFSET $2
`
type GetFeedsParams struct {
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
}
func (q *Queries) GetFeeds(ctx context.Context, arg GetFeedsParams) ([]Feed, error) {
rows, err := q.db.Query(ctx, getFeeds, arg.Limit, arg.Offset)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Feed{}
for rows.Next() {
var i Feed
if err := rows.Scan(
&i.ID,
&i.Url,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Title,
&i.Description,
&i.Link,
&i.FeedLink,
&i.Links,
&i.Updated,
&i.UpdatedParsed,
&i.Published,
&i.PublishedParsed,
&i.Language,
&i.Copyright,
&i.Generator,
&i.Categories,
&i.Custom,
&i.FeedType,
&i.FeedVersion,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getItem = `-- name: GetItem :one
SELECT
id, created_at, updated_at, deleted_at, title, description, content, link, links, updated, updated_parsed, published, published_parsed, guid, categories, custom, feed_id
FROM
items
WHERE
id = $1
`
func (q *Queries) GetItem(ctx context.Context, id int64) (Item, error) {
row := q.db.QueryRow(ctx, getItem, id)
var i Item
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Title,
&i.Description,
&i.Content,
&i.Link,
&i.Links,
&i.Updated,
&i.UpdatedParsed,
&i.Published,
&i.PublishedParsed,
&i.Guid,
&i.Categories,
&i.Custom,
&i.FeedID,
)
return i, err
}
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
FROM
items
WHERE
feed_id = $1
ORDER BY
created_at DESC
LIMIT $2
OFFSET $3
`
type GetItemsParams struct {
FeedID int64 `json:"feed_id"`
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
}
func (q *Queries) GetItems(ctx context.Context, arg GetItemsParams) ([]Item, error) {
rows, err := q.db.Query(ctx, getItems, arg.FeedID, arg.Limit, arg.Offset)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Item{}
for rows.Next() {
var i Item
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Title,
&i.Description,
&i.Content,
&i.Link,
&i.Links,
&i.Updated,
&i.UpdatedParsed,
&i.Published,
&i.PublishedParsed,
&i.Guid,
&i.Categories,
&i.Custom,
&i.FeedID,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

View file

@ -9,31 +9,31 @@ import (
) )
type Enclosure struct { type Enclosure struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Url pgtype.Text `json:"url"` Url pgtype.Text `json:"url"`
Length pgtype.Text `json:"length"` Length pgtype.Text `json:"length"`
Type pgtype.Text `json:"type"` Type pgtype.Text `json:"type"`
ItemID int32 `json:"item_id"` ItemID int64 `json:"item_id"`
} }
type Feed struct { type Feed struct {
ID int32 `json:"id"` ID int64 `json:"id"`
Url string `json:"url"` Url string `json:"url"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Title pgtype.Text `json:"title"` Title pgtype.Text `json:"title"`
Description pgtype.Text `json:"description"` Description pgtype.Text `json:"description"`
Link pgtype.Text `json:"link"` Link pgtype.Text `json:"link"`
FeedLink pgtype.Text `json:"feed_link"` FeedLink pgtype.Text `json:"feed_link"`
Links []string `json:"links"` Links []string `json:"links"`
Updated pgtype.Text `json:"updated"` Updated pgtype.Text `json:"updated"`
UpdatedParsed pgtype.Timestamp `json:"updated_parsed"` UpdatedParsed pgtype.Timestamptz `json:"updated_parsed"`
Published pgtype.Text `json:"published"` Published pgtype.Text `json:"published"`
PublishedParsed pgtype.Timestamp `json:"published_parsed"` PublishedParsed pgtype.Timestamptz `json:"published_parsed"`
Language pgtype.Text `json:"language"` Language pgtype.Text `json:"language"`
Copyright pgtype.Text `json:"copyright"` Copyright pgtype.Text `json:"copyright"`
Generator pgtype.Text `json:"generator"` Generator pgtype.Text `json:"generator"`
@ -44,21 +44,21 @@ type Feed struct {
} }
type FeedAuthor struct { type FeedAuthor struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Name pgtype.Text `json:"name"` Name pgtype.Text `json:"name"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
Uri pgtype.Text `json:"uri"` Uri pgtype.Text `json:"uri"`
FeedID int32 `json:"feed_id"` FeedID int64 `json:"feed_id"`
} }
type FeedDublinCore struct { type FeedDublinCore struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Title []string `json:"title"` Title []string `json:"title"`
Creator []string `json:"creator"` Creator []string `json:"creator"`
Author []string `json:"author"` Author []string `json:"author"`
@ -75,36 +75,36 @@ type FeedDublinCore struct {
Relation []string `json:"relation"` Relation []string `json:"relation"`
Coverage []string `json:"coverage"` Coverage []string `json:"coverage"`
Rights []string `json:"rights"` Rights []string `json:"rights"`
FeedID int32 `json:"feed_id"` FeedID int64 `json:"feed_id"`
} }
type FeedExtension struct { type FeedExtension struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Name pgtype.Text `json:"name"` Name pgtype.Text `json:"name"`
Value pgtype.Text `json:"value"` Value pgtype.Text `json:"value"`
Attrs []byte `json:"attrs"` Attrs []byte `json:"attrs"`
Children []byte `json:"children"` Children []byte `json:"children"`
FeedID int32 `json:"feed_id"` FeedID int64 `json:"feed_id"`
} }
type FeedImage struct { type FeedImage struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Url pgtype.Text `json:"url"` Url pgtype.Text `json:"url"`
Title pgtype.Text `json:"title"` Title pgtype.Text `json:"title"`
FeedID int32 `json:"feed_id"` FeedID int64 `json:"feed_id"`
} }
type FeedItune struct { type FeedItune struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Author pgtype.Text `json:"author"` Author pgtype.Text `json:"author"`
Block pgtype.Text `json:"block"` Block pgtype.Text `json:"block"`
Explicit pgtype.Text `json:"explicit"` Explicit pgtype.Text `json:"explicit"`
@ -115,14 +115,14 @@ type FeedItune struct {
Complete pgtype.Text `json:"complete"` Complete pgtype.Text `json:"complete"`
NewFeedUrl pgtype.Text `json:"new_feed_url"` NewFeedUrl pgtype.Text `json:"new_feed_url"`
Type pgtype.Text `json:"type"` Type pgtype.Text `json:"type"`
FeedID int32 `json:"feed_id"` FeedID int64 `json:"feed_id"`
} }
type Item struct { type Item struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Title pgtype.Text `json:"title"` Title pgtype.Text `json:"title"`
Description pgtype.Text `json:"description"` Description pgtype.Text `json:"description"`
Content pgtype.Text `json:"content"` Content pgtype.Text `json:"content"`
@ -135,25 +135,25 @@ type Item struct {
Guid pgtype.Text `json:"guid"` Guid pgtype.Text `json:"guid"`
Categories []string `json:"categories"` Categories []string `json:"categories"`
Custom []byte `json:"custom"` Custom []byte `json:"custom"`
FeedID int32 `json:"feed_id"` FeedID int64 `json:"feed_id"`
} }
type ItemAuthor struct { type ItemAuthor struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Name pgtype.Text `json:"name"` Name pgtype.Text `json:"name"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
Uri pgtype.Text `json:"uri"` Uri pgtype.Text `json:"uri"`
ItemID int32 `json:"item_id"` ItemID int64 `json:"item_id"`
} }
type ItemDublinCore struct { type ItemDublinCore struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Title []string `json:"title"` Title []string `json:"title"`
Creator []string `json:"creator"` Creator []string `json:"creator"`
Author []string `json:"author"` Author []string `json:"author"`
@ -170,36 +170,36 @@ type ItemDublinCore struct {
Relation []string `json:"relation"` Relation []string `json:"relation"`
Coverage []string `json:"coverage"` Coverage []string `json:"coverage"`
Rights []string `json:"rights"` Rights []string `json:"rights"`
ItemID int32 `json:"item_id"` ItemID int64 `json:"item_id"`
} }
type ItemExtension struct { type ItemExtension struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Name pgtype.Text `json:"name"` Name pgtype.Text `json:"name"`
Value pgtype.Text `json:"value"` Value pgtype.Text `json:"value"`
Attrs []byte `json:"attrs"` Attrs []byte `json:"attrs"`
Children []byte `json:"children"` Children []byte `json:"children"`
ItemID int32 `json:"item_id"` ItemID int64 `json:"item_id"`
} }
type ItemImage struct { type ItemImage struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Url pgtype.Text `json:"url"` Url pgtype.Text `json:"url"`
Title pgtype.Text `json:"title"` Title pgtype.Text `json:"title"`
ItemID int32 `json:"item_id"` ItemID int64 `json:"item_id"`
} }
type ItemItune struct { type ItemItune struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Author pgtype.Text `json:"author"` Author pgtype.Text `json:"author"`
Block pgtype.Text `json:"block"` Block pgtype.Text `json:"block"`
Duration pgtype.Text `json:"duration"` Duration pgtype.Text `json:"duration"`
@ -213,25 +213,25 @@ type ItemItune struct {
Season pgtype.Text `json:"season"` Season pgtype.Text `json:"season"`
Order pgtype.Text `json:"order"` Order pgtype.Text `json:"order"`
EpisodeType pgtype.Text `json:"episode_type"` EpisodeType pgtype.Text `json:"episode_type"`
ItemID int32 `json:"item_id"` ItemID int64 `json:"item_id"`
} }
type ItunesCategory struct { type ItunesCategory struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamp `json:"deleted_at"`
Text pgtype.Text `json:"text"` Text pgtype.Text `json:"text"`
Subcategory pgtype.Text `json:"subcategory"` Subcategory pgtype.Text `json:"subcategory"`
ItunesID int32 `json:"itunes_id"` ItunesID int64 `json:"itunes_id"`
} }
type ItunesOwner struct { type ItunesOwner struct {
ID int32 `json:"id"` ID int64 `json:"id"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
DeletedAt pgtype.Timestamp `json:"deleted_at"` DeletedAt pgtype.Timestamp `json:"deleted_at"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
Name pgtype.Text `json:"name"` Name pgtype.Text `json:"name"`
ItunesID int32 `json:"itunes_id"` ItunesID int64 `json:"itunes_id"`
} }

View file

@ -10,7 +10,13 @@ import (
type Querier interface { type Querier interface {
CountFeeds(ctx context.Context) (int64, error) CountFeeds(ctx context.Context) (int64, error)
CountItems(ctx context.Context) (int64, error)
CreateFeed(ctx context.Context, arg CreateFeedParams) (Feed, error) CreateFeed(ctx context.Context, arg CreateFeedParams) (Feed, error)
CreateItem(ctx context.Context, arg CreateItemParams) (Item, error)
GetFeed(ctx context.Context, id int64) (Feed, error)
GetFeeds(ctx context.Context, arg GetFeedsParams) ([]Feed, error)
GetItem(ctx context.Context, id int64) (Item, error)
GetItems(ctx context.Context, arg GetItemsParams) ([]Item, error)
} }
var _ Querier = (*Queries)(nil) var _ Querier = (*Queries)(nil)

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"time" "time"
"github.com/TheLovinator1/FeedVault/db" "github.com/TheLovinator1/FeedVault/db"
@ -12,11 +13,6 @@ import (
) )
func makeCreateFeedParams(feedURL string, feed *gofeed.Feed) db.CreateFeedParams { func makeCreateFeedParams(feedURL string, feed *gofeed.Feed) db.CreateFeedParams {
links := make([]string, len(feed.Items))
for i, item := range feed.Items {
links[i] = item.Link
}
var updatedTime time.Time var updatedTime time.Time
if feed.UpdatedParsed != nil { if feed.UpdatedParsed != nil {
updatedTime = *feed.UpdatedParsed updatedTime = *feed.UpdatedParsed
@ -32,20 +28,20 @@ func makeCreateFeedParams(feedURL string, feed *gofeed.Feed) db.CreateFeedParams
feedCustom = []byte("{}") feedCustom = []byte("{}")
} }
return db.CreateFeedParams{ params := db.CreateFeedParams{
Url: feedURL, Url: feedURL,
CreatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, CreatedAt: pgtype.Timestamptz{Time: time.Now(), Valid: true},
UpdatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, UpdatedAt: pgtype.Timestamptz{Time: time.Now(), Valid: true},
DeletedAt: pgtype.Timestamp{Valid: false}, DeletedAt: pgtype.Timestamptz{Valid: false},
Title: pgtype.Text{String: feed.Title, Valid: feed.Title != ""}, Title: pgtype.Text{String: feed.Title, Valid: feed.Title != ""},
Description: pgtype.Text{String: feed.Description, Valid: feed.Description != ""}, Description: pgtype.Text{String: feed.Description, Valid: feed.Description != ""},
Link: pgtype.Text{String: feed.Link, Valid: feed.Link != ""}, Link: pgtype.Text{String: feed.Link, Valid: feed.Link != ""},
FeedLink: pgtype.Text{String: feed.FeedLink, Valid: feed.FeedLink != ""}, FeedLink: pgtype.Text{String: feed.FeedLink, Valid: feed.FeedLink != ""},
Links: links, Links: feed.Links,
Updated: pgtype.Text{String: feed.Updated, Valid: feed.Updated != ""}, Updated: pgtype.Text{String: feed.Updated, Valid: feed.Updated != ""},
UpdatedParsed: pgtype.Timestamp{Time: updatedTime, Valid: !updatedTime.IsZero()}, UpdatedParsed: pgtype.Timestamptz{Time: updatedTime, Valid: !updatedTime.IsZero()},
Published: pgtype.Text{String: feed.Published, Valid: feed.Published != ""}, Published: pgtype.Text{String: feed.Published, Valid: feed.Published != ""},
PublishedParsed: pgtype.Timestamp{Time: publishedTime, Valid: !publishedTime.IsZero()}, PublishedParsed: pgtype.Timestamptz{Time: publishedTime, Valid: !publishedTime.IsZero()},
Language: pgtype.Text{String: feed.Language, Valid: feed.Language != ""}, Language: pgtype.Text{String: feed.Language, Valid: feed.Language != ""},
Copyright: pgtype.Text{String: feed.Copyright, Valid: feed.Copyright != ""}, Copyright: pgtype.Text{String: feed.Copyright, Valid: feed.Copyright != ""},
Generator: pgtype.Text{String: feed.Generator, Valid: feed.Generator != ""}, Generator: pgtype.Text{String: feed.Generator, Valid: feed.Generator != ""},
@ -54,6 +50,45 @@ func makeCreateFeedParams(feedURL string, feed *gofeed.Feed) db.CreateFeedParams
FeedType: pgtype.Text{String: feed.FeedType, Valid: feed.FeedType != ""}, FeedType: pgtype.Text{String: feed.FeedType, Valid: feed.FeedType != ""},
FeedVersion: pgtype.Text{String: feed.FeedVersion, Valid: feed.FeedVersion != ""}, FeedVersion: pgtype.Text{String: feed.FeedVersion, Valid: feed.FeedVersion != ""},
} }
log.Printf("Created feed params: %+v", params)
return params
}
func makeCreateItemParams(item *gofeed.Item, feedID int64) db.CreateItemParams {
itemCustom := []byte("{}")
if item.Custom != nil {
var err error
itemCustom, err = json.Marshal(item.Custom)
if err != nil {
fmt.Println("Error marshalling item custom data:", err)
itemCustom = []byte("{}")
}
}
params := db.CreateItemParams{
CreatedAt: pgtype.Timestamptz{Time: time.Now(), Valid: true},
UpdatedAt: pgtype.Timestamptz{Time: time.Now(), Valid: true},
DeletedAt: pgtype.Timestamptz{Valid: false},
Title: pgtype.Text{String: item.Title, Valid: item.Title != ""},
Description: pgtype.Text{String: item.Description, Valid: item.Description != ""},
Content: pgtype.Text{String: item.Content, Valid: item.Content != ""},
Link: pgtype.Text{String: item.Link, Valid: item.Link != ""},
Links: item.Links,
Updated: pgtype.Text{String: item.Updated, Valid: item.Updated != ""},
UpdatedParsed: pgtype.Timestamp{Time: *item.UpdatedParsed, Valid: item.UpdatedParsed != nil},
Published: pgtype.Text{String: item.Published, Valid: item.Published != ""},
PublishedParsed: pgtype.Timestamp{Time: *item.PublishedParsed, Valid: item.PublishedParsed != nil},
Guid: pgtype.Text{String: item.GUID, Valid: item.GUID != ""},
Categories: item.Categories,
Custom: itemCustom,
FeedID: feedID,
}
log.Printf("Created item params: %+v", params)
return params
} }
func AddFeedToDB(feedURL string) error { func AddFeedToDB(feedURL string) error {
@ -71,10 +106,19 @@ func AddFeedToDB(feedURL string) error {
} }
// Add the feed to the database // Add the feed to the database
_, err = DB.CreateFeed(ctx, makeCreateFeedParams(feedURL, feed)) newFeed, err := DB.CreateFeed(ctx, makeCreateFeedParams(feedURL, feed))
if err != nil { if err != nil {
return fmt.Errorf("Error adding feed to database: %s", err) return fmt.Errorf("Error adding feed to database: %s", err)
} }
log.Printf("Added feed to database: %+v", newFeed)
// Add the items to the database
for _, item := range feed.Items {
_, err := DB.CreateItem(ctx, makeCreateItemParams(item, newFeed.ID))
if err != nil {
log.Printf("Error adding item to database: %s", err)
}
}
fmt.Println(feed.Title) fmt.Println(feed.Title)
return nil return nil

View file

@ -1,11 +1,15 @@
package main package main
import ( import (
"context"
"io" "io"
"log" "log"
"net/http" "net/http"
"strconv"
"strings" "strings"
"github.com/TheLovinator1/FeedVault/db"
) )
func ApiHandler(w http.ResponseWriter, _ *http.Request) { func ApiHandler(w http.ResponseWriter, _ *http.Request) {
@ -25,16 +29,31 @@ func ApiHandler(w http.ResponseWriter, _ *http.Request) {
} }
func FeedsHandler(w http.ResponseWriter, _ *http.Request) { func FeedsHandler(w http.ResponseWriter, _ *http.Request) {
feeds, err := DB.GetFeeds(context.Background(), db.GetFeedsParams{
Limit: 100,
})
if err != nil {
http.Error(w, "Error getting feeds", http.StatusInternalServerError)
return
}
fb := strings.Builder{}
for _, feed := range feeds {
fb.WriteString("<li>")
fb.WriteString("<a href=\"/feed/" + strconv.FormatInt(feed.ID, 10) + "\">" + feed.Title.String + "</a> - <a href=\"" + feed.Link.String + "\">" + feed.Link.String + "</a>")
fb.WriteString("</li>")
}
htmlData := HTMLData{ htmlData := HTMLData{
Title: "FeedVault Feeds", Title: "FeedVault Feeds",
Description: "FeedVault Feeds - A feed archive", Description: "FeedVault Feeds - A feed archive",
Keywords: "RSS, Atom, Feed, Archive", Keywords: "RSS, Atom, Feed, Archive",
Author: "TheLovinator", Author: "TheLovinator",
CanonicalURL: "http://localhost:8000/feeds", CanonicalURL: "http://localhost:8000/feeds",
Content: "<p>No feeds yet.</p>", Content: "<ul>" + fb.String() + "</ul>",
} }
html := FullHTML(htmlData) html := FullHTML(htmlData)
_, err := w.Write([]byte(html)) _, err = w.Write([]byte(html))
if err != nil { if err != nil {
log.Println("Error writing response:", err) log.Println("Error writing response:", err)
} }
@ -226,3 +245,71 @@ func UploadOpmlHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Error writing response:", err) log.Println("Error writing response:", err)
} }
} }
func FeedHandler(w http.ResponseWriter, r *http.Request) {
// Get the feed ID from the URL
parts := strings.Split(r.URL.Path, "/")
if len(parts) < 3 {
http.Error(w, "No feed ID provided", http.StatusBadRequest)
return
}
feedID, err := strconv.ParseInt(parts[2], 10, 64)
if err != nil {
http.Error(w, "Invalid feed ID", http.StatusBadRequest)
return
}
// Get the feed from the database
feed, err := DB.GetFeed(context.Background(), feedID)
if err != nil {
http.Error(w, "Error getting feed", http.StatusInternalServerError)
return
}
// Get the items for the feed
items, err := DB.GetItems(context.Background(), db.GetItemsParams{
FeedID: feedID,
Limit: 100,
})
if err != nil {
http.Error(w, "Error getting items", http.StatusInternalServerError)
return
}
// Build the HTML
fb := strings.Builder{}
for _, item := range items {
fb.WriteString("<li>")
fb.WriteString("<a href=\"" + item.Link.String + "\">" + item.Title.String + "</a>")
fb.WriteString("<ul>")
if item.Published.Valid {
fb.WriteString("<li>Published: " + item.Published.String + "</li>")
}
if item.Updated.Valid {
fb.WriteString("<li>Updated: " + item.Updated.String + "</li>")
}
if item.Description.Valid {
fb.WriteString("<li>" + item.Description.String + "</li>")
}
if item.Content.Valid {
fb.WriteString("<li>" + item.Content.String + "</li>")
}
fb.WriteString("</ul>")
fb.WriteString("<hr>")
fb.WriteString("</li>")
}
htmlData := HTMLData{
Title: feed.Title.String,
Description: feed.Description.String,
Keywords: "RSS, Atom, Feed, Archive",
Author: "TheLovinator",
CanonicalURL: "http://localhost:8000/feed/" + strconv.FormatInt(feed.ID, 10),
Content: "<ul>" + fb.String() + "</ul>",
}
html := FullHTML(htmlData)
_, err = w.Write([]byte(html))
if err != nil {
log.Println("Error writing response:", err)
}
}

View file

@ -41,6 +41,7 @@ func main() {
mux.HandleFunc("/", IndexHandler) mux.HandleFunc("/", IndexHandler)
mux.HandleFunc("/api", ApiHandler) mux.HandleFunc("/api", ApiHandler)
mux.HandleFunc("/feeds", FeedsHandler) mux.HandleFunc("/feeds", FeedsHandler)
mux.HandleFunc("/feed/", FeedHandler)
mux.HandleFunc("/add", AddFeedHandler) mux.HandleFunc("/add", AddFeedHandler)
mux.HandleFunc("/upload_opml", UploadOpmlHandler) mux.HandleFunc("/upload_opml", UploadOpmlHandler)

View file

@ -51,3 +51,87 @@ SELECT
COUNT(*) COUNT(*)
FROM FROM
feeds; feeds;
-- name: CreateItem :one
INSERT INTO
items (
created_at,
updated_at,
deleted_at,
title,
"description",
content,
link,
links,
updated,
updated_parsed,
published,
published_parsed,
"guid",
categories,
custom,
feed_id
)
VALUES
(
$1,
$2,
$3,
$4,
$5,
$6,
$7,
$8,
$9,
$10,
$11,
$12,
$13,
$14,
$15,
$16
) RETURNING *;
-- name: CountItems :one
SELECT
COUNT(*)
FROM
items;
-- name: GetFeed :one
SELECT
*
FROM
feeds
WHERE
id = $1;
-- name: GetFeeds :many
SELECT
*
FROM
feeds
ORDER BY
created_at DESC
LIMIT $1
OFFSET $2;
-- name: GetItem :one
SELECT
*
FROM
items
WHERE
id = $1;
-- name: GetItems :many
SELECT
*
FROM
items
WHERE
feed_id = $1
ORDER BY
created_at DESC
LIMIT $2
OFFSET $3;

View file

@ -2,11 +2,11 @@
-- +goose StatementBegin -- +goose StatementBegin
-- Create table feeds if not exists -- Create table feeds if not exists
CREATE TABLE IF NOT EXISTS feeds ( CREATE TABLE IF NOT EXISTS feeds (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
"url" TEXT NOT NULL, "url" TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: https://github.com/mmcdole/gofeed/blob/master/feed.go -- From gofeed: https://github.com/mmcdole/gofeed/blob/master/feed.go
title TEXT, title TEXT,
"description" TEXT, "description" TEXT,
@ -14,9 +14,9 @@ CREATE TABLE IF NOT EXISTS feeds (
feed_link TEXT, feed_link TEXT,
links TEXT [], links TEXT [],
updated TEXT, updated TEXT,
updated_parsed TIMESTAMP, updated_parsed TIMESTAMPTZ,
published TEXT, published TEXT,
published_parsed TIMESTAMP, published_parsed TIMESTAMPTZ,
-- Authors - See feed_authors -- Authors - See feed_authors
"language" TEXT, "language" TEXT,
-- Image - See feed_images -- Image - See feed_images
@ -35,10 +35,10 @@ CREATE TABLE IF NOT EXISTS feeds (
-- Feed item -- Feed item
-- https://github.com/mmcdole/gofeed/blob/master/feed.go#L49 -- https://github.com/mmcdole/gofeed/blob/master/feed.go#L49
CREATE TABLE IF NOT EXISTS items ( CREATE TABLE IF NOT EXISTS items (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
title TEXT, title TEXT,
"description" TEXT, "description" TEXT,
@ -59,7 +59,7 @@ CREATE TABLE IF NOT EXISTS items (
-- Extensions - See item_extensions -- Extensions - See item_extensions
custom JSONB, custom JSONB,
-- Link to feed -- Link to feed
feed_id INTEGER NOT NULL, feed_id BIGINT NOT NULL,
CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE
); );

View file

@ -3,34 +3,34 @@
-- Extensions for feeds -- Extensions for feeds
-- https://github.com/mmcdole/gofeed/blob/master/extensions/extensions.go#L3 -- https://github.com/mmcdole/gofeed/blob/master/extensions/extensions.go#L3
CREATE TABLE IF NOT EXISTS feed_extensions ( CREATE TABLE IF NOT EXISTS feed_extensions (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
"name" TEXT, "name" TEXT,
"value" TEXT, "value" TEXT,
attrs JSONB, attrs JSONB,
children JSONB, children JSONB,
-- Link to feed -- Link to feed
feed_id INTEGER NOT NULL, feed_id BIGINT NOT NULL,
CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE
); );
-- Extensions for items -- Extensions for items
-- https://github.com/mmcdole/gofeed/blob/master/extensions/extensions.go#L3 -- https://github.com/mmcdole/gofeed/blob/master/extensions/extensions.go#L3
CREATE TABLE IF NOT EXISTS item_extensions ( CREATE TABLE IF NOT EXISTS item_extensions (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
"name" TEXT, "name" TEXT,
"value" TEXT, "value" TEXT,
attrs JSONB, attrs JSONB,
children JSONB, children JSONB,
-- Link to feed item (Also called feed entry) -- Link to feed item (Also called feed entry)
item_id INTEGER NOT NULL, item_id BIGINT NOT NULL,
CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE
); );

View file

@ -3,32 +3,32 @@
-- Person for feeds -- Person for feeds
-- https://github.com/mmcdole/gofeed/blob/master/feed.go#L73 -- https://github.com/mmcdole/gofeed/blob/master/feed.go#L73
CREATE TABLE IF NOT EXISTS feed_authors ( CREATE TABLE IF NOT EXISTS feed_authors (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
"name" TEXT, "name" TEXT,
email TEXT, email TEXT,
uri TEXT, uri TEXT,
-- Link to feed -- Link to feed
feed_id INTEGER NOT NULL, feed_id BIGINT NOT NULL,
CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE
); );
-- Person for items -- Person for items
-- https://github.com/mmcdole/gofeed/blob/master/feed.go#L73 -- https://github.com/mmcdole/gofeed/blob/master/feed.go#L73
CREATE TABLE IF NOT EXISTS item_authors ( CREATE TABLE IF NOT EXISTS item_authors (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
"name" TEXT, "name" TEXT,
email TEXT, email TEXT,
uri TEXT, uri TEXT,
-- Link to feed item (Also called feed entry) -- Link to feed item (Also called feed entry)
item_id INTEGER NOT NULL, item_id BIGINT NOT NULL,
CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE
); );

View file

@ -3,30 +3,30 @@
-- Image for feeds -- Image for feeds
-- https://github.com/mmcdole/gofeed/blob/master/feed.go#L80 -- https://github.com/mmcdole/gofeed/blob/master/feed.go#L80
CREATE TABLE IF NOT EXISTS feed_images ( CREATE TABLE IF NOT EXISTS feed_images (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
"url" TEXT, "url" TEXT,
title TEXT, title TEXT,
-- Link to feed -- Link to feed
feed_id INTEGER NOT NULL, feed_id BIGINT NOT NULL,
CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE
); );
-- Image for items -- Image for items
-- https://github.com/mmcdole/gofeed/blob/master/feed.go#L80 -- https://github.com/mmcdole/gofeed/blob/master/feed.go#L80
CREATE TABLE IF NOT EXISTS item_images ( CREATE TABLE IF NOT EXISTS item_images (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
"url" TEXT, "url" TEXT,
title TEXT, title TEXT,
-- Link to feed item (Also called feed entry) -- Link to feed item (Also called feed entry)
item_id INTEGER NOT NULL, item_id BIGINT NOT NULL,
CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE
); );

View file

@ -3,10 +3,10 @@
-- Dublin Core for feeds -- Dublin Core for feeds
-- https://github.com/mmcdole/gofeed/blob/master/extensions/dublincore.go#L5 -- https://github.com/mmcdole/gofeed/blob/master/extensions/dublincore.go#L5
CREATE TABLE IF NOT EXISTS feed_dublin_cores ( CREATE TABLE IF NOT EXISTS feed_dublin_cores (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
title TEXT [], title TEXT [],
creator TEXT [], creator TEXT [],
@ -25,17 +25,17 @@ CREATE TABLE IF NOT EXISTS feed_dublin_cores (
coverage TEXT [], coverage TEXT [],
rights TEXT [], rights TEXT [],
-- Link to feed -- Link to feed
feed_id INTEGER NOT NULL, feed_id BIGINT NOT NULL,
CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE
); );
-- Dublin Core for items -- Dublin Core for items
-- https://github.com/mmcdole/gofeed/blob/master/extensions/dublincore.go#L5 -- https://github.com/mmcdole/gofeed/blob/master/extensions/dublincore.go#L5
CREATE TABLE IF NOT EXISTS item_dublin_cores ( CREATE TABLE IF NOT EXISTS item_dublin_cores (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
title TEXT [], title TEXT [],
creator TEXT [], creator TEXT [],
@ -54,7 +54,7 @@ CREATE TABLE IF NOT EXISTS item_dublin_cores (
coverage TEXT [], coverage TEXT [],
rights TEXT [], rights TEXT [],
-- Link to feed item (Also called feed entry) -- Link to feed item (Also called feed entry)
item_id INTEGER NOT NULL, item_id BIGINT NOT NULL,
CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE
); );

View file

@ -3,10 +3,10 @@
-- Itunes for feeds -- Itunes for feeds
-- https://github.com/mmcdole/gofeed/blob/master/extensions/itunes.go#L5 -- https://github.com/mmcdole/gofeed/blob/master/extensions/itunes.go#L5
CREATE TABLE IF NOT EXISTS feed_itunes ( CREATE TABLE IF NOT EXISTS feed_itunes (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
author TEXT, author TEXT,
"block" TEXT, "block" TEXT,
@ -20,17 +20,17 @@ CREATE TABLE IF NOT EXISTS feed_itunes (
new_feed_url TEXT, new_feed_url TEXT,
"type" TEXT, "type" TEXT,
-- Link to feed -- Link to feed
feed_id INTEGER NOT NULL, feed_id BIGINT NOT NULL,
CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE CONSTRAINT fk_feed_id FOREIGN KEY (feed_id) REFERENCES feeds (id) ON DELETE CASCADE
); );
-- Itunes for items -- Itunes for items
-- https://github.com/mmcdole/gofeed/blob/master/extensions/itunes.go#L22 -- https://github.com/mmcdole/gofeed/blob/master/extensions/itunes.go#L22
CREATE TABLE IF NOT EXISTS item_itunes ( CREATE TABLE IF NOT EXISTS item_itunes (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
author TEXT, author TEXT,
"block" TEXT, "block" TEXT,
@ -46,14 +46,14 @@ CREATE TABLE IF NOT EXISTS item_itunes (
"order" TEXT, "order" TEXT,
episode_type TEXT, episode_type TEXT,
-- Link to feed item (Also called feed entry) -- Link to feed item (Also called feed entry)
item_id INTEGER NOT NULL, item_id BIGINT NOT NULL,
CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE
); );
-- Itunes categories -- Itunes categories
-- https://github.com/mmcdole/gofeed/blob/master/extensions/itunes.go#L39 -- https://github.com/mmcdole/gofeed/blob/master/extensions/itunes.go#L39
CREATE TABLE IF NOT EXISTS itunes_categories ( CREATE TABLE IF NOT EXISTS itunes_categories (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMP DEFAULT NULL,
@ -61,14 +61,14 @@ CREATE TABLE IF NOT EXISTS itunes_categories (
"text" TEXT, "text" TEXT,
subcategory TEXT, subcategory TEXT,
-- Link to itunes -- Link to itunes
itunes_id INTEGER NOT NULL, itunes_id BIGINT NOT NULL,
CONSTRAINT fk_itunes_id FOREIGN KEY (itunes_id) REFERENCES feed_itunes (id) ON DELETE CASCADE CONSTRAINT fk_itunes_id FOREIGN KEY (itunes_id) REFERENCES feed_itunes (id) ON DELETE CASCADE
); );
-- Itunes owners -- Itunes owners
-- https://github.com/mmcdole/gofeed/blob/master/extensions/itunes.go#L45 -- https://github.com/mmcdole/gofeed/blob/master/extensions/itunes.go#L45
CREATE TABLE IF NOT EXISTS itunes_owners ( CREATE TABLE IF NOT EXISTS itunes_owners (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMP DEFAULT NULL,
@ -76,7 +76,7 @@ CREATE TABLE IF NOT EXISTS itunes_owners (
email TEXT, email TEXT,
"name" TEXT, "name" TEXT,
-- Link to itunes -- Link to itunes
itunes_id INTEGER NOT NULL, itunes_id BIGINT NOT NULL,
CONSTRAINT fk_itunes_id FOREIGN KEY (itunes_id) REFERENCES feed_itunes (id) ON DELETE CASCADE CONSTRAINT fk_itunes_id FOREIGN KEY (itunes_id) REFERENCES feed_itunes (id) ON DELETE CASCADE
); );

View file

@ -3,16 +3,16 @@
-- Enclosures -- Enclosures
-- https://github.com/mmcdole/gofeed/blob/master/feed.go#L86 -- https://github.com/mmcdole/gofeed/blob/master/feed.go#L86
CREATE TABLE IF NOT EXISTS enclosures ( CREATE TABLE IF NOT EXISTS enclosures (
id SERIAL PRIMARY KEY, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMPTZ DEFAULT NULL,
-- From gofeed: -- From gofeed:
"url" TEXT, "url" TEXT,
"length" TEXT, "length" TEXT,
"type" TEXT, "type" TEXT,
-- Link to feed item (Also called feed entry) -- Link to feed item (Also called feed entry)
item_id INTEGER NOT NULL, item_id BIGINT NOT NULL,
CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE CONSTRAINT fk_item_id FOREIGN KEY (item_id) REFERENCES items (id) ON DELETE CASCADE
); );