mirror of https://github.com/Nofated095/Q2TG.git
commit
9b15340ebe
|
@ -75,6 +75,8 @@ model ForwardPair {
|
|||
joinNotice Boolean @default(true)
|
||||
poke Boolean @default(true)
|
||||
enable Boolean @default(true)
|
||||
disableQ2TG Boolean @default(false)
|
||||
disableTG2Q Boolean @default(false)
|
||||
|
||||
@@unique([qqRoomId, instanceId])
|
||||
@@unique([tgChatId, instanceId])
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
import { Api } from 'telegram';
|
||||
import { Api } from "telegram";
|
||||
|
||||
const preSetupCommands = [new Api.BotCommand({
|
||||
command: 'setup',
|
||||
description: '执行初始化配置',
|
||||
})];
|
||||
const preSetupCommands = [
|
||||
new Api.BotCommand({
|
||||
command: "setup",
|
||||
description: "执行初始化配置",
|
||||
}),
|
||||
];
|
||||
|
||||
// 这里的 group 指群组模式,Private 指在与机器人的私聊会话中
|
||||
const groupPrivateCommands = [
|
||||
new Api.BotCommand({
|
||||
command: 'add',
|
||||
description: '添加新的群转发',
|
||||
command: "add",
|
||||
description: "添加新的群转发",
|
||||
}),
|
||||
];
|
||||
|
||||
const personalPrivateCommands = [
|
||||
new Api.BotCommand({
|
||||
command: 'addfriend',
|
||||
description: '添加新的好友转发',
|
||||
command: "addfriend",
|
||||
description: "添加新的好友转发",
|
||||
}),
|
||||
new Api.BotCommand({
|
||||
command: 'addgroup',
|
||||
description: '添加新的群转发',
|
||||
command: "addgroup",
|
||||
description: "添加新的群转发",
|
||||
}),
|
||||
];
|
||||
|
||||
|
@ -28,52 +30,56 @@ const personalPrivateCommands = [
|
|||
const groupPrivateSuperAdminCommands = [
|
||||
...groupPrivateCommands,
|
||||
new Api.BotCommand({
|
||||
command: 'newinstance',
|
||||
description: '创建一个新的转发机器人实例',
|
||||
command: "newinstance",
|
||||
description: "创建一个新的转发机器人实例",
|
||||
}),
|
||||
];
|
||||
|
||||
const personalPrivateSuperAdminCommands = [
|
||||
...personalPrivateCommands,
|
||||
new Api.BotCommand({
|
||||
command: 'newinstance',
|
||||
description: '创建一个新的转发机器人实例',
|
||||
command: "newinstance",
|
||||
description: "创建一个新的转发机器人实例",
|
||||
}),
|
||||
];
|
||||
|
||||
// inChat 表示在关联了的转发群组中的命令
|
||||
const inChatCommands = [
|
||||
new Api.BotCommand({
|
||||
command: 'info',
|
||||
description: '查看本群或选定消息的详情',
|
||||
command: "info",
|
||||
description: "查看本群或选定消息的详情",
|
||||
}),
|
||||
];
|
||||
|
||||
const groupInChatCommands = [
|
||||
...inChatCommands,
|
||||
new Api.BotCommand({
|
||||
command: 'forwardoff',
|
||||
description: '暂停消息转发',
|
||||
command: "forwardoff",
|
||||
description: "暂停消息转发",
|
||||
}),
|
||||
new Api.BotCommand({
|
||||
command: 'forwardon',
|
||||
description: '恢复消息转发',
|
||||
command: "forwardon",
|
||||
description: "恢复消息转发",
|
||||
}),
|
||||
new Api.BotCommand({ command: "disableQQForward", description: "停止从QQ转发至TG" }),
|
||||
new Api.BotCommand({ command: "enableQQForward", description: "恢复从QQ转发至TG" }),
|
||||
new Api.BotCommand({ command: "disableTGForward", description: "停止从TG转发至QQ" }),
|
||||
new Api.BotCommand({ command: "enableTGForward", description: "恢复从TG转发至QQ" }),
|
||||
];
|
||||
|
||||
const personalInChatCommands = [
|
||||
...inChatCommands,
|
||||
new Api.BotCommand({
|
||||
command: 'refresh',
|
||||
description: '刷新头像和简介',
|
||||
command: "refresh",
|
||||
description: "刷新头像和简介",
|
||||
}),
|
||||
new Api.BotCommand({
|
||||
command: 'poke',
|
||||
description: '戳一戳',
|
||||
command: "poke",
|
||||
description: "戳一戳",
|
||||
}),
|
||||
new Api.BotCommand({
|
||||
command: 'nick',
|
||||
description: '获取/设置群名片',
|
||||
command: "nick",
|
||||
description: "获取/设置群名片",
|
||||
}),
|
||||
];
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Telegram from '../client/Telegram';
|
||||
import OicqClient from '../client/OicqClient';
|
||||
import ForwardService from '../services/ForwardService';
|
||||
import Telegram from "../client/Telegram";
|
||||
import OicqClient from "../client/OicqClient";
|
||||
import ForwardService from "../services/ForwardService";
|
||||
import {
|
||||
Friend,
|
||||
FriendPokeEvent,
|
||||
|
@ -8,40 +8,43 @@ import {
|
|||
GroupPokeEvent,
|
||||
MemberIncreaseEvent,
|
||||
PrivateMessageEvent,
|
||||
} from 'oicq';
|
||||
import db from '../models/db';
|
||||
import { Api } from 'telegram';
|
||||
import { getLogger, Logger } from 'log4js';
|
||||
import Instance from '../models/Instance';
|
||||
import { getAvatar } from '../utils/urls';
|
||||
import { CustomFile } from 'telegram/client/uploads';
|
||||
import forwardHelper from '../helpers/forwardHelper';
|
||||
} from "oicq";
|
||||
import db from "../models/db";
|
||||
import { Api } from "telegram";
|
||||
import { getLogger, Logger } from "log4js";
|
||||
import Instance from "../models/Instance";
|
||||
import { getAvatar } from "../utils/urls";
|
||||
import { CustomFile } from "telegram/client/uploads";
|
||||
import forwardHelper from "../helpers/forwardHelper";
|
||||
|
||||
export default class ForwardController {
|
||||
private readonly forwardService: ForwardService;
|
||||
private readonly log: Logger;
|
||||
|
||||
constructor(private readonly instance: Instance,
|
||||
private readonly tgBot: Telegram,
|
||||
private readonly tgUser: Telegram,
|
||||
private readonly oicq: OicqClient) {
|
||||
constructor(
|
||||
private readonly instance: Instance,
|
||||
private readonly tgBot: Telegram,
|
||||
private readonly tgUser: Telegram,
|
||||
private readonly oicq: OicqClient
|
||||
) {
|
||||
this.log = getLogger(`ForwardController - ${instance.id}`);
|
||||
this.forwardService = new ForwardService(this.instance, tgBot, oicq);
|
||||
oicq.addNewMessageEventHandler(this.onQqMessage);
|
||||
oicq.on('notice.group.increase', this.onQqGroupMemberIncrease);
|
||||
oicq.on('notice.friend.poke', this.onQqPoke);
|
||||
oicq.on('notice.group.poke', this.onQqPoke);
|
||||
oicq.on("notice.group.increase", this.onQqGroupMemberIncrease);
|
||||
oicq.on("notice.friend.poke", this.onQqPoke);
|
||||
oicq.on("notice.group.poke", this.onQqPoke);
|
||||
tgBot.addNewMessageEventHandler(this.onTelegramMessage);
|
||||
tgBot.addEditedMessageEventHandler(this.onTelegramMessage);
|
||||
instance.workMode === 'group' && tgBot.addChannelParticipantEventHandler(this.onTelegramParticipant);
|
||||
instance.workMode === "group" && tgBot.addChannelParticipantEventHandler(this.onTelegramParticipant);
|
||||
}
|
||||
|
||||
private onQqMessage = async (event: PrivateMessageEvent | GroupMessageEvent) => {
|
||||
try {
|
||||
const target = event.message_type === 'private' ? event.friend : event.group;
|
||||
const target = event.message_type === "private" ? event.friend : event.group;
|
||||
const pair = this.instance.forwardPairs.find(target);
|
||||
if (!pair) return;
|
||||
if (!pair.enable) return;
|
||||
if (pair.disableQ2TG) return;
|
||||
const tgMessage = await this.forwardService.forwardFromQq(event, pair);
|
||||
if (tgMessage) {
|
||||
// 更新数据库
|
||||
|
@ -60,9 +63,8 @@ export default class ForwardController {
|
|||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
this.log.error('处理 QQ 消息时遇到问题', e);
|
||||
} catch (e) {
|
||||
this.log.error("处理 QQ 消息时遇到问题", e);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -72,6 +74,7 @@ export default class ForwardController {
|
|||
const pair = this.instance.forwardPairs.find(message.chat);
|
||||
if (!pair) return false;
|
||||
if (!pair.enable) return;
|
||||
if (pair.disableTG2Q) return;
|
||||
const qqMessagesSent = await this.forwardService.forwardFromTelegram(message, pair);
|
||||
if (qqMessagesSent) {
|
||||
// 更新数据库
|
||||
|
@ -92,9 +95,8 @@ export default class ForwardController {
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
this.log.error('处理 Telegram 消息时遇到问题', e);
|
||||
} catch (e) {
|
||||
this.log.error("处理 Telegram 消息时遇到问题", e);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -104,13 +106,12 @@ export default class ForwardController {
|
|||
if (!pair?.joinNotice) return false;
|
||||
const avatar = await getAvatar(event.user_id);
|
||||
await pair.tg.sendMessage({
|
||||
file: new CustomFile('avatar.png', avatar.length, '', avatar),
|
||||
file: new CustomFile("avatar.png", avatar.length, "", avatar),
|
||||
message: `<b>${event.nickname}</b> (<code>${event.user_id}</code>) <i>加入了本群</i>`,
|
||||
silent: true,
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
this.log.error('处理 QQ 群成员增加事件时遇到问题', e);
|
||||
} catch (e) {
|
||||
this.log.error("处理 QQ 群成员增加事件时遇到问题", e);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -118,48 +119,44 @@ export default class ForwardController {
|
|||
try {
|
||||
const pair = this.instance.forwardPairs.find(event.channelId);
|
||||
if (!pair?.joinNotice) return false;
|
||||
if (!(event.newParticipant instanceof Api.ChannelParticipantAdmin)
|
||||
&& !(event.newParticipant instanceof Api.ChannelParticipantCreator)
|
||||
&& !(event.newParticipant instanceof Api.ChannelParticipant))
|
||||
if (
|
||||
!(event.newParticipant instanceof Api.ChannelParticipantAdmin) &&
|
||||
!(event.newParticipant instanceof Api.ChannelParticipantCreator) &&
|
||||
!(event.newParticipant instanceof Api.ChannelParticipant)
|
||||
)
|
||||
return false;
|
||||
const member = await this.tgBot.getChat(event.newParticipant.userId);
|
||||
await pair.qq.sendMsg(`${forwardHelper.getUserDisplayName(member.entity)} 加入了本群`);
|
||||
}
|
||||
catch (e) {
|
||||
this.log.error('处理 TG 群成员增加事件时遇到问题', e);
|
||||
} catch (e) {
|
||||
this.log.error("处理 TG 群成员增加事件时遇到问题", e);
|
||||
}
|
||||
};
|
||||
|
||||
private onQqPoke = async (event: FriendPokeEvent | GroupPokeEvent) => {
|
||||
const target = event.notice_type === 'friend' ? event.friend : event.group;
|
||||
const target = event.notice_type === "friend" ? event.friend : event.group;
|
||||
const pair = this.instance.forwardPairs.find(target);
|
||||
if (!pair?.poke) return;
|
||||
let operatorName: string, targetName: string;
|
||||
if (target instanceof Friend) {
|
||||
if (event.operator_id === target.user_id) {
|
||||
operatorName = target.remark || target.nickname;
|
||||
}
|
||||
else {
|
||||
operatorName = '你';
|
||||
} else {
|
||||
operatorName = "你";
|
||||
}
|
||||
if (event.operator_id === event.target_id) {
|
||||
targetName = '自己';
|
||||
}
|
||||
else if (event.target_id === target.user_id) {
|
||||
targetName = "自己";
|
||||
} else if (event.target_id === target.user_id) {
|
||||
targetName = target.remark || target.nickname;
|
||||
} else {
|
||||
targetName = "你";
|
||||
}
|
||||
else {
|
||||
targetName = '你';
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const operator = target.pickMember(event.operator_id);
|
||||
await operator.renew();
|
||||
operatorName = operator.card || operator.info.nickname;
|
||||
if (event.operator_id === event.target_id) {
|
||||
targetName = '自己';
|
||||
}
|
||||
else {
|
||||
targetName = "自己";
|
||||
} else {
|
||||
const targetUser = target.pickMember(event.target_id);
|
||||
await targetUser.renew();
|
||||
targetName = targetUser.card || targetUser.info.nickname;
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
import InChatCommandsService from '../services/InChatCommandsService';
|
||||
import { getLogger, Logger } from 'log4js';
|
||||
import Instance from '../models/Instance';
|
||||
import Telegram from '../client/Telegram';
|
||||
import OicqClient from '../client/OicqClient';
|
||||
import { Api } from 'telegram';
|
||||
import { Group } from 'oicq';
|
||||
import InChatCommandsService from "../services/InChatCommandsService";
|
||||
import { getLogger, Logger } from "log4js";
|
||||
import Instance from "../models/Instance";
|
||||
import Telegram from "../client/Telegram";
|
||||
import OicqClient from "../client/OicqClient";
|
||||
import { Api } from "telegram";
|
||||
import { Group } from "oicq";
|
||||
|
||||
export default class InChatCommandsController {
|
||||
private readonly service: InChatCommandsService;
|
||||
private readonly log: Logger;
|
||||
|
||||
constructor(private readonly instance: Instance,
|
||||
private readonly tgBot: Telegram,
|
||||
private readonly oicq: OicqClient) {
|
||||
constructor(
|
||||
private readonly instance: Instance,
|
||||
private readonly tgBot: Telegram,
|
||||
private readonly oicq: OicqClient
|
||||
) {
|
||||
this.log = getLogger(`InChatCommandsController - ${instance.id}`);
|
||||
this.service = new InChatCommandsService(instance, tgBot, oicq);
|
||||
tgBot.addNewMessageEventHandler(this.onTelegramMessage);
|
||||
|
@ -20,39 +22,55 @@ export default class InChatCommandsController {
|
|||
|
||||
private onTelegramMessage = async (message: Api.Message) => {
|
||||
if (!message.message) return;
|
||||
const messageParts = message.message.split(' ');
|
||||
if (!messageParts.length || !messageParts[0].startsWith('/')) return;
|
||||
const messageParts = message.message.split(" ");
|
||||
if (!messageParts.length || !messageParts[0].startsWith("/")) return;
|
||||
let command: string = messageParts.shift();
|
||||
const params = messageParts.join(' ');
|
||||
if (command.includes('@')) {
|
||||
const params = messageParts.join(" ");
|
||||
if (command.includes("@")) {
|
||||
let target: string;
|
||||
[command, target] = command.split('@');
|
||||
[command, target] = command.split("@");
|
||||
if (target !== this.tgBot.me.username) return false;
|
||||
}
|
||||
const pair = this.instance.forwardPairs.find(message.chat);
|
||||
if (!pair) return false;
|
||||
switch (command) {
|
||||
case '/info':
|
||||
case "/info":
|
||||
await this.service.info(message, pair);
|
||||
return true;
|
||||
case '/poke':
|
||||
case "/poke":
|
||||
await this.service.poke(message, pair);
|
||||
return true;
|
||||
case '/forwardoff':
|
||||
case "/forwardoff":
|
||||
pair.enable = false;
|
||||
await message.reply({ message: '转发已禁用' });
|
||||
await message.reply({ message: "转发已禁用" });
|
||||
return true;
|
||||
case '/forwardon':
|
||||
case "/forwardon":
|
||||
pair.enable = true;
|
||||
await message.reply({ message: '转发已启用' });
|
||||
await message.reply({ message: "转发已启用" });
|
||||
return true;
|
||||
case '/refresh':
|
||||
if (this.instance.workMode !== 'personal' || !message.senderId?.eq(this.instance.owner)) return false;
|
||||
case "/disableQQForward":
|
||||
pair.disableQ2TG = true;
|
||||
await message.reply({ message: "QQ->TG已禁用" });
|
||||
return true;
|
||||
case "/enableQQForward":
|
||||
pair.disableQ2TG = false;
|
||||
await message.reply({ message: "QQ->TG已启用" });
|
||||
return true;
|
||||
case "/disableTGForward":
|
||||
pair.disableTG2Q = true;
|
||||
await message.reply({ message: "TG->QQ已禁用" });
|
||||
return true;
|
||||
case "/enableTGForward":
|
||||
pair.disableTG2Q = false;
|
||||
await message.reply({ message: "TG->QQ已启用" });
|
||||
return true;
|
||||
case "/refresh":
|
||||
if (this.instance.workMode !== "personal" || !message.senderId?.eq(this.instance.owner)) return false;
|
||||
await pair.updateInfo();
|
||||
await message.reply({ message: '<i>刷新成功</i>' });
|
||||
await message.reply({ message: "<i>刷新成功</i>" });
|
||||
return true;
|
||||
case '/nick':
|
||||
if (this.instance.workMode !== 'personal' || !message.senderId?.eq(this.instance.owner)) return false;
|
||||
case "/nick":
|
||||
if (this.instance.workMode !== "personal" || !message.senderId?.eq(this.instance.owner)) return false;
|
||||
if (!(pair.qq instanceof Group)) return;
|
||||
if (!params) {
|
||||
await message.reply({
|
||||
|
@ -62,7 +80,7 @@ export default class InChatCommandsController {
|
|||
}
|
||||
const result = await pair.qq.setCard(this.instance.qqUin, params);
|
||||
await message.reply({
|
||||
message: '设置' + (result ? '成功' : '失败'),
|
||||
message: "设置" + (result ? "成功" : "失败"),
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
import { Friend, Group } from 'oicq';
|
||||
import TelegramChat from '../client/TelegramChat';
|
||||
import db from './db';
|
||||
import { getLogger } from 'log4js';
|
||||
import { getAvatar } from '../utils/urls';
|
||||
import { md5 } from '../utils/hashing';
|
||||
import getAboutText from '../utils/getAboutText';
|
||||
import { getLogger } from "log4js";
|
||||
import { Friend, Group } from "oicq";
|
||||
import TelegramChat from "../client/TelegramChat";
|
||||
import getAboutText from "../utils/getAboutText";
|
||||
import { md5 } from "../utils/hashing";
|
||||
import { getAvatar } from "../utils/urls";
|
||||
import db from "./db";
|
||||
|
||||
const log = getLogger('ForwardPair');
|
||||
const log = getLogger("ForwardPair");
|
||||
|
||||
export class Pair {
|
||||
constructor(public readonly qq: Friend | Group,
|
||||
private _tg: TelegramChat,
|
||||
public dbId: number,
|
||||
private _joinNotice: boolean,
|
||||
private _poke: boolean,
|
||||
private _enable: boolean) {
|
||||
}
|
||||
constructor(
|
||||
public readonly qq: Friend | Group,
|
||||
private _tg: TelegramChat,
|
||||
public dbId: number,
|
||||
private _joinNotice: boolean,
|
||||
private _poke: boolean,
|
||||
private _enable: boolean,
|
||||
private _disableQ2TG: boolean,
|
||||
private _disableTG2Q: boolean
|
||||
) {}
|
||||
|
||||
// 更新 TG 群组的头像和简介
|
||||
public async updateInfo() {
|
||||
|
@ -51,10 +54,11 @@ export class Pair {
|
|||
|
||||
set tg(value: TelegramChat) {
|
||||
this._tg = value;
|
||||
db.forwardPair.update({
|
||||
where: { id: this.dbId },
|
||||
data: { tgChatId: Number(value.id) },
|
||||
})
|
||||
db.forwardPair
|
||||
.update({
|
||||
where: { id: this.dbId },
|
||||
data: { tgChatId: Number(value.id) },
|
||||
})
|
||||
.then(() => log.info(`出现了到超级群组的转换: ${value.id}`));
|
||||
}
|
||||
|
||||
|
@ -64,10 +68,11 @@ export class Pair {
|
|||
|
||||
set joinNotice(value) {
|
||||
this._joinNotice = value;
|
||||
db.forwardPair.update({
|
||||
where: { id: this.dbId },
|
||||
data: { joinNotice: value },
|
||||
})
|
||||
db.forwardPair
|
||||
.update({
|
||||
where: { id: this.dbId },
|
||||
data: { joinNotice: value },
|
||||
})
|
||||
.then(() => 0);
|
||||
}
|
||||
|
||||
|
@ -77,10 +82,11 @@ export class Pair {
|
|||
|
||||
set poke(value) {
|
||||
this._poke = value;
|
||||
db.forwardPair.update({
|
||||
where: { id: this.dbId },
|
||||
data: { poke: value },
|
||||
})
|
||||
db.forwardPair
|
||||
.update({
|
||||
where: { id: this.dbId },
|
||||
data: { poke: value },
|
||||
})
|
||||
.then(() => 0);
|
||||
}
|
||||
|
||||
|
@ -90,10 +96,39 @@ export class Pair {
|
|||
|
||||
set enable(value) {
|
||||
this._enable = value;
|
||||
db.forwardPair.update({
|
||||
where: { id: this.dbId },
|
||||
data: { enable: value },
|
||||
})
|
||||
db.forwardPair
|
||||
.update({
|
||||
where: { id: this.dbId },
|
||||
data: { enable: value },
|
||||
})
|
||||
.then(() => 0);
|
||||
}
|
||||
|
||||
get disableQ2TG() {
|
||||
return this._disableQ2TG;
|
||||
}
|
||||
|
||||
set disableQ2TG(value) {
|
||||
this._disableQ2TG = value;
|
||||
db.forwardPair
|
||||
.update({
|
||||
where: { id: this.dbId },
|
||||
data: { disableQ2TG: value },
|
||||
})
|
||||
.then(() => 0);
|
||||
}
|
||||
|
||||
get disableTG2Q() {
|
||||
return this._disableTG2Q;
|
||||
}
|
||||
|
||||
set disableTG2Q(value) {
|
||||
this._disableTG2Q = value;
|
||||
db.forwardPair
|
||||
.update({
|
||||
where: { id: this.dbId },
|
||||
data: { disableTG2Q: value },
|
||||
})
|
||||
.then(() => 0);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue