Compare commits

..

5 Commits

Author SHA1 Message Date
b5437ecc62 tests: fixed tests
All checks were successful
Gitea Build Check / Build (push) Successful in 10m55s
Signed-off-by: SoXX <soxx@fenpa.ws>
2024-06-28 14:16:28 +02:00
4a0b7d71a9 refactor: reorganized code structure
Signed-off-by: SoXX <soxx@fenpa.ws>
2024-06-28 12:15:51 +02:00
5de00e6861 refactor: reorganized code structure
Signed-off-by: SoXX <soxx@fenpa.ws>
2024-06-28 10:58:07 +02:00
bc8b5bb4a7 refactor: reorganized code structure
Signed-off-by: SoXX <soxx@fenpa.ws>
2024-06-28 10:54:42 +02:00
429f68899d feat(database): new fields
Signed-off-by: SoXX <soxx@fenpa.ws>
2024-06-28 10:43:55 +02:00
18 changed files with 383 additions and 213 deletions

View File

@ -133,11 +133,11 @@ func TestCheckUserToPostLink(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if got != tt.want { if got != tt.want {
t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -266,11 +266,11 @@ func TestCheckUserToPostLinkWithNoData(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if got != tt.want { if got != tt.want {
t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want)
} }
}) })
} }

View File

@ -94,7 +94,7 @@ func TestCreateTagNodeWitRelation(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) {
if err := CreateTagAndReferenceToPost(tt.args.ctx, tt.args.db, tt.args.PostID, tt.args.tag); (err != nil) != tt.wantErr { if err := CreateTagAndReferenceToPost(tt.args.ctx, tt.args.db, tt.args.PostID, tt.args.tag); (err != nil) != tt.wantErr {
t.Errorf("CreateTagAndReferenceToPost() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("CreatePostWithReferenceToTagAnd() error = %v, wantErr %v", err, tt.wantErr)
} }
}) })
} }

View File

