|
|
@@ -1,13 +1,19 @@
|
|
|
package app
|
|
|
|
|
|
import (
|
|
|
+ "encoding/json"
|
|
|
+ "fmt"
|
|
|
+ "io"
|
|
|
+ "net/http"
|
|
|
"time"
|
|
|
|
|
|
"github.com/demdxx/gocast"
|
|
|
"github.com/gin-gonic/gin"
|
|
|
+ "go_server/base/core"
|
|
|
"go_server/model/biz_modules/app"
|
|
|
"go_server/model/common/response"
|
|
|
"go_server/service/base"
|
|
|
+ "go_server/utils"
|
|
|
)
|
|
|
|
|
|
type TgGroupService struct {
|
|
|
@@ -221,7 +227,152 @@ func (s *TgGroupService) Delete(c *gin.Context) {
|
|
|
// SyncFromBot 从 Telegram Bot 同步群组信息
|
|
|
func (s *TgGroupService) SyncFromBot(c *gin.Context) {
|
|
|
s.SetDbAlias("app")
|
|
|
- // TODO: 实现从 Telegram Bot API 获取群组列表并同步到数据库
|
|
|
- // 这个功能需要调用 magic_server 的接口来获取 bot 加入的所有群组
|
|
|
- response.Resp(c, "功能开发中")
|
|
|
+
|
|
|
+ // 调用 magic_server API 同步群组信息
|
|
|
+ groups, err := s.callMagicServerSyncGroups()
|
|
|
+ if err != nil {
|
|
|
+ core.Log.Errorf("同步群组失败: %v", err)
|
|
|
+ response.Resp(c, fmt.Sprintf("同步失败: %v", err))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 统计新增和更新的数量
|
|
|
+ newCount := 0
|
|
|
+ updateCount := 0
|
|
|
+
|
|
|
+ // 遍历群组,保存或更新到数据库
|
|
|
+ for _, groupData := range groups {
|
|
|
+ // 检查群组是否已存在
|
|
|
+ var existingGroup app.TgGroup
|
|
|
+ err := s.DB().Where("chat_id = ?", groupData.ChatId).First(&existingGroup).Error
|
|
|
+
|
|
|
+ now := time.Now().Unix()
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ // 群组不存在,创建新记录
|
|
|
+ newGroup := &app.TgGroup{
|
|
|
+ ChatId: groupData.ChatId,
|
|
|
+ ChatType: groupData.ChatType,
|
|
|
+ Title: groupData.Title,
|
|
|
+ Username: groupData.Username,
|
|
|
+ Description: groupData.Description,
|
|
|
+ MemberCount: groupData.MemberCount,
|
|
|
+ Status: 1, // 默认正常状态
|
|
|
+ BotJoinedAt: groupData.BotJoinedAt,
|
|
|
+ CreatedAt: now,
|
|
|
+ UpdatedAt: now,
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := s.DB().Create(newGroup).Error; err != nil {
|
|
|
+ core.Log.Errorf("创建群组记录失败: %v", err)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ newCount++
|
|
|
+ } else {
|
|
|
+ // 群组已存在,更新信息
|
|
|
+ updates := map[string]interface{}{
|
|
|
+ "title": groupData.Title,
|
|
|
+ "username": groupData.Username,
|
|
|
+ "description": groupData.Description,
|
|
|
+ "member_count": groupData.MemberCount,
|
|
|
+ "updated_at": now,
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := s.DB().Model(&existingGroup).Updates(updates).Error; err != nil {
|
|
|
+ core.Log.Errorf("更新群组记录失败: %v", err)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ updateCount++
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ core.Log.Infof("群组同步完成: 新增 %d 个, 更新 %d 个", newCount, updateCount)
|
|
|
+
|
|
|
+ response.Resp(c, map[string]interface{}{
|
|
|
+ "message": "同步成功",
|
|
|
+ "totalCount": len(groups),
|
|
|
+ "newCount": newCount,
|
|
|
+ "updateCount": updateCount,
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// callMagicServerSyncGroups 调用 magic_server API 同步群组
|
|
|
+func (s *TgGroupService) callMagicServerSyncGroups() ([]GroupData, error) {
|
|
|
+ core.Log.Info("========== 开始同步群组 ==========")
|
|
|
+
|
|
|
+ // magic_server API 地址
|
|
|
+ apiURL := "http://localhost:2011/api/v1/adi/telegram/groups/sync"
|
|
|
+
|
|
|
+ // 生成签名
|
|
|
+ core.Log.Info("正在生成签名...")
|
|
|
+ signMessage, err := utils.BuildSignMessage()
|
|
|
+ if err != nil {
|
|
|
+ core.Log.Errorf("生成签名失败: %v", err)
|
|
|
+ return nil, fmt.Errorf("生成签名失败: %v", err)
|
|
|
+ }
|
|
|
+ core.Log.Infof("签名生成成功: %s", signMessage[:50]+"...")
|
|
|
+
|
|
|
+ // 发送 HTTP 请求
|
|
|
+ req, err := http.NewRequest("POST", apiURL, nil)
|
|
|
+ if err != nil {
|
|
|
+ return nil, fmt.Errorf("创建 HTTP 请求失败: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ req.Header.Set("Content-Type", "application/json")
|
|
|
+ req.Header.Set("sign", signMessage)
|
|
|
+
|
|
|
+ core.Log.Infof("开始调用 magic_server API: %s", apiURL)
|
|
|
+
|
|
|
+ client := &http.Client{Timeout: 10 * time.Second}
|
|
|
+ resp, err := client.Do(req)
|
|
|
+ if err != nil {
|
|
|
+ return nil, fmt.Errorf("发送 HTTP 请求失败: %v", err)
|
|
|
+ }
|
|
|
+ defer resp.Body.Close()
|
|
|
+
|
|
|
+ core.Log.Infof("收到响应,状态码: %d", resp.StatusCode)
|
|
|
+
|
|
|
+ // 解析响应
|
|
|
+ var result struct {
|
|
|
+ Code int `json:"code"`
|
|
|
+ Msg string `json:"msg"` // magic_server 使用 msg 而不是 message
|
|
|
+ Message string `json:"message"` // 兼容两种格式
|
|
|
+ Data struct {
|
|
|
+ Groups []GroupData `json:"groups"`
|
|
|
+ Count int `json:"count"`
|
|
|
+ } `json:"data"`
|
|
|
+ }
|
|
|
+
|
|
|
+ body, err := io.ReadAll(resp.Body)
|
|
|
+ if err != nil {
|
|
|
+ return nil, fmt.Errorf("读取响应失败: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打印原始响应用于调试
|
|
|
+ core.Log.Infof("API 响应: %s", string(body))
|
|
|
+
|
|
|
+ if err := json.Unmarshal(body, &result); err != nil {
|
|
|
+ return nil, fmt.Errorf("解析响应失败: %v, 原始响应: %s", err, string(body))
|
|
|
+ }
|
|
|
+
|
|
|
+ if result.Code != 0 && result.Code != 200 {
|
|
|
+ errMsg := result.Message
|
|
|
+ if errMsg == "" {
|
|
|
+ errMsg = result.Msg
|
|
|
+ }
|
|
|
+ return nil, fmt.Errorf("API 返回错误(code=%d): %s", result.Code, errMsg)
|
|
|
+ }
|
|
|
+
|
|
|
+ return result.Data.Groups, nil
|
|
|
+}
|
|
|
+
|
|
|
+// GroupData 群组数据结构(用于与 magic_server 交互)
|
|
|
+type GroupData struct {
|
|
|
+ ChatId int64 `json:"chatId"`
|
|
|
+ ChatType string `json:"chatType"`
|
|
|
+ Title string `json:"title"`
|
|
|
+ Username string `json:"username"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ MemberCount int `json:"memberCount"`
|
|
|
+ BotJoinedAt int64 `json:"botJoinedAt"`
|
|
|
}
|