From 39892fa5eefe1a0416e89157fcdda079c8ce67f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kyoku=E2=AD=90?= <144906395+KyokuKong@users.noreply.github.com> Date: Sun, 22 Sep 2024 20:19:43 +0800 Subject: [PATCH 1/9] =?UTF-8?q?refact=EF=BC=9A=E5=87=86=E5=A4=87=E9=87=8D?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 75 --- adapter/adapter.go | 18 - adapter/bot.go | 104 ---- adapter/lagrange/element_converter.go | 107 ---- adapter/lagrange/lagrange_adapter.go | 143 ------ adapter/lagrange/lagrange_bot.go | 533 ------------------- adapter/lagrange/lagrange_config.go | 21 - adapter/lagrange/lagrange_handler.go | 97 ---- adapter/lagrange/lagrange_subscriber.go | 312 ------------ config/config_manager.go | 233 --------- config/iceinu_config.go | 22 - elements/elements.go | 650 ------------------------ go.mod | 25 - ice/adapter_events.go | 27 - ice/event_bus.go | 90 ---- ice/uni_events.go | 28 - logger/logger.go | 141 ----- logger/protocol_logger.go | 49 -- main.go | 54 -- resource/channel.go | 8 - resource/files.go | 35 -- resource/group.go | 23 - resource/interaction.go | 11 - resource/login.go | 10 - resource/message.go | 18 - resource/paged_list.go | 6 - resource/reaction.go | 3 - resource/user.go | 9 - utils/jprint.go | 23 - utils/satorize.go | 17 - 30 files changed, 2892 deletions(-) delete mode 100644 README.md delete mode 100644 adapter/adapter.go delete mode 100644 adapter/bot.go delete mode 100644 adapter/lagrange/element_converter.go delete mode 100644 adapter/lagrange/lagrange_adapter.go delete mode 100644 adapter/lagrange/lagrange_bot.go delete mode 100644 adapter/lagrange/lagrange_config.go delete mode 100644 adapter/lagrange/lagrange_handler.go delete mode 100644 adapter/lagrange/lagrange_subscriber.go delete mode 100644 config/config_manager.go delete mode 100644 config/iceinu_config.go delete mode 100644 elements/elements.go delete mode 100644 go.mod delete mode 100644 ice/adapter_events.go delete mode 100644 ice/event_bus.go delete mode 100644 ice/uni_events.go delete mode 100644 logger/logger.go delete mode 100644 logger/protocol_logger.go delete mode 100644 main.go delete mode 100644 resource/channel.go delete mode 100644 resource/files.go delete mode 100644 resource/group.go delete mode 100644 resource/interaction.go delete mode 100644 resource/login.go delete mode 100644 resource/message.go delete mode 100644 resource/paged_list.go delete mode 100644 resource/reaction.go delete mode 100644 resource/user.go delete mode 100644 utils/jprint.go delete mode 100644 utils/satorize.go diff --git a/README.md b/README.md deleted file mode 100644 index 6b2da8f..0000000 --- a/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# 🧊Iceinu 氷犬 - -![Go Badge](https://img.shields.io/badge/Go-1.22%2B-cyan?logo=go) -[![workflow](https://github.com/Iceinu-Project/iceinu/actions/workflows/go.yml/badge.svg)](https://github.com/Iceinu-Project/iceinu/actions) -[![goreportcard](https://img.shields.io/badge/go%20report-A+-brightgreen.svg?style=flat)](https://goreportcard.com/report/github.com/Iceinu-Project/iceinu) -[![QQGroup Badge](https://img.shields.io/badge/QQ群-970801565-blue?)](https://qm.qq.com/q/93crfU39ny) - -氷犬Iceinu 是一个多用途的Go语言聊天机器人框架,可以将其作为开发套件来进行二次开发,亦或者作为库按需引入来快速编写自己的聊天机器人(暂时没有实现)。 - -🚧暂时还在~~画饼~~施工中,晚点再来探索吧~ - -## 开发进度 - -目前距离第一个Release版本的发布还有很多需要进行的工作: -- [x] 基础的事件总线系统 -- [x] 内置LagrangeGo适配器的部分事件发送 -- [x] 类Satori的消息解析 -- [x] 配置读取/生成/补全 -- [ ] 数据库连接,统一数据库接口设计 -- [ ] 消息发送/统一Client设计 -- [ ] 插件系统设计和实现 -- [ ] 完善内置LagrangeGo适配器的事件接收和处理 -- [ ] 集群模式设计和实现(集群的动态和静态总控模式) -- [ ] 排障和性能优化 -- [ ] 自动化测试 -- [ ] 确定各项基础程序设计,编写使用文档 - -## 特性 - -~~哪里是特性,完全是画饼,一半都还没实现完~~ - -- 基于Go开发,性能表现良好 -- 基于统一事件驱动的消息推送机制 -- 以Satori作为基础实现了统一消息标准 -- 可直接发送Satori标准的XHTML消息 -- 模块化适配器设计 -- 动态/静态集群,跨平台集群 -- 完整的动态权限管理系统 -- 在插件间共享数据库连接池 -- 类Alconna的命令解析器 -- 可配置自动向指定用户/频道发送日志 -- 主动信息推送/订阅机制 -- 从HTML+CSS模板渲染图片(基于wkhtmltoimage集成,未来可能会实现) - -## 直接部署 - -(目前仍然属于开发前期,部署了也暂时没什么用处) - -访问[Github Action](https://github.com/Iceinu-Project/iceinu/actions)就可以获取Iceinu的自动构建二进制文件,Iceinu默认集成了`LagrangeGo`所以无需再配置onebot -协议连接,第一次启动时会自动检测并生成配置文件,完成配置之后在命令行中输入回车即可开始运行。 - -你可以参照Iceinu数据库配置指南来配置Iceinu使用的PostgreSQL数据库。 - -Iceinu在设计上支持集群部署,且支持动态组网式集群(需要各个Bot实例之间可以相互访问)和静态总控式集群(需要一个Bot实例作为总控,这个实例本身不能下线) - -## 二次开发 - -(文档还没写,Release之前会开始编写文档) - -Go语言的静态特性让它非常不怎么适合传统意义上的模块化加载,所以Iceinu并没有也不会实现从外部进行的插件加载。 - -不过Iceinu通过接口定义了内部插件的实现,直接拉取代码跟着插件文档进行二次开发即可扩展更多的插件功能。 - -```shell -git clone git@github.com:Iceinu-Project/iceinu.git -``` - -## 鸣谢 - -- [Lagrange.Core](https://github.com/LagrangeDev/Lagrange.Core) NTQQ通信协议的C#实现 -- [LagrangeGo](https://github.com/LagrangeDev/LagrangeGo) Lagrange.Core的Go实现 -- [LagrangeGo-Teamplate](https://github.com/ExquisiteCore/LagrangeGo-Template) LagrangeGo的模板示例项目 -- [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 基于 Mirai 以及 MiraiGo 的 OneBot Golang 原生实现 -- [ZeroBot](https://github.com/wdvxdr1123/ZeroBot) 基于onebot协议的Golang聊天机器人开发框架 -- [Logrus](https://github.com/sirupsen/logrus) 强大好用的Go日志库 \ No newline at end of file diff --git a/adapter/adapter.go b/adapter/adapter.go deleted file mode 100644 index f9806c0..0000000 --- a/adapter/adapter.go +++ /dev/null @@ -1,18 +0,0 @@ -package adapter - -// 继承IceAdapter接口即可实现适配器,具体的适配器实现模式参考文档 - -// IceAdapterMeta 适配器元信息 -type IceAdapterMeta struct { - AdapterName string // 适配器名称 - Version string // 适配器版本 - Platform string // 适配器平台 - Author []string // 适配器作者 - Introduce string // 适配器介绍 -} - -// IceAdapter Iceinu的适配器接口,用于实现适配器实例 -type IceAdapter interface { - GetMeta() *IceAdapterMeta // 获取适配器的元信息 - Init() // 适配器初始化 -} diff --git a/adapter/bot.go b/adapter/bot.go deleted file mode 100644 index 0a4fa0f..0000000 --- a/adapter/bot.go +++ /dev/null @@ -1,104 +0,0 @@ -package adapter - -import ( - "github.com/Iceinu-Project/iceinu/elements" - "github.com/Iceinu-Project/iceinu/resource" -) - -// Bot Iceinu的客户端接口API,用于实现iceinu对平台客户端的直接操作 -type Bot interface { - // 首先是基于Satori标准的API - // 这部分可以参考Satori文档的资源部分,但是有一定的不同,为了方便兼容各种使用方式进行了一些扩展 - // 比如没有直接支持分页这个东西,方便使用 - // https://satori.js.org/zh-CN/resources/channel.html - - GetChannel(channelId string) *resource.Channel // 获取频道信息 - GetChannelList(groupId string) []*resource.Channel // 获取指定群组中的频道列表 - GetChannelListByToken(next string) *resource.PagedList // 获取指定群组中的频道列表(分页) - CreateChannel(groupId string, data *resource.Channel) (*resource.Channel, error) // 创建频道 - UpdateChannel(groupId string, data *resource.Channel) error // 更新频道 - DeleteChannel(channelId string) error // 删除频道 - MuteChannel(channelId string, duration uint32) error // 禁言频道 - CreateUserChannel(userId string, groupId string) (*resource.Channel, error) // 创建用户(私聊)频道 - - GetGroup(groupId string) *resource.Group // 获取群组信息 - GetGroupList() []*resource.Group // 获取群组列表 - GetGroupListByToken(next string) *resource.PagedList // 获取群组列表(分页) - ApproveGroupInvite(messageId string, approve bool, comment string) error // 处理群组邀请bot加入请求 - - GetGroupMember(groupId string, userId string) *resource.GroupMember // 获取指定群组成员信息 - GetGroupMemberList(groupId string) []*resource.GroupMember // 获取群组成员列表 - GetGroupMemberListByToken(groupId string, next string) *resource.PagedList // 获取群组成员列表(分页) - KickGroupMember(groupId string, userId string, permanent bool) error // 踢出群组成员 - MuteGroupMember(groupId string, userId string, duration uint32) error // 禁言群组成员 - ApproveGroupRequest(messageId string, approve bool, comment string) error // 处理群组加入请求 - - SetGroupMemberRole(groupId string, userId string, roleId string) error // 设置群组成员角色权限 - UnsetGroupMemberRole(groupId string, userId string, roleId string) error // 取消群组成员角色权限 - GetGroupRoleList(groupId string) []*resource.GroupRole // 获取群组角色权限列表 - GetGroupRoleListByToken(groupId string, next string) *resource.PagedList // 获取群组角色权限列表(分页) - CreateGroupRole(groupId string, role *resource.GroupRole) (*resource.GroupRole, error) // 创建群组角色权限 - UpdateGroupRole(groupId string, roleId string, role *resource.GroupRole) error // 更新群组角色权限 - DeleteGroupRole(groupId string, roleId string) error // 删除群组角色权限 - - GetLoginInfo() *resource.Login // 获取登录信息 - - SendContent(groupId string, channelId string, content string) (*resource.Message, error) // 发送纯文本消息 - GetMessage(channelId string, messageId string) (*resource.Message, error) // (从缓存中)获取指定消息 - RecallMessage(channelId string, messageId string) error // 撤回指定消息 - UpdateMessage(channelId string, messageId string, content string) error // 编辑指定消息 - GetMessageList(channelId string, limit uint32, order bool) []*resource.Message // 获取一定数量的频道消息列表 - GetMessageListByRange(channelId string, messageId string, start uint32, count uint32) []*resource.Message // 获取频道消息列表(可指定范围) - - CreateReaction(channelId string, messageId string, emoji string) error // 添加消息反应 - DeleteReaction(channelId string, messageId string, emoji string, userId string) error // 删除消息反应 - ClearReaction(channelId string, messageId string, emoji string) error // 清除消息反应 - GetReactionList(channelId string, messageId string, emoji string) []resource.User // 获取消息反应列表 - GetReactionListByToken(channelId string, messageId string, emoji string, next string) *resource.PagedList // 获取消息反应列表(分页) - - GetUser(userId string) *resource.User // 获取指定用户信息 - GetFriendList() []*resource.User // 获取好友列表信息 - ApproveFriendRequest(messageId string, approve string, comment string) error // 处理好友请求 - - // Iceinu的特有API - // 其中一部分是对各个平台功能的扩展适配,还有一部分是其他功能的快捷方式 - - Send(groupId string, channelId string, elements []elements.IceinuMessageElement) (*resource.Message, error) // 直接发送Iceinu通用元素 - SendSatori(groupId string, channelId string, satori string) (*resource.Message, error) // 发送Satori XHTML格式的消息字符串,自动解析成通用元素并发送 - SendPoke(groupId string, channelId string, userId string) error // 发送戳一戳 - - GetSelfUserId() string // 获取自己的用户ID - GetSelfUserName() string // 获取自己的用户名 - GetSelfAvatarUrl() string // 获取自己的头像URL - GetSeldUserNickname() string // 获取自己的昵称 - GetGroupAvatarUrl(groupId string) string // 获取指定群组的头像URL - - RefreshUserListCache() error // 刷新用户列表 - RefreshGroupListCache() error // 刷新群组列表 - RefreshGroupMemberCache(groupId string, userId string) error // 刷新指定群组的指定成员的信息 - RefreshGroupAllMembersCache(groupId string) error // 刷新指定群组所有成员的信息 - RefreshChannelListCache(groupId string) error // 刷新指定群组的频道列表 - - RenameGroup(groupId string, name string) error // 重命名群组 - RenameGroupMember(groupId string, userId string, nickname string) error // 重命名群组成员 - RemarkGroup(groupId string, remark string) error // 设置群组备注 - SetGroupGlobalMute(groupId string, mute bool) error // 设置群组全员禁言 - LeaveGroup(groupId string) error // 退出群组 - SetGroupMemberTitle(groupId string, userId string, title string) error // 给群组成员设置头衔 - - // 这部分功能接口设计主要来自LagrangeGo,但是也可能在其他NTQQ平台上实现 - - UploadChannelFile(channelId string, filePath string) error // 向频道上传文件 - UploadGroupFile(groupId string, filePath string, targetFilePath string) error // 向群组上传文件 - GetGroupFileSystemInfo(groupId string) *resource.GroupFileSystemInfo // 获取群组文件系统信息(暂未确定) - GetGroupFilesByFolder(groupId string, folderId string) interface{} // 获取群组文件夹内的文件列表(暂未确定) - GetGroupRootFiles(groupId string) interface{} // 获取群组根目录文件列表(暂未确定) - MoveGroupFile(groupId string, fileId string, parentFolder string, targetFolderId string) error // 移动群组文件 - DeleteGroupFile(groupId string, fileId string) error // 删除群组文件 - CreateGroupFolder(groupId string, folderName string, parentFolder string) error // 创建群组文件夹 - RenameGroupFolder(groupId string, folderId string, newFolderName string) error // 重命名群组文件夹 - DeleteGroupFolder(groupId string, folderId string) error // 删除群组文件夹 - - // GetOriginalClient 获取适配器的原始客户端对象,部分适配器可能不需要这个东西,只是方便直接传递原本的客户端实例 - GetOriginalClient() interface{} // 获取原始客户端对象 -} diff --git a/adapter/lagrange/element_converter.go b/adapter/lagrange/element_converter.go deleted file mode 100644 index 1840cf5..0000000 --- a/adapter/lagrange/element_converter.go +++ /dev/null @@ -1,107 +0,0 @@ -package lagrange - -import ( - "github.com/Iceinu-Project/iceinu/elements" - "github.com/LagrangeDev/LagrangeGo/message" - "strconv" - "strings" - "time" -) - -// ConvertIceElement 将LagrangeGo的元素转换为Iceinu的元素 -func ConvertIceElement(e []message.IMessageElement) *[]elements.IceinuMessageElement { - // 从LagrangeGo的元素转换为Iceinu的元素 - var IceinuElements []elements.IceinuMessageElement - // 遍历传入的元素 - for _, ele := range e { - switch ele.Type() { - // 将元素依次对应转换并传入 - case message.Text: - ele := ele.(*message.TextElement) - // 检测文本中是否包含换行符 - if strings.Contains(ele.Content, "\n") { - // 如果包含换行符,进行拆分和处理 - textParts := strings.Split(ele.Content, "\n") - for i, part := range textParts { - // 将每段文本添加到 IceinuElements - IceinuElements = append(IceinuElements, &elements.TextElement{Text: part}) - // 如果不是最后一段文本,则插入 BrElement - if i < len(textParts)-1 { - IceinuElements = append(IceinuElements, &elements.BrElement{}) - } - } - } else { - // 如果不包含换行符,直接添加文本元素 - IceinuElements = append(IceinuElements, &elements.TextElement{Text: ele.Content}) - } - case message.At: - ele := ele.(*message.AtElement) - IceinuElements = append(IceinuElements, &elements.AtElement{ - Id: strconv.Itoa(int(ele.TargetUin)), - Name: ele.Display, - Role: "", - Type: strconv.Itoa(int(ele.Type())), - }) - case message.Face: - ele := ele.(*message.FaceElement) - IceinuElements = append(IceinuElements, &elements.FaceElement{ - Id: ele.FaceID, - }) - case message.Voice: - ele := ele.(*message.VoiceElement) - IceinuElements = append(IceinuElements, &elements.AudioElement{ - Src: ele.Url, - Title: ele.Name, - Duration: ele.Size, - Poster: "", - }) - case message.Image: - ele := ele.(*message.ImageElement) - IceinuElements = append(IceinuElements, &elements.ImageElement{ - Src: ele.Url, - Width: ele.Width, - Height: ele.Height, - Title: ele.ImageId, - }) - case message.File: - ele := ele.(*message.FileElement) - IceinuElements = append(IceinuElements, &elements.FileElement{ - Src: ele.FileUrl, - Title: ele.FileName, - }) - case message.Reply: - ele := ele.(*message.ReplyElement) - IceinuElements = append(IceinuElements, &elements.QuoteElement{ - UserId: strconv.Itoa(int(ele.SenderUin)), - UserName: ele.SenderUid, - GroupId: strconv.Itoa(int(ele.GroupUin)), - Timestamp: time.Unix(int64(ele.Time), 0), - Elements: ConvertIceElement(ele.Elements), - }) - case message.Forward: - ele := ele.(*message.ForwardMessage) - IceinuElements = append(IceinuElements, &elements.MessageElement{ - Forward: true, - Elements: UnzipNodes(ele.Nodes), - }) - - default: - IceinuElements = append(IceinuElements, &elements.UnsupportedElement{Type: strconv.Itoa(int(ele.Type()))}) - } - } - return &IceinuElements -} - -func UnzipNodes(n []*message.ForwardNode) *[]elements.IceinuMessageElement { - var IceinuElements []elements.IceinuMessageElement - for _, node := range n { - IceinuElements = append(IceinuElements, &elements.NodeElement{ - GroupId: node.GroupId, - SenderId: node.SenderId, - SenderName: node.SenderName, - Time: node.Time, - Message: ConvertIceElement(node.Message), - }) - } - return &IceinuElements -} diff --git a/adapter/lagrange/lagrange_adapter.go b/adapter/lagrange/lagrange_adapter.go deleted file mode 100644 index f2d6ce5..0000000 --- a/adapter/lagrange/lagrange_adapter.go +++ /dev/null @@ -1,143 +0,0 @@ -package lagrange - -import ( - "github.com/Iceinu-Project/iceinu/adapter" - "github.com/Iceinu-Project/iceinu/config" - "github.com/Iceinu-Project/iceinu/ice" - "github.com/Iceinu-Project/iceinu/logger" - "github.com/Iceinu-Project/iceinu/utils" - "github.com/LagrangeDev/LagrangeGo/client" - "github.com/LagrangeDev/LagrangeGo/client/auth" - "github.com/sirupsen/logrus" - "os" - "os/signal" - "syscall" - "time" -) - -type AdapterLagrange struct { -} - -type Bot struct { - *client.QQClient -} - -var LgrClient *Bot -var lagrangeConfig *AdapterLagrangeConfig - -func (lgr *AdapterLagrange) GetMeta() *adapter.IceAdapterMeta { - return &adapter.IceAdapterMeta{ - AdapterName: "Lagrange Adapter", - Version: "β0.2.1", - Platform: "NTQQ", - Author: []string{ - "Kyoku", - }, - Introduce: "基于Lagrange的NTQQ适配器,内置了LagrangeGo,无需再连接额外的协议端。", - } -} - -func (lgr *AdapterLagrange) Init() { - logger.Infof("正在初始化Lagrange适配器,适配器当前版本: %s", lgr.GetMeta().Version) - - // 获取配置文件内容 - cm := config.GetManager() - lagrangeConfig := cm.Get("lagrange.toml").(*AdapterLagrangeConfig) - logger.Infof("%v", lagrangeConfig.Password == "") - - // 发送一个适配器初始化事件 - ice.Bus.Publish("AdapterInitEvent", ice.AdapterInitEvent{ - Timestamp: time.Time{}, - AdapterMeta: lgr.GetMeta(), - }) - - // 创建LagrangeGo的客户端实例 - plogger := logger.GetProtocolLogger() - appInfo := auth.AppList["linux"]["3.2.10-25765"] - deviceInfo := auth.NewDeviceInfo(lagrangeConfig.Account) - qqClientInstance := client.NewClient(uint32(lagrangeConfig.Account), appInfo, lagrangeConfig.SignUrl) - qqClientInstance.SetLogger(plogger) - qqClientInstance.UseDevice(deviceInfo) - - data, err := os.ReadFile("signature.bin") - if err != nil { - logrus.Warnln("读取签名文件时发生错误:", err) - } else { - sig, err := auth.UnmarshalSigInfo(data, true) - if err != nil { - logrus.Warnln("加载签名文件时发生错误:", err) - } else { - qqClientInstance.UseSig(sig) - } - } - LgrClient = &Bot{QQClient: qqClientInstance} - - defer LgrClient.Release() - defer SaveSignature() - - // 登录 - err = Login() - if err != nil { - return - } - - var bot = GetBot() - - // 刷新client的缓存 - err = LgrClient.RefreshAllGroupsInfo() - if err != nil { - return - } - err = LgrClient.RefreshFriendCache() - if err != nil { - return - } - err = LgrClient.RefreshFriendCache() - - utils.JPrint(bot.GetGroupMemberList("970801565")) - bot.SendContent("0", "2913844577", "测试消息") - - // 设置事件订阅器,将LagrangeGo的事件转换并发送到iceinu的事件总线上 - SetAllHandler() - SetAllSubscribes() - - // 主协程关闭通道 - mc := make(chan os.Signal, 2) - signal.Notify(mc, os.Interrupt, syscall.SIGTERM) - for { - switch <-mc { - case os.Interrupt, syscall.SIGTERM: - return - } - } -} - -// Login 登录 -func Login() error { - // 声明 err 变量并进行错误处理 - err := LgrClient.Login("", "qrcode.png") - if err != nil { - logrus.Errorln("登录时发生错误:", err) - return err - } - // 推送登录事件 - ice.Bus.Publish("AdapterLoginEvent", ice.AdapterInitEvent{ - Timestamp: time.Time{}, - }) - return nil -} - -// SaveSignature 保存sign信息 -func SaveSignature() { - data, err := LgrClient.Sig().Marshal() - if err != nil { - logger.Error("生成签名文件时发生错误err:", err) - return - } - err = os.WriteFile("signature.bin", data, 0644) - if err != nil { - logger.Error("写入签名文件时发生错误 err:", err) - return - } - logger.Info("签名已被写入签名文件") -} diff --git a/adapter/lagrange/lagrange_bot.go b/adapter/lagrange/lagrange_bot.go deleted file mode 100644 index 54bab36..0000000 --- a/adapter/lagrange/lagrange_bot.go +++ /dev/null @@ -1,533 +0,0 @@ -package lagrange - -import ( - "github.com/Iceinu-Project/iceinu/elements" - "github.com/Iceinu-Project/iceinu/resource" - "github.com/LagrangeDev/LagrangeGo/message" - "strconv" - "time" -) - -type BotLagrange struct { -} - -func (b BotLagrange) GetChannel(channelId string) *resource.Channel { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetChannelList(groupId string) []*resource.Channel { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetChannelListByToken(next string) *resource.PagedList { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) CreateChannel(groupId string, data *resource.Channel) (*resource.Channel, error) { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) UpdateChannel(groupId string, data *resource.Channel) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) DeleteChannel(channelId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) MuteChannel(channelId string, duration uint32) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) CreateUserChannel(userId string, groupId string) (*resource.Channel, error) { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetGroup(groupId string) *resource.Group { - groupUin, _ := strconv.Atoi(groupId) - group := LgrClient.GetCachedGroupInfo(uint32(groupUin)) - return &resource.Group{ - Id: strconv.Itoa(int(group.GroupUin)), - Name: group.GroupName, - Avatar: group.Avatar, - Maxcount: group.MaxMember, - MemberCount: group.MemberCount, - } -} - -func (b BotLagrange) GetGroupList() []*resource.Group { - info, _ := LgrClient.GetAllGroupsInfo() - groups := make([]*resource.Group, 0) - for _, group := range info { - groups = append(groups, &resource.Group{ - Id: strconv.Itoa(int(group.GroupUin)), - Name: group.GroupName, - Avatar: group.Avatar, - Maxcount: group.MaxMember, - MemberCount: group.MemberCount, - }) - } - return groups -} - -func (b BotLagrange) GetGroupListByToken(next string) *resource.PagedList { - info, _ := LgrClient.GetAllGroupsInfo() - groups := make([]*resource.Group, 0) - for _, group := range info { - groups = append(groups, &resource.Group{ - Id: strconv.Itoa(int(group.GroupUin)), - Name: group.GroupName, - Avatar: group.Avatar, - Maxcount: group.MaxMember, - MemberCount: group.MemberCount, - }) - } - next = "" - return &resource.PagedList{ - Data: groups, - Next: "", - } -} - -func (b BotLagrange) ApproveGroupInvite(messageId string, approve bool, comment string) error { - messageId = "" - approve = false - comment = "" - return nil -} - -func (b BotLagrange) GetGroupMember(groupId string, userId string) *resource.GroupMember { - groupIdInt, _ := strconv.Atoi(groupId) - userIdInt, _ := strconv.Atoi(userId) - members, err := LgrClient.GetGroupMembersData(uint32(groupIdInt)) - if err != nil { - return nil - } - if member, ok := members[uint32(userIdInt)]; ok { - return &resource.GroupMember{ - User: &resource.User{ - Id: userId, - Name: member.MemberName, - Nickname: member.DisplayName(), - Avatar: member.Avatar, - IsBot: false, - }, - Nickname: member.DisplayName(), - Avatar: member.Avatar, - JoinedAt: time.Unix(int64(member.JoinTime), 0), - } - } - // 否则返回空 - return nil -} - -func (b BotLagrange) GetGroupMemberList(groupId string) []*resource.GroupMember { - groupIdInt, _ := strconv.Atoi(groupId) - members, err := LgrClient.GetGroupMembersData(uint32(groupIdInt)) - if err != nil { - return nil - } - groupMembers := make([]*resource.GroupMember, 0) - for _, member := range members { - groupMembers = append(groupMembers, &resource.GroupMember{ - User: &resource.User{ - Id: strconv.Itoa(int(member.Uin)), - Name: member.MemberName, - Nickname: member.DisplayName(), - Avatar: member.Avatar, - IsBot: false, - }, - Nickname: member.DisplayName(), - Avatar: member.Avatar, - JoinedAt: time.Unix(int64(member.JoinTime), 0), - }) - } - return groupMembers -} - -func (b BotLagrange) GetGroupMemberListByToken(groupId string, _ string) *resource.PagedList { - groupIdInt, _ := strconv.Atoi(groupId) - members, err := LgrClient.GetGroupMembersData(uint32(groupIdInt)) - if err != nil { - return nil - } - groupMembers := make([]*resource.GroupMember, 0) - for _, member := range members { - groupMembers = append(groupMembers, &resource.GroupMember{ - User: &resource.User{ - Id: strconv.Itoa(int(member.Uin)), - Name: member.MemberName, - Nickname: member.DisplayName(), - Avatar: member.Avatar, - IsBot: false, - }, - Nickname: member.DisplayName(), - Avatar: member.Avatar, - JoinedAt: time.Unix(int64(member.JoinTime), 0), - }) - } - return &resource.PagedList{ - Data: groupMembers, - Next: "", - } -} - -func (b BotLagrange) KickGroupMember(groupId string, userId string, permanent bool) error { - groupIdInt, _ := strconv.Atoi(groupId) - userIdInt, _ := strconv.Atoi(userId) - err := LgrClient.GroupKickMember(uint32(groupIdInt), uint32(userIdInt), permanent) - if err != nil { - return err - } - return nil -} - -func (b BotLagrange) MuteGroupMember(groupId string, userId string, duration uint32) error { - groupIdInt, _ := strconv.Atoi(groupId) - userIdInt, _ := strconv.Atoi(userId) - err := LgrClient.GroupMuteMember(uint32(groupIdInt), uint32(userIdInt), duration) - if err != nil { - return err - } - return nil -} - -func (b BotLagrange) ApproveGroupRequest(messageId string, approve bool, comment string) error { - // 晚点实现 - panic("implement me") -} - -// SetGroupMemberRole 设置群成员角色,在NTQQ中实际上只能是设置管理员 -func (b BotLagrange) SetGroupMemberRole(groupId string, userId string, _ string) error { - groupIdInt, _ := strconv.Atoi(groupId) - userIdInt, _ := strconv.Atoi(userId) - err := LgrClient.GroupSetAdmin(uint32(groupIdInt), uint32(userIdInt), true) - if err != nil { - return err - } - return nil -} - -// UnsetGroupMemberRole 取消群成员角色,在NTQQ中实际上只能是取消管理员 -func (b BotLagrange) UnsetGroupMemberRole(groupId string, userId string, _ string) error { - groupIdInt, _ := strconv.Atoi(groupId) - userIdInt, _ := strconv.Atoi(userId) - err := LgrClient.GroupSetAdmin(uint32(groupIdInt), uint32(userIdInt), false) - if err != nil { - return err - } - return nil -} - -func (b BotLagrange) GetGroupRoleList(_ string) []*resource.GroupRole { - return []*resource.GroupRole{ - { - Id: "1", - Name: "管理员", - }, - { - Id: "2", - Name: "群员", - }, - } -} - -func (b BotLagrange) GetGroupRoleListByToken(groupId string, next string) *resource.PagedList { - return &resource.PagedList{ - Data: []*resource.GroupRole{ - { - Id: "1", - Name: "管理员", - }, - { - Id: "2", - Name: "群员", - }, - }, - Next: "", - } -} - -func (b BotLagrange) CreateGroupRole(_ string, _ *resource.GroupRole) (*resource.GroupRole, error) { - return nil, nil -} - -func (b BotLagrange) UpdateGroupRole(_ string, _ string, _ *resource.GroupRole) error { - return nil -} - -func (b BotLagrange) DeleteGroupRole(_ string, _ string) error { - return nil -} - -func (b BotLagrange) GetLoginInfo() *resource.Login { - return nil -} - -func (b BotLagrange) SendContent(groupId string, channelId string, content string) (*resource.Message, error) { - groupIdInt, _ := strconv.Atoi(groupId) - channelIdInt, _ := strconv.Atoi(channelId) - var msg []message.IMessageElement - if groupIdInt == 0 { - msg = append(msg, message.NewText(content)) - res, err := LgrClient.SendPrivateMessage(uint32(channelIdInt), msg) - if err != nil { - return nil, err - } - return &resource.Message{ - Id: strconv.Itoa(int(res.Id)), - Content: res.ToString(), - Channel: nil, - Group: nil, - Member: nil, - User: nil, - CreatedAt: time.Unix(int64(res.Time), 0), - UpdatedAt: time.Time{}, - MessageElements: ConvertIceElement(res.Elements), - }, nil - } else { - msg = append(msg, message.NewText(content)) - res, err := LgrClient.SendGroupMessage(uint32(groupIdInt), msg) - if err != nil { - return nil, err - } - return &resource.Message{ - Id: strconv.Itoa(int(res.Id)), - Content: res.ToString(), - Channel: nil, - Group: nil, - Member: nil, - User: nil, - CreatedAt: time.Unix(int64(res.Time), 0), - UpdatedAt: time.Time{}, - MessageElements: ConvertIceElement(res.Elements), - }, nil - } -} - -func (b BotLagrange) GetMessage(channelId string, messageId string) (*resource.Message, error) { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RecallMessage(channelId string, messageId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) UpdateMessage(channelId string, messageId string, content string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetMessageList(channelId string, limit uint32, order bool) []*resource.Message { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetMessageListByRange(channelId string, messageId string, start uint32, count uint32) []*resource.Message { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) CreateReaction(channelId string, messageId string, emoji string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) DeleteReaction(channelId string, messageId string, emoji string, userId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) ClearReaction(channelId string, messageId string, emoji string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetReactionList(channelId string, messageId string, emoji string) []resource.User { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetReactionListByToken(channelId string, messageId string, emoji string, next string) *resource.PagedList { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetUser(userId string) *resource.User { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetFriendList() []*resource.User { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) ApproveFriendRequest(messageId string, approve string, comment string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) Send(groupId string, channelId string, elements []elements.IceinuMessageElement) (*resource.Message, error) { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) SendSatori(groupId string, channelId string, satori string) (*resource.Message, error) { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) SendPoke(groupId string, channelId string, userId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetSelfUserId() string { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetSelfUserName() string { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetSelfAvatarUrl() string { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetSeldUserNickname() string { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetGroupAvatarUrl(groupId string) string { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RefreshUserListCache() error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RefreshGroupListCache() error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RefreshGroupMemberCache(groupId string, userId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RefreshGroupAllMembersCache(groupId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RefreshChannelListCache(groupId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RenameGroup(groupId string, name string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RenameGroupMember(groupId string, userId string, nickname string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RemarkGroup(groupId string, remark string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) SetGroupGlobalMute(groupId string, mute bool) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) LeaveGroup(groupId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) SetGroupMemberTitle(groupId string, userId string, title string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) UploadChannelFile(channelId string, filePath string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) UploadGroupFile(groupId string, filePath string, targetFilePath string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetGroupFileSystemInfo(groupId string) *resource.GroupFileSystemInfo { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetGroupFilesByFolder(groupId string, folderId string) interface{} { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetGroupRootFiles(groupId string) interface{} { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) MoveGroupFile(groupId string, fileId string, parentFolder string, targetFolderId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) DeleteGroupFile(groupId string, fileId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) CreateGroupFolder(groupId string, folderName string, parentFolder string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) RenameGroupFolder(groupId string, folderId string, newFolderName string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) DeleteGroupFolder(groupId string, folderId string) error { - //TODO implement me - panic("implement me") -} - -func (b BotLagrange) GetOriginalClient() interface{} { - //TODO implement me - panic("implement me") -} - -func GetBot() *BotLagrange { - return &BotLagrange{} -} diff --git a/adapter/lagrange/lagrange_config.go b/adapter/lagrange/lagrange_config.go deleted file mode 100644 index a035aac..0000000 --- a/adapter/lagrange/lagrange_config.go +++ /dev/null @@ -1,21 +0,0 @@ -package lagrange - -import "github.com/Iceinu-Project/iceinu/config" - -type AdapterLagrangeConfig struct { - Account int `toml:"account"` - Password string `toml:"password"` - SignUrl string `toml:"sign_url"` - MusicSignUrl string `toml:"music_sign_url"` -} - -var manager = config.GetManager() - -func RegisterConfig() { - manager.InitConfig("lagrange.toml", &AdapterLagrangeConfig{ - Account: 0, - Password: "", - SignUrl: "https://sign.lagrangecore.org/api/sign/25765", - MusicSignUrl: "", - }) -} diff --git a/adapter/lagrange/lagrange_handler.go b/adapter/lagrange/lagrange_handler.go deleted file mode 100644 index 17e7ab2..0000000 --- a/adapter/lagrange/lagrange_handler.go +++ /dev/null @@ -1,97 +0,0 @@ -package lagrange - -import ( - "fmt" - "strconv" - "time" - - "github.com/LagrangeDev/LagrangeGo/client" - "github.com/LagrangeDev/LagrangeGo/message" - - "github.com/Iceinu-Project/iceinu/ice" - "github.com/Iceinu-Project/iceinu/logger" - "github.com/Iceinu-Project/iceinu/resource" - "github.com/Iceinu-Project/iceinu/utils" -) - -func SetAllHandler() { - Manager.RegisterPrivateMessageHandler(func(client *client.QQClient, event *message.PrivateMessage) { - self, _ := client.FetchUserInfoUin(client.Uin) - e := ice.PlatformEvent{ - EventId: uint64(event.Id), - EventType: "PrivateMessageEvent", - Platform: "QQNT", - SelfId: strconv.Itoa(int(client.Uin)), - Timestamp: time.Unix(int64(event.Time), 0), - Group: &resource.Group{ - Id: "", - Name: "", - Avatar: "", - }, - Channel: &resource.Channel{ - Id: strconv.Itoa(int(event.Sender.Uin)), - Type: 1, - Name: event.Sender.Uid, - ParentId: "", - }, - Message: &resource.Message{ - Id: strconv.Itoa(int(event.InternalId)), - Content: event.ToString(), - MessageElements: ConvertIceElement(event.Elements), - }, - Operator: &resource.User{ - Id: strconv.Itoa(int(event.Sender.Uin)), - Name: event.Sender.Uid, - Nickname: event.Sender.Nickname, - Avatar: self.Avatar, - IsBot: false, - }, - User: &resource.User{ - Id: strconv.Itoa(int(event.Target)), - Name: client.GetUid(client.Uin), - Nickname: client.NickName(), - Avatar: self.Avatar, - IsBot: false, - }, - } - logger.Infof("[私聊][%s]%s:%s", e.Operator.Id, e.Operator.Nickname, utils.SatorizeIceElements(e.Message.MessageElements)) - ice.Bus.Publish("PrivateMessageEvent", &e) - }) - Manager.RegisterGroupMessageHandler(func(client *client.QQClient, event *message.GroupMessage) { - groupinfo := client.GetCachedGroupInfo(event.GroupUin) - fmt.Println(groupinfo) - self, _ := client.FetchUserInfoUin(client.Uin) - e := ice.PlatformEvent{ - EventId: uint64(event.Id), - EventType: "GroupMessageEvent", - Platform: "QQNT", - SelfId: strconv.Itoa(int(client.Uin)), - Timestamp: time.Unix(int64(event.Time), 0), - Channel: &resource.Channel{ - Id: strconv.Itoa(int(event.GroupUin)), - Type: 0, - Name: event.GroupName, - ParentId: "", - }, - Group: &resource.Group{ - Id: strconv.Itoa(int(event.GroupUin)), - Name: event.GroupName, - Avatar: groupinfo.Avatar, - }, - Message: &resource.Message{ - Id: strconv.Itoa(int(event.InternalId)), - Content: event.ToString(), - MessageElements: ConvertIceElement(event.Elements), - }, - Operator: &resource.User{ - Id: strconv.Itoa(int(event.Sender.Uin)), - Name: event.Sender.Uid, - Nickname: event.Sender.Nickname, - Avatar: self.Avatar, - IsBot: false, - }, - } - logger.Infof("[群聊][来自群%s][%s]%s:%s", e.Group.Id, e.Operator.Id, e.Operator.Nickname, utils.SatorizeIceElements(e.Message.MessageElements)) - ice.Bus.Publish("GroupMessageEvent", &e) - }) -} diff --git a/adapter/lagrange/lagrange_subscriber.go b/adapter/lagrange/lagrange_subscriber.go deleted file mode 100644 index a922704..0000000 --- a/adapter/lagrange/lagrange_subscriber.go +++ /dev/null @@ -1,312 +0,0 @@ -package lagrange - -import ( - "github.com/LagrangeDev/LagrangeGo/client" - "github.com/LagrangeDev/LagrangeGo/client/event" - "github.com/LagrangeDev/LagrangeGo/message" -) - -// 定义各个消息类型的处理函数 - -type PrivateMessageHandler func(client *client.QQClient, message *message.PrivateMessage) -type GroupMessageHandler func(client *client.QQClient, message *message.GroupMessage) -type TempMessageHandler func(client *client.QQClient, message *message.TempMessage) - -type SelfPrivateMessageHandler func(client *client.QQClient, message *message.PrivateMessage) -type SelfGroupMessageHandler func(client *client.QQClient, message *message.GroupMessage) -type SelfTempMessageHandler func(client *client.QQClient, message *message.TempMessage) - -// 定义各个事件类型的处理函数 - -type GroupJoinEventHandler func(client *client.QQClient, event *event.GroupMemberIncrease) // bot进群 -type GroupLeaveEventHandler func(client *client.QQClient, event *event.GroupMemberDecrease) // bot退群 - -type GroupInvitedEventHandler func(client *client.QQClient, event *event.GroupInvite) // bot被邀请进群 -type GroupMemberJoinRequestEventHandler func(client *client.QQClient, event *event.GroupMemberJoinRequest) // 加群邀请 -type GroupMemberJoinEventHandler func(client *client.QQClient, event *event.GroupMemberIncrease) // 成员加群 -type GroupMemberLeaveEventHandler func(client *client.QQClient, event *event.GroupMemberDecrease) // 成员退群 -type GroupMuteEventHandler func(client *client.QQClient, event *event.GroupMute) // 禁言事件 -type GroupRecallEventHandler func(client *client.QQClient, event *event.GroupRecall) -type GroupMemberPermissionChangedEventHandler func(client *client.QQClient, event *event.GroupMemberPermissionChanged) -type GroupNameUpdatedEventHandler func(client *client.QQClient, event *event.GroupNameUpdated) // 群更名 -type MemberSpecialTitleUpdatedEventHandler func(client *client.QQClient, event *event.MemberSpecialTitleUpdated) // 群成员特殊头衔更新 -type NewFriendRequestHandler func(client *client.QQClient, event *event.NewFriendRequest) // 新朋友请求 -type FriendRecallEventHandler func(client *client.QQClient, event *event.FriendRecall) // 好友消息撤回 -type RenameEventHandler func(client *client.QQClient, event *event.Rename) // 好友昵称更改 -type FriendNotifyEventHandler func(client *client.QQClient, event event.INotifyEvent) // 好友通知 -type GroupNotifyEventHandler func(client *client.QQClient, event event.INotifyEvent) // 群通知 - -// SubscribeManager 订阅管理器实现,用于向LagrangeGo注册各类消息/事件处理函数 -type SubscribeManager struct { - privateMessageHandlers []PrivateMessageHandler - groupMessageHandlers []GroupMessageHandler - tempMessageHandlers []TempMessageHandler - selfPrivateMessageHandlers []SelfPrivateMessageHandler - selfGroupMessageHandlers []SelfGroupMessageHandler - selfTempMessageHandlers []SelfTempMessageHandler - groupJoinEventHandlers []GroupJoinEventHandler - groupLeaveEventHandlers []GroupLeaveEventHandler - groupInviteEventHandlers []GroupInvitedEventHandler - groupMemberJoinRequestEventHandlers []GroupMemberJoinRequestEventHandler - groupMemberJoinEventHandlers []GroupMemberJoinEventHandler - groupMemberLeaveEventHandlers []GroupMemberLeaveEventHandler - groupMuteEventHandlers []GroupMuteEventHandler - groupRecallEventHandlers []GroupRecallEventHandler - groupMemberPermissionChangedEventHandlers []GroupMemberPermissionChangedEventHandler - groupNameUpdatedEventHandlers []GroupNameUpdatedEventHandler - memberSpecialTitleUpdatedEventHandlers []MemberSpecialTitleUpdatedEventHandler - newFriendRequestHandlers []NewFriendRequestHandler - friendRecallEventHandlers []FriendRecallEventHandler - renameEventHandlers []RenameEventHandler - friendNotifyEventHandlers []FriendNotifyEventHandler - groupNotifyEventHandlers []GroupNotifyEventHandler -} - -// Manager 全局 SubscribeManager 实例 -var Manager = &SubscribeManager{} - -// RegisterPrivateMessageHandler 注册私聊消息处理函数 -func (sm *SubscribeManager) RegisterPrivateMessageHandler(handler PrivateMessageHandler) { - sm.privateMessageHandlers = append(sm.privateMessageHandlers, handler) -} - -// RegisterGroupMessageHandler 注册群消息处理函数 -func (sm *SubscribeManager) RegisterGroupMessageHandler(handler GroupMessageHandler) { - sm.groupMessageHandlers = append(sm.groupMessageHandlers, handler) -} - -// RegisterTempMessageHandler 注册临时消息处理函数 -func (sm *SubscribeManager) RegisterTempMessageHandler(handler TempMessageHandler) { - sm.tempMessageHandlers = append(sm.tempMessageHandlers, handler) -} - -// RegisterSelfPrivateMessageHandler 注册自己的私聊消息处理函数 -func (sm *SubscribeManager) RegisterSelfPrivateMessageHandler(handler SelfPrivateMessageHandler) { - sm.selfPrivateMessageHandlers = append(sm.selfPrivateMessageHandlers, handler) -} - -// RegisterSelfGroupMessageHandler 注册自己的群消息处理函数 -func (sm *SubscribeManager) RegisterSelfGroupMessageHandler(handler SelfGroupMessageHandler) { - sm.selfGroupMessageHandlers = append(sm.selfGroupMessageHandlers, handler) -} - -// RegisterSelfTempMessageHandler 注册自己的临时消息处理函数 -func (sm *SubscribeManager) RegisterSelfTempMessageHandler(handler SelfTempMessageHandler) { - sm.selfTempMessageHandlers = append(sm.selfTempMessageHandlers, handler) -} - -// RegisterGroupJoinEventHandler 注册群成员加入事件处理函数 -func (sm *SubscribeManager) RegisterGroupJoinEventHandler(handler GroupJoinEventHandler) { - sm.groupJoinEventHandlers = append(sm.groupJoinEventHandlers, handler) -} - -// RegisterGroupLeaveEventHandler 注册群成员离开事件处理函数 -func (sm *SubscribeManager) RegisterGroupLeaveEventHandler(handler GroupLeaveEventHandler) { - sm.groupLeaveEventHandlers = append(sm.groupLeaveEventHandlers, handler) -} - -// RegisterGroupInviteEventHandler 注册群邀请事件处理函数 -func (sm *SubscribeManager) RegisterGroupInviteEventHandler(handler GroupInvitedEventHandler) { - sm.groupInviteEventHandlers = append(sm.groupInviteEventHandlers, handler) - -} - -// RegisterGroupMemberJoinRequestEventHandler 注册群成员加群邀请事件处理函数 -func (sm *SubscribeManager) RegisterGroupMemberJoinRequestEventHandler(handler GroupMemberJoinRequestEventHandler) { - sm.groupMemberJoinRequestEventHandlers = append(sm.groupMemberJoinRequestEventHandlers, handler) -} - -// RegisterGroupMemberJoinEventHandler 注册群成员加入事件处理函数 -func (sm *SubscribeManager) RegisterGroupMemberJoinEventHandler(handler GroupMemberJoinEventHandler) { - sm.groupMemberJoinEventHandlers = append(sm.groupMemberJoinEventHandlers, handler) -} - -// RegisterGroupMemberLeaveEventHandler 注册群成员离开事件处理函数 -func (sm *SubscribeManager) RegisterGroupMemberLeaveEventHandler(handler GroupMemberLeaveEventHandler) { - sm.groupMemberLeaveEventHandlers = append(sm.groupMemberLeaveEventHandlers, handler) -} - -// RegisterGroupMuteEventHandler 注册群成员禁言事件处理函数 -func (sm *SubscribeManager) RegisterGroupMuteEventHandler(handler GroupMuteEventHandler) { - sm.groupMuteEventHandlers = append(sm.groupMuteEventHandlers, handler) -} - -// RegisterGroupRecallEventHandler 注册群消息撤回事件处理函数 -func (sm *SubscribeManager) RegisterGroupRecallEventHandler(handler GroupRecallEventHandler) { - sm.groupRecallEventHandlers = append(sm.groupRecallEventHandlers, handler) -} - -// RegisterGroupMemberPermissionChangedEventHandler 注册群成员权限变更事件处理函数 -func (sm *SubscribeManager) RegisterGroupMemberPermissionChangedEventHandler(handler GroupMemberPermissionChangedEventHandler) { - sm.groupMemberPermissionChangedEventHandlers = append(sm.groupMemberPermissionChangedEventHandlers, handler) -} - -// RegisterGroupNameUpdatedEventHandler 注册群名称变更事件处理函数 -func (sm *SubscribeManager) RegisterGroupNameUpdatedEventHandler(handler GroupNameUpdatedEventHandler) { - sm.groupNameUpdatedEventHandlers = append(sm.groupNameUpdatedEventHandlers, handler) -} - -// RegisterMemberSpecialTitleUpdatedEventHandler 注册群成员特殊头衔变更事件处理函数 -func (sm *SubscribeManager) RegisterMemberSpecialTitleUpdatedEventHandler(handler MemberSpecialTitleUpdatedEventHandler) { - sm.memberSpecialTitleUpdatedEventHandlers = append(sm.memberSpecialTitleUpdatedEventHandlers, handler) -} - -// RegisterNewFriendRequestHandler 注册新朋友请求处理函数 -func (sm *SubscribeManager) RegisterNewFriendRequestHandler(handler NewFriendRequestHandler) { - sm.newFriendRequestHandlers = append(sm.newFriendRequestHandlers, handler) -} - -// RegisterFriendRecallEventHandler 注册好友消息撤回事件处理函数 -func (sm *SubscribeManager) RegisterFriendRecallEventHandler(handler FriendRecallEventHandler) { - sm.friendRecallEventHandlers = append(sm.friendRecallEventHandlers, handler) -} - -// RegisterRenameEventHandler 注册好友昵称更改事件处理函数 -func (sm *SubscribeManager) RegisterRenameEventHandler(handler RenameEventHandler) { - sm.renameEventHandlers = append(sm.renameEventHandlers, handler) -} - -// RegisterFriendNotifyEventHandler 注册好友通知事件处理函数 -func (sm *SubscribeManager) RegisterFriendNotifyEventHandler(handler FriendNotifyEventHandler) { - sm.friendNotifyEventHandlers = append(sm.friendNotifyEventHandlers, handler) -} - -// RegisterGroupNotifyEventHandler 注册群通知事件处理函数 -func (sm *SubscribeManager) RegisterGroupNotifyEventHandler(handler GroupNotifyEventHandler) { - sm.groupNotifyEventHandlers = append(sm.groupNotifyEventHandlers, handler) -} - -// SetAllSubscribes 设置所有订阅处理 -func SetAllSubscribes() { - LgrClient.QQClient.PrivateMessageEvent.Subscribe(func(client *client.QQClient, event *message.PrivateMessage) { - for _, handler := range Manager.privateMessageHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupMessageEvent.Subscribe(func(client *client.QQClient, event *message.GroupMessage) { - for _, handler := range Manager.groupMessageHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.TempMessageEvent.Subscribe(func(client *client.QQClient, event *message.TempMessage) { - for _, handler := range Manager.tempMessageHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.SelfPrivateMessageEvent.Subscribe(func(client *client.QQClient, event *message.PrivateMessage) { - for _, handler := range Manager.selfPrivateMessageHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.SelfGroupMessageEvent.Subscribe(func(client *client.QQClient, event *message.GroupMessage) { - for _, handler := range Manager.selfGroupMessageHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.SelfTempMessageEvent.Subscribe(func(client *client.QQClient, event *message.TempMessage) { - for _, handler := range Manager.selfTempMessageHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupJoinEvent.Subscribe(func(client *client.QQClient, event *event.GroupMemberIncrease) { - for _, handler := range Manager.groupJoinEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupLeaveEvent.Subscribe(func(client *client.QQClient, event *event.GroupMemberDecrease) { - for _, handler := range Manager.groupLeaveEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupInvitedEvent.Subscribe(func(client *client.QQClient, event *event.GroupInvite) { - for _, handler := range Manager.groupInviteEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupMemberJoinRequestEvent.Subscribe(func(client *client.QQClient, event *event.GroupMemberJoinRequest) { - for _, handler := range Manager.groupMemberJoinRequestEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupMemberJoinEvent.Subscribe(func(client *client.QQClient, event *event.GroupMemberIncrease) { - for _, handler := range Manager.groupMemberJoinEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupMemberLeaveEvent.Subscribe(func(client *client.QQClient, event *event.GroupMemberDecrease) { - for _, handler := range Manager.groupMemberLeaveEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupMuteEvent.Subscribe(func(client *client.QQClient, event *event.GroupMute) { - for _, handler := range Manager.groupMuteEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupRecallEvent.Subscribe(func(client *client.QQClient, event *event.GroupRecall) { - for _, handler := range Manager.groupRecallEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupMemberPermissionChangedEvent.Subscribe(func(client *client.QQClient, event *event.GroupMemberPermissionChanged) { - for _, handler := range Manager.groupMemberPermissionChangedEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupNameUpdatedEvent.Subscribe(func(client *client.QQClient, event *event.GroupNameUpdated) { - for _, handler := range Manager.groupNameUpdatedEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.MemberSpecialTitleUpdatedEvent.Subscribe(func(client *client.QQClient, event *event.MemberSpecialTitleUpdated) { - for _, handler := range Manager.memberSpecialTitleUpdatedEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.NewFriendRequestEvent.Subscribe(func(client *client.QQClient, event *event.NewFriendRequest) { - for _, handler := range Manager.newFriendRequestHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.FriendRecallEvent.Subscribe(func(client *client.QQClient, event *event.FriendRecall) { - for _, handler := range Manager.friendRecallEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.RenameEvent.Subscribe(func(client *client.QQClient, event *event.Rename) { - for _, handler := range Manager.renameEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.FriendNotifyEvent.Subscribe(func(client *client.QQClient, event event.INotifyEvent) { - for _, handler := range Manager.friendNotifyEventHandlers { - handler(client, event) - } - }) - - LgrClient.QQClient.GroupNotifyEvent.Subscribe(func(client *client.QQClient, event event.INotifyEvent) { - for _, handler := range Manager.groupNotifyEventHandlers { - handler(client, event) - } - }) -} diff --git a/config/config_manager.go b/config/config_manager.go deleted file mode 100644 index a2fae5e..0000000 --- a/config/config_manager.go +++ /dev/null @@ -1,233 +0,0 @@ -package config - -import ( - "github.com/Iceinu-Project/iceinu/logger" - "github.com/pelletier/go-toml" - "os" - "path/filepath" - "reflect" - "sync" -) - -// Iceinu的配置文件处理器,除了iceinu自带的配置文件之外也负责处理适配器和插件的配置文件设置 -// 这配置文件管理器设计一大半是ChatGPT帮我优化的,o1模型真的是太斯巴拉西了 -// 总之是实现了动态的配置文件注册加载解析修正等等功能 - -// ConfManager 管理配置文件的结构体 -type ConfManager struct { - configs map[string]interface{} - defaults map[string]interface{} - mutex sync.RWMutex - configChanged bool // 标志位,指示配置文件是否有生成或修改 -} - -// manager 是全局的配置管理器实例 -var manager = NewManager() - -// NewManager 创建一个新的配置管理器 -func NewManager() *ConfManager { - logger.Debugf("正在初始化配置文件管理器...") - return &ConfManager{ - configs: make(map[string]interface{}), - defaults: make(map[string]interface{}), - } -} - -// InitConfig 注册一个配置文件和对应的结构体 -func (cm *ConfManager) InitConfig(filename string, configStruct interface{}) { - cm.mutex.Lock() - defer cm.mutex.Unlock() - cm.configs[filename] = configStruct - - // 保存默认配置的深拷贝 - defaultConfig := deepCopy(configStruct) - cm.defaults[filename] = defaultConfig - - logger.Debugf("已注册配置文件:%s", filename) -} - -// LoadConfigs 加载并解析所有已注册的配置文件,如果不存在则自动生成 -// 如果已有的配置文件缺少字段,则补全并写回,并在覆盖前备份原始文件 -func (cm *ConfManager) LoadConfigs() error { - cm.mutex.Lock() - defer cm.mutex.Unlock() - - // 获取当前工作目录 - dir, err := os.Getwd() - if err != nil { - logger.Errorf("获取工作目录失败:%v", err) - return err - } - - // 遍历已注册的配置文件 - for filename, configStruct := range cm.configs { - fullPath := filepath.Join(dir, filename) - - // 检查文件是否存在 - if _, err := os.Stat(fullPath); os.IsNotExist(err) { - // 如果文件不存在,生成默认配置文件 - data, err := toml.Marshal(configStruct) - if err != nil { - logger.Errorf("序列化默认配置失败:%v", err) - return err - } - - err = os.WriteFile(fullPath, data, 0644) - if err != nil { - logger.Errorf("写入配置文件失败:%v", err) - return err - } - - logger.Infof("已生成配置文件:%s", fullPath) - cm.configChanged = true // 设置标志位 - } else { - // 如果文件存在,读取并解析配置文件 - data, err := os.ReadFile(fullPath) - if err != nil { - logger.Errorf("读取配置文件失败:%v", err) - return err - } - - // 创建一个新的配置实例,用于加载文件内容 - newConfig := deepCopy(cm.defaults[filename]) - - err = toml.Unmarshal(data, newConfig) - if err != nil { - logger.Errorf("解析配置文件失败:%v", err) - return err - } - - // 比较新配置和默认配置,补全缺失的字段 - changed := mergeConfig(newConfig, cm.defaults[filename]) - - // 将补全后的配置赋值回 configs - cm.configs[filename] = newConfig - - if changed { - // 在覆盖前备份原始配置文件 - backupPath := fullPath + ".backup.toml" - err = backupFile(fullPath, backupPath) - if err != nil { - logger.Errorf("备份配置文件失败:%v", err) - return err - } - - // 将完整的配置(包含默认值和新解析的值)写回配置文件 - data, err = toml.Marshal(newConfig) - if err != nil { - logger.Errorf("序列化配置文件失败:%v", err) - return err - } - - err = os.WriteFile(fullPath, data, 0644) - if err != nil { - logger.Errorf("写入配置文件失败:%v", err) - return err - } - - logger.Infof("配置文件已更新并备份:%s", fullPath) - cm.configChanged = true // 设置标志位 - } else { - logger.Debugf("配置文件已加载,无需更新:%s", fullPath) - } - } - } - - // 如果配置文件有变动,提示用户并退出程序 - if cm.configChanged { - logger.Warnf("配置文件已生成或更新,请检查配置文件后重新启动程序。") - os.Exit(0) - } - - return nil -} - -// Get 获取指定名称的配置 -func (cm *ConfManager) Get(filename string) interface{} { - cm.mutex.RLock() - defer cm.mutex.RUnlock() - return cm.configs[filename] -} - -// GetManager 获取配置管理器实例 -func GetManager() *ConfManager { - return manager -} - -// deepCopy 深拷贝一个配置结构体 -func deepCopy(src interface{}) interface{} { - // 将 src 序列化为 TOML - data, err := toml.Marshal(src) - if err != nil { - logger.Errorf("深拷贝失败:%v", err) - return nil - } - - // 创建一个新的与 src 类型相同的实例 - dst := reflect.New(reflect.TypeOf(src).Elem()).Interface() - - // 将 TOML 反序列化到 dst - err = toml.Unmarshal(data, dst) - if err != nil { - logger.Errorf("深拷贝失败:%v", err) - return nil - } - - return dst -} - -// mergeConfig 递归地将 src 中的非零值合并到 dst 中,返回是否有修改 -func mergeConfig(dst, src interface{}) bool { - dstVal := reflect.ValueOf(dst).Elem() - srcVal := reflect.ValueOf(src).Elem() - - changed := false - - for i := 0; i < dstVal.NumField(); i++ { - dstField := dstVal.Field(i) - srcField := srcVal.Field(i) - - switch dstField.Kind() { - case reflect.Struct: - if mergeConfig(dstField.Addr().Interface(), srcField.Addr().Interface()) { - changed = true - } - case reflect.Slice, reflect.Map: - if dstField.IsNil() && !srcField.IsNil() { - dstField.Set(srcField) - changed = true - } - default: - // 如果 dstField 是零值,则使用 srcField 的值 - if isZeroValue(dstField) && !isZeroValue(srcField) { - dstField.Set(srcField) - changed = true - } - } - } - - return changed -} - -// isZeroValue 判断一个值是否是零值 -func isZeroValue(v reflect.Value) bool { - return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) -} - -// backupFile 备份原始配置文件 -func backupFile(originalPath, backupPath string) error { - // 读取原始文件内容 - data, err := os.ReadFile(originalPath) - if err != nil { - return err - } - - // 写入备份文件 - err = os.WriteFile(backupPath, data, 0644) - if err != nil { - return err - } - - logger.Infof("已备份配置文件:%s", backupPath) - return nil -} diff --git a/config/iceinu_config.go b/config/iceinu_config.go deleted file mode 100644 index 9825991..0000000 --- a/config/iceinu_config.go +++ /dev/null @@ -1,22 +0,0 @@ -package config - -type IceinuConfig struct { - BotName string `toml:"bot_name"` - LogLevel string `toml:"log_level"` - Database DatabaseConfig `toml:"database"` -} - -type DatabaseConfig struct { - URL string `toml:"url"` -} - -func init() { - // 注册Iceinu的配置文件 - manager.InitConfig("iceinu.toml", &IceinuConfig{ - BotName: "Iceinu", - LogLevel: "INFO", - Database: DatabaseConfig{ - URL: "sqlite://iceinu.db", - }, - }) -} diff --git a/elements/elements.go b/elements/elements.go deleted file mode 100644 index 4618a76..0000000 --- a/elements/elements.go +++ /dev/null @@ -1,650 +0,0 @@ -package elements - -import ( - "encoding/base64" - "fmt" - "io" - "strings" - "time" -) - -var DefaultThumb, _ = base64.StdEncoding.DecodeString("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") - -// IceinuMessageElement Iceinu的通用消息元素接口,参考了Satori的标准消息元素设计 -// https://satori.js.org/zh-CN/protocol/elements.html -// 基于对不同平台的支持,Iceinu对标准消息元素进行扩展和调整来方便一些平台特殊设计的实现 -// 带*号的消息元素是Iceinu自定义的消息元素,方便实现一些针对平台设计的特殊功能 -type IceinuMessageElement interface { - GetType() string // 获取消息元素类型 - ToSatori() string // 转换为Satori消息元素字符串 -} - -// TextElement 文本消息元素 -type TextElement struct { - Text string -} - -func (t *TextElement) GetType() string { - return "text" -} - -func (t *TextElement) ToSatori() string { - return t.Text -} - -// AtElement At提及消息元素 -type AtElement struct { - Id string // 目标用户ID - Name string // 目标用户名称 - Role string // 目标用户角色 - Type string // At请求类型,0为全体成员,1为指定成员 -} - -func (a *AtElement) GetType() string { - return "at" -} - -func (a *AtElement) ToSatori() string { - var attributes []string - if a.Id != "" { - attributes = append(attributes, fmt.Sprintf("id=\"%s\"", a.Id)) - } - if a.Name != "" { - attributes = append(attributes, fmt.Sprintf("name=\"%s\"", a.Name)) - } - if a.Role != "" { - attributes = append(attributes, fmt.Sprintf("role=\"%s\"", a.Role)) - } - if a.Type != "" { - attributes = append(attributes, fmt.Sprintf("type=\"%s\"", a.Type)) - } - return fmt.Sprintf("", strings.Join(attributes, " ")) -} - -// SharpElement Sharp提及频道消息元素 -type SharpElement struct { - Id string // 目标频道ID - Name string // 目标频道名称 -} - -func (s *SharpElement) GetType() string { - return "sharp" -} - -func (s *SharpElement) ToSatori() string { - var attributes []string - if s.Id != "" { - attributes = append(attributes, fmt.Sprintf("id=\"%s\"", s.Id)) - } - if s.Name != "" { - attributes = append(attributes, fmt.Sprintf("name=\"%s\"", s.Name)) - } - return fmt.Sprintf("", strings.Join(attributes, " ")) -} - -// LinkElement A超链接消息元素 -type LinkElement struct { - Href string // 链接地址 -} - -func (a *LinkElement) GetType() string { - return "link" -} - -func (a *LinkElement) ToSatori() string { - if a.Href != "" { - return fmt.Sprintf("", a.Href) - } - return "" -} - -// ImageElement 图片消息元素 -type ImageElement struct { - // 用于接收图片 - - ImageId string // 图片ID - Src string // 图片源地址 - Title string // 图片标题 - Width uint32 // 图片宽度 - Height uint32 // 图片高度 - - EffectId int // 图片特效ID - IsFlash bool // 是否是闪图 - - // 用于发送图片 - Summary string // 图片描述 - Path string // 图片路径或URL - Stream io.ReadSeeker // 图片流 -} - -func (i *ImageElement) GetType() string { - return "image" -} - -func (i *ImageElement) ToSatori() string { - var attributes []string - if i.ImageId != "" { - attributes = append(attributes, fmt.Sprintf("id=\"%s\"", i.ImageId)) - } - if i.Src != "" { - attributes = append(attributes, fmt.Sprintf("src=\"%s\"", i.Src)) - } - if i.Title != "" { - attributes = append(attributes, fmt.Sprintf("title=\"%s\"", i.Title)) - } - if i.Width != 0 { - attributes = append(attributes, fmt.Sprintf("width=\"%d\"", i.Width)) - } - if i.Height != 0 { - attributes = append(attributes, fmt.Sprintf("height=\"%d\"", i.Height)) - } - if i.EffectId != 0 { - attributes = append(attributes, fmt.Sprintf("effect=\"%d\"", i.EffectId)) - } - if i.IsFlash { - attributes = append(attributes, fmt.Sprintf("flash=\"%t\"", i.IsFlash)) - } - if i.Summary != "" { - attributes = append(attributes, fmt.Sprintf("summary=\"%s\"", i.Summary)) - } - if i.Path != "" { - attributes = append(attributes, fmt.Sprintf("path=\"%s\"", i.Path)) - } - return fmt.Sprintf("", strings.Join(attributes, " ")) -} - -// AudioElement 音频消息元素 -type AudioElement struct { - Src string - Title string - Duration uint32 - Poster string - Stream io.ReadSeeker - Summary string - Path string -} - -func (a *AudioElement) GetType() string { - return "audio" -} - -func (a *AudioElement) ToSatori() string { - var attributes []string - if a.Src != "" { - attributes = append(attributes, fmt.Sprintf("src=\"%s\"", a.Src)) - } - if a.Title != "" { - attributes = append(attributes, fmt.Sprintf("title=\"%s\"", a.Title)) - } - if a.Duration != 0 { - attributes = append(attributes, fmt.Sprintf("duration=\"%d\"", a.Duration)) - } - if a.Poster != "" { - attributes = append(attributes, fmt.Sprintf("poster=\"%s\"", a.Poster)) - } - if a.Summary != "" { - attributes = append(attributes, fmt.Sprintf("summary=\"%s\"", a.Summary)) - } - if a.Path != "" { - attributes = append(attributes, fmt.Sprintf("path=\"%s\"", a.Path)) - } - return fmt.Sprintf("