package model import ( "context" "time" adminentity "spark-server/internal/module/admin/entity" msgentity "spark-server/internal/module/message/entity" ) func (m *Repo) ImStats(ctx context.Context) (*adminentity.ImStats, error) { db, err := m.session(ctx) if err != nil { return nil, err } out := &adminentity.ImStats{} var priv, grp, revokedPriv, revokedGrp int64 _ = db.Table("t_private_message").Count(&priv).Error _ = db.Table("t_group_message").Count(&grp).Error _ = db.Table("t_private_message").Where("status = ?", msgentity.StatusRecalled).Count(&revokedPriv).Error _ = db.Table("t_group_message").Where("status = ?", msgentity.StatusRecalled).Count(&revokedGrp).Error out.MessageCount = priv + grp out.RevokedCount = revokedPriv + revokedGrp _ = db.Table("t_conversations").Count(&out.ConversationCount).Error _ = db.Table("`t_groups`").Where("status = ?", 1).Count(&out.GroupCount).Error return out, nil } func (m *Repo) ListRecentMessages(ctx context.Context, fetchLimit int, from, to *time.Time) ([]MessageRow, error) { db, err := m.session(ctx) if err != nil { return nil, err } sql := ` SELECT id, conversation_id, sender_id, receiver_id, 0 AS group_id, client_msg_id, message_type, content, status, created_at, 'private' AS chat_type FROM t_private_message UNION ALL SELECT id, conversation_id, sender_id, 0 AS receiver_id, group_id, client_msg_id, message_type, content, status, created_at, 'group' AS chat_type FROM t_group_message` type scanRow struct { ID int64 `gorm:"column:id"` ConversationID int64 `gorm:"column:conversation_id"` SenderID int64 `gorm:"column:sender_id"` ReceiverID int64 `gorm:"column:receiver_id"` GroupID int64 `gorm:"column:group_id"` ClientMsgID string `gorm:"column:client_msg_id"` MessageType int16 `gorm:"column:message_type"` Content []byte `gorm:"column:content"` Status int `gorm:"column:status"` CreatedAt time.Time `gorm:"column:created_at"` ChatType string `gorm:"column:chat_type"` } where := " WHERE 1=1" args := make([]any, 0, 3) if from != nil { where += " AND created_at >= ?" args = append(args, *from) } if to != nil { where += " AND created_at < ?" args = append(args, *to) } args = append(args, fetchLimit) var rows []scanRow err = db.Raw(`SELECT * FROM (`+sql+`) AS m`+where+` ORDER BY created_at DESC LIMIT ?`, args...).Scan(&rows).Error if err != nil { return nil, mapDBErr(err) } out := make([]MessageRow, 0, len(rows)) for i := range rows { out = append(out, MessageRow(rows[i])) } return out, nil } func (m *Repo) ListUserConversations(ctx context.Context, userID int64) ([]ConversationRow, error) { db, err := m.session(ctx) if err != nil { return nil, err } type scanRow struct { ID int64 `gorm:"column:id"` Type int `gorm:"column:type"` LastMsgID int64 `gorm:"column:last_msg_id"` LastMsgAt time.Time `gorm:"column:last_msg_at"` UserSmall int64 `gorm:"column:user_small"` UserBig int64 `gorm:"column:user_big"` GroupID int64 `gorm:"column:group_id"` GroupName string `gorm:"column:group_name"` } var rows []scanRow err = db.Raw(` SELECT c.id, c.type, c.last_msg_id, c.last_msg_at, COALESCE(p.user_small, 0) AS user_small, COALESCE(p.user_big, 0) AS user_big, COALESCE(g.id, 0) AS group_id, COALESCE(g.name, '') AS group_name FROM t_conversation_members cm INNER JOIN t_conversations c ON c.id = cm.conversation_id LEFT JOIN t_p2p_conversations p ON p.conversation_id = c.id LEFT JOIN `+"`t_groups`"+` g ON g.conversation_id = c.id WHERE cm.user_id = ? ORDER BY c.last_msg_at DESC LIMIT 200`, userID).Scan(&rows).Error if err != nil { return nil, mapDBErr(err) } out := make([]ConversationRow, 0, len(rows)) for i := range rows { out = append(out, ConversationRow(rows[i])) } return out, nil } func (m *Repo) ListGroupMessages(ctx context.Context, groupID int64, limit int) ([]MessageRow, error) { db, err := m.session(ctx) if err != nil { return nil, err } type scanRow struct { ID int64 `gorm:"column:id"` ConversationID int64 `gorm:"column:conversation_id"` SenderID int64 `gorm:"column:sender_id"` ReceiverID int64 `gorm:"column:receiver_id"` GroupID int64 `gorm:"column:group_id"` ClientMsgID string `gorm:"column:client_msg_id"` MessageType int16 `gorm:"column:message_type"` Content []byte `gorm:"column:content"` Status int `gorm:"column:status"` CreatedAt time.Time `gorm:"column:created_at"` ChatType string `gorm:"column:chat_type"` } var rows []scanRow err = db.Raw(` SELECT id, conversation_id, sender_id, 0 AS receiver_id, group_id, client_msg_id, message_type, content, status, created_at, 'group' AS chat_type FROM t_group_message WHERE group_id = ? ORDER BY created_at DESC LIMIT ?`, groupID, limit).Scan(&rows).Error if err != nil { return nil, mapDBErr(err) } out := make([]MessageRow, 0, len(rows)) for i := range rows { out = append(out, MessageRow(rows[i])) } return out, nil }