SkillAgentSearch skills...

CQPCPPSDK

酷Q的SDK的cpp11实现版,新版已经迁移到

Install / Use

/learn @MikuPy2001/CQPCPPSDK
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

主要分支未经过测试,不保证可以运行
请切换至ver 1.0 分支

本教程已过时...

前言

本项目由VS2017编写,如果您打算直接在本SDK项目的基础上编写,请确认兼容性。
您也可以新建一个项目,请参照下一节内容.

本SDK特点

  • 以 CQP SDK V9.16 为基础开发
  • 超棒的事件包装机制
  • 超棒的API包装机制
  • 超棒的工具集合

插件编写快速开始

  • 本教程默认读者已经知晓C++基础知识以及将C++编译成DLL部分的知识
  • 本教程随时有可能过时,请以官方易语言SDK为准

SDK目录结构说明

根目录说明

|目录 |说明| |:- |:-| |ExampleApp.sln|示例工程| |src/ |示例工程源码| |lib/ |包含sdk所需的两个lib文件| |inculde/ |CQSDK头文件目录|

然后说说头文件目录里的文件都是什么作用

|目录 |说明| |:- |:-| |CQAPI_EX |酷q功能调用,例如群消息发送,获取群列表,禁言等| |CQEVE |事件宏,用于快速建立事件接受函数,例如接受酷q启动事件| |CQEVE_* |以CQEVE_开头的文件也是事件宏,但是更加好用,请看示例| |CQEVE_ALL |包含所有事件实现宏,用于方便输入,无需包含多个CQEVE_头文件| |CQLogger |酷q日志工具,请看示例| |CQMsgCode |酷q消息处理工具以及酷q码生成方法,请看示例| |INItool |配置文件工具,请看示例| |winSpeak |非常厉害的语音生成工具,但是推荐使用酷q码的形式,请看示例|

准备编译环境

这一节为那些无法打开sln或者不是使用vs2017的人员准备

  1. 首先,强烈推荐将\src\CQSDK目录加入头文件搜索列表
    在vs2017里: 项目 - 属性 - vc++目录 - 包含目录
    如果不知道如何添加,您可以直接将此目录所有头文件复制到您的项目文件夹

  2. 推荐将appmain.cppAPPINFO.h加入到您的项目中,作为入口文件.
    appmain.cpp中有一些示例和部分必须函数 APPINFO.h则包含了插件的id和其他信息 main.cpp额外的dll主文件,如果您建立的是空项目可以使用这个

  3. 包含SDK必须的SDK_*.lib,可参照APPINFO.h第1到5行
    如果您无法包含此lib或者需要定制自己的SDK,您可以删除APPINFO.h第1到5行
    并将\src\CQSDKCPP目录复制到您的项目
    务必保持和原来一样的目录结构,否则.cpp文件找不到对应的.h文件

  4. 关闭启用C++异常 项目-->XXX属性--->配置属性--->C/C++--->代码生成-->右边--->启用C++异常--->改成:否

至此您可以尝试第一次编译. 如有问题,请带上报错和您的项目,一起反馈给我.

新项目

在开始写插件之前, 首先要决定插件id(查看规范)

  • 例如 me.cqp.coxxs.weather

注意:

  1. 插件id不是插件名称.
  2. 这个id必须独一无二且仅用于这个插件.

说明:

  • 插件id可以保证即使有人开发了和您一样的插件,也不会被人或者程序认错

决定完毕之后可以开始写一个漂亮的插件了

如无特殊说明,将用[应用ID]代指您取名的插件id.

JSON

一个插件,由两部分组成

  1. JSON文件:此文件用于描述插件功能.
  2. dll文件 :此文件是插件的本体.

先来说说JSON文件。
JSON文件是存储插件基本信息的文本文件,其数据存储格式为JSON。
以下是关于酷Q插件JSON文件的示例。
它包含了最基本的插件信息。

{  
    "ret"        : 1,
    "apiver"     : 9,
    "name"       : "应用名称",
    "version"    : "版本号",    //文字版版本号,可以加上beta或者pro什么的  
    "version_id" : 1,        //版本号,每次发布必须+1  
    "author"     : "作者",
    "description": "引用描述",
    "event"      : [],
    "menu"       : [],
    "status"     : [],
    "auth"       : []
}  

