feat(dashboard): v4 support
This commit is contained in:
@@ -404,7 +404,7 @@ func (s *Service) handleDashboard(c *gin.Context) {
|
||||
WeeklyAvg int `json:"weekly_avg"`
|
||||
MostActiveHour string `json:"most_active_hour"`
|
||||
}
|
||||
type ContentAnalysis struct { Text int64 `json:"text_messages"`; Images int64 `json:"images"`; Voice int64 `json:"voice_messages"`; Files int64 `json:"files"`; Links int64 `json:"links"`; Others int64 `json:"others"` }
|
||||
type ContentAnalysis struct { Text int64 `json:"text_messages"`; Images int64 `json:"images"`; Voice int64 `json:"voice_messages"`; Files int64 `json:"files"`; Links int64 `json:"links"`; FileLinkTotal int64 `json:"file_link_total"`; Others int64 `json:"others"` }
|
||||
type GroupListItem struct { Name string `json:"name"`; Members int `json:"members"`; Messages int64 `json:"messages"`; Active bool `json:"active"` }
|
||||
type HourlyActivity struct { Hour string `json:"hour"`; Messages int64 `json:"messages"` }
|
||||
type GroupAnalysis struct {
|
||||
@@ -510,8 +510,16 @@ func (s *Service) handleDashboard(c *gin.Context) {
|
||||
GroupAnalysis: GroupAnalysis{
|
||||
Title: "群聊分析",
|
||||
Overview: GroupOverview{ TotalGroups: len(overviewGroups), ActiveGroups: activeGroups, TodayMessages: int(todayMessages), WeeklyAvg: weeklyAvg, MostActiveHour: mostActiveHour },
|
||||
// 扩展:增加 links 字段(结构体需更新)
|
||||
ContentAnalysis: ContentAnalysis{ Text: msgTypes["文本消息"], Images: msgTypes["图片消息"], Voice: msgTypes["语音消息"], Files: msgTypes["文件消息"], Links: msgTypes["链接消息"], Others: totalMsgs - (msgTypes["文本消息"]+msgTypes["图片消息"]+msgTypes["语音消息"]+msgTypes["文件消息"]+msgTypes["链接消息"]) },
|
||||
// 扩展:增加 links 与汇总 file_link_total
|
||||
ContentAnalysis: ContentAnalysis{
|
||||
Text: msgTypes["文本消息"],
|
||||
Images: msgTypes["图片消息"],
|
||||
Voice: msgTypes["语音消息"],
|
||||
Files: msgTypes["文件消息"],
|
||||
Links: msgTypes["链接消息"],
|
||||
FileLinkTotal: msgTypes["文件消息"] + msgTypes["链接消息"],
|
||||
Others: totalMsgs - (msgTypes["文本消息"] + msgTypes["图片消息"] + msgTypes["语音消息"] + msgTypes["文件消息"] + msgTypes["链接消息"]),
|
||||
},
|
||||
GroupList: glist,
|
||||
HourlyActivity: hacts,
|
||||
},
|
||||
|
||||
@@ -774,19 +774,44 @@ func (ds *DataSource) GlobalMessageStats(ctx context.Context) (*model.GlobalMess
|
||||
if stats.EarliestUnix == 0 || (minct > 0 && minct < stats.EarliestUnix) { stats.EarliestUnix = minct }
|
||||
if maxct > stats.LatestUnix { stats.LatestUnix = maxct }
|
||||
}
|
||||
// by type
|
||||
q2 := fmt.Sprintf(`SELECT messageType, COUNT(*) FROM %s GROUP BY messageType`, tbl)
|
||||
// by type(先统计非 49)
|
||||
q2 := fmt.Sprintf(`SELECT messageType, COUNT(*) FROM %s WHERE messageType != 49 GROUP BY messageType`, tbl)
|
||||
rows, err := db.QueryContext(ctx, q2)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
var t int64; var cnt int64
|
||||
if err := rows.Scan(&t, &cnt); err == nil {
|
||||
label := mapV4TypeToLabel(t) // 复用 v4 的类型映射
|
||||
label := mapV4TypeToLabel(t)
|
||||
if label != "" { stats.ByType[label] += cnt }
|
||||
}
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
// 细分 49
|
||||
q49 := fmt.Sprintf(`SELECT msgContent FROM %s WHERE messageType = 49`, tbl)
|
||||
orows, err := db.QueryContext(ctx, q49)
|
||||
if err == nil {
|
||||
for orows.Next() {
|
||||
var mc string
|
||||
if err := orows.Scan(&mc); err == nil {
|
||||
lc := strings.ToLower(mc)
|
||||
if strings.Contains(lc, "<appmsg") {
|
||||
if strings.Contains(lc, "<type>") && strings.Contains(lc, "</type>") {
|
||||
i1 := strings.Index(lc, "<type>")
|
||||
i2 := strings.Index(lc[i1+6:], "</type>")
|
||||
if i1 >= 0 && i2 > 0 {
|
||||
val := lc[i1+6 : i1+6+i2]
|
||||
if strings.TrimSpace(val) == "6" { stats.ByType["文件消息"]++; continue }
|
||||
if strings.TrimSpace(val) == "5" || strings.TrimSpace(val) == "33" { stats.ByType["链接消息"]++; continue }
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.Contains(lc, "http://") || strings.Contains(lc, "https://") { stats.ByType["链接消息"]++; continue }
|
||||
stats.ByType["XML消息"]++
|
||||
}
|
||||
}
|
||||
orows.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
return stats, nil
|
||||
|
||||
@@ -802,8 +802,9 @@ func (ds *DataSource) GlobalMessageStats(ctx context.Context) (*model.GlobalMess
|
||||
if stats.EarliestUnix == 0 || (minct > 0 && minct < stats.EarliestUnix) { stats.EarliestUnix = minct }
|
||||
if maxct > stats.LatestUnix { stats.LatestUnix = maxct }
|
||||
}
|
||||
// by type
|
||||
q2 := fmt.Sprintf(`SELECT local_type, COUNT(*) FROM %s GROUP BY local_type`, tbl)
|
||||
// by type (细分 49)
|
||||
// 先统计除 49 之外类型
|
||||
q2 := fmt.Sprintf(`SELECT local_type, COUNT(*) FROM %s WHERE local_type != 49 GROUP BY local_type`, tbl)
|
||||
rows, err := db.QueryContext(ctx, q2)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
@@ -815,6 +816,46 @@ func (ds *DataSource) GlobalMessageStats(ctx context.Context) (*model.GlobalMess
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
// 针对 49 类型再做细分:简单解析 message_content 判断是文件、链接或通用 XML
|
||||
q49 := fmt.Sprintf(`SELECT message_content FROM %s WHERE local_type = 49`, tbl)
|
||||
orows, err := db.QueryContext(ctx, q49)
|
||||
if err == nil {
|
||||
for orows.Next() {
|
||||
var mc []byte
|
||||
if err := orows.Scan(&mc); err == nil {
|
||||
content := string(mc)
|
||||
// 可能压缩,简单特征判断(保持轻量;深度解压需额外性能,可后续拓展)
|
||||
lc := strings.ToLower(content)
|
||||
if strings.Contains(lc, "<appmsg") {
|
||||
if strings.Contains(lc, "<type>") && strings.Contains(lc, "</type>") {
|
||||
// 简单提取 type 数字
|
||||
i1 := strings.Index(lc, "<type>")
|
||||
i2 := strings.Index(lc[i1+6:], "</type>")
|
||||
if i1 >= 0 && i2 > 0 {
|
||||
val := lc[i1+6 : i1+6+i2]
|
||||
// 常见:6=文件, 5/33=链接(网页), 3=音乐, 4=视频, 其他归类为 XML
|
||||
if strings.TrimSpace(val) == "6" {
|
||||
stats.ByType["文件消息"]++
|
||||
continue
|
||||
}
|
||||
if strings.TrimSpace(val) == "5" || strings.TrimSpace(val) == "33" {
|
||||
stats.ByType["链接消息"]++
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
// 兜底:若包含 url 或 http(s) 关键词也认为链接
|
||||
if strings.Contains(lc, "http://") || strings.Contains(lc, "https://") {
|
||||
stats.ByType["链接消息"]++
|
||||
continue
|
||||
}
|
||||
// 再兜底为 XML消息
|
||||
stats.ByType["XML消息"]++
|
||||
}
|
||||
}
|
||||
}
|
||||
orows.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
return stats, nil
|
||||
|
||||
Reference in New Issue
Block a user