Add gorm models

This commit is contained in:
Joakim Hellsén 2024-02-04 01:53:49 +01:00
commit 6add647ec7
8 changed files with 266 additions and 9 deletions

3
.gitignore vendored
View file

@ -20,3 +20,6 @@ tmp/
# Environment variables file # Environment variables file
.env .env
# Database
*.db

View file

@ -8,9 +8,12 @@
"feedparser", "feedparser",
"feedvault", "feedvault",
"gaierror", "gaierror",
"gofeed",
"gorm",
"leftright", "leftright",
"levelname", "levelname",
"listparser", "listparser",
"mmcdole",
"Monero", "Monero",
"PGHOST", "PGHOST",
"PGPORT", "PGPORT",

34
db.go Normal file
View file

@ -0,0 +1,34 @@
package main
import (
"fmt"
"log"
"os"
)
// Get the size of the database and return as nearest human readable size
func GetDBSize() string {
fileInfo, err := os.Stat("feedvault.db")
if err != nil {
log.Println("Error getting file info:", err)
return "0 B"
}
// Get the file size in bytes
fileSize := fileInfo.Size()
// Convert to human readable size and append the unit (KB, MB, GB)
var size float64
if fileSize < 1024*1024 {
size = float64(fileSize) / 1024
return fmt.Sprintf("%.2f KB", size)
}
if fileSize < 1024*1024*1024 {
size = float64(fileSize) / (1024 * 1024)
return fmt.Sprintf("%.2f MB", size)
}
size = float64(fileSize) / (1024 * 1024 * 1024)
return fmt.Sprintf("%.2f GB", size)
}

13
go.mod
View file

@ -2,4 +2,15 @@ module github.com/TheLovinator1/FeedVault
go 1.21.6 go 1.21.6
require github.com/go-chi/chi/v5 v5.0.11 require (
github.com/go-chi/chi/v5 v5.0.11
github.com/mmcdole/gofeed v1.2.1
gorm.io/driver/sqlite v1.5.4
gorm.io/gorm v1.25.6
)
require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
)

36
go.sum
View file

@ -1,2 +1,38 @@
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mmcdole/gofeed v1.2.1 h1:tPbFN+mfOLcM1kDF1x2c/N68ChbdBatkppdzf/vDe1s=
github.com/mmcdole/gofeed v1.2.1/go.mod h1:2wVInNpgmC85q16QTTuwbuKxtKkHLCDDtf0dCmnrNr4=
github.com/mmcdole/goxpp v1.1.0 h1:WwslZNF7KNAXTFuzRtn/OKZxFLJAAyOA9w82mDz2ZGI=
github.com/mmcdole/goxpp v1.1.0/go.mod h1:v+25+lT2ViuQ7mVxcncQ8ch1URund48oH+jhjiwEgS8=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0=
gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
gorm.io/gorm v1.25.6 h1:V92+vVda1wEISSOMtodHVRcUIOPYa2tgQtyF+DfFx+A=
gorm.io/gorm v1.25.6/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=

27
main.go
View file

