-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
197 lines (186 loc) · 6.09 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import { Client, createClient, LogLevel, Platform } from "icqq";
import yaml from "js-yaml";
import fs from "fs/promises";
import { readFileSync } from "fs";
import path from "path";
import common from "./common.js";
import eventHandler from "./dealEvent.js"
import { Init } from "./init.js";
import { BotConf, createConfig } from "./config.js";
const _path = process.cwd();
/**
*
*
* @interface ConfigContantable Config文件基类
*/
interface ConfigContantable {
platform: undefined | Platform;
log_level: undefined | LogLevel;
resend: undefined | boolean;
Master: undefined | string[] | number[];
Waiter: undefined | number;
Blacks: {
user: any;
group: any;
}
PluginConfig: any;
}
/**
*
*
* @interface botConfig 包含账号和密码,用于和自行构建区分
* @extends {ConfigContantable}
*/
export interface botConfig extends ConfigContantable {
account: number;
pwd: string;
}
/**
*
*
* @interface simpleConfig 自行构建设置
* @extends {ConfigContantable}
*/
export interface simpleConfig extends ConfigContantable {
}
/**
* ConfigFile类用于处理机器人配置文件的读取和设置。
* 支持的配置文件格式为yaml。
*/
export class ConfigFile {
confPath: string; // 配置文件路径
Clients: Map<number, botConfig> = new Map<number, botConfig>(); // 存储各个机器人实例的配置
DefaultConfig: botConfig; // 默认配置
private configObj: any; // 存储整个配置文件对象
/**
* ConfigFile类的构造函数。
* @param {string} [filepath] 配置文件路径,如果未提供,则默认为当前路径下的config.yaml
* @memberof ConfigFile
*/
constructor(filepath?: string) {
this.confPath = filepath ?? path.join(_path, "config.yaml");
const settings: any = yaml.load(readFileSync(this.confPath, "utf-8"));
this.Clients = new Map(settings.Clients.map((client: botConfig) => [client.account, client]));
this.DefaultConfig = settings.DefaultSettings;
this.configObj = settings;
}
/**
* setConf用于设置特定机器人实例的配置项,通常用于主人通过消息管理机器人设置
* @param {number} account 机器人实例的qq号码,用于确认所设置机器人实例
* @param {simpleConfig} settings 配置项,需参考interface ConfigContantable构建,不建议在这里设置account和pwd
* @returns 返回更新后的机器人实例配置
* @memberof ConfigFile
*/
async setConf(account: number, settings: simpleConfig) {
console.log(Object.assign({}, this.Clients.get(account), settings));
const conf = Object.assign({}, this.configObj, { Clients: Array.from(this.Clients.values()) });
this.configObj = conf;
fs.writeFile("./config.yaml", yaml.dump(conf)).catch(() => console.log("配置文件保存失败,重启后将恢复原始设置"));
return this.Clients.get(account);
};
}
/**
* Bot类表示一个聊天机器人实例,用于与用户进行对话。
* @class Bot
*/
export class Bot {
/**
* Bot的配置对象
* @property {botConfig} Config - 包含Bot的配置信息的对象
*/
Config: botConfig;
/**
* Bot的自身账户的ID
* @property {number} self - Bot的账户ID
*/
self: number;
/**
* Bot的客户端实例对象
* @property {Client} Client - 表示Bot客户端实例的对象
*/
Client: Client;
/**
* 创建一个新的Bot实例
* @param {botConfig} Config - Bot的配置信息
* @constructor
*/
constructor(Config: botConfig) {
this.Config = Config;
this.self = Config.account;
// 创建一个基于配置信息的客户端实例
this.Client = createClient({
log_level: this.Config.log_level ?? "info",
platform: this.Config.platform ?? 3,
resend: this.Config.resend,
data_dir: path.join(_path, "data", this.Config.account.toString() + "_data"),
});
}
}
createConfig();
const createBot = (Config: botConfig) => new Bot(Config);
export let BotsMap: Map<string | number, Bot> = new Map();
BotConf.Clients.forEach(botSettings => BotsMap.set(botSettings.account, createBot(botSettings)));
BotsMap.forEach(bot => {
bot.Client.on("system.login.slider", function () {
const self = this;
this.logger.mark(bot.self, "请输入获取的ticket,按回车完成滑动验证");
process.stdin.once("data", (input) => {
this.submitSlider(input.toString());
});
})
bot.Client.on("system.login.error", function (e) {
if (e.code == 1) this.logger.error(bot.self, "密码错误,请修改密码重试");
process.exit();
});
bot.Client.on("system.login.device", function (e) {
this.logger.mark('请选择验证方式:(1:短信验证 其他:扫码验证)');
process.stdin.once("data", (data) => {
if (data.toString().trim() === '1') {
this.sendSmsCode();
this.logger.mark('请输入手机收到的短信验证码:');
process.stdin.once('data', (res) => {
this.submitSmsCode(res.toString().trim());
})
} else {
this.logger.mark('扫码完成后回车继续:' + e.url);
process.stdin.once('data', () => {
this.login();
})
}
});
});
bot.Client.on("system.online", function () {
Init().catch(err => {
this.logger.error(err);
process.exit();
})
})
bot.Client.login(bot.Config.account, bot.Config.pwd);
//后面是消息处理
//监听群消息事件
bot.Client.on("message.group", (event) => {
eventHandler.dealGroupMsg(event as any).catch((error) => {
bot.Client.logger.error(error);
});
});
//监听私聊消息事件
bot.Client.on("message.private", (event) => {
eventHandler.dealPrivateMsg(event as any).catch((error) => {
bot.Client.logger.error(error);
});
});
//监听好友事件
bot.Client.on("request.friend", (event) => {
eventHandler.dealFriendRequest(event);
});
//监听群通知
bot.Client.on("notice.group", (event) => {
eventHandler.dealGroupNotice(event).catch((error) => {
bot.Client.logger.error(error);
});
});
//监听群事件
bot.Client.on("request.group", (event) => {
eventHandler.dealGroupRequest(event);
});
});