def notify_completed(bot: Bot, _): logger.info('executing completed job') completed = qb.torrents(filter='completed') for t in completed: if completed_torrents.is_new(t.hash): torrent = qb.torrent(t.hash) if config.qbittorrent.get('pause_completed_torrents', False): logger.info('pausing %s (%s)', torrent.name, torrent.hash) torrent.pause() if not dont_notify_torrents.send_notification(t.hash): logger.info('we will not send a notification about %s (%s)', t.hash, t.name) continue text = '<code>{}</code> completed ({})'.format(u.html_escape(torrent.name), torrent.size_pretty) send_message_kwargs = dict( text=text, parse_mode=ParseMode.HTML, disable_web_page_preview=True, disable_notification=True ) if config.telegram.get('completed_torrents_notification', None): # don't send the message in private if there's a notifications channel set bot.send_message(config.telegram.completed_torrents_notification, **send_message_kwargs) else: bot.send_message( config.telegram.admins[0], reply_markup=torrent.short_markup(force_resume_button=False), **send_message_kwargs )
def _enrich_torrent_dict(self): if 'progress' in self._torrent_dict: self._torrent_dict['eta'] = 0 if self._torrent_dict['progress'] == 1 else self._torrent_dict['eta'] # set eta = 0 for completed torrents self._torrent_dict['progress_bar'] = u.build_progress_bar(self._torrent_dict['progress']) if 'hash' in self._torrent_dict: self._torrent_dict['manage_deeplink'] = 'https://t.me/{}?start=manage{}'.format( self._qbt._bot_username, self._torrent_dict['hash'] ) self._torrent_dict['info_deeplink'] = 'https://t.me/{}?start=info{}'.format( self._qbt._bot_username, self._torrent_dict['hash'] ) self._torrent_dict['short_name'] = self._torrent_dict['name'] if len(self._torrent_dict['name']) > 51: self._torrent_dict['short_name'] = self._torrent_dict['name'][:51].strip() + '...' self._torrent_dict['short_name_escaped'] = u.html_escape(self._torrent_dict['short_name']) self._torrent_dict['generic_speed'] = self._torrent_dict['dlspeed'] icon = '▼' if self._torrent_dict['state'] in ('uploading', 'forcedUP', 'stalledUP'): self._torrent_dict['generic_speed'] = self._torrent_dict['upspeed'] icon = '▲' generic_speed_human_readable = u.get_human_readable(self._torrent_dict['generic_speed']) self._torrent_dict['traffic_direction_icon'] = f"{icon}" for k, v in NEW_ATTRS.items(): try: self._torrent_dict[k] = v(self._torrent_dict) except KeyError: # it might be that one of the lambdas uses a key that is not available in the torrent dict, # eg. when get_additional_torrent_properties is not True continue
def ask_confirm_delete_with_files_cb(_, update, groups): logger.info('delete with files inline button') torrent_hash = groups[0] logger.info('torrent hash: %s', torrent_hash) torrent = qb.torrent(torrent_hash) # torrent.delete(with_files=True) update.callback_query.edit_message_text( '你确定要删除吗 {}, <b>连同文件一起删除</b>?'.format(u.html_escape(torrent.name)), reply_markup=kb.confirm_delete(torrent.hash), parse_mode=ParseMode.HTML) update.callback_query.answer('请再次确认')
def ask_confirm_delete_with_files_cb(_, update, groups): logger.info('delete with files inline button') torrent_hash = groups[0] logger.info('torrent hash: %s', torrent_hash) torrent = qb.torrent(torrent_hash) # torrent.delete(with_files=True) update.callback_query.edit_message_text( 'Are you sure you want to delete {}, <b>with all the connected files included</b>?' .format(u.html_escape(torrent.name)), reply_markup=kb.confirm_delete(torrent.hash), parse_mode=ParseMode.HTML) update.callback_query.answer('Confirmation needed')
def see_trackers_cb(_, update, groups): logger.info('trackers inline button') torrent_hash = groups[0] logger.info('torrent hash: %s', torrent_hash) torrent = qb.torrent(torrent_hash) trackers = torrent.trackers() strings_list = [ '<b>{status}:</b> {url} <b>({num_peers})</b>'.format( **{k: u.html_escape(str(v)) for k, v in tracker.items()}) for tracker in trackers ] text = '\n'.join(strings_list) if len(text) > MAX_MESSAGE_LENGTH: trackers_info = dict() for tracker in trackers: if not trackers_info.get(tracker['status'], None): trackers_info[tracker['status']] = dict(count=0, num_peers=0) trackers_info[tracker['status']]['count'] += 1 trackers_info[ tracker['status']]['num_peers'] += tracker['num_peers'] lines_list = list() for status, status_counts in trackers_info.items(): lines_list.append('<b>{}</b>: {} trackers, {} peers'.format( status, status_counts['count'], status_counts['num_peers'])) text = '\n'.join(lines_list) update.callback_query.edit_message_text( text or 'No trackers', reply_markup=torrent.actions_keyboard, parse_mode=ParseMode.HTML, disable_web_page_preview=True) update.callback_query.answer('Trackers list')
def see_trackers_cb(update: Update, context: CallbackContext): logger.info('trackers inline button') torrent_hash = context.match[1] logger.info('torrent hash: %s', torrent_hash) torrent = qb.torrent(torrent_hash) trackers = torrent.trackers() strings_list = [ '<b>{status}:</b> {url} <b>({num_peers} peers)</b>'.format( **{k: u.html_escape(str(v)) for k, v in tracker.items()}) for tracker in trackers ] text = '\n'.join(strings_list) if len(text) > MAX_MESSAGE_LENGTH: trackers_info = dict() for tracker in trackers: tracker_status = tracker['status'] if not trackers_info.get(tracker_status, None): trackers_info[tracker_status] = dict(count=0, num_peers=0) trackers_info[tracker_status]['count'] += 1 trackers_info[tracker_status]['num_peers'] += tracker['num_peers'] lines_list = list() for status, status_counts in trackers_info.items(): lines_list.append( f"<b>{status}</b>: {status_counts['count']} trackers, {status_counts['num_peers']} peers" ) text = '\n'.join(lines_list) update.callback_query.edit_message_text( text or 'No trackers', reply_markup=torrent.actions_keyboard, parse_mode=ParseMode.HTML) update.callback_query.answer('Trackers list')
def notify_completed(context: CallbackContext): logger.info('executing completed job') completed = qb.torrents(filter='completed') for t in completed: if not completed_torrents.is_new(t.hash): continue torrent = qb.torrent(t.hash) logger.info('completed: %s (%s)', torrent.hash, torrent.name) if not config.telegram.get('completed_torrents_notification', None): continue if not dont_notify_torrents.send_notification(t.hash): logger.info('notification disabled for torrent %s (%s)', t.hash, t.name) continue tags_lower = [tag.lower() for tag in torrent.tags] if config.telegram.get( "no_notification_tag", None ) and config.telegram.no_notification_tag.lower() in tags_lower: continue drive_free_space = u.free_space(qb.save_path) text = '<code>{}</code> completed ({}, free space: {})'.format( u.html_escape(torrent.name), torrent.size_pretty, drive_free_space) context.bot.send_message( chat_id=config.telegram.completed_torrents_notification, text=text, parse_mode=ParseMode.HTML, disable_web_page_preview=True, disable_notification=True)
'forcedDL': 'forced download', 'checkingResumeData': 'startup: checking data', 'moving': 'moving', 'unknown': 'unknown status' } # https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-torrent-list # https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-torrent-generic-properties NEW_ATTRS = { 'state_pretty': lambda t: STATES_DICT.get(t['state'], t['state']), 'size_pretty': lambda t: u.get_human_readable(t['total_size']), # already a string apparently 'dl_speed_pretty': lambda t: u.get_human_readable(t['dl_speed']), 'up_speed_pretty': lambda t: u.get_human_readable(t['up_speed']), 'dlspeed_pretty': lambda t: u.get_human_readable(t['dlspeed']), 'upspeed_pretty': lambda t: u.get_human_readable(t['upspeed']), 'name_escaped': lambda t: u.html_escape(t['name']), 'generic_speed_pretty': lambda t: u.get_human_readable(t['generic_speed']), 'progress_pretty': lambda t: math.floor(t['progress'] * 100), # eg. 99.9% should be rounded to 99% 'eta_pretty': lambda t: str(datetime.timedelta(seconds=t['eta'])), # apparently it's already a string? 'time_elapsed_pretty': lambda t: str(datetime.timedelta(seconds=t['time_elapsed'])), 'force_start_pretty': lambda t: 'yes' if t['force_start'] else 'no', 'share_ratio_rounded': lambda t: round(t['ratio'], 2), 'dl_limit_pretty': lambda t: 'no limit' if t['dl_limit'] == -1 else u.get_human_readable(t['dl_limit']), 'auto_tmm_string': lambda t: 'yes' if t['auto_tmm'] else 'no', } TORRENT_STRING = """<code>{name_escaped}</code> {progress_bar} {progress_pretty}% <b>state</b>: {state_pretty} <b>size</b>: {size_pretty} <b>dl/up speed</b>: {dl_speed_pretty}/s, {up_speed_pretty}/s