diff --git a/.gitignore b/.gitignore index 83411c1..9adc1a5 100644 --- a/.gitignore +++ b/.gitignore @@ -192,3 +192,4 @@ $RECYCLE.BIN/ .env +main.go diff --git a/internal/user.go b/internal/user.go index 89c9aa2..d4f97c2 100644 --- a/internal/user.go +++ b/internal/user.go @@ -3,6 +3,7 @@ package internal import ( "context" "fmt" + "git.dragse.it/anthrove/otter-space-sdk/internal/utils" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "github.com/neo4j/neo4j-go-driver/v5/neo4j" @@ -315,3 +316,88 @@ func GetAllAnthroveUserIDs(ctx context.Context, driver neo4j.DriverWithContext) return anthroveUsers, nil } + +func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { + var err error + var favoritePosts []models.FavoritePost + + query := ` + CALL { + MATCH (user:User{user_id: $anthrove_user_id})-[r:FAV]->(p:AnthrovePost) + RETURN p.post_id AS post_id + ORDER BY id(p) ASC + SKIP $skip + LIMIT $limit + } + WITH collect(post_id) AS faves + MATCH (a:AnthrovePost)<-[r:REFERENCE]-(s:Source) + WHERE a.post_id in faves + RETURN a AS anthrovePost, r AS postRelation, s AS Source + ` + params := map[string]any{ + "anthrove_user_id": anthroveUserID, + "limit": limit, + "skip": skip, + } + + result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) + if err != nil { + return nil, err + } + + if len(result.Records) == 0 { + return nil, nil + } + + for i := range result.Records { + record := result.Records[i] + + anthrovePost, _, err := neo4j.GetRecordValue[neo4j.Node](record, "anthrovePost") + if err != nil { + return nil, err + } + + postRelation, _, err := neo4j.GetRecordValue[neo4j.Relationship](record, "postRelation") + if err != nil { + return nil, err + } + + source, _, err := neo4j.GetRecordValue[neo4j.Node](record, "Source") + if err != nil { + return nil, err + } + + if len(favoritePosts) != 0 && favoritePosts[len(favoritePosts)-1].AnthrovePost.PostID == models.AnthrovePostID(anthrovePost.Props["post_id"].(string)) { + favoritePosts[len(favoritePosts)-1].Relations = append(favoritePosts[len(favoritePosts)-1].Relations, models.FavoriteRelations{ + SourcesID: source.Props["display_name"].(string), + Relations: models.AnthrovePostRelationship{ + PostID: postRelation.Props["source_post_id"].(string), + Url: postRelation.Props["url"].(string), + }, + }) + } else { + favoritePosts = append(favoritePosts, models.FavoritePost{ + AnthrovePost: models.AnthrovePost{ + PostID: models.AnthrovePostID(anthrovePost.Props["post_id"].(string)), + Rating: models.AnthroveRating(anthrovePost.Props["rating"].(string)), + }, + Relations: []models.FavoriteRelations{{ + SourcesID: source.Props["display_name"].(string), + Relations: models.AnthrovePostRelationship{ + PostID: postRelation.Props["source_post_id"].(string), + Url: postRelation.Props["url"].(string), + }, + }}, + }) + + } + + } + + log.WithFields(log.Fields{ + "anthrove_user_fav_count": len(favoritePosts), + }).Trace("graph: got al anthrove user favorites") + + return &models.FavoriteList{Posts: favoritePosts}, nil + +} diff --git a/pkg/graph/graph.go b/pkg/graph/graph.go index 140b8cd..a824319 100644 --- a/pkg/graph/graph.go +++ b/pkg/graph/graph.go @@ -27,6 +27,7 @@ package graph import ( "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" ) @@ -86,7 +87,7 @@ type OtterSpace interface { // It returns a map of source domains to user-source relationships, and an error if the operation fails. GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) - // GetUserSourceLinks retrieves the links between a user and sources in the OtterSpace graph. + // GetSpecifiedUserSourceLink GetUserSourceLinks retrieves the links between a user and a specific source in the OtterSpace graph. // It returns a map of source domains to user-source relationships, and an error if the operation fails. GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) @@ -97,4 +98,7 @@ type OtterSpace interface { // GetAllAnthroveUserIDs retrieves all user IDs from the OtterSpace graph. // It returns a slice of user IDs and an error if the operation fails. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) + + // GetUserFavoritePostsWithPagination gets all user favorites with relation and sources for the given user + GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) } diff --git a/pkg/graph/impl.go b/pkg/graph/impl.go index ca5fd15..4db1b3f 100644 --- a/pkg/graph/impl.go +++ b/pkg/graph/impl.go @@ -96,6 +96,10 @@ func (g *graphConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.A return internal.GetAllAnthroveUserIDs(ctx, g.driver) } +func (g *graphConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { + return internal.GetUserFavoriteNodeWithPagination(ctx, g.driver, anthroveUserID, skip, limit) +} + func logger(graphDebug bool) func(config *config.Config) { return func(config *config.Config) { config.Log = internal.NewGraphLogger(graphDebug) diff --git a/pkg/models/api.go b/pkg/models/api.go new file mode 100644 index 0000000..0c2da29 --- /dev/null +++ b/pkg/models/api.go @@ -0,0 +1,15 @@ +package models + +type FavoriteRelations struct { + SourcesID string `json:"sources_id"` + Relations AnthrovePostRelationship `json:"relations"` +} + +type FavoritePost struct { + AnthrovePost AnthrovePost `json:"anthrove_post"` + Relations []FavoriteRelations `json:"relations"` +} + +type FavoriteList struct { + Posts []FavoritePost `json:"posts,omitempty"` +}