mirror of https://github.com/Nofated095/Q2TG.git
Compare commits
9 Commits
2ed24c5579
...
cd3e2e1f2c
Author | SHA1 | Date |
---|---|---|
谷風 天音 たにかぜ あまね | cd3e2e1f2c | |
Clansty | bd8092c311 | |
Clansty | 3966a003b1 | |
Clansty | 174462119a | |
Clansty | 396037d2ce | |
Clansty | 1424da1824 | |
Clansty | 6a01f529f5 | |
Clansty | 465ae35d7f | |
Clansty | eb77e7a936 |
|
@ -42,10 +42,10 @@
|
|||
"nodejs-base64": "^2.0.0",
|
||||
"prisma": "5.8.0",
|
||||
"prompts": "^2.4.2",
|
||||
"quote-api": "https://github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz",
|
||||
"quote-api": "https://github.com/Clansty/quote-api/archive/014b21138afbbe0e12c91b00561414b1e851fc0f.tar.gz",
|
||||
"sharp": "^0.33.2",
|
||||
"silk-sdk": "^0.2.2",
|
||||
"telegram": "^2.19.10",
|
||||
"telegram": "https://github.com/clansty/gramjs/releases/download/2.19.10%2Brevert_media/telegram-2.19.10.tgz",
|
||||
"tmp-promise": "^3.0.3",
|
||||
"undici": "^6.4.0",
|
||||
"zincsearch-node": "^2.1.0",
|
||||
|
|
|
@ -60,8 +60,8 @@ dependencies:
|
|||
specifier: ^2.4.2
|
||||
version: 2.4.2
|
||||
quote-api:
|
||||
specifier: https://github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz
|
||||
version: '@github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz'
|
||||
specifier: https://github.com/Clansty/quote-api/archive/014b21138afbbe0e12c91b00561414b1e851fc0f.tar.gz
|
||||
version: '@github.com/Clansty/quote-api/archive/014b21138afbbe0e12c91b00561414b1e851fc0f.tar.gz'
|
||||
sharp:
|
||||
specifier: ^0.33.2
|
||||
version: 0.33.2
|
||||
|
@ -69,8 +69,8 @@ dependencies:
|
|||
specifier: ^0.2.2
|
||||
version: 0.2.2
|
||||
telegram:
|
||||
specifier: ^2.19.10
|
||||
version: 2.19.10
|
||||
specifier: https://github.com/clansty/gramjs/releases/download/2.19.10%2Brevert_media/telegram-2.19.10.tgz
|
||||
version: '@github.com/clansty/gramjs/releases/download/2.19.10%25252Brevert_media/telegram-2.19.10.tgz'
|
||||
tmp-promise:
|
||||
specifier: ^3.0.3
|
||||
version: 3.0.3
|
||||
|
@ -1243,7 +1243,7 @@ packages:
|
|||
engines: {node: '>=6.14.2'}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
node-gyp-build: 4.6.1
|
||||
node-gyp-build: 4.8.0
|
||||
dev: false
|
||||
|
||||
/buildcheck@0.0.6:
|
||||
|
@ -2740,8 +2740,8 @@ packages:
|
|||
whatwg-url: 5.0.0
|
||||
dev: false
|
||||
|
||||
/node-gyp-build@4.6.1:
|
||||
resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==}
|
||||
/node-gyp-build@4.8.0:
|
||||
resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
|
@ -3457,30 +3457,6 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/telegram@2.19.10:
|
||||
resolution: {integrity: sha512-5Brrn+BcYSjDUmT1/9T4Nq2tYlR1/TreRvpim1UGeuwfnIgFOiTXwDwXBOy6hbn9yssvmtk/dQJU9pBColM7ag==}
|
||||
dependencies:
|
||||
'@cryptography/aes': 0.1.1
|
||||
async-mutex: 0.3.2
|
||||
big-integer: 1.6.52
|
||||
buffer: 6.0.3
|
||||
htmlparser2: 6.1.0
|
||||
mime: 3.0.0
|
||||
node-localstorage: 2.2.1
|
||||
pako: 2.1.0
|
||||
path-browserify: 1.0.1
|
||||
real-cancellable-promise: 1.2.0
|
||||
socks: 2.7.1
|
||||
store2: 2.14.2
|
||||
ts-custom-error: 3.3.1
|
||||
websocket: 1.0.34
|
||||
optionalDependencies:
|
||||
bufferutil: 4.0.8
|
||||
utf-8-validate: 5.0.10
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/timm@1.7.1:
|
||||
resolution: {integrity: sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==}
|
||||
dev: false
|
||||
|
@ -3563,6 +3539,7 @@ packages:
|
|||
|
||||
/tslib@2.6.2:
|
||||
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
|
||||
/tsscmp@1.0.6:
|
||||
|
@ -3681,7 +3658,7 @@ packages:
|
|||
engines: {node: '>=6.14.2'}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
node-gyp-build: 4.6.1
|
||||
node-gyp-build: 4.8.0
|
||||
dev: false
|
||||
|
||||
/utif2@4.1.0:
|
||||
|
@ -3895,10 +3872,10 @@ packages:
|
|||
resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
|
||||
dev: false
|
||||
|
||||
'@github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz':
|
||||
resolution: {tarball: https://github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz}
|
||||
'@github.com/Clansty/quote-api/archive/014b21138afbbe0e12c91b00561414b1e851fc0f.tar.gz':
|
||||
resolution: {tarball: https://github.com/Clansty/quote-api/archive/014b21138afbbe0e12c91b00561414b1e851fc0f.tar.gz}
|
||||
name: quote-api
|
||||
version: 0.12.2
|
||||
version: 0.14.0
|
||||
dependencies:
|
||||
canvas: 2.11.2
|
||||
dotenv: 7.0.0
|
||||
|
@ -3925,3 +3902,29 @@ packages:
|
|||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
'@github.com/clansty/gramjs/releases/download/2.19.10%25252Brevert_media/telegram-2.19.10.tgz':
|
||||
resolution: {tarball: https://github.com/clansty/gramjs/releases/download/2.19.10%2Brevert_media/telegram-2.19.10.tgz}
|
||||
name: telegram
|
||||
version: 2.19.10
|
||||
dependencies:
|
||||
'@cryptography/aes': 0.1.1
|
||||
async-mutex: 0.3.2
|
||||
big-integer: 1.6.52
|
||||
buffer: 6.0.3
|
||||
htmlparser2: 6.1.0
|
||||
mime: 3.0.0
|
||||
node-localstorage: 2.2.1
|
||||
pako: 2.1.0
|
||||
path-browserify: 1.0.1
|
||||
real-cancellable-promise: 1.2.0
|
||||
socks: 2.7.1
|
||||
store2: 2.14.2
|
||||
ts-custom-error: 3.3.1
|
||||
websocket: 1.0.34
|
||||
optionalDependencies:
|
||||
bufferutil: 4.0.8
|
||||
utf-8-validate: 5.0.10
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
|
|
@ -60,22 +60,23 @@ model QqBot {
|
|||
}
|
||||
|
||||
model Message {
|
||||
id Int @id @default(autoincrement())
|
||||
qqRoomId BigInt @db.BigInt
|
||||
qqSenderId BigInt @db.BigInt
|
||||
time Int
|
||||
brief String?
|
||||
seq Int
|
||||
rand BigInt @db.BigInt
|
||||
pktnum Int
|
||||
tgChatId BigInt @db.BigInt
|
||||
tgMsgId Int
|
||||
instanceId Int @default(0)
|
||||
instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||
tgFileId BigInt? @db.BigInt
|
||||
tgMessageText String?
|
||||
nick String? // /抱 的时候会用到
|
||||
tgSenderId BigInt? @db.BigInt
|
||||
id Int @id @default(autoincrement())
|
||||
qqRoomId BigInt @db.BigInt
|
||||
qqSenderId BigInt @db.BigInt
|
||||
time Int
|
||||
brief String?
|
||||
seq Int
|
||||
rand BigInt @db.BigInt
|
||||
pktnum Int
|
||||
tgChatId BigInt @db.BigInt
|
||||
tgMsgId Int
|
||||
instanceId Int @default(0)
|
||||
instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||
tgFileId BigInt? @db.BigInt
|
||||
tgMessageText String?
|
||||
nick String? // /抱 的时候会用到
|
||||
tgSenderId BigInt? @db.BigInt
|
||||
richHeaderUsed Boolean @default(false)
|
||||
|
||||
@@index([qqRoomId, qqSenderId, seq, rand, pktnum, time, instanceId])
|
||||
@@index([tgChatId, tgMsgId, instanceId])
|
||||
|
|
|
@ -7,4 +7,11 @@ export default {
|
|||
index = index % arr.length;
|
||||
return arr[index];
|
||||
},
|
||||
tgColor(index: number) {
|
||||
// https://github.com/telegramdesktop/tdesktop/blob/7049929a59176a996c4257d5a09df08b04ac3b22/Telegram/SourceFiles/ui/chat/chat_style.cpp#L1043
|
||||
// https://github.com/LyoSU/quote-api/blob/master/utils/quote-generate.js#L163
|
||||
const arr = [...new Intl.Segmenter().segment('❤️🧡💜💚🩵💙🩷')].map(x => x.segment);
|
||||
index = index % arr.length;
|
||||
return arr[index];
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@ enum flags {
|
|||
NO_DELETE_MESSAGE = 1 << 4,
|
||||
NO_AUTO_CREATE_PM = 1 << 5,
|
||||
COLOR_EMOJI_PREFIX = 1 << 6,
|
||||
RICH_HEADER = 1 << 7,
|
||||
}
|
||||
|
||||
export default flags;
|
||||
|
|
|
@ -60,36 +60,32 @@ export default class ForwardController {
|
|||
});
|
||||
if (existed) return;
|
||||
// 开始转发过程
|
||||
let tgMessages: Api.Message | Api.Message[] = await this.forwardService.forwardFromQq(event, pair);
|
||||
if (!tgMessages) return;
|
||||
if (!Array.isArray(tgMessages)) {
|
||||
tgMessages = [tgMessages];
|
||||
}
|
||||
for (const tgMessage of tgMessages) {
|
||||
// 更新数据库
|
||||
await db.message.create({
|
||||
data: {
|
||||
qqRoomId: pair.qqRoomId,
|
||||
qqSenderId: event.sender.user_id,
|
||||
time: event.time,
|
||||
brief: event.raw_message,
|
||||
seq: event.seq,
|
||||
rand: event.rand,
|
||||
pktnum: event.pktnum,
|
||||
tgChatId: pair.tgId,
|
||||
tgMsgId: tgMessage.id,
|
||||
instanceId: this.instance.id,
|
||||
tgMessageText: tgMessage.message,
|
||||
tgFileId: forwardHelper.getMessageDocumentId(tgMessage),
|
||||
nick: event.nickname,
|
||||
tgSenderId: BigInt(this.tgBot.me.id.toString()),
|
||||
},
|
||||
});
|
||||
await this.forwardService.addToZinc(pair.dbId, tgMessage.id, {
|
||||
text: event.raw_message,
|
||||
let { tgMessage, richHeaderUsed } = await this.forwardService.forwardFromQq(event, pair);
|
||||
if (!tgMessage) return;
|
||||
// 更新数据库
|
||||
await db.message.create({
|
||||
data: {
|
||||
qqRoomId: pair.qqRoomId,
|
||||
qqSenderId: event.sender.user_id,
|
||||
time: event.time,
|
||||
brief: event.raw_message,
|
||||
seq: event.seq,
|
||||
rand: event.rand,
|
||||
pktnum: event.pktnum,
|
||||
tgChatId: pair.tgId,
|
||||
tgMsgId: tgMessage.id,
|
||||
instanceId: this.instance.id,
|
||||
tgMessageText: tgMessage.message,
|
||||
tgFileId: forwardHelper.getMessageDocumentId(tgMessage),
|
||||
nick: event.nickname,
|
||||
});
|
||||
}
|
||||
tgSenderId: BigInt(this.tgBot.me.id.toString()),
|
||||
richHeaderUsed,
|
||||
},
|
||||
});
|
||||
await this.forwardService.addToZinc(pair.dbId, tgMessage.id, {
|
||||
text: event.raw_message,
|
||||
nick: event.nickname,
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
this.log.error('处理 QQ 消息时遇到问题', e);
|
||||
|
|
|
@ -163,7 +163,7 @@ export default class {
|
|||
title: message.nick,
|
||||
photo: { url: getAvatarUrl(message.qqSenderId) },
|
||||
};
|
||||
if (message.qqRoomId > 0) {
|
||||
if (message.qqRoomId > 0 || message.richHeaderUsed) {
|
||||
quoteMessage.text = message.tgMessageText;
|
||||
}
|
||||
else if (message.tgMessageText.includes('\n')) {
|
||||
|
@ -195,7 +195,7 @@ export default class {
|
|||
photo = await convert.cachedBuffer(`${sender.photo.photoId.toString(16)}.jpg`, () => this.tgBot.downloadEntityPhoto(sender));
|
||||
}
|
||||
messageFrom = {
|
||||
id: Number(message.tgSenderId),
|
||||
id: sender.color || Number(message.tgSenderId),
|
||||
name: message.nick,
|
||||
title: message.nick,
|
||||
username: sender.username,
|
||||
|
|
|
@ -44,6 +44,7 @@ import ReplyKeyboardHide = Api.ReplyKeyboardHide;
|
|||
import env from '../models/env';
|
||||
import { CustomFile } from 'telegram/client/uploads';
|
||||
import flags from '../constants/flags';
|
||||
import BigInteger from 'big-integer';
|
||||
|
||||
const NOT_CHAINABLE_ELEMENTS = ['flash', 'record', 'video', 'location', 'share', 'json', 'xml', 'poke'];
|
||||
|
||||
|
@ -331,7 +332,6 @@ export default class ForwardService {
|
|||
}
|
||||
}
|
||||
message = message.trim();
|
||||
message = messageHeader + (message && messageHeader ? '\n' : '') + message;
|
||||
|
||||
// 处理回复
|
||||
if (event.source) {
|
||||
|
@ -366,28 +366,66 @@ export default class ForwardService {
|
|||
}
|
||||
|
||||
|
||||
let richHeaderUsed = false;
|
||||
// 发送消息
|
||||
const messageToSend: SendMessageParams = {
|
||||
forceDocument: forceDocument as any, // 恼
|
||||
};
|
||||
message && (messageToSend.message = message);
|
||||
if (files.length === 1) {
|
||||
messageToSend.file = files[0];
|
||||
}
|
||||
else if (files.length) {
|
||||
messageToSend.file = files;
|
||||
}
|
||||
else if ((pair.flags | this.instance.flags) & flags.RICH_HEADER) {
|
||||
// 没有文件时才能显示链接预览
|
||||
richHeaderUsed = true;
|
||||
const url = new URL('https://q2tg-header.clansty.workers.dev');
|
||||
url.searchParams.set('name', sender);
|
||||
url.searchParams.set('title', 'title' in event.sender ? event.sender.title : '');
|
||||
url.searchParams.set('role', 'role' in event.sender ? event.sender.role : '');
|
||||
url.searchParams.set('id', event.sender.user_id.toString());
|
||||
// https://github.com/tdlib/td/blob/437c2d0c6e0ad104022d5ad86ddc8aedc41cb7a8/td/telegram/MessageContent.cpp#L2575
|
||||
// https://github.com/tdlib/td/blob/437c2d0c6e0ad104022d5ad86ddc8aedc41cb7a8/td/generate/scheme/telegram_api.tl#L1841
|
||||
// https://github.com/gram-js/gramjs/pull/633
|
||||
messageToSend.file = new Api.InputMediaWebPage({
|
||||
url: url.toString(),
|
||||
forceSmallMedia: true,
|
||||
optional: true,
|
||||
});
|
||||
messageToSend.linkPreview = { showAboveText: true };
|
||||
}
|
||||
|
||||
if (!richHeaderUsed) {
|
||||
message = messageHeader + (message && messageHeader ? '\n' : '') + message;
|
||||
}
|
||||
message && (messageToSend.message = message);
|
||||
|
||||
buttons.length && (messageToSend.buttons = _.chunk(buttons, 3));
|
||||
replyTo && (messageToSend.replyTo = replyTo);
|
||||
|
||||
const tgMessage = await pair.tg.sendMessage(messageToSend);
|
||||
let tgMessage: Api.Message;
|
||||
try {
|
||||
tgMessage = await pair.tg.sendMessage(messageToSend);
|
||||
}
|
||||
catch (e) {
|
||||
if (richHeaderUsed) {
|
||||
this.log.warn('Rich Header 发送错误', messageToSend.file, e);
|
||||
delete messageToSend.file;
|
||||
delete messageToSend.linkPreview;
|
||||
message = messageHeader + (message && messageHeader ? '\n' : '') + message;
|
||||
message && (messageToSend.message = message);
|
||||
tgMessage = await pair.tg.sendMessage(messageToSend);
|
||||
}
|
||||
else throw e;
|
||||
}
|
||||
|
||||
if (this.instance.workMode === 'personal' && event.message_type === 'group' && event.atall) {
|
||||
await tgMessage.pin({ notify: false });
|
||||
}
|
||||
|
||||
tempFiles.forEach(it => it.cleanup());
|
||||
return tgMessage;
|
||||
return { tgMessage, richHeaderUsed };
|
||||
}
|
||||
catch (e) {
|
||||
this.log.error('从 QQ 到 TG 的消息转发失败', e);
|
||||
|
@ -396,11 +434,12 @@ export default class ForwardService {
|
|||
}
|
||||
catch {
|
||||
}
|
||||
return null;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
public async forwardFromTelegram(message: Api.Message, pair: Pair): Promise<Array<QQMessageSent>> {
|
||||
// console.log(message);
|
||||
try {
|
||||
const tempFiles: FileResult[] = [];
|
||||
let chain: Sendable = [];
|
||||
|
@ -415,7 +454,7 @@ export default class ForwardService {
|
|||
'') +
|
||||
': \n';
|
||||
if ((pair.flags | this.instance.flags) & flags.COLOR_EMOJI_PREFIX) {
|
||||
messageHeader = emoji.color(message.senderId.toJSNumber()) + messageHeader;
|
||||
messageHeader = emoji.tgColor((message.sender as Api.User)?.color || message.senderId.toJSNumber()) + messageHeader;
|
||||
}
|
||||
if (message.photo instanceof Api.Photo ||
|
||||
// stickers 和以文件发送的图片都是这个
|
||||
|
|
Loading…
Reference in New Issue