Compare commits
7 Commits
c2ab455d3e
...
f798869ef5
Author | SHA1 | Date | |
---|---|---|---|
f798869ef5 | |||
598ca747eb | |||
b8e29de4fc | |||
fefc777888 | |||
f940f22d67 | |||
0e6a8fd61e | |||
e62280a416 |
68
pkg/database/client.go
Normal file
68
pkg/database/client.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||||
|
migrate "github.com/rubenv/sql-migrate"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed migrations/*.sql
|
||||||
|
var embedMigrations embed.FS
|
||||||
|
var client *gorm.DB
|
||||||
|
|
||||||
|
func Connect(_ context.Context, config models.DatabaseConfig) error {
|
||||||
|
var localSSL string
|
||||||
|
|
||||||
|
if config.SSL {
|
||||||
|
localSSL = "require"
|
||||||
|
} else {
|
||||||
|
localSSL = "disable"
|
||||||
|
}
|
||||||
|
|
||||||
|
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", config.Endpoint, config.Username, config.Password, config.Database, config.Port, localSSL, config.Timezone)
|
||||||
|
sqlDB, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client = sqlDB
|
||||||
|
err = migrateDatabase(sqlDB, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func migrateDatabase(dbPool *gorm.DB, config models.DatabaseConfig) error {
|
||||||
|
dialect := "postgres"
|
||||||
|
migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"}
|
||||||
|
|
||||||
|
db, err := dbPool.DB()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("postgres migration: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := migrate.Exec(db, dialect, migrations, migrate.Up)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("postgres migration: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Debug {
|
||||||
|
if n != 0 {
|
||||||
|
log.Infof("postgres migration: applied %d migrations!", n)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.Info("postgres migration: nothing to migrate")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type OtterSpace interface {
|
|
||||||
// Connect establishes a connection to the database.
|
|
||||||
Connect(ctx context.Context, config models.DatabaseConfig) error
|
|
||||||
|
|
||||||
// Post contains all function that are needed to manage Posts
|
|
||||||
Post
|
|
||||||
|
|
||||||
// User contains all function that are needed to manage the AnthroveUser
|
|
||||||
User
|
|
||||||
|
|
||||||
// Source contains all function that are needed to manage the Source
|
|
||||||
Source
|
|
||||||
|
|
||||||
// Tag contains all functions that are used to manage Tag
|
|
||||||
Tag
|
|
||||||
|
|
||||||
// TagAlias contains all function that are needed to manage the TagAlias
|
|
||||||
TagAlias
|
|
||||||
|
|
||||||
// TagGroup contains all function that are needed to manage the TagGroup
|
|
||||||
TagGroup
|
|
||||||
|
|
||||||
// ExecuteRawStatement run a custom query.
|
|
||||||
ExecuteRawStatement(ctx context.Context, query string, args ...any) error
|
|
||||||
|
|
||||||
// QueryRawStatement runs a custom query and returns the table
|
|
||||||
QueryRawStatement(ctx context.Context, query string, args ...any) (*sql.Rows, error)
|
|
||||||
}
|
|
@ -18,7 +18,7 @@ CREATE TYPE TagType AS ENUM (
|
|||||||
|
|
||||||
CREATE TABLE "Post"
|
CREATE TABLE "Post"
|
||||||
(
|
(
|
||||||
id CHAR(25) PRIMARY KEY,
|
id CHAR(25) PRIMARY KEY,
|
||||||
rating Rating,
|
rating Rating,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
@ -28,9 +28,9 @@ CREATE TABLE "Post"
|
|||||||
CREATE TABLE "Source"
|
CREATE TABLE "Source"
|
||||||
(
|
(
|
||||||
id CHAR(25) PRIMARY KEY,
|
id CHAR(25) PRIMARY KEY,
|
||||||
display_name TEXT NULL,
|
display_name TEXT NULL,
|
||||||
icon TEXT NULL,
|
icon TEXT NULL,
|
||||||
domain TEXT NOT NULL UNIQUE,
|
domain TEXT NOT NULL UNIQUE,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
deleted_at TIMESTAMP NULL
|
deleted_at TIMESTAMP NULL
|
||||||
@ -47,7 +47,7 @@ CREATE TABLE "Tag"
|
|||||||
|
|
||||||
CREATE TABLE "User"
|
CREATE TABLE "User"
|
||||||
(
|
(
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
deleted_at TIMESTAMP NULL
|
deleted_at TIMESTAMP NULL
|
||||||
@ -57,7 +57,7 @@ CREATE TABLE "PostReference"
|
|||||||
(
|
(
|
||||||
post_id TEXT REFERENCES "Post" (id),
|
post_id TEXT REFERENCES "Post" (id),
|
||||||
source_id TEXT REFERENCES "Source" (id),
|
source_id TEXT REFERENCES "Source" (id),
|
||||||
url TEXT NOT NULL,
|
url TEXT NOT NULL,
|
||||||
full_file_url TEXT,
|
full_file_url TEXT,
|
||||||
preview_file_url TEXT,
|
preview_file_url TEXT,
|
||||||
sample_file_url TEXT,
|
sample_file_url TEXT,
|
||||||
@ -79,16 +79,12 @@ CREATE TABLE "TagGroup"
|
|||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE "UserFavorites"
|
|
||||||
(
|
|
||||||
user_id TEXT REFERENCES "User" (id),
|
|
||||||
post_id TEXT REFERENCES "Post" (id),
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (user_id, post_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE "UserSource"
|
CREATE TABLE "UserSource"
|
||||||
(
|
(
|
||||||
|
id CHAR(25) PRIMARY KEY,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
deleted_at TIMESTAMP NULL NULL,
|
||||||
user_id TEXT REFERENCES "User" (id),
|
user_id TEXT REFERENCES "User" (id),
|
||||||
source_id TEXT REFERENCES "Source" (id),
|
source_id TEXT REFERENCES "Source" (id),
|
||||||
scrape_time_interval INT,
|
scrape_time_interval INT,
|
||||||
@ -97,10 +93,20 @@ CREATE TABLE "UserSource"
|
|||||||
last_scrape_time TIMESTAMP,
|
last_scrape_time TIMESTAMP,
|
||||||
account_validate BOOL DEFAULT FALSE,
|
account_validate BOOL DEFAULT FALSE,
|
||||||
account_validation_key CHAR(25),
|
account_validation_key CHAR(25),
|
||||||
PRIMARY KEY (user_id, source_id),
|
|
||||||
UNIQUE (source_id, account_username, account_id)
|
UNIQUE (source_id, account_username, account_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "UserFavorites"
|
||||||
|
(
|
||||||
|
id CHAR(25) PRIMARY KEY,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
deleted_at TIMESTAMP NULL NULL,
|
||||||
|
user_id TEXT REFERENCES "User" (id),
|
||||||
|
post_id TEXT REFERENCES "Post" (id),
|
||||||
|
user_source_id CHAR(25) REFERENCES "UserSource" (id)
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE "post_tags"
|
CREATE TABLE "post_tags"
|
||||||
(
|
(
|
||||||
post_id TEXT REFERENCES "Post" (id),
|
post_id TEXT REFERENCES "Post" (id),
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Post interface {
|
|
||||||
|
|
||||||
// CreatePost adds a new post to the database.
|
|
||||||
CreatePost(ctx context.Context, anthrovePost *models.Post) error
|
|
||||||
|
|
||||||
// TODO: Everything
|
|
||||||
CreatePostInBatch(ctx context.Context, anthrovePost []models.Post, batchSize int) error
|
|
||||||
|
|
||||||
// GetPostByAnthroveID retrieves a post by its Anthrove ID.
|
|
||||||
GetPostByAnthroveID(ctx context.Context, anthrovePostID models.AnthrovePostID) (*models.Post, error)
|
|
||||||
|
|
||||||
// GetPostByURL retrieves a post by its source URL.
|
|
||||||
GetPostByURL(ctx context.Context, postURL string) (*models.Post, error)
|
|
||||||
|
|
||||||
// GetPostBySourceID retrieves a post by its source ID.
|
|
||||||
GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error)
|
|
||||||
|
|
||||||
// CreatePostWithReferenceToTagAnd adds a tag with a relation to a post.
|
|
||||||
CreatePostWithReferenceToTagAnd(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error
|
|
||||||
|
|
||||||
// CreatePostReference links a post with a source.
|
|
||||||
CreatePostReference(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error
|
|
||||||
}
|
|
@ -1,268 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
"embed"
|
|
||||||
"fmt"
|
|
||||||
log2 "log"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/internal/postgres"
|
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
|
||||||
_ "github.com/lib/pq"
|
|
||||||
migrate "github.com/rubenv/sql-migrate"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
gormPostgres "gorm.io/driver/postgres"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
gormLogger "gorm.io/gorm/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed migrations/*.sql
|
|
||||||
var embedMigrations embed.FS
|
|
||||||
|
|
||||||
type postgresqlConnection struct {
|
|
||||||
db *gorm.DB
|
|
||||||
debug bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPostgresqlConnection() OtterSpace {
|
|
||||||
return &postgresqlConnection{
|
|
||||||
db: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) Connect(_ context.Context, config models.DatabaseConfig) error {
|
|
||||||
var localSSL string
|
|
||||||
var logLevel gormLogger.LogLevel
|
|
||||||
|
|
||||||
if config.SSL {
|
|
||||||
localSSL = "require"
|
|
||||||
} else {
|
|
||||||
localSSL = "disable"
|
|
||||||
}
|
|
||||||
|
|
||||||
p.debug = config.Debug
|
|
||||||
|
|
||||||
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", config.Endpoint, config.Username, config.Password, config.Database, config.Port, localSSL, config.Timezone)
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if p.debug {
|
|
||||||
logLevel = gormLogger.Info
|
|
||||||
} else {
|
|
||||||
logLevel = gormLogger.Silent
|
|
||||||
}
|
|
||||||
|
|
||||||
dbLogger := gormLogger.New(log2.New(os.Stdout, "\r\n", log2.LstdFlags), gormLogger.Config{
|
|
||||||
SlowThreshold: 200 * time.Millisecond,
|
|
||||||
LogLevel: logLevel,
|
|
||||||
IgnoreRecordNotFoundError: true,
|
|
||||||
Colorful: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
db, err := gorm.Open(gormPostgres.Open(dsn), &gorm.Config{
|
|
||||||
Logger: dbLogger,
|
|
||||||
})
|
|
||||||
p.db = db
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("OtterSpace: database connection established")
|
|
||||||
|
|
||||||
err = p.migrateDatabase(db)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("OtterSpace: migration compleate")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error {
|
|
||||||
return postgres.CreateUserWithRelationToSource(ctx, p.db, anthroveUserID, sourceID, accountId, accountUsername)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateSource(ctx context.Context, anthroveSource *models.Source) error {
|
|
||||||
return postgres.CreateSource(ctx, p.db, anthroveSource)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreatePost(ctx context.Context, anthrovePost *models.Post) error {
|
|
||||||
return postgres.CreatePost(ctx, p.db, anthrovePost)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreatePostInBatch(ctx context.Context, anthrovePost []models.Post, batchSize int) error {
|
|
||||||
return postgres.CreatePostInBatch(ctx, p.db, anthrovePost, batchSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreatePostWithReferenceToTagAnd(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error {
|
|
||||||
return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreatePostReference(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error {
|
|
||||||
return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, postURL, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error {
|
|
||||||
return postgres.CreateReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CheckIfUserHasPostAsFavorite(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) {
|
|
||||||
return postgres.CheckReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetPostByAnthroveID(ctx context.Context, anthrovePostID models.AnthrovePostID) (*models.Post, error) {
|
|
||||||
return postgres.GetPostByAnthroveID(ctx, p.db, anthrovePostID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetPostByURL(ctx context.Context, sourceUrl string) (*models.Post, error) {
|
|
||||||
return postgres.GetPostBySourceURL(ctx, p.db, sourceUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error) {
|
|
||||||
return postgres.GetPostBySourceID(ctx, p.db, sourceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) {
|
|
||||||
return postgres.GetUserFavoritesCount(ctx, p.db, anthroveUserID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllUserSources(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) {
|
|
||||||
return postgres.GetUserSourceLinks(ctx, p.db, anthroveUserID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) {
|
|
||||||
return postgres.GetUserSourceBySourceID(ctx, p.db, anthroveUserID, sourceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllUsers(ctx context.Context) ([]models.User, error) {
|
|
||||||
return postgres.GetAllUsers(ctx, p.db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllUserFavoritesWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) {
|
|
||||||
return postgres.GetUserFavoriteWithPagination(ctx, p.db, anthroveUserID, skip, limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllTagsFromUser(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) {
|
|
||||||
return postgres.GetUserTagWitRelationToFavedPosts(ctx, p.db, anthroveUserID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllTags(ctx context.Context) ([]models.Tag, error) {
|
|
||||||
return postgres.GetTags(ctx, p.db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllSources(ctx context.Context) ([]models.Source, error) {
|
|
||||||
return postgres.GetAllSource(ctx, p.db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) {
|
|
||||||
return postgres.GetSourceByDomain(ctx, p.db, sourceDomain)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error {
|
|
||||||
return postgres.UpdateUserSourceScrapeTimeInterval(ctx, p.db, anthroveUserID, sourceID, scrapeTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error {
|
|
||||||
return postgres.UpdateUserSourceLastScrapeTime(ctx, p.db, anthroveUserID, sourceID, lastScrapeTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error {
|
|
||||||
return postgres.UpdateUserSourceValidation(ctx, p.db, anthroveUserID, sourceID, valid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error {
|
|
||||||
return postgres.CreateTagAlias(ctx, p.db, tagAliasName, tagID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) {
|
|
||||||
return postgres.GetAllTagAlias(ctx, p.db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) {
|
|
||||||
return postgres.GetAllTagAliasByTag(ctx, p.db, tagID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error {
|
|
||||||
return postgres.DeleteTagAlias(ctx, p.db, tagAliasName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error {
|
|
||||||
return postgres.CreateTagGroup(ctx, p.db, tagGroupName, tagID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) {
|
|
||||||
return postgres.GetAllTagGroup(ctx, p.db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) {
|
|
||||||
return postgres.GetAllTagGroupByTag(ctx, p.db, tagID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error {
|
|
||||||
return postgres.DeleteTagGroup(ctx, p.db, tagGroupName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateTag(ctx context.Context, tagName models.AnthroveTagName, tagType models.TagType) error {
|
|
||||||
return postgres.CreateTag(ctx, p.db, tagName, tagType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllTagsByTagType(ctx context.Context, tagType models.TagType) ([]models.Tag, error) {
|
|
||||||
return postgres.GetAllTagByTagsType(ctx, p.db, tagType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) DeleteTag(ctx context.Context, tagName models.AnthroveTagName) error {
|
|
||||||
return postgres.DeleteTag(ctx, p.db, tagName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateTagInBatchAndUpdate(ctx context.Context, tags []models.Tag, batchSize int) error {
|
|
||||||
return postgres.CreateTagInBatchAndUpdate(ctx, p.db, tags, batchSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateTagAliasInBatch(ctx context.Context, tagAliases []models.TagAlias, batchSize int) error {
|
|
||||||
return postgres.CreateTagAliasInBatch(ctx, p.db, tagAliases, batchSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) CreateTagGroupInBatch(ctx context.Context, tagGroups []models.TagGroup, batchSize int) error {
|
|
||||||
return postgres.CreateTagGroupInBatch(ctx, p.db, tagGroups, batchSize)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) ExecuteRawStatement(ctx context.Context, query string, args ...any) error {
|
|
||||||
return postgres.ExecuteRawStatement(ctx, p.db, query, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) QueryRawStatement(ctx context.Context, query string, args ...any) (*sql.Rows, error) {
|
|
||||||
return postgres.QueryRawStatement(ctx, p.db, query, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HELPER
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) migrateDatabase(dbPool *gorm.DB) error {
|
|
||||||
dialect := "postgres"
|
|
||||||
migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"}
|
|
||||||
|
|
||||||
db, err := dbPool.DB()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("postgres migration: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := migrate.Exec(db, dialect, migrations, migrate.Up)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("postgres migration: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.debug {
|
|
||||||
if n != 0 {
|
|
||||||
log.Infof("postgres migration: applied %d migrations!", n)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
log.Info("postgres migration: nothing to migrate")
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -2,18 +2,107 @@ package database
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error"
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Source interface {
|
func CreateUserSource(ctx context.Context, userSource models.UserSource) (models.UserSource, error) {
|
||||||
|
if client == nil {
|
||||||
|
return models.UserSource{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||||
|
}
|
||||||
|
|
||||||
// CreateSource adds a new source to the database.
|
result := client.WithContext(ctx).Create(&userSource)
|
||||||
CreateSource(ctx context.Context, anthroveSource *models.Source) error
|
if result.Error != nil {
|
||||||
|
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||||
|
return models.UserSource{}, &otterError.Database{Reason: otterError.DuplicateKey}
|
||||||
|
}
|
||||||
|
return models.UserSource{}, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
// GetAllSources retrieves all sources.
|
return userSource, nil
|
||||||
GetAllSources(ctx context.Context) ([]models.Source, error)
|
}
|
||||||
|
|
||||||
// GetSourceByDomain retrieves a source by its URL.
|
func UpdateUserSource(ctx context.Context, userSource models.UserSource) error {
|
||||||
GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error)
|
if client == nil {
|
||||||
|
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(userSource.ID) == 0 {
|
||||||
|
return &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDEmpty}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedUserSource := models.UserSource{
|
||||||
|
BaseModel: models.BaseModel[models.UserSourceID]{
|
||||||
|
ID: userSource.ID,
|
||||||
|
},
|
||||||
|
ScrapeTimeInterval: userSource.ScrapeTimeInterval,
|
||||||
|
AccountUsername: userSource.AccountUsername,
|
||||||
|
AccountID: userSource.AccountID,
|
||||||
|
LastScrapeTime: userSource.LastScrapeTime,
|
||||||
|
AccountValidate: userSource.AccountValidate,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := client.WithContext(ctx).Updates(&updatedUserSource)
|
||||||
|
if result.Error != nil {
|
||||||
|
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
||||||
|
return &otterError.Database{Reason: otterError.DuplicateKey}
|
||||||
|
}
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserSourceByID(ctx context.Context, id models.UserSourceID) (models.UserSource, error) {
|
||||||
|
var user models.UserSource
|
||||||
|
|
||||||
|
if client == nil {
|
||||||
|
return models.UserSource{}, &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(id) == 0 {
|
||||||
|
return models.UserSource{}, &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDEmpty}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(id) != 25 {
|
||||||
|
return models.UserSource{}, &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDToShort}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := client.WithContext(ctx).First(&user, id)
|
||||||
|
if result.Error != nil {
|
||||||
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||||
|
return models.UserSource{}, &otterError.Database{Reason: otterError.NoDataFound}
|
||||||
|
}
|
||||||
|
return models.UserSource{}, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteUserSource(ctx context.Context, id models.UserSourceID) error {
|
||||||
|
var user models.UserSource
|
||||||
|
|
||||||
|
if client == nil {
|
||||||
|
return &otterError.Database{Reason: otterError.DatabaseIsNotConnected}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(id) == 0 {
|
||||||
|
return &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDEmpty}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(id) != 25 {
|
||||||
|
return &otterError.EntityValidationFailed{Reason: otterError.UserSourceIDToShort}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := client.WithContext(ctx).Delete(&user, id)
|
||||||
|
if result.Error != nil {
|
||||||
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||||
|
return &otterError.Database{Reason: otterError.NoDataFound}
|
||||||
|
}
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Tag interface {
|
|
||||||
CreateTag(ctx context.Context, tagName models.AnthroveTagName, tagType models.TagType) error
|
|
||||||
|
|
||||||
CreateTagInBatchAndUpdate(ctx context.Context, tags []models.Tag, batchSize int) error
|
|
||||||
|
|
||||||
// GetAllTags retrieves all tags.
|
|
||||||
GetAllTags(ctx context.Context) ([]models.Tag, error)
|
|
||||||
|
|
||||||
GetAllTagsByTagType(ctx context.Context, tagType models.TagType) ([]models.Tag, error)
|
|
||||||
|
|
||||||
DeleteTag(ctx context.Context, tagName models.AnthroveTagName) error
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TagAlias interface {
|
|
||||||
CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error
|
|
||||||
|
|
||||||
CreateTagAliasInBatch(ctx context.Context, tagsAliases []models.TagAlias, batchSize int) error
|
|
||||||
|
|
||||||
GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error)
|
|
||||||
|
|
||||||
GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error)
|
|
||||||
|
|
||||||
DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TagGroup interface {
|
|
||||||
CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error
|
|
||||||
|
|
||||||
CreateTagGroupInBatch(ctx context.Context, tagsGroups []models.TagGroup, batchSize int) error
|
|
||||||
|
|
||||||
GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error)
|
|
||||||
|
|
||||||
GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error)
|
|
||||||
|
|
||||||
DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type User interface {
|
|
||||||
|
|
||||||
// CreateUserWithRelationToSource adds a user with a relation to a source.
|
|
||||||
CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error
|
|
||||||
|
|
||||||
// CreateReferenceBetweenUserAndPost links a user with a post.
|
|
||||||
CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error
|
|
||||||
|
|
||||||
UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error
|
|
||||||
|
|
||||||
UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error
|
|
||||||
|
|
||||||
UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error
|
|
||||||
|
|
||||||
GetAllUsers(ctx context.Context) ([]models.User, error)
|
|
||||||
|
|
||||||
// GetUserFavoritesCount retrieves the count of a user's favorites.
|
|
||||||
GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error)
|
|
||||||
|
|
||||||
// GetAllUserSources retrieves the source links of a user.
|
|
||||||
GetAllUserSources(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error)
|
|
||||||
|
|
||||||
// GetUserSourceBySourceID retrieves a specified source link of a user.
|
|
||||||
GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error)
|
|
||||||
|
|
||||||
// GetAllUserFavoritesWithPagination retrieves a user's favorite posts with pagination.
|
|
||||||
GetAllUserFavoritesWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error)
|
|
||||||
|
|
||||||
// GetAllTagsFromUser retrieves a user's tags through their favorite posts.
|
|
||||||
GetAllTagsFromUser(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error)
|
|
||||||
|
|
||||||
// CheckIfUserHasPostAsFavorite checks if a user-post link exists.
|
|
||||||
CheckIfUserHasPostAsFavorite(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, error)
|
|
||||||
}
|
|
@ -1,25 +1,19 @@
|
|||||||
package error
|
package error
|
||||||
|
|
||||||
type EntityAlreadyExists struct{}
|
import "fmt"
|
||||||
|
|
||||||
func (e *EntityAlreadyExists) Error() string {
|
const (
|
||||||
return "EntityAlreadyExists error"
|
EntityAlreadyExists = "EntityAlreadyExists"
|
||||||
|
NoDataWritten = "NoDataWritten"
|
||||||
|
NoDataFound = "NoDataFound"
|
||||||
|
DatabaseIsNotConnected = "database is not connected"
|
||||||
|
DuplicateKey = "DuplicateKey"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
Reason string
|
||||||
}
|
}
|
||||||
|
|
||||||
type NoDataWritten struct{}
|
func (e Database) Error() string {
|
||||||
|
return fmt.Sprintf("Database error: %s", e.Reason)
|
||||||
func (e *NoDataWritten) Error() string {
|
|
||||||
return "NoDataWritten error"
|
|
||||||
}
|
|
||||||
|
|
||||||
type NoDataFound struct{}
|
|
||||||
|
|
||||||
func (e *NoDataFound) Error() string {
|
|
||||||
return "NoDataFound error"
|
|
||||||
}
|
|
||||||
|
|
||||||
type NoRelationCreated struct{}
|
|
||||||
|
|
||||||
func (e *NoRelationCreated) Error() string {
|
|
||||||
return "relationship creation error"
|
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,13 @@ package error
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AnthroveUserIDIsEmpty = "anthrovePostID cannot be empty"
|
UserIDIsEmpty = "anthrovePostID cannot be empty"
|
||||||
AnthroveUserIDToShort = "anthrovePostID needs to be 25 characters long"
|
UserIDToShort = "anthrovePostID needs to be 25 characters long"
|
||||||
AnthroveSourceIDEmpty = "anthroveSourceID cannot be empty"
|
SourceIDEmpty = "anthroveSourceID cannot be empty"
|
||||||
AnthroveSourceIDToShort = "anthroveSourceID needs to be 25 characters long"
|
SourceIDToShort = "anthroveSourceID needs to be 25 characters long"
|
||||||
AnthroveTagIDEmpty = "tagID cannot be empty"
|
UserSourceIDEmpty = "anthroveUserSourceID cannot be empty"
|
||||||
|
UserSourceIDToShort = "anthroveUserSourceID needs to be 25 characters long"
|
||||||
|
TagIDEmpty = "tagID cannot be empty"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EntityValidationFailed struct {
|
type EntityValidationFailed struct {
|
||||||
|
@ -2,20 +2,25 @@ package models
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type AnthroveUserID string
|
type (
|
||||||
type AnthrovePostID string
|
UserID string
|
||||||
type AnthroveSourceID string
|
PostID string
|
||||||
type AnthroveSourceDomain string
|
SourceID string
|
||||||
type AnthrovePostURL string
|
SourceDomain string
|
||||||
type AnthroveTagGroupName string
|
PostURL string
|
||||||
type AnthroveTagAliasName string
|
TagGroupName string
|
||||||
type AnthroveTagID string
|
TagAliasName string
|
||||||
type AnthroveScrapeTimeInterval int
|
TagID string
|
||||||
type AnthroveUserLastScrapeTime time.Time
|
ScrapeTimeInterval int
|
||||||
type AnthroveTagName string
|
UserLastScrapeTime time.Time
|
||||||
|
TagName string
|
||||||
|
|
||||||
type Rating string
|
Rating string
|
||||||
type TagType string
|
TagType string
|
||||||
|
|
||||||
|
UserSourceID string
|
||||||
|
UserFavoriteID string
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SFW Rating = "safe"
|
SFW Rating = "safe"
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ID interface {
|
type ID interface {
|
||||||
AnthroveUserID | AnthroveSourceID | AnthrovePostID
|
UserID | SourceID | PostID | UserSourceID | UserFavoriteID
|
||||||
}
|
}
|
||||||
|
|
||||||
type BaseModel[T ID] struct {
|
type BaseModel[T ID] struct {
|
||||||
|
@ -42,8 +42,8 @@ func TestBaseModel_BeforeCreate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
base := &BaseModel[AnthrovePostID]{
|
base := &BaseModel[PostID]{
|
||||||
ID: AnthrovePostID(tt.fields.ID),
|
ID: PostID(tt.fields.ID),
|
||||||
CreatedAt: tt.fields.CreatedAt,
|
CreatedAt: tt.fields.CreatedAt,
|
||||||
UpdatedAt: tt.fields.UpdatedAt,
|
UpdatedAt: tt.fields.UpdatedAt,
|
||||||
DeletedAt: tt.fields.DeletedAt,
|
DeletedAt: tt.fields.DeletedAt,
|
||||||
|
@ -2,7 +2,7 @@ package models
|
|||||||
|
|
||||||
// Post model
|
// Post model
|
||||||
type Post struct {
|
type Post struct {
|
||||||
BaseModel[AnthrovePostID]
|
BaseModel[PostID]
|
||||||
Rating Rating `json:"rating" gorm:"type:enum('safe','questionable','explicit')"`
|
Rating Rating `json:"rating" gorm:"type:enum('safe','questionable','explicit')"`
|
||||||
Tags []Tag `json:"-" gorm:"many2many:post_tags;"`
|
Tags []Tag `json:"-" gorm:"many2many:post_tags;"`
|
||||||
Favorites []UserFavorites `json:"-" gorm:"foreignKey:PostID"`
|
Favorites []UserFavorites `json:"-" gorm:"foreignKey:PostID"`
|
||||||
|
@ -4,7 +4,7 @@ import "testing"
|
|||||||
|
|
||||||
func TestPost_TableName(t *testing.T) {
|
func TestPost_TableName(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
BaseModel BaseModel[AnthrovePostID]
|
BaseModel BaseModel[PostID]
|
||||||
Rating Rating
|
Rating Rating
|
||||||
Tags []Tag
|
Tags []Tag
|
||||||
Favorites []UserFavorites
|
Favorites []UserFavorites
|
||||||
|
@ -2,7 +2,7 @@ package models
|
|||||||
|
|
||||||
// Source model
|
// Source model
|
||||||
type Source struct {
|
type Source struct {
|
||||||
BaseModel[AnthroveSourceID]
|
BaseModel[SourceID]
|
||||||
DisplayName string `json:"display_name" `
|
DisplayName string `json:"display_name" `
|
||||||
Domain string `json:"domain" gorm:"not null;unique"`
|
Domain string `json:"domain" gorm:"not null;unique"`
|
||||||
Icon string `json:"icon" gorm:"not null"`
|
Icon string `json:"icon" gorm:"not null"`
|
||||||
|
@ -4,7 +4,7 @@ import "testing"
|
|||||||
|
|
||||||
func TestSource_TableName(t *testing.T) {
|
func TestSource_TableName(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
BaseModel BaseModel[AnthroveSourceID]
|
BaseModel BaseModel[SourceID]
|
||||||
DisplayName string
|
DisplayName string
|
||||||
Domain string
|
Domain string
|
||||||
Icon string
|
Icon string
|
||||||
|
@ -2,7 +2,7 @@ package models
|
|||||||
|
|
||||||
// User model
|
// User model
|
||||||
type User struct {
|
type User struct {
|
||||||
BaseModel[AnthroveUserID]
|
BaseModel[UserID]
|
||||||
Favorites []UserFavorites `json:"-" gorm:"foreignKey:UserID"`
|
Favorites []UserFavorites `json:"-" gorm:"foreignKey:UserID"`
|
||||||
Sources []UserSource `json:"-" gorm:"foreignKey:UserID"`
|
Sources []UserSource `json:"-" gorm:"foreignKey:UserID"`
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,12 @@ package models
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type UserFavorites struct {
|
type UserFavorites struct {
|
||||||
UserID string `json:"user_id" gorm:"primaryKey"`
|
BaseModel[UserFavoriteID]
|
||||||
PostID string `json:"post_id" gorm:"primaryKey"`
|
UserID string `json:"user_id"`
|
||||||
CreatedAt time.Time `json:"-"`
|
PostID string `json:"post_id"`
|
||||||
|
UserSourceID UserSourceID `json:"user_source_id"`
|
||||||
|
UserSource UserSource `json:"-" gorm:"foreignKey:ID;references:UserSourceID"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UserFavorites) TableName() string {
|
func (UserFavorites) TableName() string {
|
||||||
|
@ -3,10 +3,11 @@ package models
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type UserSource struct {
|
type UserSource struct {
|
||||||
|
BaseModel[UserSourceID]
|
||||||
User User `json:"user" gorm:"foreignKey:ID;references:UserID"`
|
User User `json:"user" gorm:"foreignKey:ID;references:UserID"`
|
||||||
UserID string `json:"user_id" gorm:"primaryKey"`
|
UserID UserID `json:"user_id"`
|
||||||
Source Source `json:"source" gorm:"foreignKey:ID;references:SourceID"`
|
Source Source `json:"source" gorm:"foreignKey:ID;references:SourceID"`
|
||||||
SourceID string `json:"source_id" gorm:"primaryKey"`
|
SourceID SourceID `json:"source_id"`
|
||||||
ScrapeTimeInterval string `json:"scrape_time_interval"`
|
ScrapeTimeInterval string `json:"scrape_time_interval"`
|
||||||
AccountUsername string `json:"account_username"`
|
AccountUsername string `json:"account_username"`
|
||||||
AccountID string `json:"account_id"`
|
AccountID string `json:"account_id"`
|
||||||
|
@ -5,9 +5,9 @@ import "testing"
|
|||||||
func TestUserSource_TableName(t *testing.T) {
|
func TestUserSource_TableName(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
User User
|
User User
|
||||||
UserID string
|
UserID UserID
|
||||||
Source Source
|
Source Source
|
||||||
SourceID string
|
SourceID SourceID
|
||||||
ScrapeTimeInterval string
|
ScrapeTimeInterval string
|
||||||
AccountUsername string
|
AccountUsername string
|
||||||
AccountID string
|
AccountID string
|
||||||
|
@ -4,7 +4,7 @@ import "testing"
|
|||||||
|
|
||||||
func TestUser_TableName(t *testing.T) {
|
func TestUser_TableName(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
BaseModel BaseModel[AnthroveUserID]
|
BaseModel BaseModel[UserID]
|
||||||
Favorites []UserFavorites
|
Favorites []UserFavorites
|
||||||
Sources []UserSource
|
Sources []UserSource
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user