diff --git a/src/client/OicqClient.ts b/src/client/OicqClient.ts index e552cbb..22e537c 100644 --- a/src/client/OicqClient.ts +++ b/src/client/OicqClient.ts @@ -15,7 +15,7 @@ interface CreateOicqParams { uin: number; password: string; platform: Platform; - // 当需要验证手机时调用此方法,应该返回收到当手机验证码 + // 当需要验证手机时调用此方法,应该返回收到的手机验证码 onVerifyDevice: (phone: string) => Promise; // 当滑块时调用此方法,返回 ticker,也可以返回假值改用扫码登录 onVerifySlider: (url: string) => Promise; diff --git a/src/controllers/ConfigController.ts b/src/controllers/ConfigController.ts index d67a081..ca4c38c 100644 --- a/src/controllers/ConfigController.ts +++ b/src/controllers/ConfigController.ts @@ -3,7 +3,6 @@ import Telegram from '../client/Telegram'; import OicqClient from '../client/OicqClient'; import ConfigService from '../services/ConfigService'; import regExps from '../constants/regExps'; -import forwardPairs from '../models/forwardPairs'; import { GroupMessageEvent, MemberIncreaseEvent, PrivateMessageEvent } from 'oicq'; import Instance from '../models/Instance'; @@ -73,7 +72,7 @@ export default class ConfigController { private handleServiceMessage = async (message: Api.MessageService) => { // 用于检测群升级为超级群的情况 if (message.action instanceof Api.MessageActionChatMigrateTo) { - const pair = forwardPairs.find((message.peerId as Api.PeerChat).chatId); + const pair = this.instance.forwardPairs.find((message.peerId as Api.PeerChat).chatId); if (!pair) return; // 会自动写入数据库 pair.tg = await this.tgBot.getChat(message.action.channelId); @@ -93,7 +92,7 @@ export default class ConfigController { private handleQqMessage = async (message: GroupMessageEvent | PrivateMessageEvent) => { if (message.message_type !== 'private') return false; - const pair = forwardPairs.find(message.friend); + const pair = this.instance.forwardPairs.find(message.friend); if (pair) return false; // 如果正在创建中,应该阻塞 let promise = this.createPrivateMessageGroupBlockList.get(message.from_id); @@ -109,7 +108,7 @@ export default class ConfigController { }; private handleMemberIncrease = async (event: MemberIncreaseEvent) => { - if (event.user_id !== this.oicq.uin || await forwardPairs.find(event.group)) return; + if (event.user_id !== this.oicq.uin || await this.instance.forwardPairs.find(event.group)) return; // 是新群并且是自己加入了 await this.configService.promptNewGroup(event.group); }; diff --git a/src/controllers/DeleteMessageController.ts b/src/controllers/DeleteMessageController.ts index 81f3220..e9b2425 100644 --- a/src/controllers/DeleteMessageController.ts +++ b/src/controllers/DeleteMessageController.ts @@ -3,7 +3,6 @@ import { getLogger } from 'log4js'; import Telegram from '../client/Telegram'; import OicqClient from '../client/OicqClient'; import { Api } from 'telegram'; -import forwardPairs from '../models/forwardPairs'; import { FriendRecallEvent, GroupRecallEvent } from 'oicq'; import { DeletedMessageEvent } from 'telegram/events/DeletedMessage'; import Instance from '../models/Instance'; @@ -25,7 +24,7 @@ export default class DeleteMessageController { } private onTelegramMessage = async (message: Api.Message) => { - const pair = forwardPairs.find(message.chat); + const pair = this.instance.forwardPairs.find(message.chat); if (!pair) return false; // TODO: 可以做成 DeleteMessageController 之类 if (message.message?.startsWith('/rm')) { @@ -36,25 +35,25 @@ export default class DeleteMessageController { }; private onTelegramEditMessage = async (message: Api.Message) => { - const pair = forwardPairs.find(message.chat); + const pair = this.instance.forwardPairs.find(message.chat); if (!pair) return; await this.deleteMessageService.telegramDeleteMessage(message.id, pair); return await this.onTelegramMessage(message); }; private onQqFriendRecall = async (event: FriendRecallEvent) => { - const pair = forwardPairs.find(event.friend); + const pair = this.instance.forwardPairs.find(event.friend); await this.deleteMessageService.handleQqRecall(event, pair); }; private onQqGroupRecall = async (event: GroupRecallEvent) => { - const pair = forwardPairs.find(event.group); + const pair = this.instance.forwardPairs.find(event.group); await this.deleteMessageService.handleQqRecall(event, pair); }; private onTgDeletedMessage = async (event: DeletedMessageEvent) => { if (!(event.peer instanceof Api.PeerChannel)) return; - const pair = forwardPairs.find(event.peer.channelId); + const pair = this.instance.forwardPairs.find(event.peer.channelId); if (!pair) return; for (const messageId of event.deletedIds) { await this.deleteMessageService.telegramDeleteMessage(messageId, pair); diff --git a/src/controllers/ForwardController.ts b/src/controllers/ForwardController.ts index 29e84e4..8e32052 100644 --- a/src/controllers/ForwardController.ts +++ b/src/controllers/ForwardController.ts @@ -1,7 +1,6 @@ import Telegram from '../client/Telegram'; import OicqClient from '../client/OicqClient'; import ForwardService from '../services/ForwardService'; -import forwardPairs from '../models/forwardPairs'; import { GroupMessageEvent, PrivateMessageEvent } from 'oicq'; import db from '../models/db'; import { Api } from 'telegram'; @@ -17,16 +16,15 @@ export default class ForwardController { private readonly tgUser: Telegram, private readonly oicq: OicqClient) { this.forwardService = new ForwardService(this.instance, tgBot, oicq); - forwardPairs.init(oicq, tgBot) - .then(() => oicq.addNewMessageEventHandler(this.onQqMessage)) - .then(() => tgBot.addNewMessageEventHandler(this.onTelegramMessage)) - .then(() => tgBot.addEditedMessageEventHandler(this.onTelegramMessage)); + oicq.addNewMessageEventHandler(this.onQqMessage); + tgBot.addNewMessageEventHandler(this.onTelegramMessage); + tgBot.addEditedMessageEventHandler(this.onTelegramMessage); } private onQqMessage = async (event: PrivateMessageEvent | GroupMessageEvent) => { try { const target = event.message_type === 'private' ? event.friend : event.group; - const pair = forwardPairs.find(target); + const pair = this.instance.forwardPairs.find(target); if (!pair) return; const tgMessage = await this.forwardService.forwardFromQq(event, pair); if (tgMessage) { @@ -53,7 +51,7 @@ export default class ForwardController { private onTelegramMessage = async (message: Api.Message) => { try { - const pair = forwardPairs.find(message.chat); + const pair = this.instance.forwardPairs.find(message.chat); if (!pair) return false; const qqMessageSent = await this.forwardService.forwardFromTelegram(message, pair); // 返回的信息不太够 diff --git a/src/models/forwardPairs.ts b/src/models/ForwardPairs.ts similarity index 64% rename from src/models/forwardPairs.ts rename to src/models/ForwardPairs.ts index 7c3e69d..95acc76 100644 --- a/src/models/forwardPairs.ts +++ b/src/models/ForwardPairs.ts @@ -4,45 +4,21 @@ import OicqClient from '../client/OicqClient'; import Telegram from '../client/Telegram'; import db from './db'; import { Entity } from 'telegram/define'; -import { getLogger } from 'log4js'; import { BigInteger } from 'big-integer'; +import { Pair } from './Pair'; -const log = getLogger('ForwardPairs'); -export class Pair { - constructor(public readonly qq: Friend | Group, - private _tg: TelegramChat, - public dbId: number) { - } - - get qqRoomId() { - return this.qq instanceof Friend ? this.qq.user_id : -this.qq.group_id; - } - - get tgId() { - return Number(this._tg.id); - } - - get tg() { - return this._tg; - } - - set tg(value: TelegramChat) { - this._tg = value; - db.forwardPair.update({ - where: { id: this.dbId }, - data: { tgChatId: Number(value.id) }, - }) - .then(() => log.info(`出现了到超级群组的转换: ${value.id}`)); - } -} - -class ForwardPairsInternal { +export default class ForwardPairs { private pairs: Pair[] = []; + private constructor(private readonly instanceId: number) { + } + // 在 forwardController 创建时初始化 - public async init(oicq: OicqClient, tgBot: Telegram) { - const dbValues = await db.forwardPair.findMany(); + private async init(oicq: OicqClient, tgBot: Telegram) { + const dbValues = await db.forwardPair.findMany({ + where: { instanceId: this.instanceId }, + }); for (const i of dbValues) { this.pairs.push(new Pair( oicq.getChat(Number(i.qqRoomId)), @@ -52,11 +28,18 @@ class ForwardPairsInternal { } } + public static async load(instanceId: number, oicq: OicqClient, tgBot: Telegram) { + const instance = new this(instanceId); + await instance.init(oicq, tgBot); + return instance; + } + public async add(qq: Friend | Group, tg: TelegramChat) { const dbEntry = await db.forwardPair.create({ data: { qqRoomId: qq instanceof Friend ? qq.user_id : -qq.group_id, tgChatId: Number(tg.id), + instanceId: this.instanceId, }, }); this.pairs.push(new Pair(qq, tg, dbEntry.id)); @@ -79,5 +62,3 @@ class ForwardPairsInternal { } } } - -export default new ForwardPairsInternal(); diff --git a/src/models/Instance.ts b/src/models/Instance.ts index 3656cca..a5f0c0b 100644 --- a/src/models/Instance.ts +++ b/src/models/Instance.ts @@ -9,6 +9,7 @@ import FileAndFlashPhotoController from '../controllers/FileAndFlashPhotoControl import Telegram from '../client/Telegram'; import OicqClient from '../client/OicqClient'; import { getLogger, Logger } from 'log4js'; +import ForwardPairs from './ForwardPairs'; export default class Instance { private _owner = 0; @@ -17,9 +18,11 @@ export default class Instance { private _qqPlatform = 0; private _isSetup = false; private _workMode = ''; + private _botToken = ''; private readonly log: Logger; + public forwardPairs: ForwardPairs; private setupController: SetupController; private configController: ConfigController; private deleteMessageController: DeleteMessageController; @@ -53,12 +56,13 @@ export default class Instance { this._qqPlatform = dbEntry.qqPlatform; this._isSetup = dbEntry.isSetup; this._workMode = dbEntry.workMode; + this._botToken = dbEntry.botToken; } private async init() { this.log.debug('正在登录 TG Bot'); const tgBot = await Telegram.create({ - botAuthToken: process.env.TG_BOT_TOKEN, + botAuthToken: this.botToken, }, 'bot'); let tgUser: Telegram, oicq: OicqClient; @@ -83,6 +87,7 @@ export default class Instance { }); this.log.debug('OICQ 登录完成'); } + this.forwardPairs = await ForwardPairs.load(this.id, oicq, tgBot); this.configController = new ConfigController(this, tgBot, tgUser, oicq); this.deleteMessageController = new DeleteMessageController(this, tgBot, tgUser, oicq); this.forwardController = new ForwardController(this, tgBot, tgUser, oicq); @@ -96,6 +101,13 @@ export default class Instance { return instance; } + public static async createNew(botToken: string) { + const dbEntry = await db.instance.create({ + data: { botToken }, + }); + return await this.start(dbEntry.id); + } + get owner() { return this._owner; } @@ -120,6 +132,10 @@ export default class Instance { return this._workMode as WorkMode; } + get botToken() { + return this.id === 0 ? process.env.TG_BOT_TOKEN : this._botToken; + } + set owner(owner: number) { this._owner = owner; db.instance.update({ diff --git a/src/models/Pair.ts b/src/models/Pair.ts new file mode 100644 index 0000000..4c75ddd --- /dev/null +++ b/src/models/Pair.ts @@ -0,0 +1,34 @@ +import { Friend, Group } from 'oicq'; +import TelegramChat from '../client/TelegramChat'; +import db from './db'; +import { getLogger } from 'log4js'; + +const log = getLogger('ForwardPairs'); + +export class Pair { + constructor(public readonly qq: Friend | Group, + private _tg: TelegramChat, + public dbId: number) { + } + + get qqRoomId() { + return this.qq instanceof Friend ? this.qq.user_id : -this.qq.group_id; + } + + get tgId() { + return Number(this._tg.id); + } + + get tg() { + return this._tg; + } + + set tg(value: TelegramChat) { + this._tg = value; + db.forwardPair.update({ + where: { id: this.dbId }, + data: { tgChatId: Number(value.id) }, + }) + .then(() => log.info(`出现了到超级群组的转换: ${value.id}`)); + } +} diff --git a/src/services/ConfigService.ts b/src/services/ConfigService.ts index 65f4e2f..88122c9 100644 --- a/src/services/ConfigService.ts +++ b/src/services/ConfigService.ts @@ -10,7 +10,6 @@ import commands from '../constants/commands'; import OicqClient from '../client/OicqClient'; import { md5 } from '../utils/hashing'; import TelegramChat from '../client/TelegramChat'; -import forwardPairs from '../models/forwardPairs'; import Instance from '../models/Instance'; const DEFAULT_FILTER_ID = 114; // 514 @@ -45,7 +44,7 @@ export default class ConfigService { // 开始添加转发群组流程 public async addGroup() { const qGroups = Array.from(this.oicq.gl).map(e => e[1]) - .filter(it => !forwardPairs.find(-it.group_id)); + .filter(it => !this.instance.forwardPairs.find(-it.group_id)); const buttons = qGroups.map(e => this.instance.workMode === 'personal' ? [Button.inline( @@ -83,7 +82,7 @@ export default class ConfigService { } private async openFriendSelection(clazz: FriendInfo[], name: string) { - clazz = clazz.filter(them => !forwardPairs.find(them.user_id)); + clazz = clazz.filter(them => !this.instance.forwardPairs.find(them.user_id)); await (await this.owner).createPaginatedInlineSelector(`选择 QQ 好友\n分组:${name}`, clazz.map(e => [ Button.inline(`${e.remark || e.nickname} (${e.user_id})`, this.tgBot.registerCallback( () => this.createGroupAndLink(e.user_id, e.remark || e.nickname), @@ -179,7 +178,7 @@ export default class ConfigService { // 关联写入数据库 const chatForBot = await this.tgBot.getChat(chat.id); status && await status.edit({ text: '正在写数据库…' }); - const dbPair = await forwardPairs.add(qEntity, chatForBot); + const dbPair = await this.instance.forwardPairs.add(qEntity, chatForBot); isFinish = true; // 更新头像 @@ -227,7 +226,7 @@ export default class ConfigService { const tgChat = await this.tgBot.getChat(tgChatId); message = `QQ群:${qGroup.group_id} (${qGroup.group_id})已与 ` + `Telegram 群 ${(tgChat.entity as Api.Channel).title} (${tgChatId})关联`; - await forwardPairs.add(qGroup, tgChat); + await this.instance.forwardPairs.add(qGroup, tgChat); } catch (e) { message = `错误:${e}`; diff --git a/src/services/DeleteMessageService.ts b/src/services/DeleteMessageService.ts index 65c2d52..3bc03da 100644 --- a/src/services/DeleteMessageService.ts +++ b/src/services/DeleteMessageService.ts @@ -2,10 +2,10 @@ import Telegram from '../client/Telegram'; import OicqClient from '../client/OicqClient'; import { getLogger } from 'log4js'; import { Api } from 'telegram'; -import { Pair } from '../models/forwardPairs'; import db from '../models/db'; import { Friend, FriendRecallEvent, GroupRecallEvent } from 'oicq'; import Instance from '../models/Instance'; +import { Pair } from '../models/Pair'; export default class DeleteMessageService { private log = getLogger('DeleteMessageService'); diff --git a/src/services/ForwardService.ts b/src/services/ForwardService.ts index 5520805..3c5cf80 100644 --- a/src/services/ForwardService.ts +++ b/src/services/ForwardService.ts @@ -1,7 +1,6 @@ import Telegram from '../client/Telegram'; import OicqClient from '../client/OicqClient'; import { Group, GroupMessageEvent, PrivateMessageEvent, Quotable, segment, Sendable } from 'oicq'; -import { Pair } from '../models/forwardPairs'; import { fetchFile, getBigFaceUrl, getImageUrlByMd5 } from '../utils/urls'; import { FileLike, MarkupLike } from 'telegram/define'; import { CustomFile } from 'telegram/client/uploads'; @@ -22,6 +21,7 @@ import tgsToGif from '../encoding/tgsToGif'; import axios from 'axios'; import { md5Hex } from '../utils/hashing'; import Instance from '../models/Instance'; +import { Pair } from '../models/Pair'; // noinspection FallThroughInSwitchStatementJS export default class ForwardService {