# Adachi-Plugin 开发者文档
# 注册插件
插件(Plugin)
是由开发者创建的 指令(Command)
的集合。注册插件只需要在 /src/plugins
目录下创建一个文件夹,然后完成「声明」和「实现」两个步骤。
# 声明
声明插件只需在上文提到的文件夹中创建一个名为 init.ts
的文件,文件的格式如下:
// /src/plugins/example/init.ts
import {PluginSetting} from "@modules/plugin";
import {OrderConfig} from "@modules/command";
const echo: OrderConfig = {
type: "order",
cmdKey: "silvery-star.echo",
desc: ["复读", "[任意内容]"],
headers: ["echo"],
regexps: [".+"]
};
// 不可 default 导出,函数名固定
export async function init(): Promise<PluginSetting> {
return {
pluginName: "example",
cfgList: [echo]
};
}
这是一个最简单的声明插件的例子,它声明了一个名为 example
的插件,同时定义了一个用于复读消息的 Order类型 指令,下面我们来实现这个插件。
# 实现
每个指令都可以配置一个可选的 main
属性,表示实现这个指令的文件位置,或实现指令的函数,它的缺省值为 index
,即在 init.ts
的同一目录下的 index.ts
文件中实现,文件的格式如下:
// /src/plugins/example/index.ts
import {InputParameter} from "@modules/command";
// 不可 default 导出,函数名固定
export async function main(i: InputParameter): Promise<void> {
await i.sendMessage(i.messageData.raw_message);
}
如此就可以非常简单的实现一个 echo
指令复读的功能。其中 InputParameter 是 main
函数的入参对象,负责提供实现指令时可能需要使用到的工具和数据。
在此基础上,你可以通过下面提供的工具来实现功能各异的插件。
# 适配热更新插件指令
BOT 存在热更新插件指令 upgrade_plugins
,如果你希望该指令能够作用于你的插件,就需要为插件声明添加 repo
属性。
return <PluginSetting>{
pluginName: "example",
cfgList: [echo],
// repo 属性,仓库拥有者名称/仓库名称
repo: "SilveryStar/example"
};
以上方式默认为 Master 分支,若你的插件并不在默认分支下,可使用对象的声明方式。
return <PluginSetting>{
pluginName: "example",
cfgList: [echo],
// repo 属性
repo: {
owner: "SilveryStar", // 仓库拥有者名称
repoName: "example", // 仓库名称
ref: "main" // 分支名称
}
};
# 适配 web console
订阅系统
如果你的插件存在用户私人订阅服务(即 BOT 将会定期主动向用户发送消息),我们强烈建议你能为插件抛出一个 subInfo
方法,来使 web console
能够更直观的为 BOT
持有则展示当前用户的订阅信息,以及支持一键清除订阅与删除好友自动清除订阅功能。该方法类型和实现方式如下:
export type SubInfo = {
name: string; // 订阅名称
users: number[]; // 用户 qq 号码列表
};
export type PluginSubSetting = {
subs: (bot: BOT) => Promise<SubInfo[]>; // 订阅数据列表
reSub: (userId: number, bot: BOT) => Promise<void>; // 清除订阅方法
}
export async function subInfo(): Promise<PluginSubSetting> {
return {
subs: subs,
reSub: decreaseFriend
}
}
# Global
# BOT
BOT
是 Adachi-BOT v2.2.0+
中定义全局工具类的接口,它被定义为:
interface BOT {
readonly redis: Database;
readonly config: BotConfig;
readonly client: sdk.Client;
readonly logger: log.Logger;
readonly interval: Interval;
readonly file: FileManagement;
readonly auth: Authorization;
readonly message: MsgManagement;
readonly command: Command;
readonly whitelist: WhiteList;
readonly refresh: RefreshConfig;
readonly renderer: BasicRenderer;
}
每个工具类的含义和包含的方法都会在后文中进行一一介绍。
这个接口实例整体会被传入 init()
,你可以通过 解构对象 (opens new window)
的方式来获取其中的某个工具,以便进行声明插件的准备工作,如创建配置文件等。在代码的其他地方,你也可以通过下面的代码导入所有工具类。
import bot from "ROOT";
# InputParameter
指令实现的入参对象,被定义为:
type Message = oicq.PrivateMessageEventData |
oicq.GroupMessageEventData;
type InputParameter = {
sendMessage: SendFunc;
messageData: Message;
matchResult: MatchResult;
} & BOT;
# CommandFunc
实际上,main
函数是这样被定义的:
type CommandFunc = (input: InputParameter) => void | Promise<void>;
换言之,在实现插件的函数内,你除了能获取所有的工具类,还能得到消息回复函数、消息事件数据和正则匹配结果。
# MessageScope
指令作用域,表示某条指令的可被触发范围,被定义为:
enum MessageScope {
Neither,
Group = 1 << 0,
Private = 1 << 1,
Both = Group | Private
}
# AuthLevel
权限等级,被定义为:
enum AuthLevel {
Banned,
User,
Manager,
Master
}
其中,User
是默认权限等级;Master
是持有者,最高权限等级。
# Command
事实上,指令才是 Adachi-BOT
设计中的「第一公民」。出于简化指令实现代码,强化用户配置的考虑,我们暂时将指令分为以下三种:命令式(Order)
、 开关式(Switch)
和 询问式(Enquire)
。
# CommandInfo
CommandInfo
表示了所有类型指令的公用配置属性,它的定义如下:
type CommandInfo = Required<Optional<BasicConfig>,
"cmdKey" | "desc"> & { main?: string | CommandFunc };
这或许有些抽象,我们可以将其展开:
interface CommandInfo {
cmdKey: string;
desc: [string, string];
detail?: string;
auth?: AuthLevel;
scope?: MessageScope;
display?: boolean;
ignoreCase?: boolean;
main?: string | CommandFunc;
}
# cmdKey
必填字段,string (opens new window) 类型。表示指令的 key
值,唯一指定,用于区分不同的指令。该值应简记为 开发者.指令功能
或 插件名.指令功能
,点号两侧均应使用 kebab-case
,如:silvery-star.uid-query
。
# desc
必填字段,[string, string] (opens new window) 类型。为对指令的基本描述。desc[0]
应为对指令作用的简短描述,四字最佳;desc[1]
应为指令的参数列表,视指令类型不同用不同的形式。
# detail
选填字段,string (opens new window)
类型,缺省值为 "该指令暂无更多信息"
。表示指令详细内容,当用户使用 adachi.detail
指令时将返回此字段。
# auth
选填字段,AuthLevel 类型,缺省值为 AuthLevel.User
。表示允许使用该指令的最低权限。设置为 AuthLevel.Banned
时无效,被封禁用户无法使用任何指令。
# scope
选填字段,MessageScope 类型,缺省值为 MessageScope.Both
。表示允许使用该指令的位置。
# display
选填字段,boolean (opens new window) 类型,缺省值为 true
。表示是否在 adachi.help
返回内容中显示此指令。
# ignoreCase
选填字段,boolean (opens new window) 类型,缺省值为 true
。表示正则匹配是否忽略大小写。
# main
选填字段,string (opens new window)
或 CommandFunc 类型,缺省值为 "index"
。表示指令入口。
# Order
命令式指令。将指令分为「指令头」和「指令参数」两个部分,其中「指令头」用于区分不同的指令,「指令参数」用于进行功能的实现。它的定义如下:
type OrderConfig = CommandInfo & {
type: "order";
headers: string[];
regexps: string[] | string[][];
start?: boolean;
stop?: boolean;
};
# type
固定字段。
# headers
必填字段,string[] (opens new window)
类型。表示该指令的所有指令头,可由用户配置。所有的指令头前都会被添加上用户在 setting.yml
中配置的 header
属性,如果你想忽略它,请在你的指令头前添加双下划线 __
。
# regexps
必填字段,string[] (opens new window) 或 string[][] (opens new window) 类型。表示该指令的所有正则匹配,不可由用户配置。该字段可以表示为一维或二维字符串数组,它们的含义分别是:
- 一维数组时,表示一个正则表达式。数组由「正则匹配单元」组成,如
[ "(add|rem)", "\\d+" ]
,在生成最终的正则表达式时,该指令头和该数组的所有元素被拼接起来,如/#example *(add|rem) *\d+/
。 - 二维数组时,表示若干个正则表达式。数组由上一点提到的一维数组组成。
# start
选填字段,boolean (opens new window) 类型,缺省值为 true
。表示是否要在最终正则表达式前添加 ^
。
# stop
选填字段,boolean (opens new window) 类型,缺省值为 true
。表示是否要在最终正则表达式后添加 $
。
# desc[1]
必填字段,string (opens new window)
类型。表示指令的参数列表,Order
型指令中,其中必填参数用 []
包裹,选填参数用 ()
包裹,如 "r(次数)d[面数]k(前k大)"
。
# messageDate.raw_message
该值将会被去除指令头。注意,ignoreCase
设置为 true
时,raw_message
将为全小写字符串。
# OrderMatchResult
Order
型指令,匹配成功后将返回给 main
函数匹配到的「指令头」。
interface OrderMatchResult {
type: "order";
header: string;
}
# Switch
开关式指令。这是「命令式指令」的一类特化。
type SwitchConfig = CommandInfo & {
type: "switch";
onKey: string;
offKey: string;
header: string;
mode: "single" | "divided";
regexp: string | string[];
start?: boolean;
stop?: boolean;
};
# type
固定字段。
# onKey
必填字段,string (opens new window) 类型。表示指令状态为「开」的关键词。
# offKey
必填字段,string (opens new window) 类型。表示指令状态为「关」的关键词。
# header
必填字段,string (opens new window)
类型。表示该指令的唯一指令头,可由用户配置。指令头前都会被添加上用户在 setting.yml
中配置的 header
属性,如果你想忽略它,请在你的指令头前添加双下划线 __
。
# mode
必填字段,"single" | "divided" (opens new window) 类型。表示开关类指令的构成模式。
- 设置为
single
时,表示单指令头模式。开/关关键词将被|
连接作为可选单元,最终被组装为形如header (on|off)
的表达式。 - 设置为
divided
时,表示拆分指令头模式。此时header
配置将被忽略,开关关键词将作为header
,最终将被组装为形如(onKey|offKey) prams
的表达式。
# regexp
必填字段,string (opens new window) 或 string[] (opens new window) 类型。表示匹配的正则表达式不可由用户配置。该字段可以表示为字符串或一维字符串数组,它们的含义分别是:
- 字符串时,表示完整的表达式,将被直接拼接到指令头上。
- 一维数组时,同 Order 指令中的
regexps
的一维数组清空。
特别的,Switch
指令还允许你在正则表达式中使用 #{OPT}
来标识开/关关键词的位置,如 [ "#{OPT}", "\\d+" ]
,这将导出如 /#calc (add|sub) \d+/
的指令。#{OPT}
标识在 divided
模式中不生效。
# start
# stop
# desc[1]
在 Switch
类型中的指令描述中,你也可以使用 #{OPT}
来标识开/关关键词的位置。同样,该标识在 divided
模式中不生效。
# SwitchMatchResult
interface SwitchMatchResult {
type: "switch";
switch: string;
match: string[];
isOn(): boolean;
}
Switch
型指令,匹配成功后将返回给 main
函数匹配到的关键词 switch
,关键词是否为 onKey
的函数 isOn
和剩余匹配结果列表 match
。
# Enquire
询问式指令。支持类似正常说话类型的指令解构。
interface RegUnit {
regexp: string;
senDesc: string;
}
type EnquireConfig = CommandInfo & {
type: "enquire";
sentences: string[];
definedPair: Record<string, RegUnit>;
};
# type
固定字段。
# sentences
必填字段,string[] (opens new window) 类型。表示「询问句式」。
# definedPair
必填字段,Record (opens new window)<string (opens new window)
, RegUnit> 类型。表示「句式单元」。这是 Enquire
类型指令的核心部分,通过开发者定义变量名和获取变量的正则表达式,来加强指令的可配置性。一个「句式单元」的组成如下:
camelCase
的string
类型变量作为key
,这个key
将被转化为SNAKE_CASE
用于「询问句式」中,并被#{}
包裹,例如webConsole => #{WEB_CONSOLE}
。RegUnit
则是一个包含「正则匹配单元」和描述的对象,其中正则匹配单元将被替换到「询问句式」含标识符的位置,并被添加()
包裹(所以你不需要为可选符号的外部添加括号)。
# desc[1]
你不需要为 Enquire
类型配置 desc[1]
,保留空字符串即可。
# EnquireMatchResult
interface EnquireMatchResult {
type: "enquire";
matchPair: Record<string, string>;
}
Enqire
型指令,匹配成功后将返回给 main
函数匹配到的所有「句式单元」表示的 key
和获取的 value
。
# #{HEADER}
这是一个保留标识符,表示用户在 setting.yml
中配置的 header
属性,你也可以在 sentences
中直接使用它,无需定义。
# Example
上面的内容并不容易让人理解 Enquire
指令的配置方法,下面将提供一个简单的实现 Enquire
指令的例子。
const simpleSentence: EnquireConfig = {
type: "enquire",
cmdKey: "tools.test",
desc: ["简单句", ""],
definedPair: {
obj: { // #{OBJ}
regexp: "\\w+",
senDesc: "宾语"
},
sub: { // #{SUB}
regexp: "I|you|he|she",
senDesc: "主语"
},
pred: { // #{PRED}
regexp: "am|is|are",
senDesc: "系动词"
},
verb: { // #{VERB}
regexp: "\\w+",
senDesc: "动词"
},
modalVerb: { // #{MODAL_VERB}
regexp: "can|could|may|might",
senDesc: "情态动词"
}
},
sentences: [
"#{SUB} #{PRED} #{OBJ}",
// => /(I|you|he|she) (am|is|are) \w+/i
"#{HEADER}#{MODAL_VERB} #{SUB} #{VERB} #{OBJ}"
// => /#(can|could|may|might) (I|you|he|she) \w+ \w+/i
]
}
在这个例子中,我们定义了五个「句式单元」,并通过它们写了两个简单的询问句式,备注中写出了它们的导出正则。了解了定义后,实现就非常简单了:
import {InputParameter} from "@modules/command";
async function main(i: InputParameter): Promise<void> {
console.log(i.matchResult);
}
/**
* <= I am developer
* => matchPair: { sub: "I", pred: "am", obj: "developer" }
*
* <= #Can you write code
* => matchPair: {
* header: "#", modalVerb: "Can",
* sub: "you", verb: "write", obj: "code"
* }
**/
# Database
Adachi-BOT
使用了 Redis
作为数据库并简单的封装了一些常用方法。
interface DatabaseMethod {
// Common
setTimeout(key: string, time: number): Promise<void>;
deleteKey(...keys: string[]): Promise<void>;
getKeysByPrefix(prefix: string): Promise<string[]>;
// Hash
setHash(key: string, value: any): Promise<void>;
getHash(key: string): Promise<any>;
delHash(key: string, ...fields: string[]): Promise<void>;
incHash(key: string, field: string, increment: number): Promise<void>;
existHashKey(key: string, field: string): Promise<boolean>;
setHashField(key: string, field: string, value: string): Promise<void>
getHashField(key: string, field: string): Promise<any>;
// String
setString(key: string, value: any, timeout?: number): Promise<void>;
getString(key: string): Promise<string | null>;
// List
getList(key: string): Promise<string[]>;
getListLength(key: string): Promise<number>;
addListElement(key: string, ...value: any[]): Promise<void>;
delListElement(key: string, ...value: any[]): Promise<void>;
existListElement(key: string, value: any): Promise<boolean>;
// Set
getSet(key: string): Promise<string[]>;
getSetMemberNum(key: string): Promise<number>;
addSetMember(key: string, ...value: any[]): Promise<void>;
delSetMember(key: string, ...value: any[]): Promise<void>;
existSetMember(key: string, value: any): Promise<boolean>;
}
# Common
通用方法。
# 键名约定
同 cmdKey ,简记为 开发者.数据作用
或 插件名.数据作用
,点号两侧均应使用 kebab-case
,如:silvery-star.user-bind-id
。
# setTimeout
作用
原型 EXPIRE (opens new window) 。设置数据过期时间。
参数列表
key
操作目标的键值time
目标的过期时间,单位 ms
# deleteKey
作用
原型 DEL (opens new window) 。删除数据。
参数列表
...key
待删除的数据的键值,可多个
# getKeysByPrefix
作用
原型 KEYS (opens new window) 。根据键值前缀获取数据库中满足条件的键的列表。
参数列表
prefix
在数据库中匹配的键值前缀
# String
字符串 (opens new window) 相关方法。
# setString
作用
原型 SET (opens new window) 。设置一个字符串类型的数据。
参数列表
key
操作目标的键值value
设置的值,通常可以是 string (opens new window) 、number (opens new window) 或 boolean (opens new window) 类型timeout
可选参数,数据过期时间,单位 ms ,默认不会过期
# getString
作用
原型 GET (opens new window) 。获取一个字符串类型的数据。当键值不存在时,返回 ""
。
参数列表
key
操作目标的键值
# Hash
哈希 (opens new window) 相关方法。
# setHash
作用
原型 HMSET (opens new window) 。设置一个 Hash 类型的数据。
参数列表
key
操作目标的键值value
设置的值,可以为 Array (opens new window) 和 Object (opens new window) 两种类型:Array
类型时,奇数位的元素为表示字段名的string
类型的值,偶数位表示前一个元素的字段对应的值,如:[ "k1", 1, "k2", "2" ]
Object
类型时,传入一个对象,且它不应该嵌套数组或对象,如:{ k1: 1, k2: "2" }
# getHash
作用
原型 HGETALL (opens new window) 。获取一个 Hash
类型数据的所有字段以及值,返回为 Object (opens new window) 类型。当键值不存在时,返回 {}
。
参数列表
key
操作目标的键值
# delHash
作用
原型 HDEL (opens new window) 。删除一个 Hash 类型数据的部分字段。
参数列表
key
操作目标的键值...fields
待删除的字段名,可多个
# incHash
作用
原型 HINCRBY (opens new window) 及 HINCRBYFLOAT (opens new window) 。给一个 Hash 类型数据的某字段加上某值。
参数列表
key
操作目标的键值field
待操作的字段名increment
添加的值,可为整形或浮点型
# existHashKey
作用
原型 HEXISTS (opens new window) 。判断一个 Hash 类型数据中是否包含某字段。
参数列表
key
操作目标的键值field
待判断的字段名
# setHashField
作用
原型 hmset (opens new window) 。将一个 Hash 类型数据中的某一个字段设置为对应的值。
参数列表
key
操作目标的键值field
待操作的字段名value
赋值的值
# getHashField
作用
原型 hget (opens new window) 。用于返回一个 Hash 类型中指定字段的值。
参数列表
key
操作目标的键值field
待操作的字段名
# List
列表 (opens new window) 相关方法。
# getList
作用
原型 LRANGE (opens new window) 。获取一个完整的 List 类型数据。当键值不存在时,返回 []
。
参数列表
key
操作目标的键值
# getListLength
作用
原型 LLEN (opens new window) 。获取一个 List 类型数据的长度。当键值不存在时,返回 0
。
参数列表
key
操作目标的键值
# addListElement
作用
原型 RPUSH (opens new window) 。向一个 List 类型数据中添加若干数据。
参数列表
key
操作目标的键值...values
待添加的数据,可多个
# delListElement
作用
原型 LREM (opens new window) 。从一个 List 类型数据中删除若干数据。
参数列表
key
操作目标的键值...values
待删除的数据,可多个
# existListElement
作用
判断一个 List 类型数据中是否包含某数据。
参数列表
key
操作目标的键值value
待判断的数据
# Set
集合 (opens new window) 相关方法。
# getSet
作用
原型 SMEMBERS (opens new window) 。获取一个 Set 类型数据。当键值不存在时,返回 []
。
参数列表
key
操作目标的键值
# getSetMemberNum
作用
原型 SCARD (opens new window) 。获取一个 Set 类型数据中含有的成员的数量。当键值不存在时,返回 0
。
参数列表
key
操作目标的键值
# addSetMember
作用
原型 SADD (opens new window) 。向一个 Set 类型数据中添加若干数据。
参数列表
key
操作目标的键值...values
待添加的数据,可多个
# delSetMember
作用
原型 SREN (opens new window) 。从一个 Set 类型数据中删除若干数据。
参数列表
key
操作目标的键值...values
待删除的数据,可多个
# existSetMember
作用
原型 SISMEMBER (opens new window) 。判断一个 Set 类型数据中是否包含某数据。
参数列表
key
操作目标的键值value
待判断的数据
# client
如果上面的方法不足以实现你的需求,可以使用 client
获取数据库实例对象。
# BotConfig
setting.yml
内的配置数据,详见配置。
# FileManagement
一套简单封装的文件管理方法。
type PresetPlace = "config" | "plugin" | "root";
interface ManagementMethod {
// Common
isExist(path: string): boolean;
getFilePath(path: string, place?: PresetPlace): string;
// File
renameFile(fileName: string, newName: string, place?: PresetPlace): void;
readFile(fileName: string, place: PresetPlace): string;
// Dir
createDir(dirName: string, place?: PresetPlace): boolean;
getDirFiles(dirName: string, place?: PresetPlace): string[];
// YAML
createYAML(ymlName: string, data: any, place?: PresetPlace): boolean;
loadYAML(ymlName: string, place?: PresetPlace): any;
writeYAML(ymlName: string, data: any, place?: PresetPlace): void;
updateYAML(ymlName: string, data: any, place?: PresetPlace, ...index: string[]): void;
}
# PresetPlace
表示用于定位目录的位置
root
表示Adachi-BOT
config
表示Adachi-BOT/config
,所有方法默认情况下都为此值plugin
表示Adachi-BOT/src/plugins
# Common
# isExist
判断某文件/目录是否存在,必须传入完整的路径(绝对路径)。
# getFilePath
根据相对路径获取绝对路径。
# File
# renameFile
更名文件,fileName
和 newName
均应为相对路径形式。
# readFile
读取文件内容。
# Directory
# createDir
创建目录。
# getDirFiles
获取一个目录下的所有子级文件名。
# YAML
# createYAML
创建 YAML 文件,并以 data
作为写入数据。
# loadYAML
读取 YAML 文件,返回 Object (opens new window) 类型数据。
# writeYAML
覆盖写入 YAML 文件。
# updateYAML
更新 YAML 文件。index
作为数据索引,将索引到的位置修改为 data
。
# BasicRenderer
Adachi-BOT
使用了 puppeteer
作为图片截图渲染工具,并简单封装了一些常用方法。
interface RenderSuccess {
code: "ok";
data: string;
}
interface RenderError {
code: "error";
error: string;
}
export type RenderResult = RenderSuccess | RenderError;
export interface PageFunction {
(page: puppeteer.Page): Promise<Buffer | string | void>
}
export interface RendererMethods {
asBase64(route: string, params?: Record<string, any>, viewPort?: puppeteer.Viewport | null, selector?: string): Promise<RenderResult>;
asCqCode(route: string, params?: Record<string, any>, viewPort?: puppeteer.Viewport | null, selector?: string): Promise<RenderResult>;
asForFunction(route: string, pageFunction: PageFunction, viewPort?: puppeteer.Viewport | null, params?: Record<string, any>): Promise<RenderResult>;
}
export interface RenderMethods {
register(name: string, route: string, port: number, defaultSelector: string): Renderer;
/* 浏览器相关 */
closeBrowser(): Promise<void>;
launchBrowser(): Promise<puppeteer.Browser>;
restartBrowser(): Promise<void>;
refresh(): Promise<string>;
/* 截图 */
screenshot(url: string, viewPort: puppeteer.Viewport | null, selector: string): Promise<string>;
screenshotForFunction(url: string, viewPort: puppeteer.Viewport | null, pageFunction: PageFunction): Promise<string>
}
# RenderSuccess
成功截图返回的数据格式。
# RenderError
截图失败返回的数据格式
# RenderResult
截图返回的数据格式(成功或失败)
# PageFunction
手动自行编写 puppeteer
执行逻辑方法,来自行编写逻辑获取截图或其他你想借用 Puppeteer
进行的操作,接受一个 puppeteer
的 页面 page
对象,返回的数据将直接赋值给 RenderSuccess
中的 data
属性。
# ScreenshotRendererMethods
截图并将截图渲染成各种格式的方法集合,渲染类 Renderer
的实现了该接口。
# asBase64
跳转打开一个指定的网页链接且传递相应参数,并对指定选择器截图,返回 base64
的图片格式。参数如下
router
: 要打开的网页路径(相对/绝对)params
: 将会被转为合法的 URL 参数字符串paramStr
。viewPort
: 浏览器设备参数,不传则不设置设备参数。selector
: 用于选择截图目标的 css 选择器,默认为Renderer
实例创建时传入的默认选择器。
当 router
为一个合法 URL 时,将直接使用 router
拼接 paramStr
生成链接地址。反正将 router
和 paramStr
与 Renderer
实例的默认本地路径 httpBase
拼接。
# asCqCode
跳转打开一个指定的网页链接且传递相应参数,并对指定选择器截图,返回可直接发送的 [CQ]
消息格式。参数于方法 asBase64
相同。
# asForFunction
跳转打开一个指定的网页链接且传递相应参数,并执行自定义的 Puppeteer
执行逻辑方法。route
、viewPort
与 params
参数同上,pageFunction
即 PageFunction
类型的自定义处理方法。
# RenderMethods
Adachi-BOT
使用了 Puppeteer
作为截图渲染工具并简单的封装了一些常用方法。
# register
注册获取一个渲染实例,该实例实现了 ScreenshotRendererMethods
接口,可使用接口内的图片渲染方法。参数如下
- name: 渲染实例名称,暂时无用
- route: 渲染实力的基础路由
- port: 渲染实例的本地路径的端口号
- defaultSelector: 渲染实例的默认选择器
port
和 route
将生成渲染实例的默认本地路径 httpBase
,即 http://localhost:${ port }${ route }
。
# closeBrowser
关闭所有页面并销毁当前打开的浏览器。
# launchBrowser
启动浏览器,若当前已存在启动的浏览器则抛出错误信息:浏览器已经启动。
# restartBrowser
关闭所有页面并销毁当前打开的浏览器后重启浏览器,并重置当前截图次数。
# screenshot
打开指定 url
的网址,通过 viewPort
来设置页面参数,并对指定的 css 选择器 selector
所选中的元素进行截图,返回截图所得图片的 base64
格式。
# screenshotForFunction
打开指定 url
的网址,通过 viewPort
来设置页面参数,并执行自定义的 PageFunction
类型的自定义处理方法,抛出经过 toString
处理的该方法返回的数据。
# Authorization
权限管理方法。
interface AuthorizationMethod {
set(userID: number, level: AuthLevel): Promise<void>;
get(userID: number): Promise<AuthLevel>;
check(userID: number, limit: AuthLevel): Promise<boolean>;
}
# MsgManagement
消息管理方法。
interface MsgManagementMethod {
getSendMessageFunc(userID: number, type: MessageType, groupID?: number): SendFunc;
sendMaster(content: string): Promise<void>;
}
# RefreshConfig
可热更新的配置文件类,用于定义配置文件的热更新方法。
interface RefreshCatch {
log: string;
msg: string;
}
type RefreshTarget =
{ [key: string]: any } &
{ refresh(): Promise<string> };
interface RefreshConfigMethod {
registerRefreshableFile(
fileName: string, target: RefreshTarget, place?: PresetPlace
): void;
registerRefreshableFunc(target: RefreshTarget): void;
}
# RefreshCatch
刷新时错误返回类型。在出现错误时需 throw
一个该类型的对象。
# RefreshTarget
配置文件类。我们要求你使用类来定义配置文件,且类中必须包含返回值为 Promise<string> (opens new window)
的公有函数 refresh
。下面以 Cookies
为例,介绍书写的格式:
class Cookies {
private index: number;
private cookies: string[];
private length: number;
constructor() {
this.cookies = bot.file.loadYAML("cookies").cookies;
this.index = 0;
this.length = this.cookies.length;
}
public async refresh(): Promise<string> {
try {
this.cookies = bot.file.loadYAML("cookies").cookies;
this.index = 0;
this.length = this.cookies.length;
return "cookies 重新加载完毕";
} catch (error) {
throw <RefreshCatch>{
log: (<Error>error).stack,
msg: "cookies 重新加载失败,请前往控制台查看日志"
};
}
}
}
# registerRefreshableFile
作用
注册一个可刷新的配置文件,当 BOT 持有者使用 adachi.refresh
指令时,重新读取所有被注册的文件。
参数列表
fileName
注册的配置文件的文件名target
实现RefreshTarget
接口的类的实例对象,如new Cookies()
place
可选参数,见 PresetPlace
# registerRefreshableFunc
作用
注册一个可刷新的对象,当 BOT 持有者使用 adachi.refresh
指令时,重新加载该对象。
参数列表
target
实现RefreshTarget
接口的类的实例对象,如new Cookies()
# Path Alias
Adachi-BOT
设有三个路径别名
@
->./src/
#
->./src/plugins/
ROOT
->app.ts
导入路径名应尽可能简洁,并尽量避免多层 ../
的出现。对于文件 A.ts
:
- 若
B.ts
与A.ts
处于同级目录或B.ts
在A.ts
的同级文件夹的子级目录中,则应该使用./
来引用 - 若
B.ts
在A.ts
的祖级目录中,则应该使用@
或#
来引用