feat: 新的好友发送消息时自动创建新的 tg 群组

This commit is contained in:
Clansty 2022-03-01 21:11:14 +08:00
parent 334aa46375
commit ffdfc90b96
No known key found for this signature in database
GPG Key ID: 05F8479BA63A8E92
4 changed files with 68 additions and 25 deletions

View File

@ -1,5 +1,5 @@
import { Client, LogLevel, Platform } from 'oicq';
import * as Buffer from 'buffer';
import { Client, DiscussMessageEvent, GroupMessageEvent, LogLevel, Platform, PrivateMessageEvent } from 'oicq';
import Buffer from 'buffer';
import { execSync } from 'child_process';
import random from '../utils/random';
import fs from 'fs';
@ -9,6 +9,8 @@ import { Config } from 'oicq/lib/client';
const LOG_LEVEL: LogLevel = 'warn';
type MessageHandler = (event: PrivateMessageEvent | GroupMessageEvent) => Promise<boolean | void>
interface CreateOicqParams {
uin: number;
password: string;
@ -23,6 +25,8 @@ interface CreateOicqParams {
// OicqExtended??
export default class OicqClient extends Client {
private readonly onMessageHandlers: Array<MessageHandler> = [];
private constructor(uin: number, conf?: Config) {
super(uin, conf);
}
@ -59,7 +63,8 @@ export default class OicqClient extends Client {
.off('system.login.slider', loginSliderHandler)
.off('system.login.qrcode', loginQrCodeHandler)
.off('system.login.error', loginErrorHandler)
.off('system.online', successLoginHandler);
.off('system.online', successLoginHandler)
.on('message', client.onMessage);
resolve(client);
}
@ -73,8 +78,8 @@ export default class OicqClient extends Client {
board: 'raincandy',
brand: random.pick('GOOGLE', 'XIAOMI', 'HUAWEI', 'SAMSUNG', 'SONY'),
model: 'raincandy',
wifi_ssid: random.pick('OpenWrt', `Redmi-${random.hex(4)}`,
`MiWifi-${random.hex(4)}`, `TP-LINK-${random.hex(6)}`),
wifi_ssid: random.pick('OpenWrt', `Redmi-${random.hex(4).toUpperCase()}`,
`MiWifi-${random.hex(4).toUpperCase()}`, `TP-LINK-${random.hex(6).toUpperCase()}`),
bootloader: random.pick('U-Boot', 'GRUB', 'gummiboot'),
android_id: random.hex(16),
proc_version: `${execSync('uname -s').toString().replace('\n', '')} version ${execSync('uname -r').toString().replace('\n', '')}`,
@ -90,7 +95,7 @@ export default class OicqClient extends Client {
const client = new this(params.uin, {
platform: params.platform,
data_dir: path.resolve('./data'),
log_level: 'warn',
log_level: LOG_LEVEL,
})
.on('system.login.device', loginDeviceHandler)
.on('system.login.slider', loginSliderHandler)
@ -101,6 +106,23 @@ export default class OicqClient extends Client {
});
}
private onMessage = async (event: PrivateMessageEvent | GroupMessageEvent | DiscussMessageEvent) => {
if (event.message_type === 'discuss') return;
for (const handler of this.onMessageHandlers) {
const res = await handler(event);
if (res) return;
}
};
public addNewMessageEventHandler(handler: MessageHandler) {
this.onMessageHandlers.push(handler);
}
public removeNewMessageEventHandler(handler: MessageHandler) {
this.onMessageHandlers.includes(handler) &&
this.onMessageHandlers.splice(this.onMessageHandlers.indexOf(handler), 1);
}
public getChat(roomId: number) {
if (roomId > 0) {
return this.pickFriend(roomId);

View File

@ -5,9 +5,11 @@ import ConfigService from '../services/ConfigService';
import { config } from '../providers/userConfig';
import regExps from '../constants/regExps';
import forwardPairs from '../providers/forwardPairs';
import { GroupMessageEvent, PrivateMessageEvent } from 'oicq';
export default class ConfigController {
private readonly configService: ConfigService;
private readonly createPrivateMessageGroupBlockList = new Map<number, Promise<void>>();
constructor(private readonly tgBot: Telegram,
private readonly tgUser: Telegram,
@ -15,6 +17,7 @@ export default class ConfigController {
this.configService = new ConfigService(tgBot, tgUser, oicq);
tgBot.addNewMessageEventHandler(this.handleMessage);
tgBot.addNewServiceMessageEventHandler(this.handleServiceMessage);
oicq.addNewMessageEventHandler(this.handleQqMessage);
this.configService.configCommands();
config.workMode === 'personal' && this.configService.setupFilter();
}
@ -69,4 +72,21 @@ export default class ConfigController {
pair.tg = await this.tgBot.getChat(message.action.channelId);
}
};
private handleQqMessage = async (message: GroupMessageEvent | PrivateMessageEvent) => {
if (message.message_type !== 'private') return false;
const pair = forwardPairs.find(message.friend);
if (pair) return false;
// 如果正在创建中,应该阻塞
let promise = this.createPrivateMessageGroupBlockList.get(message.from_id);
if (promise) {
await promise;
return false;
}
// 有未创建转发群的新私聊消息时自动创建
promise = this.configService.createGroupAndLink(message.from_id, message.friend.remark || message.friend.nickname, true);
this.createPrivateMessageGroupBlockList.set(message.from_id, promise);
await promise;
return false;
};
}

View File

@ -2,7 +2,7 @@ import Telegram from '../client/Telegram';
import OicqClient from '../client/OicqClient';
import ForwardService from '../services/ForwardService';
import forwardPairs from '../providers/forwardPairs';
import { DiscussMessageEvent, Friend, Group, GroupMessageEvent, PrivateMessageEvent } from 'oicq';
import { Friend, Group, GroupMessageEvent, PrivateMessageEvent } from 'oicq';
import db from '../providers/db';
import helper from '../helpers/forwardHelper';
import { Api } from 'telegram';
@ -15,19 +15,18 @@ export default class ForwardController {
private readonly oicq: OicqClient) {
this.forwardService = new ForwardService(tgBot, oicq);
forwardPairs.init(oicq, tgBot)
.then(() => oicq.on('message', this.onQqMessage))
.then(() => oicq.addNewMessageEventHandler(this.onQqMessage))
.then(() => tgBot.addNewMessageEventHandler(this.onTelegramMessage));
}
private onQqMessage = async (event: PrivateMessageEvent | GroupMessageEvent | DiscussMessageEvent) => {
private onQqMessage = async (event: PrivateMessageEvent | GroupMessageEvent) => {
let target: Friend | Group;
if (event.message_type === 'private') {
target = event.friend;
}
else if (event.message_type === 'group') {
else {
target = event.group;
}
else return;
const pair = forwardPairs.find(target);
if (!pair) return;
const tgMessage = await this.forwardService.forwardFromQq(event, pair);

View File

@ -109,7 +109,7 @@ export default class ConfigService {
// endregion
private async createGroupAndLink(roomId: number, title?: string) {
public async createGroupAndLink(roomId: number, title?: string, silent = false) {
this.log.info(`创建群组并关联:${roomId}`);
const qEntity = this.oicq.getChat(roomId);
if (!title) {
@ -124,7 +124,7 @@ export default class ConfigService {
let isFinish = false;
try {
// 状态信息
const status = await (await this.owner).sendMessage('正在创建 Telegram 群…');
const status = !silent && await (await this.owner).sendMessage('正在创建 Telegram 群…');
// 创建群聊,拿到的是 user 的 chat
const chat = await this.tgUser.createChat({
@ -133,12 +133,12 @@ export default class ConfigService {
});
// 设置管理员
await status.edit({ text: '正在设置管理员…' });
status && await status.edit({ text: '正在设置管理员…' });
await chat.editAdmin(this.tgBot.me.username, true);
const chatForBot = await this.tgBot.getChat(chat.id);
// 添加到 Filter
await status.edit({ text: '正在将群添加到文件夹…' });
status && await status.edit({ text: '正在将群添加到文件夹…' });
this.filter.includePeers.push(utils.getInputPeer(chat));
await this.tgUser.updateDialogFilter({
id: this.filter.id,
@ -146,16 +146,16 @@ export default class ConfigService {
});
// 关闭【添加成员】快捷条
await status.edit({ text: '正在关闭【添加成员】快捷条…' });
status && await status.edit({ text: '正在关闭【添加成员】快捷条…' });
await chat.hidePeerSettingsBar();
// 关联写入数据库
await status.edit({ text: '正在写数据库…' });
status && await status.edit({ text: '正在写数据库…' });
const dbPair = await forwardPairs.add(qEntity, chatForBot);
isFinish = true;
// 更新头像
await status.edit({ text: '正在更新头像…' });
status && await status.edit({ text: '正在更新头像…' });
const avatar = await getAvatar(roomId);
const avatarHash = md5B64(avatar);
await chatForBot.setProfilePhoto(avatar);
@ -164,16 +164,18 @@ export default class ConfigService {
});
// 更新关于文本
await status.edit({ text: '正在更新关于文本…' });
status && await status.edit({ text: '正在更新关于文本…' });
await chatForBot.editAbout(await this.getAboutText(qEntity));
// 完成
await status.edit({ text: '正在获取链接…' });
const { link } = await chat.getInviteLink();
await status.edit({
text: '创建完成!',
buttons: Button.url('打开', link),
});
if (status) {
await status.edit({ text: '正在获取链接…' });
const { link } = await chat.getInviteLink();
await status.edit({
text: '创建完成!',
buttons: Button.url('打开', link),
});
}
}
catch (e) {
this.log.error('创建群组并关联失败', e);