last commit
This commit is contained in:
@@ -0,0 +1,652 @@
|
||||
> - 傻妞 是一个 支持Node、Python 机器人框架,开发需要有一定的编程基础,以下主要对Node进行讲解,其他语言类似。
|
||||
|
||||
# 开发环境搭建
|
||||
|
||||
## 通过 vscode 开发
|
||||
|
||||
- 打开 plugins 目录
|
||||
- 运行傻妞 `./sillyGirl -t`,在这里你可以直接输入信息调试、以及观察 console.log 输出信息、收发消息情况等信息
|
||||
- 开发插件非常方便~
|
||||
 本人开发插件示例
|
||||
|
||||
## 文件目录说明
|
||||
|
||||
- 插件开发
|
||||
|
||||
- plugins 下只有二级目录下的 index.js 作为入口文件才会被尝试载入,根目录以及 3 级以下不会加载,示例 :
|
||||
|
||||
```
|
||||
plugins/hello/index.js //会被当做插件载入
|
||||
plugins/index.js //忽略
|
||||
```
|
||||
|
||||
- 重载:plugins 下的所有文件都是保存既重载
|
||||
- 默认识别为 Node 开发语言,否则请在插件目录加上 `py_` 、`php_` 前缀
|
||||
- 内置的 JS 引擎仅支持在后台管理开发面板中进行开发
|
||||
|
||||
- language
|
||||
|
||||
- 存放语言支持的一些依赖,请不要动它。当然目前只有`node`、`python`
|
||||
|
||||
# 模块方法介绍
|
||||
|
||||
## async sleep
|
||||
|
||||
Node 休眠(阻塞运行),传 number,注意单位是毫秒
|
||||
|
||||
```javascript
|
||||
//内置js
|
||||
time.sleep(5000);
|
||||
```
|
||||
|
||||
```javascript
|
||||
//node
|
||||
await sleep(5000);
|
||||
```
|
||||
|
||||
```python
|
||||
#python
|
||||
await asyncio.sleep(5)
|
||||
```
|
||||
|
||||
## utils 工具包
|
||||
|
||||
### buildCQTag 拼接 CQ 码
|
||||
|
||||
本项目消息机遇字符串,图片和视频等通过 CQ 码实现,因此提供了拼接方法
|
||||
|
||||
```
|
||||
/**
|
||||
* @author 猫咪
|
||||
* @origin 傻妞官方
|
||||
* @version v1.0.0
|
||||
* @create_at 2022-09-08 07:31:42
|
||||
* @title 二维码
|
||||
* @rule 二维码 ?
|
||||
* @description 🐒生成指定内容的一个二维码。
|
||||
* @public true
|
||||
* @icon https://bpic.51yuansu.com/pic3/cover/02/70/77/5a1878243d237_610.jpg
|
||||
* @class 图片
|
||||
*/
|
||||
```
|
||||
|
||||
```js
|
||||
//内置js
|
||||
let url = `https://api.pwmqr.com/qrcode/create/?url=${encodeURIComponent(s.param(1))}`;
|
||||
s.reply(strings.buildCQTag("image", { url }));
|
||||
//等价写法
|
||||
s.reply(image(url));
|
||||
```
|
||||
|
||||
```js
|
||||
//node
|
||||
const {
|
||||
sender: s,
|
||||
utils: { buildCQTag, image },
|
||||
} = require("sillygirl");
|
||||
|
||||
(async () => {
|
||||
let url = `https://api.pwmqr.com/qrcode/create/?url=${encodeURIComponent(
|
||||
await s.param(1)
|
||||
)}`;
|
||||
await s.reply(buildCQTag("image", { url }));
|
||||
//等价写法
|
||||
await s.reply(image(url));
|
||||
})();
|
||||
```
|
||||
|
||||
```python
|
||||
#python
|
||||
from sillygirl import sender as s, utils
|
||||
from urllib.parse import quote
|
||||
import asyncio
|
||||
|
||||
async def main():
|
||||
url = f"https://api.pwmqr.com/qrcode/create/?url={quote(await s.param(1))}"
|
||||
await s.reply(utils.buildCQTag("image", { url }))
|
||||
#等价写法
|
||||
await s.reply(utils.image(url))
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
```
|
||||
|
||||
### parseCQText 解析 CQ 码
|
||||
|
||||
```js
|
||||
/**
|
||||
* @title 钉钉机器人
|
||||
* @create_at 2023-07-03 08:07:43
|
||||
* @description 🐔钉钉机器人适配器。
|
||||
* @author 佚名
|
||||
* @version v1.0.3
|
||||
* @public true
|
||||
* @class 机器人
|
||||
* @service true
|
||||
*/
|
||||
|
||||
const {
|
||||
utils: { parseCQText },
|
||||
} = require("sillygirl");
|
||||
|
||||
(async () => {
|
||||
let adapter = new Adapter({
|
||||
platform: "dingtalk",
|
||||
bot_id: wsdata.msg.user.id,
|
||||
replyHandler: async ({ user_id, chat_id, content }) => {
|
||||
for (let item of parseCQText(content)) {
|
||||
if (typeof item == "string") {
|
||||
// item 此时是文本,执行发送文本消息逻辑
|
||||
}
|
||||
if (item.type == "image") {
|
||||
let url = item.params.url;
|
||||
// url 是图片链接,执行发送图片消息逻辑
|
||||
}
|
||||
if (item.type == "video") {
|
||||
let url = item.params.url;
|
||||
// url 是视频链接,执行发送视频消息逻辑
|
||||
}
|
||||
}
|
||||
return "${message_id}";
|
||||
},
|
||||
});
|
||||
})();
|
||||
```
|
||||
|
||||
### utils.npmInstall 安装 npm 包 (待实现)
|
||||
|
||||
```js
|
||||
await utils.npmInstall("request"); //会返回执行信息String
|
||||
await utils.npmInstall("request", { outConsole: true }); // 将会在控制台实时打印安装情况,返回结果为null
|
||||
```
|
||||
|
||||
### utils.testModule 测试 npm 包是否存在 (待实现)
|
||||
|
||||
```js
|
||||
await utils.testModule(["telegram", "input"]); //将只测试,返回结果
|
||||
await utils.testModule(["telegram", "input"], { install: true }); //发现少模块自动安装
|
||||
```
|
||||
|
||||
## Adapter 适配器构造类
|
||||
|
||||
- 具体使用方法参见适配器开发
|
||||
|
||||
## Bucket 数据库构造类
|
||||
|
||||
系统数据库为轻量型内嵌式 KV 数据库。
|
||||
|
||||
开发插件时,你可以使用任意你喜欢的数据库来存放数据 (不建议,会破坏用户使用体验)
|
||||
|
||||
有关数据库操作,你可以在官方插件中找到全部用法示例
|
||||
|
||||
> Linux 存放于 `/etc/sillyplus`
|
||||
|
||||
> Windows 存放于 `C:\ProgramData\sillyplus`
|
||||
|
||||
> Darwin 存放于 `.sillyplus`
|
||||
|
||||
> 建议定期备份
|
||||
|
||||
### get()获取数据
|
||||
|
||||
该方法接受二个参数
|
||||
|
||||
- 需要读取的 key
|
||||
- 未读取到值默认返回值(可选)
|
||||
|
||||
```javascript
|
||||
//内置js
|
||||
const test = new Bucket("test");
|
||||
//读取一个key的 value 值 如果没有该数据返回undefined
|
||||
consoloe.log(test.name1)// undefined
|
||||
consoloe.log(test["name1"])// undefined
|
||||
// 第二个参数作为未读取到数据的返回值
|
||||
test.get("name1", "阿明")// 阿明
|
||||
```
|
||||
|
||||
```javascript
|
||||
//node
|
||||
const test = new Bucket("test");
|
||||
await test.get("name1");
|
||||
await test.get("name1", "阿明");
|
||||
```
|
||||
|
||||
```python
|
||||
#python
|
||||
test = Bucket("test")
|
||||
await test.get("name1") #None
|
||||
await test.get("name1", "阿明")
|
||||
|
||||
#支持同步,小心阻塞watch方法
|
||||
print(test.name1) #None
|
||||
test.name1 = "阿明"
|
||||
print(test.name1)
|
||||
```
|
||||
|
||||
### set()存储数据
|
||||
|
||||
该方法接受三个参数
|
||||
|
||||
- 需要设置的 key
|
||||
- 需要设置的 value
|
||||
|
||||
```javascript
|
||||
//创建一个测试数据库实例
|
||||
const test = new Bucket('test');
|
||||
|
||||
const {
|
||||
changed // boolean 实际值是否变更
|
||||
message // string 修改回调消息,修改可能被变更或拦截
|
||||
error // string 修改失败时的错误消息
|
||||
} = await test.set('name', '阿明');
|
||||
```
|
||||
|
||||
### delete()删除数据
|
||||
|
||||
该方法接受一个参数
|
||||
|
||||
- 需要删除的 key
|
||||
|
||||
返回结果同 set
|
||||
|
||||
### getAll() 读取所有键值对
|
||||
|
||||
### empty() 清空数据库
|
||||
|
||||
### keys()读取所有 key 返回一个 Array
|
||||
|
||||
返回一个字符串数组
|
||||
|
||||
### watch() 监听数据变更,可进行拦截、修改
|
||||
|
||||
```python
|
||||
# python
|
||||
from sillygirl import Bucket
|
||||
import asyncio
|
||||
|
||||
test = Bucket("test")
|
||||
|
||||
async def main():
|
||||
async def handle(old_value, new_value, key):
|
||||
print("Bucket value changed!")
|
||||
print("Key:", key)
|
||||
print("Old value:", old_value)
|
||||
print("New value:", new_value)
|
||||
new_value = f"new {new_value}"
|
||||
print("New New value:", new_value)
|
||||
return {
|
||||
"now": new_value,
|
||||
#"error": "具体错误,将会撤销修改"
|
||||
#"message": "携带的额外信息"
|
||||
}
|
||||
|
||||
test.watch("*", handle)
|
||||
await asyncio.Queue().get()
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
```
|
||||
|
||||
# 适配器开发
|
||||
|
||||
## 元信息配置
|
||||
|
||||
通过 jsdoc 注释的方式来定义元信息,service true 时,将随程序一起执行
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* @service true
|
||||
*/
|
||||
```
|
||||
|
||||
## 初始化一个适配器
|
||||
|
||||
基本使用方法:
|
||||
|
||||
```
|
||||
/**
|
||||
* @title 钉钉机器人
|
||||
* @create_at 2023-07-30 11:09:12
|
||||
* @description 🐒钉钉机器人适配器。
|
||||
* @author cdle
|
||||
* @version v1.0.0
|
||||
* @service true
|
||||
*/
|
||||
```
|
||||
|
||||
```javascript
|
||||
//node
|
||||
const { Adapter, sleep } = require("sillygirl");
|
||||
|
||||
const bot_id = "";
|
||||
const platform = "dingtalk";
|
||||
|
||||
const dingtalk = new Adapter({
|
||||
platform,
|
||||
bot_id,
|
||||
// 处理 Sender.reply 回复的消息
|
||||
replyHandler: ({
|
||||
user_id, //用户ID
|
||||
chat_id, //群聊ID,为什么不用group_id,因为本人觉得别扭、不对齐
|
||||
message_id, //消息ID
|
||||
content, //消息内容,其中图片、文本使用CQ码实现
|
||||
//... 自定义参数,来自 Adapter.receive
|
||||
}) => {
|
||||
//... 实际消息发送逻辑
|
||||
return "${message_id}"; //返回消息ID,用于消息撤回等处理
|
||||
},
|
||||
// 处理 Sender.doAction 发出的指令
|
||||
actionHandler: (
|
||||
{
|
||||
//... 系列参数,如删除消息:{ type: "delete_message", message_id }
|
||||
}
|
||||
) => {
|
||||
return "${action_result}"; //返回结果
|
||||
},
|
||||
});
|
||||
|
||||
//向框架内部发送信息
|
||||
dingtalk.receive({
|
||||
user_id: "用户ID",
|
||||
chat_id: "群聊ID",
|
||||
message_id: "消息ID",
|
||||
content: "消息内容",
|
||||
//以下为可选
|
||||
user_name: "用户名", //用户名称
|
||||
chat_name: "群聊名名", //群聊名称
|
||||
//... 自定义参数
|
||||
});
|
||||
|
||||
//向框架外部推送消息,无视 unreply
|
||||
dingtalk.push({
|
||||
ser_id: "用户ID",
|
||||
chat_id: "群聊ID",
|
||||
message_id: "消息ID",
|
||||
content: "消息内容",
|
||||
});
|
||||
|
||||
//获取 sender 实例
|
||||
const ns = dingtalk.sender({
|
||||
user_id: "用户ID",
|
||||
chat_id: "群聊ID",
|
||||
message_id: "消息ID",
|
||||
content: "消息内容",
|
||||
});
|
||||
|
||||
// 1秒后主动销毁适配器,会抛出异常注意捕获
|
||||
// sleep(1000).then(() => {
|
||||
// dingtalk.destroy();
|
||||
// });
|
||||
```
|
||||
|
||||
```python
|
||||
#python
|
||||
from sillygirl import Adapter, console
|
||||
async def main():
|
||||
def replyHandler(message):
|
||||
console.log("message", message)
|
||||
return "ok"
|
||||
bot = Adapter(platform="terminal2", bot_id="default", replyHandler=replyHandler)
|
||||
ns = await bot.sender({"user_id": "user_id"})
|
||||
console.log(await ns.reply("hello"))
|
||||
# await bot.destroy()
|
||||
await asyncio.sleep(10)
|
||||
```
|
||||
|
||||
# 插件开发
|
||||
|
||||
## sender 方法合集
|
||||
|
||||
开发插件前,我们先了解一下 sender,该方法只有在插件中可用
|
||||
|
||||
### 导入 sender 为 s
|
||||
|
||||
```js
|
||||
/**
|
||||
* @rule Hello ?
|
||||
*/
|
||||
|
||||
const { sender: s } = require("sillygirl");
|
||||
```
|
||||
|
||||
### sender.getUserId() 获取用户 id
|
||||
|
||||
```js
|
||||
//内置js
|
||||
console.log(s.getUserId())
|
||||
```
|
||||
|
||||
```js
|
||||
//node
|
||||
s.getUserId().then((user_id) => console.log(`用户ID:${user_id}`));
|
||||
```
|
||||
|
||||
```python
|
||||
#python
|
||||
print(await s.getUserId())
|
||||
```
|
||||
|
||||
### sender.getChatId() 获取群聊 id
|
||||
|
||||
```js
|
||||
s.getChatId().then((chat_id) => console.log(`群聊ID:${chat_id}`));
|
||||
```
|
||||
|
||||
### sender.getMessageId() 获取消息 id
|
||||
|
||||
```js
|
||||
s.getMessageId().then((message_id) => console.log(`消息ID:${message_id}`));
|
||||
```
|
||||
|
||||
### sender.getContent() 获取消息内容
|
||||
|
||||
```js
|
||||
s.getContent().then((content) => console.log(`消息内容:${content}`));
|
||||
```
|
||||
|
||||
### sender.param() 获取参数,对应元消息中的 rule 中子匹配
|
||||
|
||||
```js
|
||||
s.param(1).then((param1) => console.log(`参数1:${param1}`));
|
||||
```
|
||||
|
||||
### sender.reply() 回复消息
|
||||
|
||||
```js
|
||||
s.reply("你好").then((message_id) => console.log(`消息ID:${message_id}`));
|
||||
```
|
||||
|
||||
### sender.listen() 监听消息
|
||||
|
||||
#### 例 1
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
await s.reply("请输入11位手机号:");
|
||||
let s2 = await s.listen({
|
||||
rules: ["^\\d{11}$"],
|
||||
});
|
||||
let phone = await s2.getContent();
|
||||
await s.reply(`你的手机号码是:${phone}`);
|
||||
//... 业务逻辑
|
||||
})();
|
||||
```
|
||||
|
||||
#### 例 2
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
await s.reply("请在10秒内输入11位手机号:");
|
||||
let s2 = await s.listen({
|
||||
rules: ["^\\d{11}$"],
|
||||
timeout: 10000,
|
||||
});
|
||||
if (!s2) {
|
||||
await s.reply("输入超时!");
|
||||
} else {
|
||||
let phone = await s2.getContent();
|
||||
await s.reply(`你的手机号码是:${phone}`);
|
||||
//... 业务逻辑
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
### sender.holdOn() 继续监听消息
|
||||
|
||||
#### 例 3
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
await s.reply("请在10秒内输入11位手机号:");
|
||||
let phone = "";
|
||||
await s.listen({
|
||||
handle: async (s) => {
|
||||
phone = await s.getContent();
|
||||
if (phone.length != 11) {
|
||||
return s.holdOn("错误,请重新输入(直到正确):");
|
||||
} else {
|
||||
return "输入正确。";
|
||||
}
|
||||
},
|
||||
});
|
||||
await s.reply(`你的手机号码是:${phone}`);
|
||||
//... 业务逻辑
|
||||
})();
|
||||
```
|
||||
|
||||
### sender.doAction() 发起指令
|
||||
|
||||
#### 撤回消息
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
const { sleep } = require("sillygirl");
|
||||
let message_id = await s.reply("本消息3秒后撤回!");
|
||||
await sleep(3000);
|
||||
await s.doAction({
|
||||
type: "delete_message",
|
||||
message_id,
|
||||
});
|
||||
})();
|
||||
```
|
||||
|
||||
### sender.getEvent() 获取事件
|
||||
|
||||
### sender.isAdmin() 是否管理员消息
|
||||
|
||||
```javascript
|
||||
sender.isAdmin().then((bool) => console.log(`${bool ? "是" : "不是"}管理员。`));
|
||||
```
|
||||
|
||||
### sender.getUserName() 获取用户昵称
|
||||
|
||||
```javascript
|
||||
s.getUserName().then((user_name) => console.log(user_name));
|
||||
```
|
||||
|
||||
### sender.getChatName() 获取群聊昵称
|
||||
|
||||
```javascript
|
||||
s.getChatName().then((v) => console.log(v));
|
||||
```
|
||||
|
||||
### sender.getPlatform() 获取消息平台
|
||||
|
||||
```javascript
|
||||
s.getPlatform().then((v) => console.log(v));
|
||||
```
|
||||
|
||||
### sender.getBotId() 获取机器人 id
|
||||
|
||||
```javascript
|
||||
s.getBotId().then((v) => console.log(v));
|
||||
```
|
||||
|
||||
### sender.getAdapter() 获取适配器
|
||||
|
||||
```javascript
|
||||
s.getAdapter().then((adapter) => console.log(adapter););
|
||||
```
|
||||
|
||||
### sender.continue() 消息继续向下传递
|
||||
|
||||
### sender.setContent() 篡改消息内容
|
||||
|
||||
### sender.destroy() 销毁会话,
|
||||
|
||||
脚本结束后自动调用,如果脚本长期不结束需要用手动调用避免内存泄漏
|
||||
|
||||
## 元信息配置
|
||||
|
||||
```js
|
||||
/**作者
|
||||
* @author Cdle
|
||||
* 插件名
|
||||
* @name 日常命令
|
||||
* 组织名
|
||||
* @origin 傻妞官方
|
||||
* 版本号
|
||||
* @version 1.0.5
|
||||
* 说明
|
||||
* @description 🐷日常命令,个人认为会比较便捷
|
||||
* 限制平台 不在该范围内的平台消息该插件不会被触发
|
||||
* @platform tg qq
|
||||
* 触发正则,^开头或raw 开头
|
||||
* @rule ^你好 ([^\n]+)$
|
||||
* @rule raw 你好
|
||||
* 直接用问号代替要匹配的内容
|
||||
* @rule 你好 ?
|
||||
* 使用方括号代替要匹配的内容,s.param("姓名") 取参
|
||||
* @rule 你好 [姓名]
|
||||
* 参数名加?表示为选值
|
||||
* @rule 你好 [姓名?]
|
||||
* // 是否管理员才能触发命令
|
||||
* @admin true
|
||||
* // 是否发布插件
|
||||
* @public false
|
||||
* // 插件优先级,越大优先级越高 如果两个插件正则一样,则优先级高的先被匹配
|
||||
* @priority 9999
|
||||
* // 是否禁用插件
|
||||
* @disable false
|
||||
* // 每5小时运行一次插件,触发时 platform 为 cron
|
||||
* @cron 0 0 *\/5 * * *
|
||||
* // 是否服务模块,会在系统启动时执行该插件内容,触发时 platform 为 *
|
||||
* @service false
|
||||
* // 给插件设置一个好看的头像
|
||||
* @icon https://wx.zsxq.com/dweb2/assets/images/favicon_32.ico
|
||||
```
|
||||
|
||||
## 写一个简单的 hello world
|
||||
|
||||
```js
|
||||
/**作者
|
||||
* @author Cdle
|
||||
* @name Hello
|
||||
* @version 1.0.5
|
||||
* @description 你好,世界!
|
||||
* @rule [参数1:hello,你好] [参数2]
|
||||
* @admin false
|
||||
* @public false
|
||||
* @priority 1
|
||||
* @disable false
|
||||
*/
|
||||
|
||||
(async (s) => {
|
||||
let name = await s.param("参数2");
|
||||
await s.reply(`你好,我是${name}`);
|
||||
})();
|
||||
```
|
||||
|
||||
## 插件加密(暂未实现)
|
||||
|
||||
为保护开发者知识产权,如果不想公开插件源码,可以用块级注释来包裹需要加密的内容
|
||||
`/*hidden*/` 开始,`/*neddih*/`结束,必须严格按照要求,多/少空格都不会被识别到
|
||||
|
||||
```js
|
||||
/*hidden*/
|
||||
let key = 1234;
|
||||
/*neddih*/
|
||||
|
||||
console.log("key");
|
||||
```
|
||||
|
||||
到底啦~ 详细的开发还是要靠插件来说明,多看看官方插件吧~~
|
||||
+483
@@ -0,0 +1,483 @@
|
||||
# 傻妞
|
||||
|
||||
一个不太有用的机器人,不生产消息,只搬运消息。
|
||||
|
||||
## 特性
|
||||
|
||||
- 简单易用的消息搬运功能。
|
||||
- 简单强大的自定义回复功能。
|
||||
- 完整支持 ECMAScript 5.1 的插件系统,基于 [otto](https://github.com/robertkrimen/otto)。
|
||||
- 支持通过内置的阉割版 `Express` / `request` ,接入互联网。
|
||||
- 内置 `Cron` ,轻松实现定时任务。
|
||||
- 持久化的 `Bucket` 存储模块。
|
||||
- 支持同时接入多个平台多个机器人,自己开发。
|
||||
|
||||
## 快速上手
|
||||
|
||||
### 安装
|
||||
|
||||
在 [releases](https://github.com/cdle/sillyGirl/releases) 中找到合适自己系统版本的程序运行带 `-t` 可以开启终端机器人,直接与程序进行交互。
|
||||
|
||||
```shell
|
||||
./sillyplus -t
|
||||
2023/05/24 14:12:01.859 [I] 默认使用boltdb进行数据存储。
|
||||
2023/05/24 14:12:01.950 [I] Http服务已运行(8080)。
|
||||
```
|
||||
|
||||
### 开发第一个插件
|
||||
|
||||
```js
|
||||
/**
|
||||
* @title HelleWorld
|
||||
* @rule raw ^你好$
|
||||
*/
|
||||
|
||||
s.reply("Helle World!");
|
||||
```
|
||||
|
||||
怼着程序输入 `你好` ,就可以看到机器人回复的 `Helle World!` 了
|
||||
|
||||
```sh
|
||||
你好
|
||||
2023/05/24 14:15:48.350 [I] 匹配到规则:^你好$
|
||||
Helle World!
|
||||
```
|
||||
|
||||
插件注释 `@rule raw ^你好$` 中的正则表达式被消息匹配时插件脚本就会被触发。
|
||||
|
||||
### 添加和销毁定时任务
|
||||
|
||||
插件注释 `@service true` 时是作为傻妞系统服务,伴随机器人一起启动。
|
||||
|
||||
```js
|
||||
/**
|
||||
* @title 定时任务
|
||||
* @service true
|
||||
*/
|
||||
|
||||
const task = Cron();
|
||||
let taskId = 0;
|
||||
let times = 5;
|
||||
const { id } = task.add("*/5 * * * * *", () => {
|
||||
// 同样支持分钟级任务,如:*/5 * * * *
|
||||
times--;
|
||||
console.log(
|
||||
`每5秒执行一次任务,${
|
||||
times ? `${times}次后结束任务` : "这是最后一次任务"
|
||||
}。`
|
||||
);
|
||||
if (times == 0) {
|
||||
task.remove(taskId); //移除任务
|
||||
}
|
||||
});
|
||||
taskId = id;
|
||||
```
|
||||
|
||||
程序输出:
|
||||
|
||||
```sh
|
||||
2023/05/27 19:57:00.000 [I] 每5秒执行一次任务,4次后结束任务。
|
||||
2023/05/27 19:57:05.001 [I] 每5秒执行一次任务,3次后结束任务。
|
||||
2023/05/27 19:57:10.001 [I] 每5秒执行一次任务,2次后结束任务。
|
||||
2023/05/27 19:57:15.001 [I] 每5秒执行一次任务,1次后结束任务。
|
||||
2023/05/27 19:57:20.000 [I] 每5秒执行一次任务,这是最后一次任务。
|
||||
```
|
||||
|
||||
### 与用户交互
|
||||
|
||||
```js
|
||||
/**
|
||||
* @title 用户交互插件
|
||||
* @rule 猜拳
|
||||
*/
|
||||
|
||||
s.reply("你先出,请在10秒内出拳!");
|
||||
ns = s.listen({
|
||||
rules: ["[出拳:剪刀,石头,布]"], // []中出拳是参数名,剪刀,石头,布是参数可能值
|
||||
timeout: 10000, // 超时设置
|
||||
handle: (s) => {
|
||||
let choose = s.param("出拳");
|
||||
s.reply(
|
||||
`我出${
|
||||
choose == "石头" ? "剪刀" : choose == "布" ? "剪刀" : "石头"
|
||||
},我赢了。`
|
||||
);
|
||||
},
|
||||
});
|
||||
if (!ns) {
|
||||
s.reply("你没出拳,算我赢了!");
|
||||
}
|
||||
```
|
||||
|
||||
### 开发 HTTP 接口
|
||||
|
||||
```js
|
||||
/**
|
||||
* @title 第一个web服务
|
||||
* @service true
|
||||
*/
|
||||
|
||||
const app = Express(); //导入HTTP服务,傻妞默认开启,端口8080
|
||||
app.get("/helloWorld", function (req, res) {
|
||||
res.send("Hello world!");
|
||||
});
|
||||
```
|
||||
|
||||
打开浏览器访问 `http://127.0.0.1:8080/helloWorld` ,当然地址根据实际情况,理论上可以看到接口返回的 `Hello world!` 。
|
||||
|
||||
### 实现一个 HTTP 请求
|
||||
|
||||
```js
|
||||
/**
|
||||
* @title 实现一个HTTP 请求
|
||||
* @service true
|
||||
*/
|
||||
|
||||
let api = "/testRequest"; //接口地址
|
||||
|
||||
//第一步,实现一个原样返回请求数据的接口
|
||||
const app = Express();
|
||||
app.post(api, (req, res) => res.json(req.json()));
|
||||
|
||||
//第二步,请求第一步实现的接口
|
||||
const port = Bucket("app").port ?? "8080"; // 获取http服务端口
|
||||
const url = `http://127.0.0.1:${port}${api}`;
|
||||
const { body } = request({
|
||||
url,
|
||||
method: "POST",
|
||||
body: { value: "test" },
|
||||
json: true,
|
||||
});
|
||||
console.log(`value is ${body.value}`);
|
||||
```
|
||||
|
||||
### 持久化存储
|
||||
|
||||
```js
|
||||
/**
|
||||
* @title 持久化存储
|
||||
* @rule raw ^我是谁$
|
||||
* @rule 我是[姓名]
|
||||
*/
|
||||
|
||||
const user = Bucket("user"); //初始化存储桶user
|
||||
let name = s.param("姓名");
|
||||
|
||||
if (user.name == "") {
|
||||
s.reply(`我不知道你是谁!`);
|
||||
} else if (name == "谁") {
|
||||
s.reply(`你是${user.name}`);
|
||||
} else {
|
||||
user.name = name;
|
||||
s.reply(`好的,你的姓名更新为${user.name}`);
|
||||
}
|
||||
```
|
||||
|
||||
插件实现了记名字的功能,其中`姓名`是方括号里匹配到的值,本质还是正则匹配到的。
|
||||
|
||||
```
|
||||
我是谁
|
||||
2023/05/24 15:43:40.121 [I] 匹配到规则:^我是谁$
|
||||
我不知道你是谁!
|
||||
我是小千
|
||||
2023/05/24 15:43:49.735 [I] 匹配到规则:^我是([\s\S]+)$
|
||||
好的,你的姓名更新为小千
|
||||
我是谁
|
||||
2023/05/24 15:43:53.727 [I] 匹配到规则:^我是谁$
|
||||
你是小千
|
||||
```
|
||||
|
||||
有了 `Bucket` 才有了傻妞从不认识小千到认识小千的过程。
|
||||
|
||||
### 管理员
|
||||
|
||||
```js
|
||||
const masters = Bucket("qq")["masters"];
|
||||
```
|
||||
|
||||
`masters` 是管理员账号通过"&"拼接起来的,系统默认依此判断用户是否是管理员。
|
||||
|
||||
### 群组消息
|
||||
|
||||
默认不监听不回复任何群组,监听口令 `listen` 和 `unlisten`,回复口令 `reply` 和 `noreply`,需要管理员在对应群组发送口令。
|
||||
|
||||
## 深入了解
|
||||
|
||||
### 插件注释
|
||||
|
||||
| 字段 | 举例 | 用法 |
|
||||
| ------------- | ---------------------------------- | -------------------------------------------------- |
|
||||
| `title` | HelloWorld | 插件标题 |
|
||||
| `rule` | raw `^我是([\s\S]+)$` | 可写多行,取括号内参数 `s.param(1)` ,多个参数类推 |
|
||||
| `priority` | `1` | 插件优先级,越高则优先处理 |
|
||||
| `service` | `true` | 插件后台任务执行脚本,避免重复运行 |
|
||||
| `disable` | `true` | 禁用脚本 |
|
||||
| `form` | `{title: "姓名", key:"user.name"}` | 插件表,key 值对应 `存储桶.键名` |
|
||||
| `public` | `true` | 公开插件 |
|
||||
| `create_at` | 2023-05-24 15:14:53 | 插件创建时间 |
|
||||
| `description` | 本插件用于每天向女友问好 | 插件描述 |
|
||||
| `author` | `cdle` | 插件作者 |
|
||||
| `version` | `v1.0.0` | 插件版本 |
|
||||
| `icon` | url 省略... | 给插件增加图标 |
|
||||
|
||||
### Sender
|
||||
|
||||
傻妞搬运的核心对象,在插件中为全局变量 s or sender。
|
||||
|
||||
```ts
|
||||
interface Sender {
|
||||
getUserId(): string; //获取用户ID
|
||||
getUserName(): string; //获取用户昵称
|
||||
getChatId(): string; //获取群聊ID
|
||||
getChatName(): string; //获取群聊名称
|
||||
getMessageId(): string; //获取消息ID
|
||||
getContent(): string; //获取消息内容
|
||||
continue(): void; //使消息继续往下匹配正则,消息正常第一次被匹配就会停止继续匹配
|
||||
setContent(content: string): void; //修改接收到的消息内容,可配合`continue`被其他规则匹配
|
||||
param(index: string | number): string; //获取`rule`匹配参数,可取[]内参数,?型参数从1开始取,例 `@rule 回复 ?` 对应 `s.param(1)`
|
||||
holdOn(content: string): string; //持续监听
|
||||
listen({
|
||||
rules: string[]; //匹配规则
|
||||
timeout: number; //超时,单位毫秒
|
||||
handle: (s: Sender): string;//如果匹配成功,则进入消息处理逻辑。如果将 holdOn(content) 的结果作为返回值,会继续监听
|
||||
listen_private: boolean; //监听用户群内消息时,同时监听用户消息
|
||||
listen_group: boolean; //监听用户群内消息时,同时监听群员消息
|
||||
allow_platforms: string[]; //平台白名单
|
||||
prohibit_platforms: string[]; //平台黑名单
|
||||
allow_groups: string[]; //群聊白名单
|
||||
prohibit_groups: string[]; //群聊黑名单
|
||||
allow_users: string[]; //用户白名单
|
||||
prohibit_users: string[]; //群聊白名单
|
||||
}): Sender; //超时,返回undefined
|
||||
isAdmin(): boolean; //判断消息是否来自管理员
|
||||
getPlatform(): string; //获取消息平台
|
||||
getBotId(): string; //获取机器人ID
|
||||
reply(content: string): {message_id: string, error: string}; //回复消息,媒体消息推荐使用CQ码实现,返回消息ID
|
||||
recallMessage(meesageId: string | string[] | number): {error: string}; //撤回消息,number类型时为延时毫秒
|
||||
kick(user_id: string): {error: string}; //移出群聊
|
||||
unkick(user_id: string): {error: string}; //取消移出群聊
|
||||
ban(user_id: string, duration: number): {error: string}; //禁言,并指定时长
|
||||
unban(user_id: string): {error: string}; //取消禁言
|
||||
}
|
||||
```
|
||||
|
||||
### Express `Request` / `Response`
|
||||
|
||||
只能说是够用,有需求可联系作者。插件中通过 `Express()` 返回一个对象。
|
||||
|
||||
```ts
|
||||
interface Request {
|
||||
body(): string; //获取请求体
|
||||
json(): any; //将请求体解析为JSON
|
||||
ip(): string; //获取客户端IP地址
|
||||
originalUrl(): string; //获取原始请求URL
|
||||
query(param: string): string; //获取查询参数
|
||||
param(i: number): string; //根据索引获取路径参数
|
||||
querys(): Record<string, string[]>; //获取所有查询参数
|
||||
postForm(s: string): string; //获取表单数据
|
||||
postForms(): Record<string, string[]>; //获取所有表单数据
|
||||
path(): string; //获取请求路径
|
||||
header(s: string): string; //获取请求头
|
||||
get(s: string): string; //获取请求头
|
||||
headers(): Record<string, string[]>; //获取所有请求头
|
||||
method(): string; //获取请求方法
|
||||
cookie(s: string): string; //获取 cookie
|
||||
cookies(): Record<string, string>; //获取 cookies
|
||||
continue(): void; //继续匹配其他路由
|
||||
setSession(k: string, v: string): string; //设置会话值
|
||||
getSession(k: string): string; //获取会话值
|
||||
getSessionId(): string; //获取会话ID
|
||||
destroySession(): string; //销毁会话
|
||||
logined(): boolean; //是否面板登录状态
|
||||
}
|
||||
|
||||
interface Response {
|
||||
send(body: any): Response; //发送响应体
|
||||
sendStatus(status: number): Response; //发送状态码
|
||||
json(...ps: any[]): Response; //发送JSON响应
|
||||
header(str: string, value: string): Response; //设置响应头
|
||||
set(str: string, value: string): void; //设置响应头
|
||||
render(view: string, params: Record<string, any>): Response; //渲染视图
|
||||
redirect(...is: any[]): void; //重定向到URL
|
||||
status(i: number, ...s: string[]): Response; //设置状态码和文本
|
||||
setCookie(name: string, value: string, ...i: any[]): Response; //设置 Cookie
|
||||
stop(): void; //代码片段停止
|
||||
}
|
||||
```
|
||||
|
||||
### request
|
||||
|
||||
由 `net/http` 封装而成,如有更多需求可以联系作者。
|
||||
|
||||
```ts
|
||||
function request(options: {
|
||||
url: string; //请求地址
|
||||
method: string; //请求方法
|
||||
headers: { [key: string]: string }; //请求头
|
||||
json: boolean; // 返回json对象,等价于 responseType: "json"
|
||||
timeout: number; //超时参数,单位毫秒
|
||||
form: { [key: string]: any }; //formData表单数据,优先于下面的body
|
||||
body: any; // 请求体,支持字符串、二进制,对象自动转json字符串和添加相应请求头
|
||||
allow_redirects: boolean; // 是否允许重定向,默认允许
|
||||
proxy: {};
|
||||
}): {
|
||||
status: number; // 状态码,同statusCode
|
||||
headers: { [key: string]: string };
|
||||
body: any;
|
||||
};
|
||||
```
|
||||
|
||||
### Adapter
|
||||
|
||||
```ts
|
||||
interface Message{
|
||||
message_id: string; // 消息ID
|
||||
user_id: string; // 用户ID
|
||||
chat_id: string; // 聊天ID
|
||||
content: string; // 聊天内容
|
||||
user_name: string; // 用户名
|
||||
chat_name: string; // 群组名
|
||||
}
|
||||
|
||||
class Adapter(botplt: string, botid: string) {
|
||||
isAdapter(botid: string): boolean; //判断id是否为机器人
|
||||
push(message: Message): string; //推送消息,无视禁言设置
|
||||
getReplyMessage(): Promise<message: Message>; //获取一条回复消息,实际发送成功后,如果有id,请设置 message.message_id
|
||||
setReplyHandler(func: (message: Message): string): void; //设置回复事件处理方法,方法中返回消息ID,不推荐使用。
|
||||
receive(message: Message): Sender; //接收一个消息,并返回一个Sender对象
|
||||
setRecallMessage(func: (i: string | string[]) => boolean): void;//设置撤回消息函数。
|
||||
setGroupKick(func: (user_id: string, chat_id: string, reject_add_request: boolean) => void): boolean; //设置群聊成员移除函数,reject_add_request指5是否继续接受请求
|
||||
setGroupBan(func: (user_id: string, chat_id: string, duration: number) => void): boolean;//设置群聊成员禁言函数
|
||||
setGroupUnban(func: (user_id: string, chat_id: string) => void): boolean;//设置群聊成员解除禁言函数
|
||||
setIsAdmin(func: (user_id: string) => boolean): void; //设置用户是否是成员函数,默认自动实现
|
||||
destroy(): void;//销毁机器人
|
||||
}
|
||||
function getAdapter(platform: string, bot_id string): {Adapter: string, error: string}; //获取一个机器人
|
||||
|
||||
function getAdapterBotsID(bot_id string): Adapter[]; //获取一个平台的所有机器人
|
||||
|
||||
function getAdapterBotPlts(platform: string): string[]; //所有机器人平台
|
||||
```
|
||||
|
||||
### Bucket
|
||||
|
||||
例:通过 `Bucket("app")` 初始化一个 app 存储痛
|
||||
|
||||
```ts
|
||||
interface Bucket(name: string) {
|
||||
get(key: string, defaultValue: any): any; // 取值
|
||||
set(key: string, value: any): Error | null; // 设值
|
||||
watch(key: string, event: (old: any, new_: any, key: string) => void); // 设置监听器,key 值为 * 时将监听整个桶的存储事件
|
||||
getAll(): []; // 获取全部值
|
||||
delete(key: string): Error | null; // 删值
|
||||
empty(): Error | undefined; // 清空桶
|
||||
keys(): string[]; // 获取所有键名
|
||||
len(): number | undefined; // 获取数据数目
|
||||
buckets(): string[]; // 获取所有存在的桶名
|
||||
_name(): string; // 获取当前桶名
|
||||
}
|
||||
```
|
||||
|
||||
### Cron
|
||||
|
||||
可以通过`let task = Cron()`返回的对象来添加定时任务 `const {id, error} = task.add("* * * * *", ()=>{})`
|
||||
|
||||
```ts
|
||||
interface Cron {
|
||||
add(crontab: string, ()=>void): {id: number, error: string}//添加定时任务 crontab同时支持秒级和分钟级
|
||||
remove(id: number): void//移除定时任务
|
||||
}
|
||||
```
|
||||
|
||||
### 插件表单
|
||||
|
||||
可以使用注释 `@form {title: "标题", key: "test.title"}` 添加表单元素。当如也可以直接在插件代码中添加,如下。
|
||||
|
||||
```js
|
||||
// 单个表单元素
|
||||
Form({
|
||||
title: "姓名",
|
||||
key: "test.name",
|
||||
});
|
||||
// 多个表单元素
|
||||
Form([
|
||||
{
|
||||
title: "姓名",
|
||||
key: "test.name",
|
||||
},
|
||||
{
|
||||
title: "性别",
|
||||
key: "test.sex",
|
||||
},
|
||||
]);
|
||||
// 使用schema-form
|
||||
Form([
|
||||
{
|
||||
title: "创建时间",
|
||||
key: "test.createName",
|
||||
dataIndex: "test.createName",
|
||||
valueType: "date",
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
key: "test.createName",
|
||||
dataIndex: "test.createName",
|
||||
valueType: "date",
|
||||
},
|
||||
{
|
||||
title: "分组",
|
||||
valueType: "group",
|
||||
columns: [
|
||||
{
|
||||
title: "状态",
|
||||
dataIndex: "test.groupState",
|
||||
valueType: "select",
|
||||
width: "xs",
|
||||
valueEnum: {
|
||||
all: { text: "全部", status: "Default" },
|
||||
open: {
|
||||
text: "未解决",
|
||||
status: "Error",
|
||||
},
|
||||
closed: {
|
||||
text: "已解决",
|
||||
status: "Success",
|
||||
disabled: true,
|
||||
},
|
||||
processing: {
|
||||
text: "解决中",
|
||||
status: "Processing",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "标题",
|
||||
width: "md",
|
||||
dataIndex: "test.groupTitle",
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "此项为必填项",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
```
|
||||
|
||||
### 其他
|
||||
|
||||
```ts
|
||||
sleep(millsec: number): void; //等待
|
||||
md5(string): string; //加密
|
||||
running(): boolean; //服务是否运行
|
||||
genUuid(): string; //生成uuid
|
||||
```
|
||||
|
||||
### 项目赞助
|
||||
|
||||
打开微信扫一扫,深入了解作者~
|
||||

|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 495 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 436 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 291 KiB |
@@ -0,0 +1,64 @@
|
||||
|
||||
目前支持 `windows amd64`/`liunx amd64`/`darwin arm64`二进制双击运行安装
|
||||
|
||||
## Docker
|
||||
```bash
|
||||
# 在你要存放数据的目录下手动新建sillyGirl文件夹
|
||||
# (以root目录为例)
|
||||
# 警告!群晖用户请勿在root下存放任何文件!修改成你的硬盘目录!
|
||||
mkdir /root/sillyGirl #在root目录新建sillyGirl文件夹
|
||||
|
||||
# 拉取并运行容器 并进入交互控制台
|
||||
docker run -itd \
|
||||
-v /root/sillyGirl/data:/etc/sillyplus \
|
||||
-v /root/sillyGirl/plugins:/usr/local/sillyplus/plugins \
|
||||
-p 8080:8080 \
|
||||
--name sillyGirl \
|
||||
--restart always \
|
||||
jackytj/sillyplus && docker attach sillyGirl
|
||||
|
||||
```
|
||||
进入容器交互控制台
|
||||
```bash
|
||||
#进入
|
||||
docker attach sillyGirl
|
||||
# 退出交互控制台
|
||||
Ctrl+p Ctrl+q
|
||||
```
|
||||
|
||||
查看日志
|
||||
```bash
|
||||
docker logs sillyGirl
|
||||
```
|
||||
|
||||
进入容器命令行(一般用不到)
|
||||
```bash
|
||||
docker exec -it sillyGirl /bin/sh
|
||||
```
|
||||
|
||||
|
||||
## Windows
|
||||
下载双击运行
|
||||
|
||||
- [sillyGirl_windows_amd64.exe](https://github.com/cdle/sillyGirl/releases/download/main/sillyGirl_windows_amd64.exe)
|
||||
|
||||
|
||||
## MacOS
|
||||
|
||||
敬请期待
|
||||
|
||||
## Liunx
|
||||
|
||||
下载双击运行
|
||||
|
||||
- [sillyGirl_linux_amd64](https://github.com/cdle/sillyGirl/releases/download/main/sillyGirl_linux_amd64)
|
||||
|
||||
- [sillyGirl_linux_arm64](https://github.com/cdle/sillyGirl/releases/download/main/sillyGirl_linux_arm64)
|
||||
|
||||
## Other
|
||||
|
||||
- 如果你的运行环境不受支持
|
||||
|
||||
- 如果你在使用上有任何困难
|
||||
|
||||
- 可以加入本项目的[知识星球](https://wx.zsxq.com/dweb2/index/group/28885424215821),以获取手拉手教程、特殊资源共享、定制需求和同作者实时交流
|
||||
@@ -0,0 +1,68 @@
|
||||
# 配置
|
||||
初次启动创建3个文件夹,分别为 `language` `plugins`
|
||||
`/etc/sillyplus` 会自动生成一些启动所需的配置文件,已进行详细注释,根据自己情况来填写;
|
||||
|
||||
`language` 计算机语言支持依赖,请不要动它;
|
||||
|
||||
`plugins` 插件目录,从插件市场安装的插件都在这里;
|
||||
|
||||
`/etc/sillyplus` 为系统数据库存放目录;
|
||||
|
||||
# 面板
|
||||
|
||||
运行时会提示面板,本人蹩脚前端,将就用吧;
|
||||
|
||||
# 适配器
|
||||
|
||||
运行傻妞`-t`启用自带`terminal`适配器,其他适配器请前往插件市场,目前已支持`QQ`、`QQ频道`、`微信`、`公众号`、`飞书`、`钉钉`、`Telegram`、`Pagermaid`等,从`机器人`分类安装;
|
||||
|
||||
|
||||
# 管理员命令没反应?群聊不回复群友?
|
||||
参见 [**常见问题Q&A**](/help/Q&A.md)
|
||||
|
||||
# 常用指令
|
||||
|
||||
首次安装时将自动从插件市场安装,如果不需要可以禁用
|
||||
|
||||
```js
|
||||
//获取数据库数据
|
||||
get 表 key
|
||||
//例如获取管理员
|
||||
get qq masters
|
||||
// 设置数据库
|
||||
set 表 key value
|
||||
//例如设置管理员
|
||||
set qq masters 123456789
|
||||
//获取时间
|
||||
time
|
||||
//启动时间
|
||||
started_at
|
||||
//获取机器码
|
||||
machine_id
|
||||
//获取版本
|
||||
compiled_at
|
||||
// 获取群id
|
||||
chat_id
|
||||
//获取个人id
|
||||
myuid
|
||||
//监听群消息 (默认屏蔽所有群)
|
||||
listen
|
||||
//屏蔽群消息
|
||||
unlisten
|
||||
//不回复该群
|
||||
unreply
|
||||
//回复该群
|
||||
reply
|
||||
|
||||
```
|
||||
|
||||
# 其他命令
|
||||
其他命令要视插件情况而定,具体问队友插件作者
|
||||
|
||||
# 关于报错!
|
||||
|
||||
## Error: Cannot find module 'xxxxx'
|
||||
统一为缺少npm模块,通过管理员对机器人发送 npm i xxxx 命令安装模块后重启即可解决
|
||||
|
||||
## Error: Cannot find module './xxxxx'
|
||||
统一为缺少自定义模块,谁写的插件找谁要这些模块,一般对应的插件仓库都有的,是你没装好!
|
||||
Vendored
+108
@@ -0,0 +1,108 @@
|
||||
declare class Sender {
|
||||
private uuid;
|
||||
private destoried;
|
||||
constructor(uuid: string);
|
||||
destroy(): void;
|
||||
getUserId(): Promise<string>;
|
||||
getUserName(): Promise<string>;
|
||||
getChatId(): Promise<string>;
|
||||
getChatName(): Promise<string>;
|
||||
getMessageId(): Promise<string>;
|
||||
getPlatform(): Promise<string>;
|
||||
getBotId(): Promise<string>;
|
||||
getContent(): Promise<string>;
|
||||
isAdmin(): Promise<boolean>;
|
||||
param(key: number | string): Promise<string>;
|
||||
setContent(content: string): Promise<undefined>;
|
||||
continue(): Promise<undefined>;
|
||||
getAdapter(): Promise<Adapter>;
|
||||
listen(options?: {
|
||||
rules?: string[];
|
||||
timeout?: number;
|
||||
handle?: (s: Sender) => Promise<string | void> | string | void;
|
||||
listen_private?: boolean;
|
||||
listen_group?: boolean;
|
||||
allow_platforms?: string[];
|
||||
prohibit_platforms?: string[];
|
||||
allow_groups?: string[];
|
||||
prohibit_groups?: string[];
|
||||
allow_users?: string[];
|
||||
prohibit_users?: string[];
|
||||
}): Promise<Sender | undefined>;
|
||||
holdOn(str: string): string;
|
||||
reply(content: string): Promise<string>;
|
||||
doAction(options: Record<string, any>): Promise<any>;
|
||||
getEvent(): Promise<Record<string, any>>;
|
||||
}
|
||||
declare class Bucket {
|
||||
private name;
|
||||
constructor(name: string);
|
||||
transform(v: string | undefined): string | number | boolean | undefined;
|
||||
reverseTransform(value: any): string;
|
||||
get(key: string, defaultValue?: any): Promise<any>;
|
||||
set(key: string, value: any): Promise<{
|
||||
message?: string;
|
||||
changed?: boolean;
|
||||
}>;
|
||||
getAll(): Promise<Record<string, any>>;
|
||||
delete(key: string): Promise<{
|
||||
message?: string;
|
||||
changed?: boolean;
|
||||
}>;
|
||||
deleteAll(): Promise<undefined>;
|
||||
keys(): Promise<string[]>;
|
||||
len(): Promise<number>;
|
||||
buckets(): Promise<string[]>;
|
||||
watch(key: string, handle: (old: any, now: any, key: string) => StorageModifier | void): void;
|
||||
getName(): Promise<string>;
|
||||
}
|
||||
interface StorageModifier {
|
||||
echo?: string;
|
||||
now?: any;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
interface Message {
|
||||
message_id?: string;
|
||||
user_id: string;
|
||||
chat_id?: string;
|
||||
content: string;
|
||||
user_name?: string;
|
||||
chat_name?: string;
|
||||
}
|
||||
declare class Adapter {
|
||||
platform: string;
|
||||
bot_id: string;
|
||||
call: any;
|
||||
constructor(options: {
|
||||
platform: string;
|
||||
bot_id: string;
|
||||
replyHandler?: (message: Message) => Promise<string | undefined>;
|
||||
actionHandler?: (message: Message) => Promise<string | undefined>;
|
||||
});
|
||||
receive(message: Message): Promise<undefined>;
|
||||
push(message: Message): Promise<string>;
|
||||
destroy(): Promise<void>;
|
||||
sender(options: any): Promise<Sender>;
|
||||
}
|
||||
declare let sender: Sender;
|
||||
declare function sleep(ms?: number): Promise<unknown>;
|
||||
interface CQItem {
|
||||
type: string;
|
||||
params: Record<string, string>;
|
||||
}
|
||||
interface CQParams {
|
||||
[key: string]: string | number | boolean;
|
||||
}
|
||||
declare let utils: {
|
||||
buildCQTag: (type: string, params: CQParams, prefix?: string) => string;
|
||||
parseCQText: (text: string, prefix?: string) => (string | CQItem)[];
|
||||
};
|
||||
declare let console: {
|
||||
log(...args: any[]): void;
|
||||
info(...args: any[]): void;
|
||||
error(...args: any[]): void;
|
||||
debug(...args: any[]): void;
|
||||
};
|
||||
|
||||
export { Adapter, Bucket, sender, sleep, utils, console };
|
||||
@@ -0,0 +1,2 @@
|
||||
# 1.0.0
|
||||
正式版本
|
||||
Reference in New Issue
Block a user