package logic import ( "fmt" "strconv" "strings" "time" adminentity "spark-server/internal/module/admin/entity" adminmodel "spark-server/internal/module/admin/model" groupentity "spark-server/internal/module/group/entity" msgentity "spark-server/internal/module/message/entity" userentity "spark-server/internal/module/user/entity" ) func messageView(r adminmodel.MessageRow) adminentity.ImMessageView { return adminentity.ImMessageView{ ID: strconv.FormatInt(r.ID, 10), ClientMsgID: r.ClientMsgID, From: r.SenderID, To: r.ReceiverID, GroupID: r.GroupID, ChatType: r.ChatType, Type: msgTypeName(msgentity.Type(r.MessageType)), Text: previewText(r.Content, msgentity.Type(r.MessageType)), Revoked: r.Status == int(msgentity.StatusRecalled), Ts: r.CreatedAt.UnixMilli(), } } func messageMatch(v adminentity.ImMessageView, q string) bool { ql := strings.ToLower(q) if strings.Contains(strings.ToLower(v.Text), ql) { return true } if strings.Contains(strings.ToLower(v.ID), ql) { return true } if strings.Contains(strings.ToLower(v.Type), ql) { return true } if strings.Contains(strconv.FormatInt(v.From, 10), q) { return true } if v.To > 0 && strings.Contains(strconv.FormatInt(v.To, 10), q) { return true } if v.GroupID > 0 && strings.Contains(strconv.FormatInt(v.GroupID, 10), q) { return true } return false } func msgTypeName(t msgentity.Type) string { switch t { case msgentity.TypeText: return "text" case msgentity.TypeImage: return "image" case msgentity.TypeVoice: return "voice" case msgentity.TypeVideo: return "video" case msgentity.TypeEmoji: return "emoji" case msgentity.TypeGIF: return "gif" case msgentity.TypeFile: return "file" case msgentity.TypeLocation: return "location" case msgentity.TypeSystem: return "system" default: return fmt.Sprintf("type_%d", t) } } func previewText(raw []byte, t msgentity.Type) string { c, err := msgentity.UnmarshalContent(raw) if err != nil || c == nil { return "" } switch t { case msgentity.TypeText: if c.Text != nil { return c.Text.Body } case msgentity.TypeImage: return "[图片]" case msgentity.TypeVoice: return "[语音]" case msgentity.TypeVideo: return "[视频]" case msgentity.TypeEmoji: return "[表情]" case msgentity.TypeGIF: return "[GIF]" case msgentity.TypeFile: if c.File != nil && c.File.Name != "" { return "[文件] " + c.File.Name } return "[文件]" case msgentity.TypeLocation: if c.Location != nil && c.Location.Name != "" { return "[位置] " + c.Location.Name } return "[位置]" case msgentity.TypeSystem: if c.System != nil { if c.System.Body != "" { return c.System.Body } return c.System.Kind } } return "" } func userView(r adminmodel.UserRow) adminentity.UserView { v := adminentity.UserView{ ID: r.ID, Email: r.Email, Nickname: r.Nickname, SparkID: r.SparkID, AvatarURL: r.Avatar, Channel: r.Platform, Status: r.Status, Banned: r.Status == int(userentity.StatusDisabled), CreatedAt: r.CreatedAt.Format(time.RFC3339), } if r.DeviceID > 0 { v.DeviceID = strconv.FormatUint(r.DeviceID, 10) } if r.LastActiveAt != nil { v.LastActiveAt = r.LastActiveAt.Format(time.RFC3339) } return v } func groupSummary(r adminmodel.GroupRow) adminentity.GroupView { return adminentity.GroupView{ GroupID: strconv.FormatInt(r.ID, 10), Name: r.Name, Avatar: r.Avatar, OwnerID: r.OwnerID, MuteAll: r.MutedAll != 0, MemberCount: r.MemberCount, Active: r.Status == int(groupentity.StatusActive), UpdatedAt: r.UpdatedAt.Format(time.RFC3339), CreatedAt: r.CreatedAt.Format(time.RFC3339), } } func roleName(role int) string { switch groupentity.Role(role) { case groupentity.RoleOwner: return "owner" case groupentity.RoleAdmin: return "admin" default: return "member" } }