@ -6,6 +6,7 @@ import (
otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error" otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models"
gonanoid "github.com/matoous/go-nanoid/v2"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -56,15 +57,21 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs
return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"} return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"}
} }
validationCode, err := gonanoid.New(25)
if err != nil {
return err
}
result := db.WithContext(ctx).Exec(`WITH userObj AS ( result := db.WithContext(ctx).Exec(`WITH userObj AS (
INSERT INTO "User" (id) INSERT INTO "User" (id)
VALUES ($1) VALUES ($1)
ON CONFLICT (id) DO NOTHING ON CONFLICT (id) DO NOTHING
) )
INSERT INTO "UserSource" (user_id, source_id, account_username, account_id) INSERT INTO "UserSource" (user_id, source_id, account_username, account_id, account_validate, account_validation_key)
SELECT $2, source.id, $3, $4 SELECT $2, source.id, $3, $4, false, $5
FROM "Source" AS source FROM "Source" AS source
WHERE source.id = $5;`, anthroveUserID, anthroveUserID, accountUsername, accountId, sourceID) WHERE source.id = $6;`, anthroveUserID, anthroveUserID, accountUsername, accountId, validationCode, sourceID)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrDuplicatedKey) { if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
@ -162,9 +169,8 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models.
return userSourceMap, nil return userSourceMap, nil
} }
func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) { func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) {
var userSources []models.UserSource var userSource models.UserSource
userSourceMap := make(map[string]models.UserSource)
if anthroveUserID == "" { if anthroveUserID == "" {
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
@ -182,7 +188,7 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo
return nil, &otterError.EntityValidationFailed{Reason: "sourceID needs to be 25 characters long"} return nil, &otterError.EntityValidationFailed{Reason: "sourceID needs to be 25 characters long"}
} }
result := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(&userSources) result := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(&userSource)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &otterError.NoDataFound{} return nil, &otterError.NoDataFound{}
@ -190,38 +196,16 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo
return nil, result.Error return nil, result.Error
} }
for _, userSource := range userSources {
var source models.Source
result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &otterError.NoDataFound{}
}
return nil, result.Error
}
userSourceMap[source.DisplayName] = models.UserSource{
UserID: userSource.AccountID,
AccountUsername: userSource.AccountUsername,
Source: models.Source{
DisplayName: source.DisplayName,
Domain: source.Domain,
Icon: source.Icon,
},
}
}
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"anthrove_user_id": anthroveUserID, "anthrove_user_id": anthroveUserID,
"source_id": sourceID, "source_id": sourceID,
}).Trace("database: got specified user source link") }).Trace("database: got specified user source link")
return userSourceMap, nil return &userSource, nil
} }
func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) { func GetAllUsers(ctx context.Context, db *gorm.DB) ([]models.User, error) {
var users []models.User var users []models.User
var userIDs []models.AnthroveUserID
result := db.WithContext(ctx).Model(&models.User{}).Find(&users) result := db.WithContext(ctx).Model(&models.User{}).Find(&users)
if result.Error != nil { if result.Error != nil {
@ -231,15 +215,11 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU
return nil, result.Error return nil, result.Error
} }
for _, user := range users {
userIDs = append(userIDs, user.ID)
}
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"anthrove_user_id_count": len(userIDs), "anthrove_user_id_count": len(users),
}).Trace("database: got all anthrove user IDs") }).Trace("database: got all anthrove user IDs")
return userIDs, nil return users, nil
} }
func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) {

View File

@ -198,7 +198,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) {
} }
} }
func TestGetAllAnthroveUserIDs(t *testing.T) { func TestGetAllUsers(t *testing.T) {
// Setup trow away container // Setup trow away container
ctx := context.Background() ctx := context.Background()
container, gormDB, err := test.StartPostgresContainer(ctx) container, gormDB, err := test.StartPostgresContainer(ctx)
@ -212,10 +212,20 @@ func TestGetAllAnthroveUserIDs(t *testing.T) {
validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2")) validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2"))
validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3")) validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3"))
users := []models.AnthroveUserID{validUserID01, validUserID02, validUserID03} users := []models.User{
{
BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID01},
},
{
BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID02},
},
{
BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID03},
},
}
for _, user := range users { for _, user := range users {
err = CreateUser(ctx, gormDB, user) err = CreateUser(ctx, gormDB, user.ID)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -229,7 +239,7 @@ func TestGetAllAnthroveUserIDs(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args args args args
want []models.AnthroveUserID want []models.User
wantErr bool wantErr bool
}{ }{
{ {
@ -244,13 +254,13 @@ func TestGetAllAnthroveUserIDs(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) {
got, err := GetAllAnthroveUserIDs(tt.args.ctx, tt.args.db) got, err := GetAllUsers(tt.args.ctx, tt.args.db)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetAllAnthroveUserIDs() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetAllUsers() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !checkUser(got, tt.want) {
t.Errorf("GetAllAnthroveUserIDs() got = %v, want %v", got, tt.want) t.Errorf("GetAllUsers() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -278,13 +288,14 @@ func TestGetUserSourceBySourceID(t *testing.T) {
}, },
DisplayName: "e621", DisplayName: "e621",
Domain: "e621.net", Domain: "e621.net",
Icon: "https://e621.icon",
} }
expectedResult := make(map[string]models.UserSource) expectedResult := &models.UserSource{
expectedResult["e621"] = models.UserSource{ UserID: string(validUserID),
UserID: "e1",
AccountUsername: "euser", AccountUsername: "euser",
Source: models.Source{ Source: models.Source{
BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: source.ID},
DisplayName: source.DisplayName, DisplayName: source.DisplayName,
Domain: source.Domain, Domain: source.Domain,
Icon: source.Icon, Icon: source.Icon,
@ -296,7 +307,7 @@ func TestGetUserSourceBySourceID(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult.UserID, expectedResult.AccountUsername)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -311,7 +322,7 @@ func TestGetUserSourceBySourceID(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args args args args
want map[string]models.UserSource want *models.UserSource
wantErr bool wantErr bool
}{ }{
{ {
@ -400,7 +411,7 @@ func TestGetUserSourceBySourceID(t *testing.T) {
t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !checkUserSource(got, tt.want) {
t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want) t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want)
} }
}) })
@ -558,11 +569,11 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := GetUserFavoriteWithPagination(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) got, err := GetUserFavoriteWithPagination(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.skip, tt.args.limit)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetUserFavoriteWithPagination() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetAllUserFavoritesWithPagination() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetUserFavoriteWithPagination() got = %v, want %v", got, tt.want) t.Errorf("GetAllUserFavoritesWithPagination() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -798,11 +809,11 @@ func TestGetUserSourceLinks(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := GetUserSourceLinks(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) got, err := GetUserSourceLinks(tt.args.ctx, tt.args.db, tt.args.anthroveUserID)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetUserSourceLinks() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetAllUserSources() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetUserSourceLinks() got = %v, want %v", got, tt.want) t.Errorf("GetAllUserSources() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -930,12 +941,48 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := GetUserTagWitRelationToFavedPosts(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) got, err := GetUserTagWitRelationToFavedPosts(tt.args.ctx, tt.args.db, tt.args.anthroveUserID)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetUserTagWitRelationToFavedPosts() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetAllTagsFromUser() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetUserTagWitRelationToFavedPosts() got = %v, want %v", got, tt.want) t.Errorf("GetAllTagsFromUser() got = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func checkUser(got []models.User, want []models.User) bool {
for i, user := range want {
if user.ID != got[i].ID {
return false
}
}
return true
}
func checkUserSource(got *models.UserSource, want *models.UserSource) bool {
if got == nil && want == nil {
return true
} else if got == nil || want == nil {
return false
}
if got.UserID != want.UserID {
return false
}
if got.AccountUsername != want.AccountUsername {
return false
}
if got.Source.DisplayName != want.Source.DisplayName {
return false
}
if got.Source.Domain != want.Source.Domain {
return false
}
if got.Source.Icon != want.Source.Icon {
return false
}
return true
}

View File

@ -2,6 +2,7 @@ package database
import ( import (
"context" "context"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models"
) )
@ -9,72 +10,18 @@ type OtterSpace interface {
// Connect establishes a connection to the database. // Connect establishes a connection to the database.
Connect(ctx context.Context, config models.DatabaseConfig) error Connect(ctx context.Context, config models.DatabaseConfig) error
// CreateUserWithRelationToSource adds a user with a relation to a source. // Post contains all function that are needed to manage Posts
CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error Post
// CreateSource adds a new source to the database. // User contains all function that are needed to manage the AnthroveUser
CreateSource(ctx context.Context, anthroveSource *models.Source) error User
// CreatePost adds a new post to the database. // Source contains all function that are needed to manage the Source
CreatePost(ctx context.Context, anthrovePost *models.Post) error Source
// CreateTagAndReferenceToPost adds a tag with a relation to a post. // TagAlias contains all function that are needed to manage the TagAlias
CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error TagAlias
// CreateReferenceBetweenPostAndSource links a post with a source. // TagGroup contains all function that are needed to manage the TagGroup
CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error TagGroup
// CreateReferenceBetweenUserAndPost links a user with a post.
CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error
// CheckReferenceBetweenUserAndPost checks if a user-post link exists.
CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, 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)
// GetUserFavoritesCount retrieves the count of a user's favorites.
GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error)
// GetUserSourceLinks retrieves the source links of a user.
GetUserSourceLinks(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) (map[string]models.UserSource, error)
// GetAllAnthroveUserIDs retrieves all Anthrove user IDs.
GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error)
// GetUserFavoriteWithPagination retrieves a user's favorite posts with pagination.
GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error)
// GetUserTagWitRelationToFavedPosts retrieves a user's tags through their favorited posts.
GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error)
// GetAllTags retrieves all tags.
GetAllTags(ctx context.Context) ([]models.Tag, error)
// GetAllSources retrieves all sources.
GetAllSources(ctx context.Context) ([]models.Source, error)
// GetSourceByDomain retrieves a source by its URL.
GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error)
GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error)
GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error)
CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error
DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error
GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error)
GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error)
CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID)
DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error
UpdateUserWithScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error
} }

