简介
本教程主要实现:
新人入群:
发送群内欢迎信息
发送私聊新成员
说明:
1.支持契约单Q版和多Q版框架
2.支持内置变量 防止消息内容相同 被屏蔽
3.使用易语言进行开发,需要大家有基础或者需要有恒心坚持看完
学习内容
契约群发、私聊 功能的使用
发送内容: 文本、图片、语音、卡片
声明
本教程非契约官方教程,为作者学习易语言过程的知识总结,将主要内容整理、汇总后,形成本教程。
致力于进行技术交流,帮助新人快速入门,少走弯路。
请在遵守中华人民共和国法律、腾讯相关规定和契约框架相关说明下进行使用
如您使用本技术,进行包括但不限于如下行为,软件作者并不知情,不承担任何法律风险
1.违法行为
2.违法腾讯规定
3.违法契约框架规定
教程内容
环境准备
易语言环境安装
契约SDK下载
使用易语言软件,打开com.contract.testapp 文件,会提示选择 QYPluginSDK文件,选择正确文件路径 点击 确认 按钮,如图所示:
开始开发
界面制作
鼠标点击 窗口 -> 右键 -> 点击 插入新窗口 ,进入窗口操作界面,如下图
为了兼容契约多Q版,所以我们先在 新建窗口上,放一个树形控件 存放所有登录的QQ机器人号码,鼠标点击右侧 组件的 树形 控件,然后在窗口 界面点击鼠标左键 完成树形控件添加
点击 树形 控件,左侧 将会看到很多 树形配置,暂时我们只需要修改 是否有检查框 将其修改为 真,这样树形控件 中的内容前面 会多个复选框 供选择,进而进行其他操作
添加一个 超级列表框 操作过程同上, 设置两个属性为 如下图所示:
超级列表框 主要显示 QQ的群号,所以第一列 为 序号,第二列为 群号,第三列为 群名称,右键超级列表框,选择 设置报表列 ,如下配置
添加一个配置规则页面框 和 一个显示所有规则的超级列表框,最终插件的界面效果图
如果想看看 运行后的实际效果,可以在界面上右键鼠标 点击 预览 可以看到实际执行的效果
将界面和插件关联
在 程序 页面中 找到_menuA 和_menuB 两个函数 进行如下修改即可
此时我们可以进行实际测试,将代码编译成插件 放到契约框架进行测试
在易语言编辑器中 选择 编译 -> 编译为指定类型 -> windows 动态链接库
选择要保存的文件路径 即可。本教程直接将其放到 契约框架的 plugin目录下
运行契约框架 -> 载入插件 会看到我们编译的插件,然后点击 启用 按钮,点击 菜单 -> 设置A 则会看到 我们刚开发的窗口 界面
如果你觉得插件上 介绍信息太土 需要在哪里进行修改? 契约框架 是使用json进行配置的,可以点击 程序 ->常量表 -> 应用信息 修改响应内容,如果你对json格式不了解 建议慎重修改。如下所示:
功能开发
在树形控件 显示所有机器人QQ号码
需要用到的契约API
QY.取登录QQ列表() '可以获得所有登录的机器人QQ号
所以变形的函数为如下,获得所有QQ号码 将其加入到树形控件中
.版本 2
.支持库 iext
.子程序 load_qq_lists
.局部变量 i, 整数型
.局部变量 QQ列表, 长整数型, , "0"
QY.取登录QQ列表 (QQ列表)
.计次循环首 (取数组成员数 (QQ列表), i)
树型框1.加入项目 (, 到文本 (QQ列表 [i]), 0, , , , )
.计次循环尾 ()
什么时候调用该方法 更新列表树形框中的机器人个数?
窗口初始化后 按钮触发事件 即可
树形控件 点击机器人号码后 刷新机器人所在群列表
需要的API
QY.取群列表() ’将会获得所有群信息 群号 和群名称
树形框 事件: 窗口2->点击树形框,在此次选择加入事件处理子程序 中 选择 检查框状态被改变 ,加入如下代码:
.版本 2
.支持库 iext
.子程序 _树型框1_检查框状态被改变
.参数 表项索引, 整数型
.参数 检查框状态, 整数型
.局部变量 robotqq, 文本型
.局部变量 群列表, 数_群列表, , "0"
.局部变量 数量, 整数型
.局部变量 r, 整数型
.局部变量 index, 整数型
.局部变量 i, 整数型
.如果真 (检查框状态 = 1)
robotqq = 树型框1.取项目文本 (表项索引)
QY.取群列表 (robotqq, 群列表)
数量 = 取数组成员数 (群列表)
.计次循环首 (数量, r)
index = 超级列表框1.插入表项 (, , , , , )
超级列表框1.插入列 (, , , , , )
超级列表框1.置标题 (index, 0, 到文本 (r))
超级列表框1.置标题 (index, 1, 到文本 (群列表 [r].群号))
超级列表框1.置标题 (index, 2, 到文本 (群列表 [r].群名))
.计次循环尾 ()
.如果真结束
群号被选择后,将群号 加入到文本框中
选择超级列表框 添加 检查框状态被改变 事件,添加如下代码:
.版本 2
.支持库 iext
.如果真 (检查框状态 = 1)
robotqq = 超级列表框1.取标题 (表项索引, 1)
.如果真 (寻找文本 (编辑框_关键字_群号.内容, robotqq, , 假) = -1)
编辑框_关键字_群号.内容 = 编辑框_关键字_群号.内容 + robotqq + “#”
.如果真结束
注释:判断群号是否已经在文本框 如果不在,将当前群号 加入到文本框
添加一条监控规则
保存按钮的处理路径
将相关信息 保存到一个文本数组中,每条规则是一个json结构
名称是规则唯一标识,如果名称已经存在 点击保存时,将更新规则内容,不会进行新添加规则
每一次保存 将规则显示在右侧超级列表框中,并且写入到规则文件中,防止关闭窗口 规则丢失
.版本 2
.子程序 _按钮2_被单击
.局部变量 action, 文本型
.局部变量 kaiguan, 文本型
.局部变量 data, 类_json
.局部变量 i, 整数型
.局部变量 tmp, 类_json
.局部变量 index, 整数型
.局部变量 isold, 逻辑型
.局部变量 name, 文本型
.局部变量 c, 文本型
action = 组合框_关键字_动作.取项目文本 (组合框_关键字_动作.现行选中项)
kaiguan = 组合框_关键字_开关.取项目文本 (组合框_关键字_开关.现行选中项)
.如果真 (取文本长度 (编辑框_关键字_名称.内容) < 1)
信息框 (“必须输入唯一名称”, 0, QQgruop, )
返回 ()
.如果真结束
.如果真 (取文本长度 (编辑框_关键字_群号.内容) < 1)
信息框 (“必须输入群号 所有群填写0 多个群使用#分隔”, 0, QQgruop, )
返回 ()
.如果真结束
isold = 假
data.清除 ()
.计次循环首 (取数组成员数 (keywordsrules), i)
tmp.清除 ()
tmp.解析 (keywordsrules [i])
.如果真 (tmp.取通用属性 (“name”) = 编辑框_关键字_名称.内容)
keywordsindex = i ' 保存下标
data = tmp
index = i - 1 ' 列表框的下标
' 更新操作
isold = 真
跳出循环 ()
.如果真结束
.计次循环尾 ()
data.置属性 (“name”, 编辑框_关键字_名称.内容)
data.置属性 (“kaiguan”, kaiguan)
data.置属性 (“qqun”, 编辑框_关键字_群号.内容)
data.置属性 (“keyword”, 编辑框_关键字_关键字.内容)
data.置属性 (“action”, action)
data.置属性 (“msg”, 子文本替换 (编辑框_关键字_消息内容.内容, #换行符, “[n]”, , , 真))
data.置属性 (“time”, 编辑框_关键字_禁言.内容)
下半段代码
.版本 2
.支持库 iext
' 是否是新规则 还是老规则更新
.如果 (isold)
keywordsrules [keywordsindex] = data.取数据文本 () ' 替换掉原来的
.否则
加入成员 (keywordsrules, data.取数据文本 ())
index = 超级列表框_智能_关键字.插入表项 (, , , , , )
.如果结束
.如果 (kaiguan = “开”)
超级列表框_智能_关键字.置状态图片 (index, 1)
.否则
超级列表框_智能_关键字.置状态图片 (index, 0) ' 是否选中 检查框
.如果结束
超级列表框_智能_关键字.置标题 (index, 0, 到文本 (编辑框_关键字_名称.内容))
超级列表框_智能_关键字.置标题 (index, 1, kaiguan) ' 选中项 开/关
' 组合框_群.取项目文本 (组合框_群.现行选中项)
' 超级列表框_智能_关键字.置标题 (index, 2, 编辑框_关键字_关键字.内容) ' 内容
超级列表框_智能_关键字.置标题 (index, 2, 编辑框_关键字_群号.内容) ' 群号
' 超级列表框_智能_关键字.置标题 (index, 4, action) ' 动作
超级列表框_智能_关键字.置标题 (index, 3, 编辑框_关键字_禁言.内容) ' 禁言时间
超级列表框_智能_关键字.置标题 (index, 4, 编辑框_关键字_消息内容.内容) ' 消息内容
' 将消息内容保存到文件中,防止丢失
c = “”
.计次循环首 (取数组成员数 (keywordsrules), i)
tmp.清除 ()
tmp.解析 (keywordsrules [i])
c = c + tmp.取数据文本 () + #换行符
' 保存到文件
.计次循环尾 ()
name = 应用目录 + “keywords.txt”
' 保存到文件
写到文件 (name, 到字节集 (c))
信息框 (“保存成功”, 0, QQgruop, )
超级列表框 规则管理
修改规则开关
规则的超级列表框 检查框状态被改变 改变时,将随时调整规则的开关状态
.版本 2
.支持库 iext
.子程序 _超级列表框2_检查框状态被改变
.参数 表项索引, 整数型
.参数 检查框状态, 整数型
.局部变量 name, 文本型
.局部变量 tmp, 类_json
.局部变量 i, 整数型
.如果 (检查框状态 = 1)
超级列表框2.置标题 (表项索引, 1, “开”)
.否则
超级列表框2.置标题 (表项索引, 1, “关”)
.如果结束
name = 超级列表框2.取标题 (表项索引, 0) ' 取标题 修改规则
.计次循环首 (取数组成员数 (keywordsrules), i)
tmp.清除 ()
tmp.解析 (keywordsrules [i])
.如果真 (tmp.取通用属性 (“name”) = name)
.如果 (检查框状态 = 1)
tmp.置属性 (“kaiguan”, “开”)
.否则
tmp.置属性 (“kaiguan”, “关”)
.如果结束
跳出循环 ()
.如果真结束
.计次循环尾 ()
只进行规则的当前状态的改变,并未保存到记录中
删除规则
在规则超级列表框上 添加一个菜单 删除对应规则
删除按钮代码如下
.版本 2
.支持库 iext
.子程序 _删除_被选择
.参数 i, 整数型
.参数 c, 文本型
.参数 tmp, 类_json
.参数 name, 文本型
.如果真 (信息框 (“是否删除规则”, #是否钮, “”, ) = #是钮)
name = 超级列表框2.取标题 (超级列表框2.现行选中项, 0)
.计次循环首 (取数组成员数 (keywordsrules), i)
tmp.清除 ()
tmp.解析 (keywordsrules [i])
.如果真 (tmp.取通用属性 (“name”) = name)
删除成员 (keywordsrules, i, 1)
超级列表框2.删除表项 (超级列表框2.现行选中项)
跳出循环 ()
.如果真结束
.计次循环尾 ()
c = “”
.计次循环首 (取数组成员数 (keywordsrules), i)
tmp.清除 ()
tmp.解析 (keywordsrules [i])
c = c + tmp.取数据文本 () + #换行符
' 保存到文件
.计次循环尾 ()
name = 应用目录 + “keywords.txt”
' 保存到文件
写到文件 (name, 到字节集 (c))
信息框 (“成功删除规则”, 0, QQgruop, )
.如果真结束
清空 按钮代码
.版本 2
.支持库 iext
.子程序 _清空_被选择
清除数组 (keywordsrules)
超级列表框2.全部删除 () ' 全部删除
name = 应用目录 + “keywords.txt”
.如果真 (文件是否存在 (name))
删除文件 (name)
.如果真结束
规则超级列表框 编辑规则
添加一个左键点击事件,代码如下:
.版本 2
.支持库 iext
.子程序 _超级列表框2_左键单击表项
编辑框_关键字_名称.内容 = 超级列表框2.取标题 (超级列表框2.现行选中项, 0) ' 标题
组合框_关键字_开关.现行选中项 = 1 ' 默认选择真 选择关
.如果真 (超级列表框_智能_关键字.取标题 (超级列表框_智能_关键字.现行选中项, 1) = “开”)
组合框_关键字_开关.现行选中项 = 0 ' 选择0 开
.如果真结束
' 编辑框_关键字_关键字.内容 = 超级列表框_智能_关键字.取标题 (超级列表框_智能_关键字.现行选中项, 2) ' 关键字
编辑框_关键字_群号.内容 = 超级列表框_智能_关键字.取标题 (超级列表框_智能_关键字.现行选中项, 2) ' 群号
编辑框_关键字_禁言.内容 = 超级列表框_智能_关键字.取标题 (超级列表框_智能_关键字.现行选中项, 3) ' 禁言时间
编辑框_关键字_消息内容.内容 = 子文本替换 (超级列表框_智能_关键字.取标题 (超级列表框_智能_关键字.现行选中项, 4), “[n]”, #换行符, , , 真) ' 消息
规则 超级列表框 右键添加菜单
.版本 2
.子程序 _超级列表框2_右键单击表项
弹出菜单 (规则, , )
至此,核心的界面功能 就开发完成了 接下来开发新人入群事件
新人入群事件
群成员 增加时 会触发 事件 _eventSystem_GroupMemberIncrease,所以我们将处理代码 放到这个函数里面即可
.版本 2
.子程序 _eventSystem_GroupMemberIncrease, 整数型, 公开, Type=104 群事件-群成员增加
.参数 QQID, 长整数型, , 用于区分多号登录
.参数 subtype, 整数型, , 子类型,1/管理员已同意 2/管理员邀请
.参数 sendTime, 长整数型, , 发送时间(时间戳)
.参数 fromGroup, 长整数型, , 来源群号
.参数 fromQQ, 长整数型, , 操作者QQ(即管理员QQ)
.参数 beingOperateQQ, 长整数型, , 被操作QQ(即加群的QQ)
.局部变量 i, 整数型
.局部变量 tmp_config, 类_json
' 本子程序会在【线程】中被调用,请注意使用对象等需要初始化(CoInitialize,CoUninitialize)。
' 这里处理消息
.计次循环首 (取数组成员数 (keywordsrules), i)
tmp_config.清除 ()
tmp_config.解析 (keywordsrules [i])
.如果真 (tmp_config.取通用属性 (“kaiguan”) = “开”) ' 开关
.如果真 (tmp_config.取通用属性 (“action”) = “新人入群(欢迎信息)”)
.如果真 (tmp_config.取通用属性 (“qqun”) = “0” 或 寻找文本 (tmp_config.取通用属性 (“qqun”), 到文本 (fromGroup), , 假) > -1) ' 群号匹配
.如果真 (取文本长度 (tmp_config.取通用属性 (“msg”)) > 0)
程序_延时 (到长整数 (tmp_config.取通用属性 (“time”)), 1)
text = tmp_config.取通用属性 (“msg”)
.如果真 (寻找文本 (text, “[AT]”, , 假) > -1)
text = 子文本替换 (text, “[AT]”, QY.LQ码_At (beingOperateQQ), , , 真)
.如果真结束
QY.发送群消息 (QQID, fromGroup, 子文本替换 (获得随机表情消息 (text), “[n]”, #换行符, , , 真))
.如果真结束
.如果真结束
.如果真结束
.如果真结束
.计次循环尾 ()
添加了一个AT新人的功能 使用的代码 QY.LQ码_At()函数
至此,我们需要的 新人入群后的欢迎信息基本实现,但如果用户关闭插件,在重新打开插件时 没有办法将已经保存的规则加载到插件里面,因此我们需要添加一个初始化功能
插件初始化配置 加载规则文件
_eventStartup 事件中添加初始化代码
.版本 2
.子程序 _eventStartup, 整数型, 公开, Type=1001 启动
.局部变量 name, 文本型
.局部变量 content, 文本型
.局部变量 array_list, 文本型, , "0"
应用目录 = QY.取应用目录 ()
' 获取应用数据目录
' 返回如:D:robotplugincom.contract.testapp
' 应用的所有数据、配置【必须】存放于此目录,避免给用户带来困扰。
name = 应用目录 + “keywords.txt”
清除数组 (keywordsrules) ' 初始化数组
.如果真 (文件是否存在 (name))
content = 到文本 (读入文件 (name))
清除数组 (array_list)
array_list = 分割文本 (content, #换行符, )
.计次循环首 (取数组成员数 (array_list), i)
.如果真 (取文本长度 (array_list [i]) > 4) ' 过滤掉空行
加入成员 (keywordsrules, array_list [i])
.如果真结束
.计次循环尾 ()
至此基本功能开发完成,整体流程ok了,我们接下来需要做一些调优
支持随机变量
让发送的消息支持更多随机变量,可以大大降低被封号的风险
代码如下:
.版本 2
.子程序 获得随机表情消息, 文本型
.参数 message, 文本型
.局部变量 ret, 文本型
ret = 子文本替换 (message, “[Time]”, 时间_到文本 (, 1, ), , , 真)
ret = 子文本替换 (ret, “[Rface]”, “[Face” + 到文本 (取随机数 (1, 212)) + “.gif]”, , , 真)
ret = 子文本替换 (ret, “[Num]”, 文本_取随机数字 (取随机数 (1, 20), ), , , 真)
ret = 子文本替换 (ret, “[Hanzi]”, 文本_取随机汉字 (取随机数 (5, 20), 0), , , 真)
ret = 子文本替换 (ret, “[Zimu]”, 文本_取随机字母 (取随机数 (1, 20), 2), , , 真)
ret = 子文本替换 (ret, “[n]”, #换行符, , , 真)
返回 (ret)
支持发送图片
契约框架发图片是免费的 ,因此备受欢迎,代码也非常简单 ,增加一个选择图片按钮
最核心的代码是契约选择图片的API QY.LQ码_本地图片
.版本 2
.支持库 shell
.子程序 _按钮3_被单击
.局部变量 name, 文本型
.局部变量 Text, 文本型
.局部变量 群列表, 文本型
.局部变量 群列表数组, 文本型, , "0"
.局部变量 MSG, 文本型
' 插入图片
name = 浏览文件夹 (“”, 真)
.如果真 (文件是否存在 (name))
MSG = QY.LQ码_本地图片 (name)
编辑框_关键字_消息内容.内容 = 编辑框_关键字_消息内容.内容 + MSG + #换行符
支持发送语音
同样契约框架 支持发送语音,与发图片类似 只需要调用一个API即可
.版本 2
.支持库 shell
.子程序 _按钮4_被单击
.局部变量 MSG, 文本型
.局部变量 name, 文本型
.如果真 (信息框 (“只能选择本地 语音文件 如(mp3, amr) 否则发送会失败”, #确认取消钮, “”, ) = #取消钮)
返回 ()
.如果真结束
name = 浏览文件夹 (“只能选择 语音文件 如(mp3, amr) ”, 真)
.如果真 (文件是否存在 (name))
MSG = QY.LQ码_本地语音 (name)
编辑框_关键字_消息内容.内容 = 编辑框_关键字_消息内容.内容 + MSG
.如果真结束
支持卡片
契约框架支持发送卡片消息 即json或者xml需要调用特殊API即可 QY.LQ码_特殊消息
使用样例如下
保存规则处判断 是否是卡片消息 进行转换
.版本 2
message = 子文本替换 (编辑框_关键字_消息内容.内容, #换行符, “[n]”, , , 真)
.判断开始 (msg_type_xml)
message = QY.LQ码_特殊消息 (0, message)
.判断 (msg_type_json)
message = QY.LQ码_特殊消息 (1, message)
.默认
.判断结束
至此本次教程主要代码就逐个讲解完成,接下来进入我们最关键的环节,编译生成dll插件和调试
[知乎](https://www.zhihu.com/)