支持 square/squarenovel/squaresteps/squarehealth 实例与 category 筛选;音乐增加免登录 grouped/track;订阅套餐按 package_name 区分;补 migration 0030/0031 与 OpenAPI。 Co-authored-by: Cursor <cursoragent@cursor.com>
218 lines
7.8 KiB
Go
218 lines
7.8 KiB
Go
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"spark-server/internal/module/square/entity"
|
|
)
|
|
|
|
// Post maps table square_posts.
|
|
type Post struct {
|
|
ID int64 `gorm:"column:id;primaryKey;autoIncrement:false;comment:Snowflake 帖 id"`
|
|
UserID int64 `gorm:"column:user_id;comment:作者 users.id"`
|
|
Channel string `gorm:"column:channel;comment:广场实例"`
|
|
Category string `gorm:"column:category;comment:内容标签"`
|
|
Kind int16 `gorm:"column:kind;comment:1纯文 2图 3视频"`
|
|
Text string `gorm:"column:text;comment:正文"`
|
|
Content []byte `gorm:"column:content;type:varbinary(16384);comment:序列化 JSON 字节"`
|
|
POILat float64 `gorm:"column:poi_lat;comment:地点纬度"`
|
|
POILng float64 `gorm:"column:poi_lng;comment:地点经度"`
|
|
POIName string `gorm:"column:poi_name;comment:地点名称"`
|
|
POIAddress string `gorm:"column:poi_address;comment:地点地址"`
|
|
Visibility int16 `gorm:"column:visibility;comment:0公开 1私密 2白名单 3黑名单"`
|
|
AuditStatus int16 `gorm:"column:audit_status;comment:0待审 1通过 2拒绝"`
|
|
AuditNote string `gorm:"column:audit_note;comment:拒绝原因"`
|
|
AuditedAt *time.Time `gorm:"column:audited_at;comment:审核时间"`
|
|
Status int16 `gorm:"column:status;comment:0正常 1已删"`
|
|
Source int16 `gorm:"column:source;comment:0用户 1机器人海外媒体RSS"`
|
|
SourceURL string `gorm:"column:source_url;comment:原文 URL"`
|
|
ExpiresAt *time.Time `gorm:"column:expires_at;comment:机器人帖过期时间"`
|
|
LikeCount int `gorm:"column:like_count;comment:点赞数"`
|
|
CommentCount int `gorm:"column:comment_count;comment:评论数"`
|
|
CreatedAt time.Time `gorm:"column:created_at;comment:发帖时间"`
|
|
}
|
|
|
|
func (Post) TableName() string { return "t_square_posts" }
|
|
|
|
func (r *Post) Entity() *entity.Post {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
ch := entity.Channel(r.Channel)
|
|
if ch == "" {
|
|
ch = entity.ChannelSquare
|
|
}
|
|
p := &entity.Post{
|
|
ID: r.ID, UserID: r.UserID, Channel: ch, Category: entity.Category(r.Category),
|
|
Kind: entity.Kind(r.Kind), Text: r.Text, Content: r.Content,
|
|
POI: entity.POI{Lat: r.POILat, Lng: r.POILng, Name: r.POIName, Address: r.POIAddress},
|
|
Visibility: entity.Visibility(r.Visibility), AuditStatus: entity.AuditStatus(r.AuditStatus),
|
|
Status: entity.Status(r.Status), Source: entity.Source(r.Source), SourceURL: r.SourceURL,
|
|
LikeCount: r.LikeCount, CommentCount: r.CommentCount, CreatedAtMS: r.CreatedAt.UnixMilli(),
|
|
}
|
|
if r.ExpiresAt != nil {
|
|
p.ExpiresAtMS = r.ExpiresAt.UnixMilli()
|
|
}
|
|
return p
|
|
}
|
|
|
|
func postFrom(p *entity.Post) *Post {
|
|
if p == nil {
|
|
return nil
|
|
}
|
|
ch := string(p.Channel)
|
|
if ch == "" {
|
|
ch = string(entity.ChannelSquare)
|
|
}
|
|
row := &Post{
|
|
ID: p.ID, UserID: p.UserID, Channel: ch, Category: string(p.Category),
|
|
Kind: int16(p.Kind), Text: p.Text, Content: p.Content,
|
|
POILat: p.POI.Lat, POILng: p.POI.Lng, POIName: p.POI.Name, POIAddress: p.POI.Address,
|
|
Visibility: int16(p.Visibility), AuditStatus: int16(p.AuditStatus), Status: int16(p.Status),
|
|
Source: int16(p.Source), SourceURL: p.SourceURL, LikeCount: p.LikeCount, CommentCount: p.CommentCount,
|
|
}
|
|
if p.CreatedAtMS > 0 {
|
|
row.CreatedAt = time.UnixMilli(p.CreatedAtMS)
|
|
}
|
|
if p.ExpiresAtMS > 0 {
|
|
t := time.UnixMilli(p.ExpiresAtMS)
|
|
row.ExpiresAt = &t
|
|
}
|
|
if p.AuditStatus == entity.AuditApproved {
|
|
t := row.CreatedAt
|
|
if t.IsZero() {
|
|
t = time.Now()
|
|
}
|
|
row.AuditedAt = &t
|
|
}
|
|
return row
|
|
}
|
|
|
|
// BotLink maps t_square_bot_links (RSS URL 去重).
|
|
type BotLink struct {
|
|
URLHash string `gorm:"column:url_hash;primaryKey;comment:URL SHA-256 hex"`
|
|
URL string `gorm:"column:url;comment:原文 URL"`
|
|
PostID int64 `gorm:"column:post_id;comment:帖 id"`
|
|
CreatedAt time.Time `gorm:"column:created_at;comment:入库时间"`
|
|
}
|
|
|
|
func (BotLink) TableName() string { return "t_square_bot_links" }
|
|
|
|
// Audience maps square_audience.
|
|
type Audience struct {
|
|
PostID int64 `gorm:"column:post_id;primaryKey;comment:帖 id"`
|
|
PeerID int64 `gorm:"column:peer_id;primaryKey;comment:好友 uid"`
|
|
}
|
|
|
|
func (Audience) TableName() string { return "t_square_audience" }
|
|
|
|
// Like maps square_likes.
|
|
type Like struct {
|
|
PostID int64 `gorm:"column:post_id;primaryKey;comment:帖 id"`
|
|
UserID int64 `gorm:"column:user_id;primaryKey;comment:点赞人"`
|
|
CreatedAt time.Time `gorm:"column:created_at;comment:点赞时间"`
|
|
}
|
|
|
|
func (Like) TableName() string { return "t_square_likes" }
|
|
|
|
func (r *Like) Entity() *entity.Like {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
return &entity.Like{PostID: r.PostID, UserID: r.UserID, CreatedAtMS: r.CreatedAt.UnixMilli()}
|
|
}
|
|
|
|
// Comment maps square_comments.
|
|
type Comment struct {
|
|
ID int64 `gorm:"column:id;primaryKey;autoIncrement:false;comment:Snowflake 评论 id"`
|
|
PostID int64 `gorm:"column:post_id;comment:帖 id"`
|
|
UserID int64 `gorm:"column:user_id;comment:评论人"`
|
|
ReplyToID int64 `gorm:"column:reply_to_id;comment:父评论 id"`
|
|
ReplyToUID int64 `gorm:"column:reply_to_uid;comment:被回复用户"`
|
|
Text string `gorm:"column:text;comment:评论文本"`
|
|
Status int16 `gorm:"column:status;comment:0正常 1已删"`
|
|
CreatedAt time.Time `gorm:"column:created_at;comment:评论时间"`
|
|
}
|
|
|
|
func (Comment) TableName() string { return "t_square_comments" }
|
|
|
|
func (r *Comment) Entity() *entity.Comment {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
return &entity.Comment{
|
|
ID: r.ID, PostID: r.PostID, UserID: r.UserID, ReplyToID: r.ReplyToID, ReplyToUID: r.ReplyToUID,
|
|
Text: r.Text, Status: entity.Status(r.Status), CreatedAtMS: r.CreatedAt.UnixMilli(),
|
|
}
|
|
}
|
|
|
|
func commentFrom(c *entity.Comment) *Comment {
|
|
if c == nil {
|
|
return nil
|
|
}
|
|
row := &Comment{
|
|
ID: c.ID, PostID: c.PostID, UserID: c.UserID, ReplyToID: c.ReplyToID, ReplyToUID: c.ReplyToUID,
|
|
Text: c.Text, Status: int16(c.Status),
|
|
}
|
|
if c.CreatedAtMS > 0 {
|
|
row.CreatedAt = time.UnixMilli(c.CreatedAtMS)
|
|
}
|
|
return row
|
|
}
|
|
|
|
// Notice maps square_notices.
|
|
type Notice struct {
|
|
ID int64 `gorm:"column:id;primaryKey;autoIncrement:false;comment:Snowflake 通知 id"`
|
|
ToUserID int64 `gorm:"column:to_user_id;comment:接收人"`
|
|
Channel string `gorm:"column:channel;comment:广场实例"`
|
|
FromUserID int64 `gorm:"column:from_user_id;comment:发起人"`
|
|
Kind int16 `gorm:"column:kind;comment:1赞 2评论 3回复"`
|
|
PostID int64 `gorm:"column:post_id;comment:帖 id"`
|
|
CommentID int64 `gorm:"column:comment_id;comment:评论 id"`
|
|
ReadAt *time.Time `gorm:"column:read_at;comment:已读时间"`
|
|
CreatedAt time.Time `gorm:"column:created_at;comment:通知时间"`
|
|
}
|
|
|
|
func (Notice) TableName() string { return "t_square_notices" }
|
|
|
|
func (r *Notice) Entity() *entity.Notice {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
ch := entity.Channel(r.Channel)
|
|
if ch == "" {
|
|
ch = entity.ChannelSquare
|
|
}
|
|
n := &entity.Notice{
|
|
ID: r.ID, ToUserID: r.ToUserID, Channel: ch, FromUserID: r.FromUserID, Kind: entity.NoticeKind(r.Kind),
|
|
PostID: r.PostID, CommentID: r.CommentID, CreatedAtMS: r.CreatedAt.UnixMilli(),
|
|
}
|
|
if r.ReadAt != nil {
|
|
n.ReadAtMS = r.ReadAt.UnixMilli()
|
|
}
|
|
return n
|
|
}
|
|
|
|
// NoticeState maps square_notice_state.
|
|
type NoticeState struct {
|
|
UserID int64 `gorm:"column:user_id;primaryKey;comment:用户 id"`
|
|
Channel string `gorm:"column:channel;primaryKey;comment:广场实例"`
|
|
LastReadNoticeID int64 `gorm:"column:last_read_notice_id;comment:已读水位"`
|
|
UpdatedAt time.Time `gorm:"column:updated_at;comment:更新时间"`
|
|
}
|
|
|
|
func (NoticeState) TableName() string { return "t_square_notice_state" }
|
|
|
|
func (r *NoticeState) Entity() *entity.NoticeState {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
ch := entity.Channel(r.Channel)
|
|
if ch == "" {
|
|
ch = entity.ChannelSquare
|
|
}
|
|
return &entity.NoticeState{
|
|
UserID: r.UserID, Channel: ch, LastReadNoticeID: r.LastReadNoticeID, UpdatedAtMS: r.UpdatedAt.UnixMilli(),
|
|
}
|
|
}
|