♻️ Globally apply the V2 api
This commit is contained in:
parent
c51721505f
commit
4901557217
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
# 默认忽略的文件
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# 基于编辑器的 HTTP 客户端请求
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
9
.idea/Interactive.iml
generated
9
.idea/Interactive.iml
generated
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="WEB_MODULE" version="4">
|
|
||||||
<component name="Go" enabled="true" />
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$" />
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
12
.idea/dataSources.xml
generated
12
.idea/dataSources.xml
generated
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
|
||||||
<data-source source="LOCAL" name="hy_interactive@localhost" uuid="a2f70c83-03f8-4240-bb8b-ac697502cfe2">
|
|
||||||
<driver-ref>postgresql</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:postgresql://localhost:5432/hy_interactive</jdbc-url>
|
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
|
||||||
</data-source>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
6
.idea/inspectionProfiles/Project_Default.xml
generated
6
.idea/inspectionProfiles/Project_Default.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/Interactive.iml" filepath="$PROJECT_DIR$/.idea/Interactive.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -65,7 +65,7 @@ func apUserOutbox(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var activities []activitypub.Item
|
var activities []activitypub.Item
|
||||||
if posts, err := services.ListPost(tx, limit, (page-1)*limit, "published_at DESC", nil); err != nil {
|
if posts, err := services.ListPostV1(tx, limit, (page-1)*limit, "published_at DESC", nil); err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
} else {
|
} else {
|
||||||
for _, post := range posts {
|
for _, post := range posts {
|
||||||
|
@ -59,7 +59,6 @@ func MapControllers(app *fiber.App, baseURL string) {
|
|||||||
posts := api.Group("/posts").Name("Posts API")
|
posts := api.Group("/posts").Name("Posts API")
|
||||||
{
|
{
|
||||||
posts.Get("/", listPost)
|
posts.Get("/", listPost)
|
||||||
posts.Get("/v2", listPostV2)
|
|
||||||
posts.Get("/search", searchPost)
|
posts.Get("/search", searchPost)
|
||||||
posts.Get("/minimal", listPostMinimal)
|
posts.Get("/minimal", listPostMinimal)
|
||||||
posts.Get("/drafts", listDraftPost)
|
posts.Get("/drafts", listDraftPost)
|
||||||
|
@ -26,17 +26,26 @@ func getPost(c *fiber.Ctx) error {
|
|||||||
var item models.Post
|
var item models.Post
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
tx := database.C
|
var userId *uint
|
||||||
|
if user, authenticated := c.Locals("user").(authm.Account); authenticated {
|
||||||
|
userId = &user.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := database.C
|
||||||
if tx, err = services.UniversalPostFilter(c, tx, services.UniversalPostFilterConfig{
|
if tx, err = services.UniversalPostFilter(c, tx, services.UniversalPostFilterConfig{
|
||||||
ShowReply: true,
|
ShowReply: true,
|
||||||
ShowDraft: true,
|
ShowDraft: true,
|
||||||
|
ShowCollapsed: true,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if numericId, paramErr := strconv.Atoi(id); paramErr == nil {
|
if numericId, paramErr := strconv.Atoi(id); paramErr == nil {
|
||||||
item, err = services.GetPost(tx, uint(numericId))
|
if c.Get("X-API-Version", "1") == "2" {
|
||||||
|
item, err = queries.GetPost(tx, uint(numericId), userId)
|
||||||
|
} else {
|
||||||
|
item, err = services.GetPost(tx, uint(numericId))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
segments := strings.Split(id, ":")
|
segments := strings.Split(id, ":")
|
||||||
if len(segments) != 2 {
|
if len(segments) != 2 {
|
||||||
@ -44,7 +53,11 @@ func getPost(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
area := segments[0]
|
area := segments[0]
|
||||||
alias := segments[1]
|
alias := segments[1]
|
||||||
item, err = services.GetPostByAlias(tx, alias, area)
|
if c.Get("X-API-Version", "1") == "2" {
|
||||||
|
item, err = queries.GetPostByAlias(tx, alias, area, userId)
|
||||||
|
} else {
|
||||||
|
item, err = services.GetPostByAlias(tx, alias, area)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -88,22 +101,27 @@ func searchPost(c *fiber.Ctx) error {
|
|||||||
userId = &user.ID
|
userId = &user.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var count int64
|
||||||
countTx := tx
|
countTx := tx
|
||||||
count, err := services.CountPost(countTx)
|
count, err = services.CountPost(countTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := services.ListPost(tx, take, offset, "published_at DESC", userId)
|
var items []models.Post
|
||||||
|
|
||||||
|
if c.Get("X-API-Version", "1") == "2" {
|
||||||
|
items, err = queries.ListPost(tx, take, offset, "published_at DESC", userId)
|
||||||
|
} else {
|
||||||
|
items, err = services.ListPostV1(tx, take, offset, "published_at DESC", userId)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.QueryBool("truncate", true) {
|
if c.QueryBool("truncate", true) {
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
if item != nil {
|
item = services.TruncatePostContent(item)
|
||||||
item = lo.ToPtr(services.TruncatePostContent(*item))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,54 +147,20 @@ func listPost(c *fiber.Ctx) error {
|
|||||||
userId = &user.ID
|
userId = &user.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var count int64
|
||||||
countTx := tx
|
countTx := tx
|
||||||
count, err := services.CountPost(countTx)
|
count, err = services.CountPost(countTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := services.ListPost(tx, take, offset, "published_at DESC", userId)
|
var items []models.Post
|
||||||
if err != nil {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
if c.Get("X-API-Version", "1") == "2" {
|
||||||
|
items, err = queries.ListPost(tx, take, offset, "published_at DESC", userId)
|
||||||
|
} else {
|
||||||
|
items, err = services.ListPostV1(tx, take, offset, "published_at DESC", userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.QueryBool("truncate", true) {
|
|
||||||
for _, item := range items {
|
|
||||||
if item != nil {
|
|
||||||
item = lo.ToPtr(services.TruncatePostContent(*item))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(fiber.Map{
|
|
||||||
"count": count,
|
|
||||||
"data": items,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func listPostV2(c *fiber.Ctx) error {
|
|
||||||
take := c.QueryInt("take", 10)
|
|
||||||
offset := c.QueryInt("offset", 0)
|
|
||||||
|
|
||||||
tx := database.C
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if tx, err = services.UniversalPostFilter(c, tx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var userId *uint
|
|
||||||
if user, authenticated := c.Locals("user").(authm.Account); authenticated {
|
|
||||||
userId = &user.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
countTx := tx
|
|
||||||
count, err := services.CountPost(countTx)
|
|
||||||
if err != nil {
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
items, err := queries.ListPostV2(tx, take, offset, "published_at DESC", userId)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
@ -238,6 +222,7 @@ func listDraftPost(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
user := c.Locals("user").(authm.Account)
|
user := c.Locals("user").(authm.Account)
|
||||||
|
|
||||||
|
var err error
|
||||||
tx := services.FilterPostWithAuthorDraft(database.C, user.ID)
|
tx := services.FilterPostWithAuthorDraft(database.C, user.ID)
|
||||||
|
|
||||||
var userId *uint
|
var userId *uint
|
||||||
@ -245,21 +230,27 @@ func listDraftPost(c *fiber.Ctx) error {
|
|||||||
userId = &user.ID
|
userId = &user.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := services.CountPost(tx)
|
var count int64
|
||||||
|
countTx := tx
|
||||||
|
count, err = services.CountPost(countTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := services.ListPost(tx, take, offset, "created_at DESC", userId, true)
|
var items []models.Post
|
||||||
|
|
||||||
|
if c.Get("X-API-Version", "1") == "2" {
|
||||||
|
items, err = queries.ListPost(tx, take, offset, "published_at DESC", userId)
|
||||||
|
} else {
|
||||||
|
items, err = services.ListPostV1(tx, take, offset, "published_at DESC", userId)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.QueryBool("truncate", true) {
|
if c.QueryBool("truncate", true) {
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
if item != nil {
|
item = services.TruncatePostContent(item)
|
||||||
item = lo.ToPtr(services.TruncatePostContent(*item))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ func listPinnedPost(c *fiber.Ctx) error {
|
|||||||
userId = &user.ID
|
userId = &user.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := services.ListPost(tx, 100, 0, "published_at DESC", userId)
|
items, err := services.ListPostV1(tx, 100, 0, "published_at DESC", userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ func listRecommendation(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tx := database.C.Where("id IN ?", postIdx)
|
tx := database.C.Where("id IN ?", postIdx)
|
||||||
newPosts, err := services.ListPost(tx, featuredMax, 0, "id ASC", userId)
|
newPosts, err := services.ListPostV1(tx, featuredMax, 0, "id ASC", userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ func listRecommendationShuffle(c *fiber.Ctx) error {
|
|||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := services.ListPost(tx, take, offset, "RANDOM()", userId)
|
items, err := services.ListPostV1(tx, take, offset, "RANDOM()", userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ func getRecommendationFeed(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
var cursorTime *time.Time
|
var cursorTime *time.Time
|
||||||
if cursor > 0 {
|
if cursor > 0 {
|
||||||
cursorTime = lo.ToPtr(time.UnixMilli(int64(cursor) + 1))
|
cursorTime = lo.ToPtr(time.UnixMilli(int64(cursor - 1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
var userId *uint
|
var userId *uint
|
||||||
|
@ -47,7 +47,7 @@ func listPostReplies(c *fiber.Ctx) error {
|
|||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := services.ListPost(tx, take, offset, "published_at DESC", userId)
|
items, err := services.ListPostV1(tx, take, offset, "published_at DESC", userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ func listPostFeaturedReply(c *fiber.Ctx) error {
|
|||||||
tx = services.FilterPostWithTag(tx, c.Query("tag"))
|
tx = services.FilterPostWithTag(tx, c.Query("tag"))
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := services.ListPost(tx, take, 0, "(COALESCE(total_upvote, 0) - COALESCE(total_downvote, 0)) DESC, published_at DESC", userId)
|
items, err := services.ListPostV1(tx, take, 0, "(COALESCE(total_upvote, 0) - COALESCE(total_downvote, 0)) DESC, published_at DESC", userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func getWhatsNew(c *fiber.Ctx) error {
|
|||||||
order = "published_at DESC, (COALESCE(total_upvote, 0) - COALESCE(total_downvote, 0)) DESC"
|
order = "published_at DESC, (COALESCE(total_upvote, 0) - COALESCE(total_downvote, 0)) DESC"
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := services.ListPost(tx, 10, 0, order, userId)
|
items, err := services.ListPostV1(tx, 10, 0, order, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -79,14 +79,14 @@ func GetFeed(c *fiber.Ctx, limit int, user *uint, cursor *time.Time) ([]FeedEntr
|
|||||||
// Only manage to pulling the content only
|
// Only manage to pulling the content only
|
||||||
|
|
||||||
func ListPostForFeed(tx *gorm.DB, limit int, user *uint) ([]FeedEntry, error) {
|
func ListPostForFeed(tx *gorm.DB, limit int, user *uint) ([]FeedEntry, error) {
|
||||||
posts, err := ListPost(tx, limit, -1, "published_at DESC", user)
|
posts, err := ListPostV1(tx, limit, -1, "published_at DESC", user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
entries := lo.Map(posts, func(post *models.Post, _ int) FeedEntry {
|
entries := lo.Map(posts, func(post models.Post, _ int) FeedEntry {
|
||||||
return FeedEntry{
|
return FeedEntry{
|
||||||
Type: "interactive.post",
|
Type: "interactive.post",
|
||||||
Data: TruncatePostContent(*post),
|
Data: TruncatePostContent(post),
|
||||||
CreatedAt: post.CreatedAt,
|
CreatedAt: post.CreatedAt,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -339,14 +339,7 @@ func PreloadGeneral(tx *gorm.DB) *gorm.DB {
|
|||||||
Preload("Tags").
|
Preload("Tags").
|
||||||
Preload("Categories").
|
Preload("Categories").
|
||||||
Preload("Publisher").
|
Preload("Publisher").
|
||||||
Preload("ReplyTo").
|
Preload("Poll")
|
||||||
Preload("ReplyTo.Publisher").
|
|
||||||
Preload("ReplyTo.Tags").
|
|
||||||
Preload("ReplyTo.Categories").
|
|
||||||
Preload("RepostTo").
|
|
||||||
Preload("RepostTo.Publisher").
|
|
||||||
Preload("RepostTo.Tags").
|
|
||||||
Preload("RepostTo.Categories")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPost(tx *gorm.DB, id uint) (models.Post, error) {
|
func GetPost(tx *gorm.DB, id uint) (models.Post, error) {
|
||||||
@ -403,7 +396,7 @@ func CountPostReactions(id uint) int64 {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListPost(tx *gorm.DB, take int, offset int, order any, user *uint, noReact ...bool) ([]*models.Post, error) {
|
func ListPostV1(tx *gorm.DB, take int, offset int, order any, user *uint, noReact ...bool) ([]models.Post, error) {
|
||||||
if take > 100 {
|
if take > 100 {
|
||||||
take = 100
|
take = 100
|
||||||
}
|
}
|
||||||
@ -415,77 +408,64 @@ func ListPost(tx *gorm.DB, take int, offset int, order any, user *uint, noReact
|
|||||||
tx = tx.Offset(offset)
|
tx = tx.Offset(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
var items []*models.Post
|
tx = tx.Preload("Tags").
|
||||||
if err := PreloadGeneral(tx).
|
Preload("Categories").
|
||||||
Order(order).
|
Preload("Publisher")
|
||||||
Find(&items).Error; err != nil {
|
|
||||||
return items, err
|
// Fetch posts
|
||||||
|
var posts []models.Post
|
||||||
|
if err := tx.Order(order).Find(&posts).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
idx := lo.Map(items, func(item *models.Post, index int) uint {
|
// If no posts found, return early
|
||||||
return item.ID
|
if len(posts) == 0 {
|
||||||
})
|
return posts, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Load reactions
|
// Collect post IDs
|
||||||
if len(noReact) <= 0 || !noReact[0] {
|
idx := make([]uint, len(posts))
|
||||||
if mapping, err := BatchListPostReactions(database.C.Where("post_id IN ?", idx), "post_id"); err != nil {
|
itemMap := make(map[uint]*models.Post, len(posts))
|
||||||
return items, err
|
for i, item := range posts {
|
||||||
} else {
|
idx[i] = item.ID
|
||||||
itemMap := lo.SliceToMap(items, func(item *models.Post) (uint, *models.Post) {
|
itemMap[item.ID] = &item
|
||||||
return item.ID, item
|
}
|
||||||
})
|
|
||||||
|
|
||||||
for k, v := range mapping {
|
// Batch load reactions
|
||||||
if post, ok := itemMap[k]; ok {
|
if mapping, err := BatchListPostReactions(database.C.Where("post_id IN ?", idx), "post_id"); err != nil {
|
||||||
post.Metric = models.PostMetric{
|
return posts, err
|
||||||
ReactionList: v,
|
} else {
|
||||||
}
|
for postID, reactions := range mapping {
|
||||||
}
|
if post, exists := itemMap[postID]; exists {
|
||||||
|
post.Metric.ReactionList = reactions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load replies
|
// Batch load reply counts efficiently
|
||||||
if len(noReact) <= 0 || !noReact[0] {
|
var replies []struct {
|
||||||
var replies []struct {
|
PostID uint
|
||||||
PostID uint
|
Count int64
|
||||||
Count int64
|
}
|
||||||
}
|
if err := database.C.Model(&models.Post{}).
|
||||||
|
Select("reply_id as post_id, COUNT(id) as count").
|
||||||
if err := database.C.Model(&models.Post{}).
|
Where("reply_id IN (?)", idx).
|
||||||
Select("reply_id as post_id, COUNT(id) as count").
|
Group("post_id").
|
||||||
Where("reply_id IN (?)", idx).
|
Find(&replies).Error; err != nil {
|
||||||
Group("post_id").
|
return posts, err
|
||||||
Scan(&replies).Error; err != nil {
|
}
|
||||||
return items, err
|
for _, info := range replies {
|
||||||
}
|
if post, exists := itemMap[info.PostID]; exists {
|
||||||
|
post.Metric.ReplyCount = info.Count
|
||||||
itemMap := lo.SliceToMap(items, func(item *models.Post) (uint, *models.Post) {
|
|
||||||
return item.ID, item
|
|
||||||
})
|
|
||||||
|
|
||||||
list := map[uint]int64{}
|
|
||||||
for _, info := range replies {
|
|
||||||
list[info.PostID] = info.Count
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range list {
|
|
||||||
if post, ok := itemMap[k]; ok {
|
|
||||||
post.Metric = models.PostMetric{
|
|
||||||
ReactionList: post.Metric.ReactionList,
|
|
||||||
ReplyCount: v,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add post views for the user
|
||||||
if user != nil {
|
if user != nil {
|
||||||
AddPostViews(lo.Map(items, func(item *models.Post, index int) models.Post {
|
AddPostViews(posts, *user)
|
||||||
return *item
|
|
||||||
}), *user)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return items, nil
|
return posts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListPostMinimal(tx *gorm.DB, take int, offset int, order any) ([]*models.Post, error) {
|
func ListPostMinimal(tx *gorm.DB, take int, offset int, order any) ([]*models.Post, error) {
|
||||||
|
@ -2,6 +2,7 @@ package queries
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
|
||||||
"git.solsynth.dev/hypernet/interactive/pkg/internal/database"
|
"git.solsynth.dev/hypernet/interactive/pkg/internal/database"
|
||||||
@ -19,47 +20,18 @@ import (
|
|||||||
|
|
||||||
var singularAttachmentFields = []string{"video", "thumbnail"}
|
var singularAttachmentFields = []string{"video", "thumbnail"}
|
||||||
|
|
||||||
// This api still is experimental and finally with replace the old one
|
func CompletePostMeta(in ...models.Post) ([]models.Post, error) {
|
||||||
// Some changes between ListPost and ListPostV2:
|
|
||||||
// - Post reply to and repost to are not included
|
|
||||||
func ListPostV2(tx *gorm.DB, take int, offset int, order any, user *uint) ([]models.Post, error) {
|
|
||||||
if take > 100 {
|
|
||||||
take = 100
|
|
||||||
}
|
|
||||||
|
|
||||||
if take >= 0 {
|
|
||||||
tx = tx.Limit(take)
|
|
||||||
}
|
|
||||||
if offset >= 0 {
|
|
||||||
tx = tx.Offset(offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
tx = tx.Preload("Tags").
|
|
||||||
Preload("Categories").
|
|
||||||
Preload("Publisher")
|
|
||||||
|
|
||||||
// Fetch posts
|
|
||||||
var posts []models.Post
|
|
||||||
if err := tx.Order(order).Find(&posts).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no posts found, return early
|
|
||||||
if len(posts) == 0 {
|
|
||||||
return posts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect post IDs
|
// Collect post IDs
|
||||||
idx := make([]uint, len(posts))
|
idx := make([]uint, len(in))
|
||||||
itemMap := make(map[uint]*models.Post, len(posts))
|
itemMap := make(map[uint]*models.Post, len(in))
|
||||||
for i, item := range posts {
|
for i, item := range in {
|
||||||
idx[i] = item.ID
|
idx[i] = item.ID
|
||||||
itemMap[item.ID] = &item
|
itemMap[item.ID] = &item
|
||||||
}
|
}
|
||||||
|
|
||||||
// Batch load reactions
|
// Batch load reactions
|
||||||
if mapping, err := services.BatchListPostReactions(database.C.Where("post_id IN ?", idx), "post_id"); err != nil {
|
if mapping, err := services.BatchListPostReactions(database.C.Where("post_id IN ?", idx), "post_id"); err != nil {
|
||||||
return posts, err
|
return in, err
|
||||||
} else {
|
} else {
|
||||||
for postID, reactions := range mapping {
|
for postID, reactions := range mapping {
|
||||||
if post, exists := itemMap[postID]; exists {
|
if post, exists := itemMap[postID]; exists {
|
||||||
@ -78,7 +50,7 @@ func ListPostV2(tx *gorm.DB, take int, offset int, order any, user *uint) ([]mod
|
|||||||
Where("reply_id IN (?)", idx).
|
Where("reply_id IN (?)", idx).
|
||||||
Group("post_id").
|
Group("post_id").
|
||||||
Find(&replies).Error; err != nil {
|
Find(&replies).Error; err != nil {
|
||||||
return posts, err
|
return in, err
|
||||||
}
|
}
|
||||||
for _, info := range replies {
|
for _, info := range replies {
|
||||||
if post, exists := itemMap[info.PostID]; exists {
|
if post, exists := itemMap[info.PostID]; exists {
|
||||||
@ -93,12 +65,12 @@ func ListPostV2(tx *gorm.DB, take int, offset int, order any, user *uint) ([]mod
|
|||||||
// Scan records that can be load eagerly
|
// Scan records that can be load eagerly
|
||||||
var bodies []models.PostStoryBody
|
var bodies []models.PostStoryBody
|
||||||
{
|
{
|
||||||
raw, _ := json.Marshal(lo.Map(posts, func(item models.Post, _ int) map[string]any {
|
raw, _ := json.Marshal(lo.Map(in, func(item models.Post, _ int) map[string]any {
|
||||||
return item.Body
|
return item.Body
|
||||||
}))
|
}))
|
||||||
json.Unmarshal(raw, &bodies)
|
json.Unmarshal(raw, &bodies)
|
||||||
}
|
}
|
||||||
for idx, info := range posts {
|
for idx, info := range in {
|
||||||
if info.Publisher.AccountID != nil {
|
if info.Publisher.AccountID != nil {
|
||||||
usersId = append(usersId, *info.Publisher.AccountID)
|
usersId = append(usersId, *info.Publisher.AccountID)
|
||||||
}
|
}
|
||||||
@ -117,19 +89,19 @@ func ListPostV2(tx *gorm.DB, take int, offset int, order any, user *uint) ([]mod
|
|||||||
attachmentsRid = lo.Uniq(attachmentsRid)
|
attachmentsRid = lo.Uniq(attachmentsRid)
|
||||||
attachments, err := filekit.ListAttachment(gap.Nx, attachmentsRid)
|
attachments, err := filekit.ListAttachment(gap.Nx, attachmentsRid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return posts, fmt.Errorf("failed to load attachments: %v", err)
|
return in, fmt.Errorf("failed to load attachments: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Batch load publisher users
|
// Batch load publisher users
|
||||||
usersId = lo.Uniq(usersId)
|
usersId = lo.Uniq(usersId)
|
||||||
users, err := authkit.ListUser(gap.Nx, usersId)
|
users, err := authkit.ListUser(gap.Nx, usersId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return posts, fmt.Errorf("failed to load users: %v", err)
|
return in, fmt.Errorf("failed to load users: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Putting information back to data
|
// Putting information back to data
|
||||||
log.Info().Int("attachments", len(attachments)).Int("users", len(users)).Msg("Batch loaded metadata for listing post...")
|
log.Info().Int("attachments", len(attachments)).Int("users", len(users)).Msg("Batch loaded metadata for listing post...")
|
||||||
for idx, item := range posts {
|
for idx, item := range in {
|
||||||
var this []fmodels.Attachment
|
var this []fmodels.Attachment
|
||||||
if len(bodies[idx].Attachments) > 0 {
|
if len(bodies[idx].Attachments) > 0 {
|
||||||
this = lo.Filter(attachments, func(item fmodels.Attachment, _ int) bool {
|
this = lo.Filter(attachments, func(item fmodels.Attachment, _ int) bool {
|
||||||
@ -152,7 +124,90 @@ func ListPostV2(tx *gorm.DB, take int, offset int, order any, user *uint) ([]mod
|
|||||||
}
|
}
|
||||||
return acc.ID == *item.Publisher.AccountID
|
return acc.ID == *item.Publisher.AccountID
|
||||||
})
|
})
|
||||||
posts[idx] = item
|
in[idx] = item
|
||||||
|
}
|
||||||
|
|
||||||
|
return in, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPost(tx *gorm.DB, id uint, user *uint) (models.Post, error) {
|
||||||
|
var post models.Post
|
||||||
|
if err := tx.Preload("Tags").
|
||||||
|
Preload("Categories").
|
||||||
|
Preload("Publisher").
|
||||||
|
Preload("Poll").
|
||||||
|
First(&post, id).Error; err != nil {
|
||||||
|
return post, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := CompletePostMeta(post)
|
||||||
|
if err != nil {
|
||||||
|
return post, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if user != nil {
|
||||||
|
services.AddPostView(post, *user)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPostByAlias(tx *gorm.DB, alias, area string, user *uint) (models.Post, error) {
|
||||||
|
var post models.Post
|
||||||
|
if err := tx.Preload("Tags").
|
||||||
|
Preload("Categories").
|
||||||
|
Preload("Publisher").
|
||||||
|
Preload("Poll").
|
||||||
|
Where("alias = ?", alias).
|
||||||
|
Where("alias_prefix = ?", area).
|
||||||
|
First(&post).Error; err != nil {
|
||||||
|
return post, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := CompletePostMeta(post)
|
||||||
|
if err != nil {
|
||||||
|
return post, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if user != nil {
|
||||||
|
services.AddPostView(post, *user)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListPost(tx *gorm.DB, take int, offset int, order any, user *uint) ([]models.Post, error) {
|
||||||
|
if take > 100 {
|
||||||
|
take = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
if take >= 0 {
|
||||||
|
tx = tx.Limit(take)
|
||||||
|
}
|
||||||
|
if offset >= 0 {
|
||||||
|
tx = tx.Offset(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx = tx.Preload("Tags").
|
||||||
|
Preload("Categories").
|
||||||
|
Preload("Publisher").
|
||||||
|
Preload("Poll")
|
||||||
|
|
||||||
|
// Fetch posts
|
||||||
|
var posts []models.Post
|
||||||
|
if err := tx.Order(order).Find(&posts).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no posts found, return early
|
||||||
|
if len(posts) == 0 {
|
||||||
|
return posts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load data eagerly
|
||||||
|
posts, err := CompletePostMeta(posts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add post views for the user
|
// Add post views for the user
|
||||||
|
Loading…
x
Reference in New Issue
Block a user