如果您要使用这份JSON。
请按照实际情况修改 name, version, version_id, author, description字段。
最后将文件名改为 [应用ID].JSON 并保存到您的项目文件夹备用.

DLL

酷Q要求有指定函数AppInfo用于返回应用ID。
这也是唯一的硬性要求。
您可以在您的代码加入以下代码快速实现。

#define CQAPPID "[应用ID]"  
  
#include "CQEVE.h"//位于SDK源码 src/CQSDK 目录下  
MUST_AppInfo_RETURN(CQAPPID)  

关于这个函数的更多说明可以参阅详细说明书(暂无)

现在将其编译为[应用ID].DLL,然后和JSON文件一起放入开启了开发者模式的酷Q的APP目录。
启动酷Q后就能在插件管理器看到这款插件了.

开发模式

虽然这并不是本教程的范畴,姑且从官方网站复制一份

打开酷Q目录下的 conf\CQP.cfg 文件,并在文件末尾插入以下两行,即可开启开发模式。

  • 您可以使用“Notepad++”、“记事本”等文本编辑器编辑本文件。
  • 如果本文件不存在,您可以先启动一次 酷Q,本文件将自动被生成。
[Dev]  
Enable=1  

开启开发模式后,酷Q将新增以下功能,帮助您进行开发:

  • 错误信息将会详细显示。
  • 支持载入、打包未打包应用。(开启开发者模式后才能载入开发中的应用)
  • 在应用窗口,按住shift并单击“重启酷Q”,可以快速重载应用(而无需重启)。

事件系统

酷Q是事件驱动模式.

大部分应用都是从收到一个事件开始.方式如下

  1. 在JSON中向酷Q申明要接收的事件
  2. 然后在C++中实现事件的接收函数

1. JSON部分

首先通过以下方式向酷Q申明要接收的事件

{
	//其他部分与前面的示例一致  
	"event": //在这里增加  
	[  
		//新增的部分  
		{  
			"id"      : 1,                      // 事件ID  
			"type"    : 21,                     // 事件类型  
			"name"    : "私聊消息处理",          // 事件名称  
			"function": "functionPrivateMsg",   // 事件对应函数  
			"priority": 30000                   // 事件优先级(参见 cqp.im/deveventpriority)  
		}  
		//新增结束  
	]  
}

|字段名称|说明|
|:-|:-|
|id|事件ID,保证唯一即可|
|type|事件类型, CQEVE.h中有详细说明|
|name|显示给用户的名称|
|function|C++中处理事件的函数名字|
|priority|优先级事件优先级(参见 cqp.im/deveventpriority)|
|regex|(可选)只接受符合此项正则表达式的消息|

priority优先级,整数,数值越大,优先级越低。
目前支持以下四种优先级:

|数值|优先级|说明| |:-|:-|:-| |10000|最高|监控类应用,无法用于拦截消息。(如:消息数目统计等)| |20000|高|消息控制类应用,可用于拦截消息。(如:机器人开关等)| |30000|一般|普通功能类应用。(如:天气查询、游戏类等)| |40000|低|聊天对话类应用。(如:词库、云词库)|

2. CPP部分

然后在CPP文件中加入对应的处理函数

#include "CQSDK/CQEVE_ALL.h"//这个头文件包含了所有事件的实现宏  
EVE_PrivateMsg_EX(functionPrivateMsg) {  
	//要执行的代码  
}  

部分事件拥有有EX版本的实现宏,区别在于它以_EX结尾
当事件拥有EX版宏时,强烈建议使用EX版进行实现
在EX版本的事件函数中,可以用eve对象完成所有和事件有关的操作
例如:

EVE_PrivateMsg_EX(functionPrivateMsg) {  
	if (eve.isSystem())return;//不对系统消息做处理  
	int i = eve.font.气泡;  //获取对方的气泡类型  
  
	eve.sendMsg() << "你发送了这样的消息:" << endl << eve.message <<send;  
	eve.message_block();//拦截消息  
	//EX函数无需返回值,默认不拦截消息,如需拦截,请使用 eve.message_block();  
}  

所有事件在CQEVE.h有详细的说明

CQAPI

