Compare commits

..

6 Commits

Author SHA1 Message Date
李寻欢
b49247bf89 🐛 Fix a bug. 2023-12-07 23:27:07 +08:00
李寻欢
8b7487b42b 🎨 优化写法 2023-12-07 23:00:57 +08:00
李寻欢
ac9f68c80d 🎨 打印 sql 语句 2023-12-07 23:00:16 +08:00
李寻欢
43ddd23258 🐛 Fix a bug. 2023-12-07 22:38:49 +08:00
李寻欢
ccb0216484 🐛 Fix a bug. 2023-12-07 16:04:32 +08:00
李寻欢
37bf8de132 🎨 优化迎新逻辑,引入资源概念 2023-12-07 15:58:55 +08:00
13 changed files with 167 additions and 22 deletions

View File

@@ -4,6 +4,7 @@ import (
"go-wechat/config" "go-wechat/config"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger"
"log" "log"
) )
@@ -17,7 +18,13 @@ func InitMySQLClient() {
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式 DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式
DontSupportRenameColumn: true, // 用 `change` 重命名列 DontSupportRenameColumn: true, // 用 `change` 重命名列
} }
conn, err := gorm.Open(mysql.New(mysqlConfig))
// gorm 配置
gormConfig := gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
}
conn, err := gorm.Open(mysql.New(mysqlConfig), &gormConfig)
if err != nil { if err != nil {
log.Panicf("初始化MySQL连接失败, 错误信息: %v", err) log.Panicf("初始化MySQL连接失败, 错误信息: %v", err)
} else { } else {

19
common/current/robot.go Normal file
View File

@@ -0,0 +1,19 @@
package current
import "go-wechat/model"
var robotInfo model.RobotUserInfo
// SetRobotInfo
// @description: 设置机器人信息
// @param info
func SetRobotInfo(info model.RobotUserInfo) {
robotInfo = info
}
// GetRobotInfo
// @description: 获取机器人信息
// @return model.RobotUserInfo
func GetRobotInfo() model.RobotUserInfo {
return robotInfo
}

View File

@@ -8,7 +8,7 @@ wechat:
callback: 10.0.0.51 callback: 10.0.0.51
# 转发到其他地址 # 转发到其他地址
forward: forward:
- 10.0.0.247:4299 # - 10.0.0.247:4299
# 数据库 # 数据库
mysql: mysql:
@@ -43,8 +43,10 @@ ai:
# 人设 # 人设
personality: 你的名字叫张三,你是一个百科机器人,你的爱好是看电影,你的性格是开朗的,你的专长是讲故事,你的梦想是当一名童话故事作家。你对政治没有一点儿兴趣,也不会讨论任何与政治相关的话题,你甚至可以拒绝回答这一类话题。 personality: 你的名字叫张三,你是一个百科机器人,你的爱好是看电影,你的性格是开朗的,你的专长是讲故事,你的梦想是当一名童话故事作家。你对政治没有一点儿兴趣,也不会讨论任何与政治相关的话题,你甚至可以拒绝回答这一类话题。
# 资源配置这玩意儿是机器人那个机器上的smb文件夹 # 资源配置
# 暂时没用 - 2023-12-6 # map[k]v结构k 会变成全小写,所以这儿不能用大写字母
resource: resource:
localPath: /files # 欢迎新成员表情包
remotePath: D:\Share\ welcome-new:
type: emotion
path: 58e4150be2bba8f7b71974b10391f9e9

View File

@@ -1,12 +1,14 @@
package config package config
var Conf Config // Conf 配置
var Conf conf
// Config // Config
// @description: 配置 // @description: 配置
type Config struct { type conf struct {
Task task `json:"task" yaml:"task"` // 定时任务配置 Task task `json:"task" yaml:"task"` // 定时任务配置
MySQL mysql `json:"mysql" yaml:"mysql"` // MySQL 配置 MySQL mysql `json:"mysql" yaml:"mysql"` // MySQL 配置
Wechat wechat `json:"wechat" yaml:"wechat"` // 微信助手 Wechat wechat `json:"wechat" yaml:"wechat"` // 微信助手
Ai ai `json:"ai" yaml:"ai"` // AI配置 Ai ai `json:"ai" yaml:"ai"` // AI配置
Resource map[string]resourceItem `json:"resource" yaml:"resource"` // 资源配置
} }

8
config/resource.go Normal file
View File

@@ -0,0 +1,8 @@
package config
// resourceItem
// @description: 资源项
type resourceItem struct {
Type string `json:"type" yaml:"type"` // 类型
Path string `json:"path" yaml:"path"` // 路径
}

View File

@@ -24,9 +24,8 @@ func Parse(remoteAddr net.Addr, msg []byte) {
return return
} }
// 提取出群成员信息 // 提取出群成员信息
//groupUser := "" // Sys类型的消息正文不包含微信 Id所以不需要处理
//msgStr := m.Content if m.IsGroup() && m.Type != types.MsgTypeSys {
if strings.Contains(m.FromUser, "@") {
// 群消息,处理一下消息和发信人 // 群消息,处理一下消息和发信人
groupUser := strings.Split(m.Content, "\n")[0] groupUser := strings.Split(m.Content, "\n")[0]
groupUser = strings.ReplaceAll(groupUser, ":", "") groupUser = strings.ReplaceAll(groupUser, ":", "")
@@ -42,6 +41,7 @@ func Parse(remoteAddr net.Addr, msg []byte) {
// 异步处理消息 // 异步处理消息
go func() { go func() {
if m.IsNewUserJoin() { if m.IsNewUserJoin() {
log.Printf("%s -> 开始迎新 -> %s", m.FromUser, m.Content)
// 欢迎新成员 // 欢迎新成员
go handleNewUserJoin(m) go handleNewUserJoin(m)
} else if m.IsAt() { } else if m.IsAt() {

View File

@@ -2,6 +2,7 @@ package handler
import ( import (
"go-wechat/client" "go-wechat/client"
"go-wechat/config"
"go-wechat/entity" "go-wechat/entity"
"go-wechat/model" "go-wechat/model"
"go-wechat/utils" "go-wechat/utils"
@@ -13,13 +14,26 @@ import (
func handleNewUserJoin(m model.Message) { func handleNewUserJoin(m model.Message) {
// 判断是否开启迎新 // 判断是否开启迎新
var count int64 var count int64
_ = client.MySQL.Model(&entity.Friend{}).Where("enable_welcome IS TRUE").Where("wxid = ?", m.FromUser).Count(&count).Error client.MySQL.Model(&entity.Friend{}).Where("enable_welcome IS TRUE").Where("wxid = ?", m.FromUser).Count(&count)
if count < 1 { if count < 1 {
return return
} }
// 发一张图乐呵乐呵 // 读取欢迎新成员配置
conf, ok := config.Conf.Resource["welcome-new"]
// 自己欢迎自己图片地址 D:\Share\emoticon\welcome-yourself.gif if !ok {
utils.SendImage(m.FromUser, "D:\\Share\\emoticon\\welcome-yourself.gif", 0) // 未配置,跳过
return
}
switch conf.Type {
case "text":
// 文字类型
utils.SendMessage(m.FromUser, "", conf.Path, 0)
case "image":
// 图片类型
utils.SendImage(m.FromUser, conf.Path, 0)
case "emotion":
// 表情类型
utils.SendEmotion(m.FromUser, conf.Path, 0)
}
} }

31
initialization/wechat.go Normal file
View File

@@ -0,0 +1,31 @@
package initialization
import (
"github.com/go-resty/resty/v2"
"go-wechat/common/current"
"go-wechat/config"
"go-wechat/model"
"log"
)
// InitWechatRobotInfo
// @description: 初始化微信机器人信息
func InitWechatRobotInfo() {
// 获取数据
var base model.Response[model.RobotUserInfo]
_, err := resty.New().R().
SetHeader("Content-Type", "application/json;chartset=utf-8").
SetResult(&base).
Post(config.Conf.Wechat.GetURL("/api/userInfo"))
if err != nil {
log.Printf("获取机器人信息失败: %s", err.Error())
return
}
log.Printf("机器人Id: %s", base.Data.WxId)
log.Printf("机器人微信号: %s", base.Data.Account)
log.Printf("机器人名称: %s", base.Data.Name)
// 设置为单例
current.SetRobotInfo(base.Data)
}

View File

@@ -16,8 +16,9 @@ import (
) )
func init() { func init() {
initialization.InitConfig() initialization.InitConfig() // 初始化配置
tasks.InitTasks() initialization.InitWechatRobotInfo() // 初始化机器人信息
tasks.InitTasks() // 初始化定时任务
} }
func main() { func main() {

View File

@@ -33,6 +33,10 @@ type systemMsgDataXml struct {
// @description: 消息主体 // @description: 消息主体
type sysMsg struct{} type sysMsg struct{}
func (m Message) IsGroup() bool {
return strings.HasSuffix(m.FromUser, "@chatroom")
}
// IsPat // IsPat
// @description: 是否是拍一拍消息 // @description: 是否是拍一拍消息
// @receiver m // @receiver m

18
model/userinfo.go Normal file
View File

@@ -0,0 +1,18 @@
package model
// RobotUserInfo
// @description: 机器人用户信息
type RobotUserInfo struct {
WxId string `json:"wxid"` // 微信Id
Account string `json:"account"` // 微信号
Name string `json:"name"` // 昵称
HeadImage string `json:"headImage"` // 头像
Mobile string `json:"mobile"` // 手机
Signature string `json:"signature"` // 个人签名
Country string `json:"country"` // 国家
Province string `json:"province"` // 省
City string `json:"city"` // 城市
CurrentDataPath string `json:"currentDataPath"` // 当前数据目录,登录的账号目录
DataSavePath string `json:"dataSavePath"` // 微信保存目录
DbKey string `json:"dbKey"` // 数据库的SQLCipher的加密key可以使用该key配合decrypt.py解密数据库
}

View File

@@ -2,7 +2,9 @@ package utils
import ( import (
"encoding/json" "encoding/json"
"fmt"
"github.com/go-resty/resty/v2" "github.com/go-resty/resty/v2"
"go-wechat/common/current"
"go-wechat/config" "go-wechat/config"
"log" "log"
"time" "time"
@@ -82,3 +84,40 @@ func SendImage(toId, imgPath string, retryCount int) {
} }
log.Printf("发送图片消息结果: %s", resp.String()) log.Printf("发送图片消息结果: %s", resp.String())
} }
// SendEmotion
// @description: 发送自定义表情包
// @param toId string 群或者好友Id
// @param emotionHash string 表情包hash(md5值)
// @param retryCount int 重试次数
func SendEmotion(toId, emotionHash string, retryCount int) {
if retryCount > 5 {
log.Printf("重试五次失败,停止发送")
return
}
// 组装表情包本地地址
// 规则:机器人数据目录\FileStorage\CustomEmotion\表情包hash前两位\表情包hash
emotionPath := fmt.Sprintf("%sFileStorage\\CustomEmotion\\%s\\%s",
current.GetRobotInfo().CurrentDataPath, emotionHash[:2], emotionHash)
// 组装参数
param := map[string]any{
"wxid": toId, // 群或好友Id
"filePath": emotionPath, // 图片地址
}
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/sendCustomEmotion"))
if err != nil {
log.Printf("发送表情包消息失败: %s", err.Error())
// 休眠五秒后重新发送
time.Sleep(5 * time.Second)
SendImage(toId, emotionHash, retryCount+1)
}
log.Printf("发送表情包消息结果: %s", resp.String())
}