View File

@ -27,7 +27,7 @@ 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,
@ -89,11 +89,14 @@ CREATE TABLE "UserFavorites"
CREATE TABLE "UserSource" CREATE TABLE "UserSource"
( (
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 TEXT, scrape_time_interval INT,
account_username TEXT, account_username TEXT,
account_id TEXT, account_id TEXT,
last_scrape_time TIMESTAMP,
account_validate BOOL DEFAULT FALSE,
account_validation_key CHAR(25),
PRIMARY KEY (user_id, source_id), PRIMARY KEY (user_id, source_id),
UNIQUE (source_id, account_username, account_id) UNIQUE (source_id, account_username, account_id)
); );
@ -104,16 +107,3 @@ CREATE TABLE "post_tags"
tag_name TEXT REFERENCES "Tag" (name), tag_name TEXT REFERENCES "Tag" (name),
PRIMARY KEY (post_id, tag_name) PRIMARY KEY (post_id, tag_name)
); );
-- +migrate Down
DROP TYPE Rating;
DROP TYPE TagType;
DROP TABLE Post;
DROP TABLE Source;
DROP TABLE Tag;
DROP TABLE User;
DROP TABLE PostReference;
DROP TABLE TagAlias;
DROP TABLE TagGroup;
DROP TABLE UserFavorites;
DROP TABLE UserSource;

