220 lines
6.7 KiB
Go
220 lines
6.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"github.com/ArtalkJS/Artalk/internal/core"
|
|
"github.com/ArtalkJS/Artalk/internal/entity"
|
|
"github.com/ArtalkJS/Artalk/internal/log"
|
|
"github.com/ArtalkJS/Artalk/server/common"
|
|
"github.com/gofiber/fiber/v2"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type ParamsGet struct {
|
|
PageKey string `form:"page_key" validate:"required"`
|
|
SiteName string
|
|
|
|
Limit int `form:"limit"`
|
|
Offset int `form:"offset"`
|
|
|
|
FlatMode bool `form:"flat_mode"`
|
|
SortBy string `form:"sort_by"` // date_asc, date_desc, vote
|
|
ViewOnlyAdmin bool `form:"view_only_admin"` // 只看 admin
|
|
|
|
Search string `form:"search"`
|
|
|
|
// Message Center
|
|
Type string `form:"type"` // ["", "all", "mentions", "mine", "pending", "admin_all", "admin_pending"]
|
|
Name string `form:"name"`
|
|
Email string `form:"email"`
|
|
|
|
SiteID uint
|
|
SiteAll bool
|
|
|
|
IsMsgCenter bool
|
|
User *entity.User
|
|
IsAdminReq bool
|
|
}
|
|
|
|
type ResponseGet struct {
|
|
Comments []entity.CookedComment `json:"comments"`
|
|
Total int64 `json:"total"`
|
|
TotalRoots int64 `json:"total_roots"`
|
|
Page entity.CookedPage `json:"page"`
|
|
Unread []entity.CookedNotify `json:"unread"`
|
|
UnreadCount int `json:"unread_count"`
|
|
ApiVersion common.ApiVersionData `json:"api_version"`
|
|
Conf common.Map `json:"conf,omitempty"`
|
|
}
|
|
|
|
// @Summary Comment List
|
|
// @Description Get a list of comments by some conditions
|
|
// @Tags Comment
|
|
// @Param page_key formData string true "the comment page_key"
|
|
// @Param site_name formData string false "the site name of your content scope"
|
|
// @Param limit formData int false "the limit for pagination"
|
|
// @Param offset formData int false "the offset for pagination"
|
|
// @Param flat_mode formData bool false "enable flat_mode"
|
|
// @Param sort_by formData string false "sort by condition" Enums(date_asc, date_desc, vote)
|
|
// @Param view_only_admin formData bool false "only show comments by admin"
|
|
// @Param search formData string false "search keywords"
|
|
// @Param type formData string false "message center show type" Enums(all, mentions, mine, pending, admin_all, admin_pending)
|
|
// @Param name formData string false "the username"
|
|
// @Param email formData string false "the user email"
|
|
// @Security ApiKeyAuth
|
|
// @Success 200 {object} common.JSONResult{data=ResponseGet}
|
|
// @Router /get [post]
|
|
func CommentGet(app *core.App, router fiber.Router) {
|
|
router.Post("/get", func(c *fiber.Ctx) error {
|
|
var p ParamsGet
|
|
if isOK, resp := common.ParamsDecode(c, &p); !isOK {
|
|
return resp
|
|
}
|
|
|
|
// use site
|
|
common.UseSite(c, &p.SiteName, &p.SiteID, &p.SiteAll)
|
|
|
|
// handle params
|
|
UseCfgFrontend(app, &p)
|
|
|
|
// find page
|
|
var page entity.Page
|
|
if !p.SiteAll {
|
|
page = app.Dao().FindPage(p.PageKey, p.SiteName)
|
|
if page.IsEmpty() { // if page not found
|
|
page = entity.Page{
|
|
Key: p.PageKey,
|
|
SiteName: p.SiteName,
|
|
}
|
|
}
|
|
}
|
|
|
|
// find user
|
|
var user entity.User
|
|
if p.Name != "" && p.Email != "" {
|
|
user = app.Dao().FindUser(p.Name, p.Email)
|
|
p.User = &user // init params user field
|
|
}
|
|
|
|
// check if admin
|
|
if common.CheckIsAdminReq(app, c) {
|
|
p.IsAdminReq = true
|
|
}
|
|
|
|
// check if msg center
|
|
if p.Type != "" && p.Name != "" && p.Email != "" {
|
|
p.IsMsgCenter = true
|
|
p.FlatMode = true // 通知中心强制平铺模式
|
|
}
|
|
|
|
// prepare the first query
|
|
findScopes := []func(*gorm.DB) *gorm.DB{}
|
|
if !p.FlatMode {
|
|
// nested_mode prepare the root comments as first query result
|
|
findScopes = append(findScopes, RootComments())
|
|
}
|
|
if !p.IsMsgCenter {
|
|
// pinned comments ignore
|
|
findScopes = append(findScopes, func(d *gorm.DB) *gorm.DB {
|
|
return d.Where("is_pinned = ?", false) // 因为置顶是独立的查询,这里就不再查)
|
|
})
|
|
}
|
|
|
|
// search function
|
|
if p.Search != "" {
|
|
findScopes = append(findScopes, CommentSearchScope(app, p))
|
|
}
|
|
|
|
// get comments for the first query
|
|
var comments []entity.Comment
|
|
GetCommentQuery(app, c, p, p.SiteID, findScopes...).Scopes(Paginate(p.Offset, p.Limit)).Find(&comments)
|
|
|
|
// prepend the pinned comments
|
|
prependPinnedComments(app, c, p, &comments)
|
|
|
|
// cook
|
|
cookedComments := app.Dao().CookAllComments(comments)
|
|
|
|
switch {
|
|
case !p.FlatMode:
|
|
// ==========
|
|
// 层级嵌套模式
|
|
// ==========
|
|
|
|
// 获取 comment 子评论
|
|
for _, parent := range cookedComments { // TODO: Read more children, pagination for children comment
|
|
children := app.Dao().FindCommentChildren(parent.ID, SiteIsolationChecker(app, c, p), AllowedCommentChecker(app, c, p))
|
|
cookedComments = append(cookedComments, app.Dao().CookAllComments(children)...)
|
|
}
|
|
|
|
case p.FlatMode:
|
|
// ==========
|
|
// 平铺模式
|
|
// ==========
|
|
|
|
// find linked comments (被引用的评论,不单独显示)
|
|
for _, comment := range comments {
|
|
if comment.Rid == 0 || entity.ContainsCookedComment(cookedComments, comment.Rid) {
|
|
continue
|
|
}
|
|
|
|
rComment := app.Dao().FindComment(comment.Rid, SiteIsolationChecker(app, c, p)) // 查找被回复的评论
|
|
if rComment.IsEmpty() {
|
|
continue
|
|
}
|
|
|
|
rCooked := app.Dao().CookComment(&rComment)
|
|
rCooked.Visible = false // 设置为不可见
|
|
cookedComments = append(cookedComments, rCooked)
|
|
}
|
|
}
|
|
|
|
// count comments
|
|
total := CountComments(GetCommentQuery(app, c, p, p.SiteID))
|
|
totalRoots := CountComments(GetCommentQuery(app, c, p, p.SiteID, RootComments()))
|
|
|
|
// mark all as read in msg center
|
|
if p.IsMsgCenter {
|
|
app.Dao().UserNotifyMarkAllAsRead(p.User.ID)
|
|
}
|
|
|
|
// unread notifies
|
|
var unreadNotifies = []entity.CookedNotify{}
|
|
if p.User != nil {
|
|
unreadNotifies = app.Dao().CookAllNotifies(app.Dao().FindUnreadNotifies(p.User.ID))
|
|
}
|
|
|
|
// IP region query
|
|
if app.Conf().IPRegion.Enabled {
|
|
ipRegionService, err := core.AppService[*core.IPRegionService](app)
|
|
if err == nil {
|
|
nCookedComments := []entity.CookedComment{}
|
|
for _, c := range cookedComments {
|
|
rawC := app.Dao().FindComment(c.ID)
|
|
|
|
c.IPRegion = ipRegionService.Query(rawC.IP)
|
|
nCookedComments = append(nCookedComments, c)
|
|
}
|
|
cookedComments = nCookedComments
|
|
} else {
|
|
log.Error("[IPRegionService] err: ", err)
|
|
}
|
|
}
|
|
|
|
resp := ResponseGet{
|
|
Comments: cookedComments,
|
|
Total: total,
|
|
TotalRoots: totalRoots,
|
|
Page: app.Dao().CookPage(&page),
|
|
Unread: unreadNotifies,
|
|
UnreadCount: len(unreadNotifies),
|
|
ApiVersion: common.GetApiVersionDataMap(),
|
|
}
|
|
|
|
if p.Offset == 0 {
|
|
resp.Conf = common.GetApiPublicConfDataMap(app, c)
|
|
}
|
|
|
|
return common.RespData(c, resp)
|
|
})
|
|
}
|