Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(telegram): attempt to reuse fileid if possible #275

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions adapters/telegram/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,19 @@
if (config.files.server ?? selfUrl) {
const route = `/telegram/${this.selfId}`
this.server = selfUrl + route
ctx.get('server').get(route + '/:file+', async ctx => {
const { data, mime } = await this.$getFile(ctx.params.file)
ctx.set('content-type', mime)
ctx.body = Buffer.from(data)
})
ctx.get('server')
.get(route + '/tg-fileid/:file+', async ctx => {
const file = await this.internal.getFile({ file_id: ctx.params.file })
const { data, mime } = await this.$getFile(file.file_path)
ctx.set('content-type', mime)
ctx.set('content-disposition', `inline; filename="${file.file_path}"`)
ctx.body = Buffer.from(data)
})
.get(route + '/:file+', async ctx => {
const { data, mime } = await this.$getFile(ctx.params.file)
ctx.set('content-type', mime)
ctx.body = Buffer.from(data)
})
}
}

Expand Down Expand Up @@ -152,8 +160,16 @@

async $getFileFromId(file_id: string) {
try {
if(this.server) {

Check failure on line 163 in adapters/telegram/src/bot.ts

View workflow job for this annotation

GitHub Actions / lint

Expected space(s) after "if"

Check failure on line 163 in adapters/telegram/src/bot.ts

View workflow job for this annotation

GitHub Actions / lint

Expected space(s) after "if"
return {
src: `${this.server}/tg-fileid/${file_id}`

Check failure on line 165 in adapters/telegram/src/bot.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma

Check failure on line 165 in adapters/telegram/src/bot.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma
}
}
const file = await this.internal.getFile({ file_id })
return await this.$getFileFromPath(file.file_path)
const { src } = await this.$getFileFromPath(file.file_path)
return {
src: src + '#fileid="' + file_id + '"'

Check failure on line 171 in adapters/telegram/src/bot.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma

Check failure on line 171 in adapters/telegram/src/bot.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma
}
} catch (e) {
this.logger.warn('get file error', e)
}
Expand Down Expand Up @@ -264,6 +280,7 @@
HTTP.createConfig('https://api.telegram.org'),
Schema.object({
files: Schema.object({
reuseFileid: Schema.boolean().description('是否尝试复用文件 ID。').default(true),
endpoint: Schema.string().description('文件请求的终结点。'),
local: Schema.boolean().description('是否启用 [Telegram Bot API](https://github.com/tdlib/telegram-bot-api) 本地模式。'),
server: Schema.boolean().description('是否启用文件代理。若开启将会使用 `selfUrl` 进行反代,否则会下载所有资源文件 (包括图片、视频等)。当配置了 `selfUrl` 时将默认开启。'),
Expand Down
131 changes: 94 additions & 37 deletions adapters/telegram/src/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,25 @@
}

async flush() {
if (this.payload.caption || this.asset.length > 0) {
const send = async ({
reuseFileId

Check failure on line 34 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma

Check failure on line 34 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma
}) => {
const results = []
const payload = JSON.parse(JSON.stringify(this.payload))
let rows = this.rows


Check failure on line 40 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

More than 1 blank line not allowed

Check failure on line 40 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

More than 1 blank line not allowed
this.trimButtons()


Check failure on line 43 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

More than 1 blank line not allowed

Check failure on line 43 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

More than 1 blank line not allowed
if (this.asset.length > 0) {
const files: {
filename: string
data: ArrayBuffer
mime: string
type: string
element: Element
fileid?: string
}[] = []

const typeMap = {
Expand All @@ -52,6 +61,23 @@

let i = 0
for (const element of this.asset) {
if (reuseFileId) {
const url = element.attrs.src || element.attrs.url
const hash = url.slice(url.lastIndexOf('#') + 1)
const fileid = /^fileid="(.*?)"$/.exec(hash)?.[1] || /\/tg\-fileid\/(.*)/.exec(url)?.[1]
if (fileid) {
this.session.bot.logger.debug('trying to reuse fileid', fileid)
files.push({
filename: (i++).toString(),
data: null,
mime: 'application/octet-stream',
type: typeMap[element.type] ?? element.type,
fileid,
element

Check failure on line 76 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma

Check failure on line 76 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma
})
continue
}
}
const { filename, data, mime } = await this.bot.ctx.http.file(element.attrs.src || element.attrs.url, element.attrs)
files.push({
filename: (i++) + filename,
Expand All @@ -75,8 +101,8 @@
}

if (files.length > 1) {
inputFiles[0].caption = this.payload.caption
inputFiles[0].parse_mode = this.payload.parse_mode
inputFiles[0].caption = payload.caption
inputFiles[0].parse_mode = payload.parse_mode

const form = new FormData()

Expand All @@ -91,36 +117,37 @@
}

for (const { filename, data, mime } of files) {
form.append(filename, new Blob([data], { type: mime }), filename)
if (data)
form.append(filename, new Blob([data], { type: mime }), filename)

Check failure on line 121 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Expected { after 'if' condition

Check failure on line 121 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Expected { after 'if' condition
}

// @ts-ignore
const result = await this.bot.internal.sendMediaGroup(form)

for (const x of result) { await this.addResult(x) }

if (this.rows.length > 0 && this.rows[0].length > 0) {
if (rows.length > 0 && rows[0].length > 0) {
const result2 = await this.bot.internal.sendMessage({
chat_id: this.payload.chat_id,
text: this.payload.caption,
parse_mode: this.payload.parse_mode,
chat_id: payload.chat_id,
text: payload.caption,
parse_mode: payload.parse_mode,
reply_to_message_id: result[0].message_id,
message_thread_id: this.payload.message_thread_id,
message_thread_id: payload.message_thread_id,
disable_web_page_preview: !this.options.linkPreview,
reply_markup: {
inline_keyboard: this.rows,
inline_keyboard: rows,
},
})

await this.addResult(result2)
delete this.payload.reply_to_message_id
this.payload.caption = ''
this.rows = []
results.push(result2)
delete payload.reply_to_message_id
payload.caption = ''
rows = []
}

delete this.payload.reply_to_message_id
this.payload.caption = ''
this.rows = []
delete payload.reply_to_message_id
payload.caption = ''
rows = []
} else {
const sendMap = [
['audio', ['sendAudio', 'audio']],
Expand All @@ -135,38 +162,68 @@
const [, [method, dataKey]] = sendMap.find(([key]) => files[0].type.startsWith(key)) || []

const formData = new FormData()
formData.append('chat_id', this.payload.chat_id)
formData.append('caption', this.payload.caption)
formData.append('parse_mode', this.payload.parse_mode)
formData.append('reply_to_message_id', this.payload.reply_to_message_id)
formData.append('message_thread_id', this.payload.message_thread_id)
formData.append('chat_id', payload.chat_id)
formData.append('caption', payload.caption)
formData.append('parse_mode', payload.parse_mode)
formData.append('reply_to_message_id', payload.reply_to_message_id)
formData.append('message_thread_id', payload.message_thread_id)
formData.append('has_spoiler', files[0].element.attrs.spoiler ? 'true' : 'false')
formData.append(dataKey, 'attach://' + files[0].filename)
formData.append(files[0].filename, new Blob([files[0].data], { type: files[0].mime }), files[0].filename)
formData.append(dataKey, files[0].fileid ? files[0].fileid : 'attach://' + files[0].filename)
if (files[0].data)
formData.append(files[0].filename, new Blob([files[0].data], { type: files[0].mime }), files[0].filename)

Check failure on line 173 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Expected { after 'if' condition

Check failure on line 173 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Expected { after 'if' condition

// @ts-ignore
const result = await this.bot.internal[method](formData)
await this.addResult(result)
this.payload.caption = ''
this.rows = []
delete this.payload.reply_to_message_id
results.push(result)
payload.caption = ''
rows = []
delete payload.reply_to_message_id
}
} else {
const result = await this.bot.internal.sendMessage({
chat_id: this.payload.chat_id,
text: this.payload.caption,
parse_mode: this.payload.parse_mode,
reply_to_message_id: this.payload.reply_to_message_id,
message_thread_id: this.payload.message_thread_id,
chat_id: payload.chat_id,
text: payload.caption,
parse_mode: payload.parse_mode,
reply_to_message_id: payload.reply_to_message_id,
message_thread_id: payload.message_thread_id,
disable_web_page_preview: !this.options.linkPreview,
reply_markup: {
inline_keyboard: this.rows,
inline_keyboard: rows,
},
})
results.push(result)
delete payload.reply_to_message_id
payload.caption = ''
rows = []
}

delete this.payload.reply_to_message_id
this.payload.caption = ''
this.rows = []
this.asset = []

return results
}

if (this.payload.caption || this.asset.length > 0) {
let res: unknown[]
if (this.session.bot.config.files.reuseFileid) {
try {
res = await send({ reuseFileId: true })
} catch (e) {
if (e.message.includes('Telegram API error 400.')) {
res = await send({ reuseFileId: false })
}

Check failure on line 216 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Closing curly brace does not appear on the same line as the subsequent block

Check failure on line 216 in adapters/telegram/src/message.ts

View workflow job for this annotation

GitHub Actions / lint

Closing curly brace does not appear on the same line as the subsequent block
else {
throw e
}
}
} else {
res = await send({ reuseFileId: false })
}

for (const result of res) {
await this.addResult(result)
delete this.payload.reply_to_message_id
this.payload.caption = ''
this.rows = []
}
}
}
Expand Down
Loading