| import streamSaver from 'streamsaver' |
| import { Api } from 'telegram' |
| import { req } from './Fetcher' |
| import { telegramClient } from './Telegram' |
|
|
| export async function download(id: string): Promise<ReadableStream> { |
| const { data: response } = await req.get(`/files/${id}`, { params: { raw: 1, as_array: 1 } }) |
| let cancel = false |
|
|
| const client = await telegramClient.connect() |
| const readableStream = new ReadableStream({ |
| start(_controller: ReadableStreamDefaultController) { |
| }, |
| async pull(controller: ReadableStreamDefaultController) { |
| let countFiles = 1 |
| console.log('start downloading:', response.files) |
|
|
| const promises = response.files.map(async (file) => { |
| let chat: any |
| if (file.forward_info && file.forward_info.match(/^channel\//gi)) { |
| const [type, peerId, id, accessHash] = file.forward_info.split('/') |
| let peer: Api.InputPeerChannel | Api.InputPeerUser | Api.InputPeerChat |
| if (type === 'channel') { |
| peer = new Api.InputPeerChannel({ |
| channelId: BigInt(peerId) as any, |
| accessHash: BigInt(accessHash as string) as any }) |
| chat = await client.invoke(new Api.channels.GetMessages({ |
| channel: peer, |
| id: [new Api.InputMessageID({ id: Number(id) })] |
| })) |
| } |
| } else { |
| chat = await client.invoke(new Api.messages.GetMessages({ |
| id: [new Api.InputMessageID({ id: Number(file.message_id) })] |
| })) |
| } |
|
|
| const getData = async () => await client.downloadMedia(chat['messages'][0].media, { |
| outputFile: { |
| write: (chunk: Buffer) => { |
| if (cancel) return false |
| return controller.enqueue(chunk) |
| }, |
| close: () => { |
| if (countFiles++ >= Number(response.files.length)) |
| controller.close() |
| } |
| }, |
| progressCallback: (received, total) => { |
| console.log('progress: ', (Number(received)/Number(total)*100).toFixed(2), '%') |
| } |
| }) |
|
|
| return getData() |
| }) |
|
|
| await Promise.all(promises) |
| }, |
| cancel() { |
| cancel = true |
| } |
| }, { |
| size(chunk: any) { |
| return chunk.length |
| } |
| }) |
| return readableStream |
| } |
|
|
| export const directDownload = async (id: string, name: string): Promise<void> => { |
| const fileStream = streamSaver.createWriteStream(name) |
| const writer = fileStream.getWriter() |
| const reader = (await download(id)).getReader() |
| const pump = () => reader.read().then(({ value, done }) => { |
| if (done) return writer.close() |
| writer.write(value) |
| return writer.ready.then(pump) |
| }) |
| await pump() |
|
|
| } |