28
pkg/database/post.go Normal file
View File

@ -0,0 +1,28 @@
package database
import (
"context"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models"
)
type Post interface {
// CreatePost adds a new post to the database.
CreatePost(ctx context.Context, anthrovePost *models.Post) 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
}

View File

@ -84,11 +84,11 @@ func (p *postgresqlConnection) CreatePost(ctx context.Context, anthrovePost *mod
return postgres.CreatePost(ctx, p.db, anthrovePost) return postgres.CreatePost(ctx, p.db, anthrovePost)
} }
func (p *postgresqlConnection) CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error { func (p *postgresqlConnection) CreatePostWithReferenceToTagAnd(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error {
return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag) return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag)
} }
func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error { 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) return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, postURL, config)
} }
@ -96,7 +96,7 @@ func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Con
return postgres.CreateReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID) return postgres.CreateReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID)
} }
func (p *postgresqlConnection) CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { func (p *postgresqlConnection) CheckIfUserHasPostAsFavorite(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) {
return postgres.CheckReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID) return postgres.CheckReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID)
} }
@ -116,23 +116,23 @@ func (p *postgresqlConnection) GetUserFavoritesCount(ctx context.Context, anthro
return postgres.GetUserFavoritesCount(ctx, p.db, anthroveUserID) return postgres.GetUserFavoritesCount(ctx, p.db, anthroveUserID)
} }
func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) { func (p *postgresqlConnection) GetAllUserSources(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) {
return postgres.GetUserSourceLinks(ctx, p.db, anthroveUserID) return postgres.GetUserSourceLinks(ctx, p.db, anthroveUserID)
} }
func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) { func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) {
return postgres.GetUserSourceBySourceID(ctx, p.db, anthroveUserID, sourceID) return postgres.GetUserSourceBySourceID(ctx, p.db, anthroveUserID, sourceID)
} }
func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { func (p *postgresqlConnection) GetAllUsers(ctx context.Context) ([]models.User, error) {
return postgres.GetAllAnthroveUserIDs(ctx, p.db) return postgres.GetAllUsers(ctx, p.db)
} }
func (p *postgresqlConnection) GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { 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) return postgres.GetUserFavoriteWithPagination(ctx, p.db, anthroveUserID, skip, limit)
} }
func (p *postgresqlConnection) GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { func (p *postgresqlConnection) GetAllTagsFromUser(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) {
return postgres.GetUserTagWitRelationToFavedPosts(ctx, p.db, anthroveUserID) return postgres.GetUserTagWitRelationToFavedPosts(ctx, p.db, anthroveUserID)
} }
@ -193,6 +193,21 @@ func (p *postgresqlConnection) UpdateUserWithScrapeTimeInterval(ctx context.Cont
panic("implement me") panic("implement me")
} }
func (p *postgresqlConnection) UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error {
//TODO implement me
panic("implement me")
}
func (p *postgresqlConnection) UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error {
//TODO implement me
panic("implement me")
}
func (p *postgresqlConnection) UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error {
//TODO implement me
panic("implement me")
}
func (p *postgresqlConnection) migrateDatabase(dbPool *gorm.DB) error { func (p *postgresqlConnection) migrateDatabase(dbPool *gorm.DB) error {
dialect := "postgres" dialect := "postgres"
migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"} migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"}

View File

@ -420,8 +420,8 @@ func Test_postgresqlConnection_CreateTagAndReferenceToPost(t *testing.T) {
db: gormDB, db: gormDB,
debug: true, debug: true,
} }
if err := p.CreateTagAndReferenceToPost(tt.args.ctx, tt.args.anthrovePostID, tt.args.anthroveTag); (err != nil) != tt.wantErr { if err := p.CreatePostWithReferenceToTagAnd(tt.args.ctx, tt.args.anthrovePostID, tt.args.anthroveTag); (err != nil) != tt.wantErr {
t.Errorf("CreateTagAndReferenceToPost() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("CreatePostWithReferenceToTagAnd() error = %v, wantErr %v", err, tt.wantErr)
} }
}) })
} }
@ -521,8 +521,8 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T)
db: gormDB, db: gormDB,
debug: true, debug: true,
} }
if err := p.CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain, tt.args.postURl, models.PostReferenceConfig{}); (err != nil) != tt.wantErr { if err := p.CreatePostReference(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain, tt.args.postURl, models.PostReferenceConfig{}); (err != nil) != tt.wantErr {
t.Errorf("CreateReferenceBetweenPostAndSource() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("CreatePostReference() error = %v, wantErr %v", err, tt.wantErr)
} }
}) })
} }
@ -713,13 +713,13 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) {
db: gormDB, db: gormDB,
debug: true, debug: true,
} }
got, err := p.CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.anthroveUserID, tt.args.anthrovePostID) got, err := p.CheckIfUserHasPostAsFavorite(tt.args.ctx, tt.args.anthroveUserID, tt.args.anthrovePostID)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if got != tt.want { if got != tt.want {
t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -1206,13 +1206,13 @@ func Test_postgresqlConnection_GetUserSourceLinks(t *testing.T) {
db: gormDB, db: gormDB,
debug: true, debug: true,
} }
got, err := p.GetUserSourceLinks(tt.args.ctx, tt.args.anthroveUserID) got, err := p.GetAllUserSources(tt.args.ctx, tt.args.anthroveUserID)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetUserSourceLinks() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetAllUserSources() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetUserSourceLinks() got = %v, want %v", got, tt.want) t.Errorf("GetAllUserSources() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -1234,20 +1234,20 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) {
validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1"))
expectedResult := make(map[string]models.UserSource)
source := &models.Source{ source := &models.Source{
BaseModel: models.BaseModel[models.AnthroveSourceID]{ BaseModel: models.BaseModel[models.AnthroveSourceID]{
ID: validSourceID, ID: validSourceID,
}, },
DisplayName: "e621", DisplayName: "e621",
Domain: "e621.net", Domain: "e621.net",
Icon: "https://e621.icon",
} }
expectedResult["e621"] = models.UserSource{ expectedResult := &models.UserSource{
UserID: "e1", UserID: string(validUserID),
AccountUsername: "euser", AccountUsername: "euser",
Source: models.Source{ Source: models.Source{
BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: source.ID},
DisplayName: source.DisplayName, DisplayName: source.DisplayName,
Domain: source.Domain, Domain: source.Domain,
Icon: source.Icon, Icon: source.Icon,
@ -1259,7 +1259,7 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult.UserID, expectedResult.AccountUsername)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -1270,10 +1270,11 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) {
anthroveUserID models.AnthroveUserID anthroveUserID models.AnthroveUserID
sourceID models.AnthroveSourceID sourceID models.AnthroveSourceID
} }
tests := []struct { tests := []struct {
name string name string
args args args args
want map[string]models.UserSource want *models.UserSource
wantErr bool wantErr bool
}{ }{
{ {
@ -1348,14 +1349,14 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) {
t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !checkUserSource(got, tt.want) {
t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want) t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) { func Test_postgresqlConnection_GetAllUsers(t *testing.T) {
// Setup trow away container // Setup trow away container
ctx := context.Background() ctx := context.Background()
container, gormDB, err := test.StartPostgresContainer(ctx) container, gormDB, err := test.StartPostgresContainer(ctx)
@ -1369,10 +1370,20 @@ func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) {
validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2")) validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2"))
validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3")) validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3"))
users := []models.AnthroveUserID{validUserID01, validUserID02, validUserID03} users := []models.User{
{
BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID01},
},
{
BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID02},
},
{
BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID03},
},
}
for _, user := range users { for _, user := range users {
err = postgres.CreateUser(ctx, gormDB, user) err = postgres.CreateUser(ctx, gormDB, user.ID)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -1385,7 +1396,7 @@ func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args args args args
want []models.AnthroveUserID want []models.User
wantErr bool wantErr bool
}{ }{
{ {
@ -1402,13 +1413,13 @@ func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) {
db: gormDB, db: gormDB,
debug: true, debug: true,
} }
got, err := p.GetAllAnthroveUserIDs(tt.args.ctx) got, err := p.GetAllUsers(tt.args.ctx)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetAllAnthroveUserIDs() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetAllUsers() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !checkUser(got, tt.want) {
t.Errorf("GetAllAnthroveUserIDs() got = %v, want %v", got, tt.want) t.Errorf("GetAllUsers() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -1539,13 +1550,13 @@ func Test_postgresqlConnection_GetUserFavoriteWithPagination(t *testing.T) {
db: gormDB, db: gormDB,
debug: true, debug: true,
} }
got, err := p.GetUserFavoriteWithPagination(tt.args.ctx, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) got, err := p.GetAllUserFavoritesWithPagination(tt.args.ctx, tt.args.anthroveUserID, tt.args.skip, tt.args.limit)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetUserFavoriteWithPagination() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetAllUserFavoritesWithPagination() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetUserFavoriteWithPagination() got = %v, want %v", got, tt.want) t.Errorf("GetAllUserFavoritesWithPagination() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -1653,13 +1664,13 @@ func Test_postgresqlConnection_GetUserTagWitRelationToFavedPosts(t *testing.T) {
db: gormDB, db: gormDB,
debug: true, debug: true,
} }
got, err := p.GetUserTagWitRelationToFavedPosts(tt.args.ctx, tt.args.anthroveUserID) got, err := p.GetAllTagsFromUser(tt.args.ctx, tt.args.anthroveUserID)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetUserTagWitRelationToFavedPosts() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetAllTagsFromUser() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetUserTagWitRelationToFavedPosts() got = %v, want %v", got, tt.want) t.Errorf("GetAllTagsFromUser() got = %v, want %v", got, tt.want)
} }
}) })
} }
@ -1974,3 +1985,38 @@ func Test_postgresqlConnection_migrateDatabase(t *testing.T) {
}) })
} }
} }
func checkUser(got []models.User, want []models.User) bool {
for i, user := range want {
if user.ID != got[i].ID {
return false
}
}
return true
}
func checkUserSource(got *models.UserSource, want *models.UserSource) bool {
if got == nil && want == nil {
return true
} else if got == nil || want == nil {
return false
}
if got.UserID != want.UserID {
return false
}
if got.AccountUsername != want.AccountUsername {
return false
}
if got.Source.DisplayName != want.Source.DisplayName {
return false
}
if got.Source.Domain != want.Source.Domain {
return false
}
if got.Source.Icon != want.Source.Icon {
return false
}
return true
}

