From a012a64598990b98a961308db7469c1d2c918acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kyoku=E2=AD=90?= <144906395+KyokuKong@users.noreply.github.com> Date: Fri, 20 Sep 2024 09:28:35 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=BB=E6=9B=B4=E5=A4=9A=E7=9A=84=E9=A5=BC?= =?UTF-8?q?=EF=BC=8C=E5=87=86=E5=A4=87=E7=BB=A7=E7=BB=AD=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=85=83=E7=B4=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 +++++++---- adapter/bot.go | 104 ++++++++++++++++++++++------------------- resource/files.go | 35 ++++++++++++++ resource/paged_list.go | 6 +++ 4 files changed, 117 insertions(+), 55 deletions(-) create mode 100644 resource/files.go create mode 100644 resource/paged_list.go diff --git a/README.md b/README.md index 95ae4f7..6b2da8f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # 🧊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) -![QQGroup Badge](https://img.shields.io/badge/QQ群-970801565-blue?) +[![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语言聊天机器人框架(主要为NTQQ设计),可以将其作为开发套件来进行二次开发,亦或者作为库按需引入来快速编写自己的聊天机器人(暂时没有实现)。 +氷犬Iceinu 是一个多用途的Go语言聊天机器人框架,可以将其作为开发套件来进行二次开发,亦或者作为库按需引入来快速编写自己的聊天机器人(暂时没有实现)。 🚧暂时还在~~画饼~~施工中,晚点再来探索吧~ @@ -19,17 +20,27 @@ - [ ] 消息发送/统一Client设计 - [ ] 插件系统设计和实现 - [ ] 完善内置LagrangeGo适配器的事件接收和处理 -- [ ] 集群模式设计和实现(集群的动态总控和静态总控模式) +- [ ] 集群模式设计和实现(集群的动态和静态总控模式) - [ ] 排障和性能优化 - [ ] 自动化测试 - [ ] 确定各项基础程序设计,编写使用文档 ## 特性 +~~哪里是特性,完全是画饼,一半都还没实现完~~ + - 基于Go开发,性能表现良好 -- 基于事件驱动的消息推送机制 -- 类Satori的事件和消息系统,可以直接构建Satori标准的XHTML作为消息内容 -- 模块化设计,适配多平台,可自由开发插件 +- 基于统一事件驱动的消息推送机制 +- 以Satori作为基础实现了统一消息标准 +- 可直接发送Satori标准的XHTML消息 +- 模块化适配器设计 +- 动态/静态集群,跨平台集群 +- 完整的动态权限管理系统 +- 在插件间共享数据库连接池 +- 类Alconna的命令解析器 +- 可配置自动向指定用户/频道发送日志 +- 主动信息推送/订阅机制 +- 从HTML+CSS模板渲染图片(基于wkhtmltoimage集成,未来可能会实现) ## 直接部署 @@ -40,7 +51,7 @@ 你可以参照Iceinu数据库配置指南来配置Iceinu使用的PostgreSQL数据库。 -Iceinu可以以分布式模式进行部署,通过在启动时附加`--node`参数即可启动Iceinu的子节点模式,在子节点的配置文件中设置主节点的ip即可进行连接。 +Iceinu在设计上支持集群部署,且支持动态组网式集群(需要各个Bot实例之间可以相互访问)和静态总控式集群(需要一个Bot实例作为总控,这个实例本身不能下线) ## 二次开发 diff --git a/adapter/bot.go b/adapter/bot.go index f4d1b4b..00954a7 100644 --- a/adapter/bot.go +++ b/adapter/bot.go @@ -8,51 +8,57 @@ import ( // Bot Iceinu的客户端接口API,用于实现iceinu对平台客户端的直接操作 type Bot interface { // 首先是基于Satori标准的API - // 这部分可以参考Satori文档的资源部分,但是有一定的不同 + // 这部分可以参考Satori文档的资源部分,但是有一定的不同,为了方便兼容各种使用方式进行了一些扩展 // 比如没有直接支持分页这个东西,方便使用 // https://satori.js.org/zh-CN/resources/channel.html - GetChannel(channelId string) *resource.Channel - GetChannelList(groupId string) []*resource.Channel - 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 - ApproveGroupInvite(messageId string, approve bool, comment string) error - - GetGroupMember(groupId string, userId string) *resource.GroupMember - GetGroupMemberList(groupId string) []*resource.GroupMember - 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) - 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(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 - - 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) - GetReactionList(channelId string, messageId string, emoji string) []resource.User - - GetUser(userId string) *resource.User - GetFriendList() []*resource.User - ApproveFriendRequest(messageId string, approve string, comment string) error + 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(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 // 其中一部分是对各个平台功能的扩展适配,还有一部分是其他功能的快捷方式 @@ -63,10 +69,11 @@ type Bot interface { SendGroupPoke(groupId string) error // 发送群组戳一戳 SendChannelPoke(channelId string) error // 发送频道戳一戳 - GetSelfUserId() string // 获取自己的用户ID - GetSelfUserName() string // 获取自己的用户名 - GetSelfAvatarUrl() string // 获取自己的头像URL - GetSeldUserNickname() string // 获取自己的昵称 + GetSelfUserId() string // 获取自己的用户ID + GetSelfUserName() string // 获取自己的用户名 + GetSelfAvatarUrl() string // 获取自己的头像URL + GetSeldUserNickname() string // 获取自己的昵称 + GetGroupAvatarUrl(groupId string) string // 获取指定群组的头像URL RefreshUserListCache() error // 刷新用户列表 RefreshGroupListCache() error // 刷新群组列表 @@ -85,7 +92,7 @@ type Bot interface { UploadChannelFile(channelId string, filePath string) error // 向频道上传文件 UploadGroupFile(groupId string, filePath string, targetFilePath string) error // 向群组上传文件 - GetGroupFileSystemInfo(groupId string) interface{} // 获取群组文件系统信息(暂未确定) + 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 // 移动群组文件 @@ -93,4 +100,7 @@ type Bot interface { 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/resource/files.go b/resource/files.go new file mode 100644 index 0000000..7edd10c --- /dev/null +++ b/resource/files.go @@ -0,0 +1,35 @@ +package resource + +// From LagrangeGo:https://github.com/LagrangeDev/LagrangeGo/blob/master/client/entity/group_file.go + +type GroupFileSystemInfo struct { + GroupUin uint32 + FileCount uint32 + LimitCount uint32 + UsedSpace uint64 + TotalSpace uint64 +} + +type GroupFile struct { + GroupUin uint32 + FileId string + FileName string + BusId uint32 + FileSize uint64 + UploadTime uint32 + DeadTime uint32 + ModifyTime uint32 + DownloadTimes uint32 + Uploader uint32 + UploaderName string +} + +type GroupFolder struct { + GroupUin uint32 + FolderId string + FolderName string + CreateTime uint32 + Creator uint32 + CreatorName string + TotalFileCount uint32 +} diff --git a/resource/paged_list.go b/resource/paged_list.go new file mode 100644 index 0000000..8c80f16 --- /dev/null +++ b/resource/paged_list.go @@ -0,0 +1,6 @@ +package resource + +type PagedList struct { + data []interface{} + next string +}