Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b49247bf89 | ||
|
|
8b7487b42b | ||
|
|
ac9f68c80d | ||
|
|
43ddd23258 | ||
|
|
ccb0216484 | ||
|
|
37bf8de132 |
@@ -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
19
common/current/robot.go
Normal 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
|
||||||
|
}
|
||||||
12
config.yaml
12
config.yaml
@@ -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
|
||||||
|
|||||||
@@ -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
8
config/resource.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
// resourceItem
|
||||||
|
// @description: 资源项
|
||||||
|
type resourceItem struct {
|
||||||
|
Type string `json:"type" yaml:"type"` // 类型
|
||||||
|
Path string `json:"path" yaml:"path"` // 路径
|
||||||
|
}
|
||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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
31
initialization/wechat.go
Normal 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)
|
||||||
|
}
|
||||||
5
main.go
5
main.go
@@ -16,8 +16,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
initialization.InitConfig()
|
initialization.InitConfig() // 初始化配置
|
||||||
tasks.InitTasks()
|
initialization.InitWechatRobotInfo() // 初始化机器人信息
|
||||||
|
tasks.InitTasks() // 初始化定时任务
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -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
18
model/userinfo.go
Normal 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解密数据库
|
||||||
|
}
|
||||||
@@ -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())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user