UNPKG

tg-torrent-bot

Version:

A telegram bot implementation for torrents search and download.

99 lines (84 loc) 3.27 kB
import moment from 'moment/moment.js'; import pretty from 'prettysize'; import fs from 'fs'; import PendingUser from '../model/pending-user.js'; const FORMATTED_MESSAGE_CONFIG = { parse_mode: 'markdown', disable_web_page_preview: true, }; export default class MessageHandler { #bot; #rutrackerApi; #downloadsTracker; #torrentsDir; constructor(bot, rutrackerApi, downloadsTracker, torrentsDir) { this.#bot = bot; this.#rutrackerApi = rutrackerApi; this.#downloadsTracker = downloadsTracker; this.#torrentsDir = torrentsDir; } handle() { this.#bot.onText(/^[^/]/, (msg) => this.#main(msg)); this.#bot.onText(/\/d_(.+)/, (msg, match) => this.#downloadTorrentFile(match, msg)); this.#bot.onText(/\/m_(.+)/, (msg, match) => this.#getMagnetLink(match, msg)); this.#bot.onText(/^\/start|^\/help/, (msg) => this.#bot.sendMessage(msg.chat.id, msg.__('Help Message'))); } async #main(msg) { let { text } = msg; if (text.includes('#kinopoisk')) { // FIXME: doesn't work, #9 text = text.match(/Фильм (.+)#/)[1].replace(/["(),]/g, ''); } const torrents = await this.#rutrackerApi.search({ query: text, sort: 'seeds', order: 'desc', }); const response = torrents.length === 0 ? msg.__('No results for "%s".', text) : torrents.slice(0, 10) .map((torrent) => this.#toTorrentDescription(torrent, msg)) .join('\n'); await this.#bot.sendMessage(msg.chat.id, response, FORMATTED_MESSAGE_CONFIG); } #toTorrentDescription(torrent, msg) { return `${torrent.title}\n` + `${torrent.id}\n` + `[${msg.__('Description')}](${this.#rutrackerApi.host}/forum/viewtopic.php?t=${torrent.id})\n` + `S ${torrent.seeds} | L ${torrent.leeches} | ${msg.__('Downloaded')} ${torrent.downloads} | ` + `${msg.__('Reg')} ${moment(torrent.registered) .format('YYYY-MM-DD')} | ` + `${msg.__('Size')} ${pretty(torrent.size)}\n` + `*${this.#torrentsDir ? msg.__('Download') : msg.__('Get .torrent file')}*: /d\\_${torrent.id}\n` + `${msg.__('Get link')}: /m\\_${torrent.id}\n`; } #downloadTorrentFile(match, msg) { const param = match[1]; if (this.#torrentsDir) { this.#rutrackerApi.getMagnetLink(param) .then((link) => { const torrentHash = link.match(/urn:btih:([a-z0-9]+)&/i)[1].toLowerCase(); return this.#downloadsTracker.add( torrentHash, new PendingUser(msg.chat.id, msg.from.language_code), ); }); } this.#rutrackerApi.download(param) .then((stream) => { if (this.#torrentsDir) { this.#bot.sendMessage(msg.chat.id, msg.__('Sent for downloading')); stream.pipe(fs.createWriteStream(`${this.#torrentsDir}/${param}.torrent`)); } else { this.#bot.sendDocument(msg.chat.id, stream, {}, { filename: `${param}.torrent`, contentType: 'application/x-bittorrent', }); } }); } async #getMagnetLink(match, msg) { const param = match[1]; const link = await this.#rutrackerApi.getMagnetLink(param); await this.#bot.sendMessage(msg.chat.id, `\`\`\`\n${link}\n\`\`\``, FORMATTED_MESSAGE_CONFIG); } }