Files
artalkjs/server/handler/comment_list.go
qwqcode cf7725edba refactor(go): bump the module version and support go install (#979)
BREAKING CHANGE: The original Go module name was `github.com/ArtalkJS/Artalk`, which has now been modified to `github.com/artalkjs/artalk/v2` (all lowercase). This change may affect the CI pipeline or other areas if you are compiling the Artalk server and have specified the fixed Go module name. Regarding the original `-ldflags -X github.com/ArtalkJS/Artalk/internal/config.Version` and `CommitHash` definitions, please remove them, as they are now obsolete. The `Version` has been hardcoded into the Go code, and the `CommitHash` is now read from the Go build info via runtime/debug’s vcs.revision value. This change only affects the server developers and does not impact the frontend UI client.
2024-09-18 21:43:43 +08:00

166 lines
5.0 KiB
Go

package handler
import (
"errors"
"github.com/artalkjs/artalk/v2/internal/core"
"github.com/artalkjs/artalk/v2/internal/dao"
"github.com/artalkjs/artalk/v2/internal/entity"
"github.com/artalkjs/artalk/v2/internal/log"
"github.com/artalkjs/artalk/v2/server/common"
cog "github.com/artalkjs/artalk/v2/server/handler/comments_get"
"github.com/gofiber/fiber/v2"
"github.com/samber/lo"
)
type ParamsCommentList struct {
PageKey string `query:"page_key" json:"page_key" validate:"required"` // The comment page_key
SiteName string `query:"site_name" json:"site_name" validate:"optional"` // The site name of your content scope
Limit int `query:"limit" json:"limit" validate:"optional"` // The limit for pagination
Offset int `query:"offset" json:"offset" validate:"optional"` // The offset for pagination
FlatMode bool `query:"flat_mode" json:"flat_mode" validate:"optional"` // Enable flat_mode
SortBy string `query:"sort_by" json:"sort_by" enums:"date_asc,date_desc,vote" validate:"optional"` // Sort by condition
ViewOnlyAdmin bool `query:"view_only_admin" json:"view_only_admin" validate:"optional"` // Only show comments by admin
Search string `query:"search" json:"search" validate:"optional"` // Search keywords
Type string `query:"type" json:"type" enums:"all,mentions,mine,pending" validate:"optional"` // Message center show type
Scope string `query:"scope" json:"scope" enums:"page,user,site" validate:"optional"` // The scope of comments
Name string `query:"name" json:"name" validate:"optional"` // The username
Email string `query:"email" json:"email" validate:"optional"` // The user email
}
type ResponseCommentList struct {
Comments []entity.CookedComment `json:"comments"`
Count int64 `json:"count"`
RootsCount int64 `json:"roots_count"`
Page *entity.CookedPage `json:"page,omitempty"`
}
// @Id GetComments
// @Summary Get Comment List
// @Description Get a list of comments by some conditions
// @Tags Comment
// @Security ApiKeyAuth
// @Param options query ParamsCommentList true "The options"
// @Accept json
// @Produce json
// @Success 200 {object} ResponseCommentList
// @Failure 500 {object} Map{msg=string}
// @Router /comments [get]
func CommentList(app *core.App, router fiber.Router) {
router.Get("/comments", func(c *fiber.Ctx) error {
var p ParamsCommentList
if isOK, resp := common.ParamsDecode(c, &p); !isOK {
return resp
}
// Get current user
user, err := common.GetUserByReq(app, c)
if errors.Is(err, common.ErrTokenNotProvided) {
// If not login, find user by name and email
user = app.Dao().FindUser(p.Name, p.Email)
// If user is admin, but not login yet, clear user
if user.IsAdmin {
user = entity.User{}
}
}
// Query scope
scope := cog.ScopePage
if p.Scope != "" {
scope = cog.Scope(p.Scope)
}
// if query scope is page, check page exist
if scope == cog.ScopePage {
if _, ok, resp := common.CheckSiteExist(app, c, p.SiteName); !ok {
return resp
}
}
// Query options
queryOpts := cog.QueryOptions{
User: user,
Scope: scope,
SitePayload: cog.SitePayload{
Type: cog.SiteScopeType(p.Type),
SiteName: p.SiteName,
},
PagePayload: cog.PageScopePayload{
Tags: lo.If(p.ViewOnlyAdmin, []cog.PageScopeTag{cog.AdminOnly}).Else([]cog.PageScopeTag{}),
PageKey: p.PageKey,
SiteName: p.SiteName,
},
UserPayload: cog.UserScopePayload{
Type: cog.UserScopeType(p.Type),
},
SortBy: cog.SortRule(p.SortBy),
Search: p.Search,
}
// Generate query by options
comments, count, rootsCount := cog.FindComments(app.Dao(), queryOpts, cog.FindOptions{
Limit: p.Limit,
Offset: p.Offset,
Nested: !p.FlatMode,
})
// Get IP region
comments = findIPRegionForComments(app, comments)
// The response data
resp := ResponseCommentList{
Comments: comments,
Count: count,
RootsCount: rootsCount,
}
// If query scope is page, extra query page data
if scope == cog.ScopePage {
resp.Page = findPageData(app.Dao(), p.PageKey, p.SiteName)
}
return common.RespData(c, resp)
})
}
func findPageData(dao *dao.Dao, pageKey string, siteName string) *entity.CookedPage {
page := dao.FindPage(pageKey, siteName)
if page.IsEmpty() {
// If page not found, create a new one but not save it
page = entity.Page{
Key: pageKey,
SiteName: siteName,
}
}
cooked := dao.CookPage(&page)
return &cooked
}
// Find the IP region of each comment
func findIPRegionForComments(app *core.App, comments []entity.CookedComment) []entity.CookedComment {
if !app.Conf().IPRegion.Enabled {
return comments
}
ipRegionService, err := core.AppService[*core.IPRegionService](app)
if err == nil {
for i, c := range comments {
comments[i].IPRegion = ipRegionService.Query(c.IP)
}
} else {
log.Error("[IPRegionService] err: ", err)
}
return comments
}