19
pkg/database/source.go Normal file
View File

@ -0,0 +1,19 @@
package database
import (
"context"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models"
)
type Source interface {
// CreateSource adds a new source to the database.
CreateSource(ctx context.Context, anthroveSource *models.Source) error
// GetAllSources retrieves all sources.
GetAllSources(ctx context.Context) ([]models.Source, error)
// GetSourceByDomain retrieves a source by its URL.
GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error)
}

12
pkg/database/tag.go Normal file
View File

@ -0,0 +1,12 @@
package database
import (
"context"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models"
)
type Tag interface {
// GetAllTags retrieves all tags.
GetAllTags(ctx context.Context) ([]models.Tag, error)
}

17
pkg/database/tagalias.go Normal file
View File

@ -0,0 +1,17 @@
package database
import (
"context"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models"
)
type TagAlias interface {
CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) 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
}

17
pkg/database/taggroup.go Normal file
View File

@ -0,0 +1,17 @@
package database
import (
"context"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models"
)
type TagGroup interface {
CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID)
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
}

42
pkg/database/user.go Normal file
View File

@ -0,0 +1,42 @@
package database
import (
"context"
"git.dragse.it/anthrove/otter-space-sdk/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)
}

View File

@ -1,7 +1,5 @@
package models package models
import "google.golang.org/genproto/googleapis/type/date"
type AnthroveUserID string type AnthroveUserID string
type AnthrovePostID string type AnthrovePostID string
type AnthroveSourceID string type AnthroveSourceID string
@ -10,7 +8,8 @@ type AnthrovePostURL string
type AnthroveTagGroupName string type AnthroveTagGroupName string
type AnthroveTagAliasName string type AnthroveTagAliasName string
type AnthroveTagID string type AnthroveTagID string
type AnthroveScrapeTimeInterval date.Date type AnthroveScrapeTimeInterval int
type AnthroveUserLastScrapeTime int
type Rating string type Rating string
type TagType string type TagType string

