diff --git a/app/pages.go b/app/pages.go index 1c8d5c8..dd0ecb5 100644 --- a/app/pages.go +++ b/app/pages.go @@ -107,6 +107,27 @@ func Assistant(ctx *gin.Context) { ctx.HTML(http.StatusOK, "assistant.html", result) } +// ManageWithGroupAdmin +// @description: 群组管理(管理员可用) +// @param ctx +func ManageWithGroupAdmin(ctx *gin.Context) { + // 取出id + id := ctx.Query("id") + if id == "" { + ctx.HTML(http.StatusOK, "404.html", nil) + return + } + + var result = gin.H{ + "msg": "success", + } + result["info"], _ = service.GetFriendInfoById(id) + result["aiModels"] = config.Conf.Ai.Models + result["assistant"], _ = service.GetAllAiAssistant() + // 渲染页面 + ctx.HTML(http.StatusOK, "manager-one.html", result) +} + // PageNotFound // @description: 404页面 // @param ctx diff --git a/config.yaml b/config.yaml index 8aa8746..82b76b9 100644 --- a/config.yaml +++ b/config.yaml @@ -2,6 +2,8 @@ system: # 每日新闻接口 Token # 获取地址: https://admin.alapi.cn/api_manager/token_manager alApiToken: xxx + # 系统访问域名 + domain: https://wechat.abc.com # 添加新好友或群之后通知给指定的人 newFriendNotify: enable: true @@ -48,7 +50,7 @@ mysql: # 定时任务 task: - enable: true + enable: false news: enable: false cron: '14 11 * * *' # 每天0:30 diff --git a/config/system.go b/config/system.go index 49ec19b..d9475e4 100644 --- a/config/system.go +++ b/config/system.go @@ -2,6 +2,7 @@ package config // 系统配置 type system struct { + Domain string `json:"domain" yaml:"domain"` // 域名 AlApiToken string `json:"alApiToken" yaml:"alApiToken"` // AL API Token NewFriendNotify newFriendNotify `json:"newFriendNotify" yaml:"newFriendNotify"` // 新好友通知 DefaultRule defaultRule `json:"defaultRule" yaml:"defaultRule"` // 默认规则 diff --git a/main.go b/main.go index 0ca0fbe..ece9e8d 100644 --- a/main.go +++ b/main.go @@ -60,6 +60,10 @@ func main() { } return "否" }, + "checkIsGroup": func(str string) bool { + // 如果id包含@chatroom就是群组 + return strings.HasSuffix(str, "@chatroom") + }, }) app.LoadHTMLGlob("views/*.html") diff --git a/model/entity/friend.go b/model/entity/friend.go index 1e497aa..95a0fc5 100644 --- a/model/entity/friend.go +++ b/model/entity/friend.go @@ -1,29 +1,30 @@ package entity import ( + "go-wechat/common/types" "time" ) // Friend // @description: 好友列表 type Friend struct { - Wxid string `json:"wxid"` // 微信原始Id - CustomAccount string `json:"customAccount"` // 微信号 - Nickname string `json:"nickname"` // 昵称 - Pinyin string `json:"pinyin"` // 昵称拼音大写首字母 - PinyinAll string `json:"pinyinAll"` // 昵称全拼 - LastActive time.Time `json:"lastActive"` // 最后活跃时间 - EnableAi bool `json:"enableAI" gorm:"type:tinyint(1) default 0 not null"` // 是否使用AI - AiModel string `json:"aiModel"` // AI模型 - Prompt string `json:"prompt"` // 提示词 - EnableChatRank bool `json:"enableChatRank" gorm:"type:tinyint(1) default 0 not null"` // 是否使用聊天排行 - EnableWelcome bool `json:"enableWelcome" gorm:"type:tinyint(1) default 0 not null"` // 是否启用迎新 - EnableSummary bool `json:"enableSummary" gorm:"type:tinyint(1) default 0 not null"` // 是否启用总结 - EnableNews bool `json:"enableNews" gorm:"type:tinyint(1) default 0 not null"` // 是否启用新闻 - EnableHotTop bool `json:"enableHotTop" gorm:"type:tinyint(1) default 0 not null"` // 是否启用热榜新闻 - ClearMember int `json:"clearMember"` // 清理成员配置(多少天未活跃的) - IsOk bool `json:"isOk" gorm:"type:tinyint(1) default 0 not null"` // 是否正常 - UsedTokens int `json:"usedTokens"` // 已使用的AI Token数量 + Wxid string `json:"wxid"` // 微信原始Id + CustomAccount string `json:"customAccount"` // 微信号 + Nickname string `json:"nickname"` // 昵称 + Pinyin string `json:"pinyin"` // 昵称拼音大写首字母 + PinyinAll string `json:"pinyinAll"` // 昵称全拼 + LastActive types.DateTime `json:"lastActive"` // 最后活跃时间 + EnableAi bool `json:"enableAI" gorm:"type:tinyint(1) default 0 not null"` // 是否使用AI + AiModel string `json:"aiModel"` // AI模型 + Prompt string `json:"prompt"` // 提示词 + EnableChatRank bool `json:"enableChatRank" gorm:"type:tinyint(1) default 0 not null"` // 是否使用聊天排行 + EnableWelcome bool `json:"enableWelcome" gorm:"type:tinyint(1) default 0 not null"` // 是否启用迎新 + EnableSummary bool `json:"enableSummary" gorm:"type:tinyint(1) default 0 not null"` // 是否启用总结 + EnableNews bool `json:"enableNews" gorm:"type:tinyint(1) default 0 not null"` // 是否启用新闻 + EnableHotTop bool `json:"enableHotTop" gorm:"type:tinyint(1) default 0 not null"` // 是否启用热榜新闻 + ClearMember int `json:"clearMember"` // 清理成员配置(多少天未活跃的) + IsOk bool `json:"isOk" gorm:"type:tinyint(1) default 0 not null"` // 是否正常 + UsedTokens int `json:"usedTokens"` // 已使用的AI Token数量 } func (Friend) TableName() string { diff --git a/router/router.go b/router/router.go index 2b40dfd..90a05a9 100644 --- a/router/router.go +++ b/router/router.go @@ -14,10 +14,11 @@ func Init(g *gin.Engine) { ctx.Redirect(302, "/index.html") }) - g.GET("/index.html", app.Index) // 首页 - g.GET("/friend.html", app.Friend) // 好友列表 - g.GET("/group.html", app.Group) // 群组列表 - g.GET("/assistant.html", app.Assistant) // AI角色 + g.GET("/index.html", app.Index) // 首页 + g.GET("/friend.html", app.Friend) // 好友列表 + g.GET("/group.html", app.Group) // 群组列表 + g.GET("/assistant.html", app.Assistant) // AI角色 + g.GET("/manager.html", app.ManageWithGroupAdmin) // 自己管理配置 g.GET("/404.html", app.PageNotFound) // 群组列表 diff --git a/tasks/friends/friends.go b/tasks/friends/friends.go index 6496aba..80bf35f 100644 --- a/tasks/friends/friends.go +++ b/tasks/friends/friends.go @@ -5,6 +5,7 @@ import ( "github.com/go-resty/resty/v2" "go-wechat/client" "go-wechat/common/constant" + "go-wechat/common/types" "go-wechat/config" "go-wechat/model/dto" "go-wechat/model/entity" @@ -77,7 +78,7 @@ func Sync() { EnableNews: config.Conf.System.DefaultRule.News, EnableHotTop: config.Conf.System.DefaultRule.HotTop, ClearMember: 0, - LastActive: time.Now().Local(), + LastActive: types.DateTime(time.Now().Local()), }).Error if err != nil { log.Printf("新增好友失败: %s", err.Error()) @@ -98,6 +99,14 @@ func Sync() { utils.SendEmotion(friend.Wxid, conf.Path, 0) } } + // 发送配置网页 + if config.Conf.System.Domain != "" { + title := "欢迎使用微信机器人" + desc := "点我可以配置功能喔,提示非微信官方网页,点击继续访问即可" + url := config.Conf.System.Domain + "/manager.html?id=" + friend.Wxid + utils.SendPublicMsg(friend.Wxid, title, desc, url, 0) + } + } else { pm := map[string]any{ "nickname": friend.Nickname, diff --git a/utils/send.go b/utils/send.go index 6d725f2..5a4652b 100644 --- a/utils/send.go +++ b/utils/send.go @@ -188,3 +188,42 @@ func QuitChatroom(chatRoomId string, retryCount int) { } log.Printf("退群结果: %s", resp.String()) } + +// SendPublicMsg +// @description: 发送公众号消息 +// @param wxId string 群或者好友Id +// @param title string 标题 +// @param digest string 摘要 +// @param url string 链接 +// @param retryCount int 重试次数 +func SendPublicMsg(wxId, title, digest, url string, retryCount int) { + if retryCount > 5 { + log.Printf("重试五次失败,停止发送") + return + } + + // 组装参数 + param := map[string]any{ + "appName": "公安部网安局", // 假装是公安部发的,看着都牛逼 + "userName": "gh_e406f4bcdf34", // 这个是公安部网安局的公众号id + "title": title, + "digest": digest, + "url": url, + "thumbUrl": "https://gitee.ltd/assets/img/logo.png", // 这个logo写死了,懒得搞,要改的自己改一下 + "wxid": wxId, + } + pbs, _ := json.Marshal(param) + + res := resty.New() + resp, err := res.R(). + SetHeader("Content-Type", "application/json;chartset=utf-8"). + SetBody(string(pbs)). + Post(config.Conf.Wechat.GetURL("/api/forwardPublicMsg")) + if err != nil { + log.Printf("发送公众号消息失败: %s", err.Error()) + // 休眠五秒后重新发送 + time.Sleep(5 * time.Second) + SendPublicMsg(wxId, title, digest, url, retryCount+1) + } + log.Printf("发送公众号消息结果: %s", resp.String()) +} diff --git a/views/group.html b/views/group.html index 04990f4..3407bfc 100644 --- a/views/group.html +++ b/views/group.html @@ -149,7 +149,8 @@ - {{ end }} + + {{ end }} diff --git a/views/manager-one.html b/views/manager-one.html new file mode 100644 index 0000000..c44b588 --- /dev/null +++ b/views/manager-one.html @@ -0,0 +1,151 @@ + + + + + 水群助手 + + + + + + + + + + +
+ +
+
+ Tuple +
+
{{ .info.Nickname }}
+
{{ .info.Wxid }}
+ {{ template "flagTag" .info.IsOk }} + +
+
+ +
+ +
+
最后活跃时间
+
+ {{ if eq .info.LastActive.IsNil true }} + 无活跃数据 + {{ else }} + + {{ end }} +
+
+ +
+
AI(模型可选默认或者指定模型)
+
+
+ {{ template "ai" .info }} +
+ {{ if eq .info.EnableAi true }} +
+
+ +
+
+ +
+
+ {{ end }} +
+
+ + {{$isGroup := checkIsGroup .info.Wxid}} + {{ if eq $isGroup true }} + +
+
水群排行榜
+
+ {{ template "chatRank" .info }} +
+
+ +
+
群聊总结
+
+ {{ template "summary" .info }} +
+
+ +
+
迎新
+
+ {{ template "welcome" .info }} +
+
+ {{ end }} + +
+
早报
+
+ {{ template "news" .info }} +
+
+ +
+
热榜
+
+ {{ template "hotTop" .info }} +
+
+ {{ if eq $isGroup true }} + +
+
+ 末位淘汰(需要机器人是管理员) +
+ * 清理多少天不说话的成员,0表示不清理 +
+
+
+ +
+ +
+
+
+
+ {{ end }} +
+
+ +
+ +