只是被动接受事件当然是不够的
酷Q提供了一系列公开函数用于插件主动向酷Q提出各式各样的请求
包括且不限于日志写入, 消息发送, 信息获取, 信息修改
他们被实现于CQAPI.hCQAPI_EX.h
其中CQAPI.h是直接从酷Q导出的函数
SDK增强并包装了它们,实现在CQAPI_EX.h
请自行查阅

注意,所有CQAPI的调用都需要权限,并且需要在json里申明

{
	//其他部分与前面的示例一致  

	//修改部分
	"auth": [101,103,106]  
	//修改结束  
}

|权限代码|说明|函数| |:-|:-|:-| |20|[敏感]取Cookies|getCookies / getCsrfToken| |30|接收语音|getRecord| |101|发送群消息|sendGroupMsg| |103|发送讨论组消息|sendDiscussMsg| |106|发送私聊消息|sendPrivateMsg| |110|发送赞|sendLike| |120|置群员移除|setGroupKick| |121|置群员禁言|setGroupBan| |122|置群管理员|setGroupAdmin| |123|置全群禁言|setGroupWholeBan| |124|置匿名群员禁言|setGroupAnonymousBan| |125|置群匿名设置|setGroupAnonymous| |126|置群成员名片|setGroupCard| |127|[敏感]置群退出|setGroupLeave| |128|置群成员专属头衔|setGroupSpecialTitle| |130|取群成员信息|getGroupMemberInfoV2 / getGroupMemberInfo| |131|取陌生人信息|getStrangerInfo| |140|置讨论组退出|setDiscussLeave| |150|置好友添加请求|setFriendAddRequest| |151|置群添加请求|setGroupAddRequest| |160|取群成员列表|getGroupMemberList| |161|取群列表|getGroupList| |180|撤回消息|deleteMsg| |~~170~~|~~重启酷q~~|~~未知~~|

标注为粗体的Api涉及帐号权限等安全问题,因此在使用时会向用户进行“敏感权限”确认。

其他高级选项

CQ码如何发送

CQMsgCode.h中的code类包含各种作者已知的CQ码工厂方法

正则消息如何接受

json部分略过..
此条目待编辑

消息和原始的不一样怎么办

因为为了不把普通消息错当成CQ码,所以消息会被编码
可以通过 CQTools.h
std::string&msg_decode(std::string & s, bool isCQ = false);函数将消息解码

解码之后还是难以理解怎么办.

那就使用CodeMsgs工具

CodeMsgs工具

这是一个用于解码消息的工具,
不同于std::string&msg_decode(std::string & s, bool isCQ = false);函数
这是一个工具集合,专门用于处理消息. 使用方法如下:

CodeMsgs m("123456[CQ:sign,title=aaa:bbb,image=ccc=ddd]654321");
//首先初始化
//这时候消息将被解析成3段
//m[0].get()=="123456";
//m[1].get()=="sign";//对于CQ码来说,get是返回CQ类型
//m[1].get("title")=="aaa:bbb";//对于CQ码来说,get("")是返回对应的值
//m[2].get()=="654321";
//----------------------
//CodeMsgs 使用了数据库的操作思想.
//m[0]实际上是将指针定位到了第1段.
//也就是说
m[0];
bool True=m.get()=="123456";
m[1];
bool False=m.get()=="123456";
bool True=m.get()=="sign";//对于CQ码来说,get是返回CQ类型
//理解起来应该不困难
//随时使用以下函数判断是否是CQ码
bool True=m.isCode();
bool True=m.is("sign");
//当遇到未知CQ码时,还能遍历参数
auto keys = m.keys();
for each (auto key in keys)
	m.get(key);
//还能查找指定CQ码
m[0].find("sign");//从头找起
int pos=m.pos();//获得指针位置
//其实CodeMsgs本身也能迭代
for each (auto&code in m)
{
	if (code.isCQcode()) {
		auto keys = m.keys();

		cout << "{code:" << code.get() << ", args:{";
		for each (auto key in keys)
		{
			cout << "'" << key << "': '" << code.get(key) << "'" << ", ";
		}
		cout << "}";
	}
	else {
		cout << "[" << code.get() << "]";
	}
}

待续未完

View on GitHub
GitHub Stars11
CategoryDevelopment
Updated4y ago
Forks3

Languages

C

Security Score

65/100

Audited on Oct 6, 2021

No findings