View File

@ -26,13 +26,15 @@ func TestPostReference_TableName(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) {
po := PostReference{ po := PostReference{
PostID: tt.fields.PostID, PostID: tt.fields.PostID,
SourceID: tt.fields.SourceID, SourceID: tt.fields.SourceID,
URL: tt.fields.URL, URL: tt.fields.URL,
SourcePostID: tt.fields.SourcePostID, PostReferenceConfig: PostReferenceConfig{
FullFileURL: tt.fields.FullFileURL, SourcePostID: tt.fields.SourcePostID,
PreviewFileURL: tt.fields.PreviewFileURL, FullFileURL: tt.fields.FullFileURL,
SampleFileURL: tt.fields.SampleFileURL, PreviewFileURL: tt.fields.PreviewFileURL,
SampleFileURL: tt.fields.SampleFileURL,
},
} }
if got := po.TableName(); got != tt.want { if got := po.TableName(); got != tt.want {
t.Errorf("TableName() = %v, want %v", got, tt.want) t.Errorf("TableName() = %v, want %v", got, tt.want)

View File

@ -1,13 +1,18 @@
package models package models
import "time"
type UserSource struct { type UserSource struct {
User User `gorm:"foreignKey:ID;references:UserID"` User User `gorm:"foreignKey:ID;references:UserID"`
UserID string `gorm:"primaryKey"` UserID string `gorm:"primaryKey"`
Source Source `gorm:"foreignKey:ID;references:SourceID"` Source Source `gorm:"foreignKey:ID;references:SourceID"`
SourceID string `gorm:"primaryKey"` SourceID string `gorm:"primaryKey"`
ScrapeTimeInterval string ScrapeTimeInterval string
AccountUsername string AccountUsername string
AccountID string AccountID string
LastScrapeTime time.Time
AccountValidate bool
AccountValidationKey string
} }
func (UserSource) TableName() string { func (UserSource) TableName() string {

View File

@ -3,15 +3,17 @@ package test
import ( import (
"context" "context"
"database/sql" "database/sql"
"net/url"
"strconv"
"strings"
"time"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models"
migrate "github.com/rubenv/sql-migrate" migrate "github.com/rubenv/sql-migrate"
postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres" postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres"
"gorm.io/driver/postgres" "gorm.io/driver/postgres"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
"net/url"
"strconv"
"strings"
"github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait" "github.com/testcontainers/testcontainers-go/wait"
@ -21,7 +23,7 @@ const (
databaseName = "anthrove" databaseName = "anthrove"
databaseUser = "anthrove" databaseUser = "anthrove"
databasePassword = "anthrove" databasePassword = "anthrove"
migrationSource = "../../pkg/database/migrations" migrationSource = "../../pkg/database/migrations/"
) )
func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresContainer, *gorm.DB, error) { func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresContainer, *gorm.DB, error) {
@ -32,7 +34,9 @@ func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresCon
postgrescontainer.WithUsername(databaseUser), postgrescontainer.WithUsername(databaseUser),
postgrescontainer.WithPassword(databasePassword), postgrescontainer.WithPassword(databasePassword),
testcontainers.WithWaitStrategy( testcontainers.WithWaitStrategy(
wait.ForLog("database system is ready to accept connections"))) wait.ForLog("database system is ready to accept connections").
WithOccurrence(2).WithStartupTimeout(60*time.Second)),
)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -88,12 +92,12 @@ func DatabaseModesFromConnectionString(ctx context.Context, pgContainer *postgre
return nil, err return nil, err
} }
url, err := url.Parse(connectionString) connectionStringUrl, err := url.Parse(connectionString)
if err != nil { if err != nil {
return nil, err return nil, err
} }
split := strings.Split(url.Host, ":") split := strings.Split(connectionStringUrl.Host, ":")
host := split[0] host := split[0]
port, err := strconv.Atoi(split[1]) port, err := strconv.Atoi(split[1])
@ -101,10 +105,10 @@ func DatabaseModesFromConnectionString(ctx context.Context, pgContainer *postgre
return nil, err return nil, err
} }
database := strings.TrimPrefix(url.Path, "/") database := strings.TrimPrefix(connectionStringUrl.Path, "/")
username := url.User.Username() username := connectionStringUrl.User.Username()
password, _ := url.User.Password() password, _ := connectionStringUrl.User.Password()
return &models.DatabaseConfig{ return &models.DatabaseConfig{
Endpoint: host, Endpoint: host,