@ -8,9 +8,27 @@ import (
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
) )
// Database connection
var db *gorm.DB
func main() { func main() {
log.Println("Starting FeedVault...")
db, err := gorm.Open(sqlite.Open("feedvault.db"), &gorm.Config{})
if err != nil {
panic("Failed to connect to database")
}
// Migrate the schema
err = db.AutoMigrate(&Feed{}, &Item{}, &Person{}, &Image{}, &Enclosure{}, &DublinCoreExtension{}, &ITunesFeedExtension{}, &ITunesItemExtension{}, &ITunesCategory{}, &ITunesOwner{}, &Extension{})
if err != nil {
panic("Failed to migrate the database")
}
// Create a new router
r := chi.NewRouter() r := chi.NewRouter()
r.Use(middleware.RealIP) r.Use(middleware.RealIP)
r.Use(middleware.Logger) r.Use(middleware.Logger)
@ -40,16 +58,12 @@ type Data struct {
Author string Author string
CanonicalURL string CanonicalURL string
FeedCount int FeedCount int
DatabaseSize int DatabaseSize string
Request *http.Request Request *http.Request
} }
func (d *Data) GetDatabaseSizeAndFeedCount() { func (d *Data) GetDatabaseSizeAndFeedCount() {
// Set the database size to 0 d.DatabaseSize = GetDBSize()
d.DatabaseSize = 0
// Set the feed count to 0
d.FeedCount = 0
} }
func renderPage(w http.ResponseWriter, title, description, keywords, author, url, templateName string) { func renderPage(w http.ResponseWriter, title, description, keywords, author, url, templateName string) {
@ -60,7 +74,6 @@ func renderPage(w http.ResponseWriter, title, description, keywords, author, url
Author: author, Author: author,
CanonicalURL: url, CanonicalURL: url,
FeedCount: 0, FeedCount: 0,
DatabaseSize: 0,
} }
data.GetDatabaseSizeAndFeedCount() data.GetDatabaseSizeAndFeedCount()

157
models.go Normal file
View file

@ -0,0 +1,157 @@
package main
import (
"time"
"gorm.io/gorm"
)
type Feed struct {
gorm.Model
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Link string `json:"link,omitempty"`
FeedLink string `json:"feedLink,omitempty"`
Links []string `gorm:"type:text[]" json:"links,omitempty"`
Updated string `json:"updated,omitempty"`
UpdatedParsed *time.Time `json:"updatedParsed,omitempty"`
Published string `json:"published,omitempty"`
PublishedParsed *time.Time `json:"publishedParsed,omitempty"`
Authors []*Person `gorm:"many2many:feed_authors;" json:"authors,omitempty"`
Language string `json:"language,omitempty"`
Image *Image `gorm:"foreignKey:ID" json:"image,omitempty"`
Copyright string `json:"copyright,omitempty"`
Generator string `json:"generator,omitempty"`
Categories []string `gorm:"type:text[]" json:"categories,omitempty"`
DublinCoreExt *DublinCoreExtension `gorm:"foreignKey:ID" json:"dcExt,omitempty"`
ITunesExt *ITunesFeedExtension `gorm:"foreignKey:ID" json:"itunesExt,omitempty"`
Extensions Extensions `gorm:"type:json" json:"extensions,omitempty"`
Custom map[string]string `gorm:"type:json" json:"custom,omitempty"`
Items []*Item `gorm:"foreignKey:ID" json:"items,omitempty"`
FeedType string `json:"feedType"`
FeedVersion string `json:"feedVersion"`
}
type Item struct {
gorm.Model
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Content string `json:"content,omitempty"`
Link string `json:"link,omitempty"`
Links []string `gorm:"type:text[]" json:"links,omitempty"`
Updated string `json:"updated,omitempty"`
UpdatedParsed *time.Time `json:"updatedParsed,omitempty"`
Published string `json:"published,omitempty"`
PublishedParsed *time.Time `json:"publishedParsed,omitempty"`
Authors []*Person `gorm:"many2many:item_authors;" json:"authors,omitempty"`
GUID string `json:"guid,omitempty"`
Image *Image `gorm:"foreignKey:ID" json:"image,omitempty"`
Categories []string `gorm:"type:text[]" json:"categories,omitempty"`
Enclosures []*Enclosure `gorm:"foreignKey:ID" json:"enclosures,omitempty"`
DublinCoreExt *DublinCoreExtension `gorm:"foreignKey:ID" json:"dcExt,omitempty"`
ITunesExt *ITunesFeedExtension `gorm:"foreignKey:ID" json:"itunesExt,omitempty"`
Extensions Extensions `gorm:"type:json" json:"extensions,omitempty"`
Custom map[string]string `gorm:"type:json" json:"custom,omitempty"`
}
type Person struct {
gorm.Model
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
}
func (Person) TableName() string {
return "feed_authors"
}
type Image struct {
gorm.Model
URL string `json:"url,omitempty"`
Title string `json:"title,omitempty"`
}
type Enclosure struct {
gorm.Model
URL string `json:"url,omitempty"`
Length string `json:"length,omitempty"`
Type string `json:"type,omitempty"`
}
type DublinCoreExtension struct {
gorm.Model
Title []string `gorm:"type:text[]" json:"title,omitempty"`
Creator []string `gorm:"type:text[]" json:"creator,omitempty"`
Author []string `gorm:"type:text[]" json:"author,omitempty"`
Subject []string `gorm:"type:text[]" json:"subject,omitempty"`
Description []string `gorm:"type:text[]" json:"description,omitempty"`
Publisher []string `gorm:"type:text[]" json:"publisher,omitempty"`
Contributor []string `gorm:"type:text[]" json:"contributor,omitempty"`
Date []string `gorm:"type:text[]" json:"date,omitempty"`
Type []string `gorm:"type:text[]" json:"type,omitempty"`
Format []string `gorm:"type:text[]" json:"format,omitempty"`
Identifier []string `gorm:"type:text[]" json:"identifier,omitempty"`
Source []string `gorm:"type:text[]" json:"source,omitempty"`
Language []string `gorm:"type:text[]" json:"language,omitempty"`
Relation []string `gorm:"type:text[]" json:"relation,omitempty"`
Coverage []string `gorm:"type:text[]" json:"coverage,omitempty"`
Rights []string `gorm:"type:text[]" json:"rights,omitempty"`
}
type ITunesFeedExtension struct {
gorm.Model
Author string `json:"author,omitempty"`
Block string `json:"block,omitempty"`
Categories []*ITunesCategory `gorm:"many2many:feed_itunes_categories;" json:"categories,omitempty"`
Explicit string `json:"explicit,omitempty"`
Keywords string `json:"keywords,omitempty"`
Owner *ITunesOwner `gorm:"foreignKey:ID" json:"owner,omitempty"`
Subtitle string `json:"subtitle,omitempty"`
Summary string `json:"summary,omitempty"`
Image string `json:"image,omitempty"`
Complete string `json:"complete,omitempty"`
NewFeedURL string `json:"newFeedUrl,omitempty"`
Type string `json:"type,omitempty"`
}
type ITunesItemExtension struct {
gorm.Model
Author string `json:"author,omitempty"`
Block string `json:"block,omitempty"`
Duration string `json:"duration,omitempty"`
Explicit string `json:"explicit,omitempty"`
Keywords string `json:"keywords,omitempty"`
Subtitle string `json:"subtitle,omitempty"`
Summary string `json:"summary,omitempty"`
Image string `json:"image,omitempty"`
IsClosedCaptioned string `json:"isClosedCaptioned,omitempty"`
Episode string `json:"episode,omitempty"`
Season string `json:"season,omitempty"`
Order string `json:"order,omitempty"`
EpisodeType string `json:"episodeType,omitempty"`
}
type ITunesCategory struct {
gorm.Model
Text string `json:"text,omitempty"`
Subcategory *ITunesCategory `gorm:"many2many:feed_itunes_categories;" json:"subcategory,omitempty"`
}
func (ITunesCategory) TableName() string {
return "feed_itunes_categories"
}
type ITunesOwner struct {
gorm.Model
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
}
type Extensions map[string]map[string][]Extension
type Extension struct {
gorm.Model
Name string `json:"name"`
Value string `json:"value"`
Attrs map[string]string `gorm:"type:json" json:"attrs"`
Children map[string][]Extension `gorm:"type:json" json:"children"`
}

View file

@ -20,7 +20,7 @@
</span> </span>
<div class="leftright"> <div class="leftright">
<div class="left"> <div class="left">
<small>Archive of <a href="https://en.wikipedia.org/wiki/Web_feed">web feeds</a>. {{ .FeedCount }} feeds. ~{{ .DatabaseSize }} MB.</small> <small>Archive of <a href="https://en.wikipedia.org/wiki/Web_feed">web feeds</a>. {{ .FeedCount }} feeds. ~{{ .DatabaseSize }}</small>
</div> </div>
<div class="right"> <div class="right">
<!-- Search --> <!-- Search -->