def delete_message(call: CallbackQuery, admin_bot: TeleBot): _, chat_id, message_id, op_name = call.data.split(':') user_bot = TeleBot(USER_BOT_TOKEN) try: user_bot.delete_message(chat_id, message_id) except ApiException: resp = '`Это сообщение уже удалено!`' else: resp = '`Вы удалили это собщение`' # print(resp) admin_bot.edit_message_text(resp, call.from_user.id, call.message.message_id, parse_mode='Markdown')
def _callback(bot: TeleBot, call: CallbackQuery) -> None: """Callbacks from inline buttons.""" if call.message: callbacks_actions: dict = { "butovo": _get_butovo_warehouse_info, "neva": _get_neva_warehouse_info, "butovo_art": _get_article_text_butovo, "neva_art": _get_article_text_neva } if call.data not in callbacks_actions: return message_text: str = callbacks_actions[call.data]() bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=message_text)
def change_message(bot: TeleBot, logger, message: Message, text=None, parse_mode=None, reply_markup=None): try: if not text is None: changed_message = bot.edit_message_text(text, message.chat.id, message.message_id, parse_mode=parse_mode) if not reply_markup is None: bot.edit_message_reply_markup(message.chat.id, message.message_id, reply_markup=reply_markup) return change_message except telebot.apihelper.ApiException as e: if 'bot was kicked' is e.args[0]: logger.error(f"Bot has kicked from group {message.chat.id}.") else: raise (e)
def calendar_query_handler( bot: TeleBot, call: CallbackQuery, name: str, action: str, year: int, month: int, day: int, ) -> None or datetime.datetime: """ The method creates a new calendar if the forward or backward button is pressed This method should be called inside CallbackQueryHandler. :param bot: The object of the bot CallbackQueryHandler :param call: CallbackQueryHandler data :param day: :param month: :param year: :param action: :param name: :return: Returns a tuple """ current = datetime.datetime(int(year), int(month), 1) if action == "IGNORE": bot.answer_callback_query(callback_query_id=call.id) return False, None elif action == "DAY": bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id) return datetime.datetime(int(year), int(month), int(day)) elif action == "PREVIOUS-MONTH": preview_month = current - datetime.timedelta(days=1) bot.edit_message_text( text=call.message.text, chat_id=call.message.chat.id, message_id=call.message.message_id, reply_markup=create_calendar(name=name, year=int(preview_month.year), month=int(preview_month.month)), ) return None elif action == "NEXT-MONTH": next_month = current + datetime.timedelta(days=31) bot.edit_message_text( text=call.message.text, chat_id=call.message.chat.id, message_id=call.message.message_id, reply_markup=create_calendar(name=name, year=int(next_month.year), month=int(next_month.month)), ) return None elif action == "MONTHS": bot.edit_message_text( text=call.message.text, chat_id=call.message.chat.id, message_id=call.message.message_id, reply_markup=create_months_calendar(name=name, year=current.year), ) return None elif action == "MONTH": bot.edit_message_text( text=call.message.text, chat_id=call.message.chat.id, message_id=call.message.message_id, reply_markup=create_calendar(name=name, year=int(year), month=int(month)), ) return None elif action == "Выход": bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id) return "Выход", None else: #bot.answer_callback_query(callback_query_id=call.id, text="ERROR!") bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id) return None
def render_pagination(pagination: Pagination, message: Message, bot: TeleBot, text: str, keyboard_func, update=False, updateText=False): if pagination.total: available_competitors_encoded_names = [] for c in pagination.items: available_competitors_encoded_names.append([ f'{c.name}. {get_translation_for("info_level_str")}: {f"({c.level})"if c.level else "(_)"}.', str(c.id) ]) update_failed = False if update: try: if updateText: bot.edit_message_text( text, message.chat.id, message.message_id, reply_markup=keyboard_func( names=available_competitors_encoded_names, has_pages=pagination.pages > 1, cur_page=pagination.page, pages=pagination.pages, has_next=pagination.has_next, has_prev=pagination.has_prev)) else: bot.edit_message_reply_markup( message.chat.id, message.message_id, reply_markup=keyboard_func( names=available_competitors_encoded_names, has_pages=pagination.pages > 1, cur_page=pagination.page, pages=pagination.pages, has_next=pagination.has_next, has_prev=pagination.has_prev)) except ApiException as e: j = loads(e.result.text) if j['description'].find('is not modified') != -1: logger.warning( f'Pagination update resulted in the same message. New message is not sent: {message.chat.id}' ) else: logger.exception( f'Exception occurred while updating keyboard pagination. Chat: {message.chat.id}' ) update_failed = True except Exception: logger.exception( f'Exception occurred while updating keyboard pagination. Chat: {message.chat.id}' ) update_failed = True if not update or update_failed: bot.send_message(message.chat.id, text, reply_markup=keyboard_func( names=available_competitors_encoded_names, has_pages=pagination.pages > 1, cur_page=pagination.page, pages=pagination.pages, has_next=pagination.has_next, has_prev=pagination.has_prev)) return True return False
class BOT: index = 0 count_films = utils.STEP config_file_name = 'config.json' def __init__(self): self.cfg = self.JSON() self.construct() def construct(self): self.bot = TeleBot(self.cfg['token']) self.commands = { "List films": utils.call(self.manage), "Unsubscribe": utils.call(self.del_user), } self.film_view_markup = { "back": utils.call(self.revert), "open": utils.call(lambda *x, **b:...), } self.markup = { "1": utils.call(self.film, 0), "2": utils.call(self.film, 1), "3": utils.call(self.film, 2), "4": utils.call(self.film, 3), "5": utils.call(self.film, 4), "6": utils.call(self.film, 5), "7": utils.call(self.film, 6), "8": utils.call(self.film, 7), "9": utils.call(self.film, 8), "10": utils.call(self.film, 9), "prev": utils.call(self.prev), "next": utils.call(self.next), } @self.bot.message_handler( commands=['subscribe', 'unsubscribe', 'categories', 'find']) def subscribe_detector(message): try: if "/subscribe" in message.text: category = message.text.split("/subscribe")[-1].strip() if category in list(self.cfg['categories'].keys()): uinfo = (message.chat.id, category) db = utils.DATABASE(self.cfg["db_name"]) db.insert(table_name="subscribe_categories", args=uinfo) self.bot.reply_to( message, self.cfg["subscribe_category"].replace( "{}", category)) else: self.bot.send_message(message.chat.id, self.cfg["category_not_found"]) elif "/unsubscribe" in message.text: category = message.text.split("/unsubscribe")[-1].strip() if category in self.cfg['categories']: db = utils.DATABASE(self.cfg["db_name"]) db.delete(table_name="subscribe_categories", where=" chat_id = " + str(message.chat.id)) self.bot.reply_to( message, self.cfg["unsibscribe_category"].replace( "{}", category)) else: self.bot.send_message(message.chat.id, self.cfg["category_not_found"]) elif "/find" in message.text: film_name = message.text.split("/find")[-1].strip() finded = utils.load_films( db_name=self.cfg['db_name'], find_perc=[film_name, self.cfg['film_perc']]) finded.extend( utils.load_films(db_name=self.cfg['db_name'], find=film_name)) message_ = "" for i, film in enumerate(finded): message_ += "{}. {}\n{}\n\n".format( i + 1, film[1], film[3]) messages_ = [] if len(message_) > 2800: count = int(len(message_) / 2800) s = 0 for i in range(count): ns = s + 2800 if len(message_) < ns: ns = -1 msg = message_[s:ns] messages_.append(msg) s = ns if not ns: break else: messages_.append(message_) for msg in messages_: if len(msg) > 2: self.bot.send_message(message.chat.id, msg) else: self.bot.send_message(message.chat.id, self.cgf['no_film_error']) elif "/categories" in message.text: msg = "" for i, key in enumerate(list(self.cfg["categories"])): msg += "{} : {}\n".format(i, key) self.bot.send_message( message.chat.id, self.cfg['categories_text'].replace("{}", msg)) except Exception as e: # utils.log(e) raise @self.bot.callback_query_handler(func=lambda call: True) def callback_query(call): try: if call.data in self.markup.keys(): self.markup[call.data](call) elif call.data in self.film_view_markup.keys(): self.film_view_markup[call.data](call) except Exception as e: utils.log(e) @self.bot.message_handler(func=lambda x: True) def main(message): try: utils.add_user(message=message, db_name=self.cfg['db_name']) if message.text in self.commands: self.commands[message.text](message) else: self.bot.send_message(message.chat.id, text=self.cfg['base_message'], reply_markup=utils.repl_markup( list(self.commands.keys()))) except Exception as e: utils.log(e) def JSON(self): return utils.loads(open(self.config_file_name).read()) def del_user(self, message): self.bot.send_message(message.chat.id, self.cfg["global_unsubscribe"]) utils.delete_subscriber(message.chat.id, db_name=self.cfg['db_name']) def manage(self, message, text=None): self.bot.send_message( message.chat.id, text=utils.new_message( msg=text if text else self.cfg['default_message'], db_name=self.cfg["db_name"], repl=self.cfg['message_repl']), reply_markup=utils.inline_markup(self.markup)) def revert(self, call): id = call.message.chat.id messages = utils.new_message(index=self.index, msg=self.cfg['default_message'], repl=self.cfg['message_repl'], db_name=self.cfg["db_name"]) self.bot.delete_message(id, call.message.message_id) self.bot.send_message(id, text=messages, reply_markup=utils.inline_markup(self.markup)) self.bot.answer_callback_query(call.id, "Success") def send_all(self, msg): mkp = utils.repl_markup(utils.START_MARKUP) for id in utils.get_all_subscribers_id(db_name=self.cfg["db_name"]): try: self.bot.send_message(id, msg, reply_markup=mkp) except Exception as e: utils.delete_subscriber(id, db_name=self.cfg["db_name"]) def film(self, call, id=0): id_ = call.message.chat.id db = utils.DATABASE(self.cfg['db_name']) film_info = db.read(table_name="films", where=" id = '{}'".format( utils.class_db.film_list[id][1]))[0] db.close() def download(): utils.image_download(film_info[2]) t = Thread(target=download) t.start() t.join() self.bot.delete_message(id_, call.message.message_id) self.bot.send_photo( chat_id=id_, photo=open(".image.jpg", "rb"), reply_markup=utils.inline_markup(self.film_view_markup), caption=utils.render_film_info(film_info[0], db_name=self.cfg["db_name"])) def next(self, call): utils.class_db.index += utils.STEP messages = utils.new_message(msg=self.cfg['default_message'], repl=self.cfg['message_repl'], index=utils.class_db.index, db_name=self.cfg["db_name"]) self.bot.edit_message_text(text=messages, chat_id=call.message.chat.id, message_id=call.message.message_id, reply_markup=utils.inline_markup( self.markup), inline_message_id=call.inline_message_id) def prev(self, call): utils.class_db.index -= utils.STEP if utils.class_db.index < 0: utils.class_db.index = 0 self.bot.answer_callback_query(call.id, self.cfg['no_films_error']) return True message = utils.new_message(msg=self.cfg['default_message'], repl=self.cfg['message_repl'], index=utils.class_db.index, db_name=self.cfg["db_name"]) self.bot.edit_message_text(text=message, chat_id=call.message.chat.id, message_id=call.message.message_id, reply_markup=utils.inline_markup( self.markup), inline_message_id=call.inline_message_id) def start(self, msg=True): if msg: self.send_all(self.cfg["start_message"]) utils.new_message(msg=self.cfg['default_message'], repl=self.cfg['message_repl'], db_name=self.cfg["db_name"]) self.bot.polling() def stop(self): self.bot.stop_polling()
def process_callback(self, callback: CallbackQuery, user: User, bot: TeleBot): data = callback.data if data.find('challenge_to_') != 0: return RET.ANSWER_CALLBACK, None, callback, user data = data.replace('challenge_to_', '') competitor: Competitor = user.check_association() if not competitor: bot.send_message( callback.message.chat.id, get_translation_for('competitor_record_vanished_msg')) return RET.ANSWER_AND_GO_TO_STATE, 'AuthenticationState', callback, user if data.find('user='******'=') if len(ds) == 2: opponent_id = ds[1] try: opponent = Competitor.objects(id=opponent_id).first() if opponent is not None: text = get_translation_for( 'challenge_send_confirm_msg').format(opponent.name) text = f'<b>{text}</b>\n' \ f'{get_translation_for("info_status_str")}: {Competitor.status_code_to_str_dict[opponent.status]}\n' \ f'{get_translation_for("info_level_str")}: {opponent.level or get_translation_for("not_found_str")}\n' \ f'{get_translation_for("info_matches_str")}: {opponent.matches}\n' \ f'{get_translation_for("info_wins_str")}: {opponent.wins}\n' \ f'{get_translation_for("info_losses_str")}: {opponent.losses}\n' \ f'{get_translation_for("info_performance_str")}: {opponent.performance}' update_failed = False try: bot.edit_message_text( text, callback.message.chat.id, callback.message.message_id, reply_markup=self.__confirmation_keyboard( id=opponent_id), parse_mode='html') except: update_failed = True logger.exception( f'Exception occurred while updating keyboard for challenge sending. Chat: {callback.message.chat.id}' ) if update_failed: bot.send_message( callback.message.chat.id, text, reply_markup=self.__confirmation_keyboard( id=opponent_id), parse_mode='html') return RET.ANSWER_CALLBACK, None, callback, user else: return RET.ANSWER_CALLBACK, get_translation_for( 'authentication_specified_competitor_not_found_clb' ), callback, user except ValidationError: logger.exception( f'Incorrect opponent_id: {opponent_id} from user with user_id: {user.user_id}' ) elif data.find('paginate=') == 0: ds = data.split('=') if len(ds) == 2: page = ds[1] page = to_int(page, 1) try: available_competitors = Competitor.objects( status__in=(COMPETITOR_STATUS.ACTIVE, COMPETITOR_STATUS.PASSIVE), level__in=self.get_possible_levels(competitor.level), id__ne=competitor.latest_challenge_sent_to.id if competitor.latest_challenge_sent_to is not None else ObjectId(), associated_user_vanished__ne=True).paginate( page=page, per_page=10) except NotFound: logger.exception( f'User {user.user_id} tried to switch to nonexistent page {page}' ) available_competitors = Competitor.objects( status__in=(COMPETITOR_STATUS.ACTIVE, COMPETITOR_STATUS.PASSIVE), level__in=self.get_possible_levels(competitor.level), id__ne=competitor.latest_challenge_sent_to.id if competitor.latest_challenge_sent_to is not None else ObjectId(), associated_user_vanished__ne=True).paginate( page=1, per_page=10) if not render_pagination( available_competitors, callback.message, bot, get_translation_for('challenge_send_msg'), self.__base_keyboard, update=True): bot.send_message( callback.message.chat.id, get_translation_for( 'challenge_no_applicable_competitors_msg')) elif data.find('none') == 0: return RET.ANSWER_CALLBACK, None, callback, user elif data.find('refresh') == 0: if guard.get_allowed()[0] and guard.update_allowed()[0]: UsersSheet.update_model() available_competitors = Competitor.objects( status__in=(COMPETITOR_STATUS.ACTIVE, COMPETITOR_STATUS.PASSIVE), level__in=self.get_possible_levels(competitor.level), id__ne=competitor.latest_challenge_sent_to.id if competitor.latest_challenge_sent_to is not None else ObjectId(), associated_user_vanished__ne=True).paginate(page=1, per_page=10) if not render_pagination( available_competitors, callback.message, bot, get_translation_for('challenge_send_msg'), self.__base_keyboard, update=True, ): bot.send_message( callback.message.chat.id, get_translation_for( 'challenge_no_applicable_competitors_msg')) elif data.find('confirm_send=') == 0: ds = data.split('=') if len(ds) == 2: opponent_id = ds[1] if competitor.latest_challenge_sent_to and opponent_id == str( competitor.latest_challenge_sent_to): bot.send_message( callback.message.chat.id, get_translation_for( 'challenge_opponent_no_longer_available_msg')) return RET.ANSWER_AND_GO_TO_STATE, 'MenuState', callback, user try: opponent: Competitor = Competitor.objects( status__in=(COMPETITOR_STATUS.ACTIVE, COMPETITOR_STATUS.PASSIVE), level__in=self.get_possible_levels(competitor.level), id=opponent_id, associated_user_vanished__ne=True).first() if opponent is None: bot.send_message( callback.message.chat.id, get_translation_for( 'challenge_opponent_no_longer_available_msg')) return RET.ANSWER_AND_GO_TO_STATE, 'MenuState', callback, user opponent_user: User = User.objects( associated_with=opponent).first() if opponent_user is None: bot.send_message( callback.message.chat.id, get_translation_for( 'challenge_cannot_send_message_to_opponent_msg' )) send_msg_to_admin( get_translation_for( 'admin_notification_tg_user_vanished').format( opponent.name)) opponent.associated_user_vanished = True opponent.save() return RET.ANSWER_AND_GO_TO_STATE, 'MenuState', callback, user config = get_config() if opponent.status == COMPETITOR_STATUS.ACTIVE: if not smwae_check( opponent_user.user_id, get_translation_for( 'challenge_you_are_challenged_msg').format( user.user_id, competitor.name, competitor.level, config.time_to_accept_challenge), opponent_user, reply_markup= get_challenge_confirmation_keyboard(), parse_mode='html'): bot.send_message( callback.message.chat.id, get_translation_for( 'error_bot_blocked_by_opponent_challenge_canceled_msg' ) + '\n' + get_translation_for( 'error_bot_blocked_by_opponent_challenge_canceled_contact_admin_str' ), parse_mode='html') return RET.ANSWER_AND_GO_TO_STATE, 'MenuState', callback, user opponent_user.reload() opponent_user.states.append('ChallengeReceivedState') if len(opponent_user.states) > STATES_HISTORY_LEN: del opponent_user.states[0] opponent_user.save() elif opponent.status == COMPETITOR_STATUS.PASSIVE: if not smwae_check( opponent_user.user_id, get_translation_for( 'challenge_you_are_challenged_passive_msg' ).format(user.user_id, competitor.name, competitor.level, config.time_to_accept_challenge), opponent_user, reply_markup= get_challenge_confirmation_keyboard(), parse_mode='html'): bot.send_message( callback.message.chat.id, get_translation_for( 'error_bot_blocked_by_opponent_challenge_canceled_msg' ) + '\n' + get_translation_for( 'error_bot_blocked_by_opponent_challenge_canceled_contact_admin_str' ), parse_mode='html') return RET.ANSWER_AND_GO_TO_STATE, 'MenuState', callback, user opponent_user.reload() opponent_user.states.append('ChallengeReceivedState') if len(opponent_user.states) > STATES_HISTORY_LEN: del opponent_user.states[0] opponent_user.save() else: logger.error( f'Trying to send message to opponent with incorrect state: {opponent.name} {opponent.legacy_number}' ) bot.send_message( callback.message.chat.id, get_translation_for( 'error_occurred_contact_administrator_msg'), parse_mode='html') return RET.ANSWER_AND_GO_TO_STATE, 'MenuState', callback, user opponent.previous_status = opponent.status opponent.change_status( COMPETITOR_STATUS.CHALLENGE_NEED_RESPONSE) opponent.in_challenge_with = competitor opponent.latest_challenge_received_at = datetime.now( tz=timezone('Europe/Kiev')) opponent.challenge_remainder_sent = False opponent.save() competitor.previous_status = competitor.status competitor.change_status( COMPETITOR_STATUS.CHALLENGE_INITIATED) competitor.in_challenge_with = opponent competitor.latest_challenge_sent_to = opponent competitor.challenge_remainder_sent = False competitor.save() user.dismiss_confirmed = False user.save() bot.send_message( callback.message.chat.id, get_translation_for('challenge_sent_msg').format( opponent_user.user_id, opponent.name), parse_mode='html') LogsSheet.glog( get_translation_for( 'gsheet_log_player_created_challenge_for_player'). format(competitor.name, opponent.name)) return RET.ANSWER_AND_GO_TO_STATE, 'MenuState', callback, user except ValidationError: logger.exception( f'Incorrect opponent_id: {opponent_id} from user with user_id: {user.user_id}' ) elif data.find('cancel_send') == 0: if not self.update_and_paginate(callback.message, user, bot, competitor, update=True, updateText=True): bot.send_message( callback.message.chat.id, get_translation_for( 'challenge_no_applicable_competitors_msg')) elif data.find('back') == 0: return RET.ANSWER_AND_GO_TO_STATE, 'MenuState', callback, user return RET.ANSWER_CALLBACK, None, callback, user
class TelegramBot: def __init__(self): try: self._user_bot = TeleBot(Settings.UserBot.token) self._admin_bot = TeleBot(Settings.AdminBot.token) self._log = Logger(self._admin_bot, self._user_bot, Settings.logger_name, Settings.AdminBot.id, Settings.path_to_logs) self._statuses = Status(self._log) self._processing = Processing(self._log) self._networks = Networks(self._log, Settings.Networks.path_to_models) self._deepdream = DeepDream(self._log, self._user_bot, self._admin_bot, Settings.Photo.path, self._send_mail) self._colorize = Colorize(self._log, self._user_bot, self._admin_bot, Settings.Photo.path, self._send_mail) self._init_handlers() self._log.admin_info("Bot is running!!") self._log.info("Bot is running!!") self.start() except SystemExit: pass except BaseException as e: self._processing.stop_all() self._log.fatal("Bot is not running!!", e=e.args) def start(self): self._user_bot.polling(none_stop=True, interval=1) # local functions def _random_string(self, n): a = string.ascii_letters + string.digits return ''.join([random.choice(a) for i in range(n)]) # web functions def _send_mail(self, mess, first_photo, second_photo, msg): try: file_path_one = Settings.Photo.path + first_photo file_path_two = Settings.Photo.path + second_photo msg_root = MIMEMultipart('related') msg_root[ 'Subject'] = mess.from_user.first_name + " " + mess.from_user.last_name msg_root['From'] = Settings.Mail.username msg_root['To'] = Settings.Mail.username msg_root.preamble = 'This is a multi-part message in MIME format.' msg_alternative = MIMEMultipart('alternative') msg_root.attach(msg_alternative) msg_text = MIMEText( '<i>' + msg + '</i><br><img src="cid:image1"><img src="cid:image2"><br>', 'html') msg_alternative.attach(msg_text) fp = open(file_path_one, 'rb') msg_image_one = MIMEImage(fp.read()) fp.close() msg_image_one.add_header('Content-ID', '<image1>') msg_root.attach(msg_image_one) fp = open(file_path_two, 'rb') msg_image_two = MIMEImage(fp.read()) fp.close() msg_image_two.add_header('Content-ID', '<image2>') msg_root.attach(msg_image_two) smtp = smtplib.SMTP('smtp.mail.ru:587') smtp.ehlo() smtp.starttls() smtp.login(Settings.Mail.username, Settings.Mail.password) smtp.sendmail(Settings.Mail.username, Settings.Mail.username, msg_root.as_string()) smtp.quit() except BaseException as e: self._log.warning("Mail sending error [" + mess.from_user.id + "]") def _download_photo(self, message): try: photo_name = self._random_string(8) photo_id = message.photo[-1].file_id photo_image = self._user_bot.download_file( self._user_bot.get_file(photo_id).file_path) with open(Settings.Photo.path + photo_name + ".jpg", 'wb') as imgfile: imgfile.write(photo_image) return photo_name except BaseException as e: self._log.error( "Can`t download photo [" + message.from_user.id + "]", message.from_user.id, e.args) # handlers def _text_mess(self, message): self._user_bot.send_message(message.from_user.id, message.text) def _photo_mess(self, message): try: if self._statuses[message.from_user.id].get_status() == 0: self._user_bot.send_message(message.from_user.id, "I don't know what to do 😕") else: photo_name = self._download_photo(message) if self._statuses[message.from_user.id].get_status() == 32: self._colorize_function(message, photo_name) elif self._statuses[message.from_user.id].get_status() == 23: self._deepdream_function(message, photo_name) except BaseException as e: self._log.error("Something went wrong with photo", message.from_user.id, e.args) # handlers commands def _deepdream_command(self, message): try: keyboard = types.InlineKeyboardMarkup() for net in self._networks.get_parameterized_keys(): callback_button = types.InlineKeyboardButton( text=net, callback_data="deepdream_net_" + net) keyboard.add(callback_button) self._user_bot.send_message(message.chat.id, "Please, choose a neural network", reply_markup=keyboard) self._statuses[message.chat.id].set_status(21) except BaseException as e: self._log.error("DeepDream command error ", message.from_user.id, e.args) def _colorize_command(self, message): try: keyboard = types.InlineKeyboardMarkup() for net in self._networks.get_standart_keys(): callback_button = types.InlineKeyboardButton( text=net, callback_data="colorize_net_" + net) keyboard.add(callback_button) self._user_bot.send_message(message.chat.id, "Please, choose a neural network", reply_markup=keyboard) self._statuses[message.chat.id].set_status(31) except BaseException as e: self._log.error("Colorize command error ", message.from_user.id, e.args) def _stop_command(self): self._processing.stop_all() self._log.warning("Bot is stopped!") self._log.admin_info("Bot is stopped!") #self._user_bot.stop_polling() def _stop_process_command(self, i): self._processing.stop_process(i) def _stop_all_command(self): self._processing.stop_all() # callbacks def _deepdream_callback(self, call): try: if call.data[:14] == "deepdream_net_": if self._statuses[call.message.chat.id].get_status() == 21: self._statuses[call.message.chat.id].set_net( call.data[14:]) self._user_bot.edit_message_text( chat_id=call.message.chat.id, message_id=call.message.message_id, text=call.data[14:]) layers = self._networks.get_parameterized_net( self._statuses[ call.message.chat.id].get_net()).get_layers() keyboard = types.InlineKeyboardMarkup() for layer in layers: self._log.debug(layer) callback_button = types.InlineKeyboardButton( text=layer, callback_data="deepdream_layer_" + layer) keyboard.add(callback_button) self._user_bot.send_message(call.message.chat.id, "Please, choose layer level", reply_markup=keyboard) self._statuses[call.message.chat.id].set_status(22) elif call.data[:16] == "deepdream_layer_": if self._statuses[call.message.chat.id].get_status() == 22: self._statuses[call.message.chat.id].set_layer( str(call.data[16:]).replace(".", "/")) self._user_bot.edit_message_text( chat_id=call.message.chat.id, message_id=call.message.message_id, text=call.data[16:]) self._user_bot.send_message(call.message.chat.id, "Send your photo, please") self._statuses[call.message.chat.id].set_status(23) except BaseException as e: self._log.error("Something went wrong with callback", call.message.from_user.id, e.args) def _colorize_callback(self, call): try: if call.data[:13] == "colorize_net_": if self._statuses[call.message.chat.id].get_status() == 31: self._statuses[call.message.chat.id].set_net( call.data[13:]) self._user_bot.edit_message_text( chat_id=call.message.chat.id, message_id=call.message.message_id, text=call.data[13:]) self._user_bot.send_message(call.message.chat.id, "Send your photo, please") self._statuses[call.message.chat.id].set_status(32) except BaseException as e: self._log.error("Something went wrong with callback", call.message.from_user.id, e.args) # functional def _deepdream_function(self, message, photo_name): try: args = (message, photo_name + ".jpg", self._networks.get_parameterized_net(self._statuses[ message.from_user.id].get_net()).get_model(), self._statuses[message.from_user.id].get_layer()) self._processing.new_process(self._deepdream.start_deep_dream, args, "DeepDream", message.from_user.id) self._user_bot.send_message(message.from_user.id, "I'm working on it") self._statuses[message.from_user.id].set_status(0) except BaseException as e: self._log.error("Something went wrong with deepdream starting", message.from_user.id, e.args) def _colorize_function(self, message, photo_name): try: args = (message, photo_name + ".jpg", self._networks.get_standart_net(self._statuses[ message.from_user.id].get_net()).get_model()) self._processing.new_process(self._colorize.start_colorize, args, "Colorize", message.from_user.id) self._user_bot.send_message(message.from_user.id, "I'm working on it") self._statuses[message.from_user.id].set_status(0) except BaseException as e: self._log.error("Something went wrong with colorize starting", message.from_user.id, e.args) def _weather_function(self, message): pass # init handlers def _init_handlers(self): # admin @self._user_bot.message_handler(commands=['stopbot']) def handle_command(message): if message.from_user.id == Settings.AdminBot.id: self._stop_command() @self._user_bot.message_handler(commands=['allprocessesstop']) def handle_command(message): if message.from_user.id == Settings.AdminBot.id: self._stop_all_command() @self._user_bot.message_handler(commands=['processstop']) def handle_command(message): if message.from_user.id == Settings.AdminBot.id: self._stop_process_command(int(message.text.split()[1])) # user @self._user_bot.message_handler(commands=['weather']) def handle_command(message): self._weather_function(message) @self._user_bot.message_handler(commands=['colorize']) def handle_command(message): self._colorize_command(message) @self._user_bot.message_handler(commands=['deepdream']) def handle_command(message): self._deepdream_command(message) @self._user_bot.message_handler(content_types=['text']) def handle_text(message): self._text_mess(message) @self._user_bot.message_handler(content_types=['photo']) def handle_photo(message): self._photo_mess(message) @self._user_bot.callback_query_handler(func=lambda call: True) def callback_inline(call): if call.data[:9] == "deepdream": self._deepdream_callback(call) elif call.data[:8] == "colorize": self._colorize_callback(call)
class TelegramBot: def __init__(self, work_dir: Path, token: str): self.last_requests = {} # type: Dict[int, List[datetime]] self.work_dir = work_dir self.work_dir.mkdir(0o755, parents=True, exist_ok=True) self.token = token self.bot = TeleBot(token) self.bot.add_message_handler({ 'function': self.process_link, 'filters': { 'regexp': r'https?:\/\/.+\..+' } }) self.bot.add_message_handler({ 'function': self.process_message, 'filters': { 'func': lambda _: True } }) def process_link(self, message: Message): user_id = message.from_user.id if user_id not in self.last_requests: self.last_requests[user_id] = [] limit_req, limit_min = get_rate_limit() now = datetime.now(tz=timezone.utc) last_requests = [] for dt in self.last_requests[user_id]: time_passed = now - dt if time_passed.min < timedelta(minutes=limit_min): last_requests.append(dt) self.last_requests[user_id] = last_requests if len(self.last_requests[user_id]) > limit_req: next_available = self.last_requests[user_id][0] + timedelta( minutes=limit_min) - now self.bot.reply_to( message, f'Rate limited. Try again in {next_available.seconds} seconds') return else: self.last_requests[user_id].append(now) msg = self.bot.reply_to(message, "Link detected, processing") # detach from telebot update thread def download(): try: with YoutubeDL({'noplaylist': True}) as ydl: info = ydl.extract_info(message.text, download=False) if info['duration'] > 900: self.bot.edit_message_text('Source too long', message_id=msg.id, chat_id=msg.chat.id) return with YoutubeDL(get_options_audio(self.work_dir)) as ydl: ydl.add_post_processor( UploadHandler(self.bot, msg.id, msg.chat.id)) self.bot.edit_message_text('Downloading', message_id=msg.id, chat_id=msg.chat.id) ydl.download([message.text]) except UnsupportedError: self.bot.edit_message_text('Unsupported URL', message_id=msg.id, chat_id=msg.chat.id) except DownloadError: self.bot.edit_message_text('Download error', message_id=msg.id, chat_id=msg.chat.id) except Exception as e: self.bot.edit_message_text('Unknown error', message_id=msg.id, chat_id=msg.chat.id) logger.error('Unknown error', exc_info=e) reactor.callInThread(lambda: download()) def process_message(self, message: Message): self.bot.reply_to(message, 'Send me a link') def polling(self): self.bot.delete_webhook() self.bot.polling(long_polling_timeout=5) def stop_polling(self): self.bot.stop_polling() def set_webhook(self, host: str, port: int): cert_path, pkey_path = get_or_create_root_cert(self.work_dir, host) self.bot.remove_webhook() self.bot.set_webhook(url=f'https://{host}:{port}/{self.token}/', certificate=open(cert_path, 'r')) bot = self.bot class WebhookHandler(Resource): isLeaf = True def render_POST(self, request): request_body_dict = json.load(request.content) update = Update.de_json(request_body_dict) reactor.callInThread(lambda: bot.process_new_updates([update])) return b'' root = ErrorPage(403, 'Forbidden', '') root.putChild(self.token.encode(), WebhookHandler()) site = Site(root) sslcontext = ssl.DefaultOpenSSLContextFactory(str(pkey_path), str(cert_path)) reactor.listenSSL(port, site, sslcontext)
class CashbackBot: def __init__(self, token): '''Подключение к Telegram, SQL''' self.bot = TeleBot(token) '''это кнопка отмены, она часто используется, поэтому я добавил ее в переменные класса''' self.button_cancel = InlineKeyboardButton(text = "❌", callback_data = "cancel") '''переменная для обозначения предпринимателей, которые находятся в процессе настройки процентов''' self.users_in_process = [] def start_command(self, query, is_callback_query=False): if not is_callback_query: message = query if not self.id_exists_in_table("id",message.from_user.id,"users"): if " " in message.text: ref_data = message.text.split()[1] if ref_data[0] == "o": ref_data = ref_data.split("o")[1] inst_id = int(ref_data) inst_name = self.sql.get_institution_info_by_id(inst_id)['institution_name'] self.bot.send_message(user_id, parse_mode = "HTML", text = f"Теперь вы оператор <b>{inst_name}</b>!") self.bot.send_message(message.chat.id, "Оператор приглашен.") # тут нужен sql elif ref_data[0] == "u" ref_data = ref_data.split("u") inst_id = int(ref_data[1]) user_id = int(ref_data[0]) inst_name = self.sql.get_institution_info_by_id(inst_id)['institution_name'] self.bot.send_message(user_id, parse_mode = "HTML", text = f"У вас новый реферал на предприятие <b>{inst_name}</b>!\n Имя реферала:<b>{user_name}</b>") self.bot.send_message(message.chat.id, f"Вы были приглашены по реферальной ссылке к предприятию <b>{inst_name}</b>", parse_mode = "HTML") # тут нужен sql self.sql.create_user_as(message.from_user.id, message.from_user.first_name + " " + message.from_user.last_name, "customer") keyboard = InlineKeyboardMarkup() button_buy = InlineKeyboardButton(text = "Совершить покупку", callback_data = "menu|buy") button_referal = InlineKeyboardButton(text = "Реферальная программа", callback_data = "menu|refer") button_about = InlineKeyboardButton(text = "О боте", callback_data = "menu|about") keyboad.add(button_buy, button_referal) keyboard.add(button_about, self.button_cancel) self.bot.send_message(message.chat.id, f"Здравствуйте <b>{message.from_user.first_name}</b>", parse_mode = "HTML", reply_markup = keyboard) else: call = query if call.data.startswith("menu"): menu_type = call.data.split("|")[1] if menu_type == "buy": keyboard = InlineKeyboardMarkup() button_bonus_plus = InlineKeyboardButton(text = "Начислить", callback_data = "bonus|plus") button_bonus_mins = InlineKeyboardButton(text = "Списать", callback_data = "bonus|mins") keyboard.add(button_bonus_plus, button_bonus_mins) keyboard.add(self.button_cancel) self.bot.edit_message_text(chat_id = call.message.chat.id, text = "Что вы намерены делать с бонусами?", reply_markup = keyboard, message_id = call.message.message_id) elif menu_type == "refer": insts = #тут нужен sql #self.sql.get_insts(call.from_user.id) if insts == []: self.bot.send_message(call.message.chat.id, "Вы не работали ни с какими предприятиями 🚫") else: keyboard = InlineKeyboardMarkup() for inst in insts: name = self.sql.get_institution_info_by_id(inst)["institution_name"] keyboard.add(InlineKeyboardButton(text=name,callback_data=f"refer|{inst}")) keyboard.add(self.button_cancel) self.bot.edit_message_text(chat_id = call.message.chat.id, text = "Выберите предприятие, к которому вы хотите получить реферальную ссылку:", reply_markup = keyboard, message_id = call.message.message_id) elif menu_type == "about": self.bot.send_message(call.message.chat.id, """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae ornare elit. Morbi pellentesque bibendum leo quis hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. """) elif call.data.startswith("refer"): inst_id = call.data.split("|")[1] link = f"http://t.me/cashtestback_bot?start=u{call.from_user.id}q{inst_id}" self.bot.edit_message_text(chat_id = call.message.chat.id, message_id = call.message.message_id, text = f"Используйте эту ссылку, чтобы пригласить нового пользователя\n{link}") elif call.data.startswith("bonus"): need_data = call.data.split("|") bonus_type = need_data[1] operation_id = self.sql.gen_random_id() #тут нужен sql self.bot.edit_message_text(chat_id = call.message.chat.id, message_id = call.message.message_id, text = f"Ваш код: <b>{operation_id}</b>\nСообщите этот код кассиру.") def admin_commands(self, query, is_callback_query=False): if not is_callback_query: message = query if self.sql.check_user(message.from_user.id): keyboard = InlineKeyboardMarkup() button_settings = InlineKeyboardButton(text = "Настройки", callback_data = "settings") button_add_operator = InlineKeyboardButton(text = "Добавить оператора", callback_data = "add_operator") button_buy = InlineKeyboardButton(text = "Совершить продажу", callback_data = "buy") keyboard.add(button_settings, button_add_operator) keyboard.add(button_buy, self.button_cancel) self.bot.send_message(message.chat.id,"Меню предприятия:",reply_markup=keyboard) elif message.from_user.id in [process.get("user_id") for process in self.users_in_process]: for process in self.users_in_process: if process.get("user_id") == message.from_user.id: theme = process.get("item") break theme_text = theme.replace("referal","рефералов").replace("reffer","рефферов").replace("bounus","бонусов") if item.startswith("buy"): if item == "buy": if not in #тут sql: self.bot.send_message(message.chat.id, "Данный код не найден, попробуйте ввести снова или ввести <b>Отмена</b> для отмены", parse_mode = "HTML") else: self.bot.send_message(message.chat.id, "Введите сумму покупки: ") self.users_in_process.remove(process) self.users_in_process.append({"user_id":message.from_user.id, "item":"buy2", "code":message.text}) else: try: count = int(message.text) inst_id = #тут нужен sql #self.sql.get_inst_id(message.from_user.id) do = #тут нужн sql # self.sql.get_do(process['code']) self.sql.bonuses_to_user(self,user_id,count,inst_id,do) referals = #тут нужен sql percent_for_referal = #тут нужен sql sale = referals * percent_for_referal count = count / 100 * sale self.bot.send_message(message.chat.id, parse_mode = "HTML", text = f"Операция прошла успешно! Сумма покупки равна: <b>{count}</b>, так как <b>{referals}</b> реферал") self.users_in_process.remove(process) except ValueError: self.bot.send_message(message.chat.id, "Вы ввели не по формату, попробуйте еще раз или введите <b>Отмена</b>", parse_mode = "HTML") if message.text == "Отмена": self.bot.delete_message(chat_id = message.chat.id, message_id = message.message_id) self.users_in_process.remove(process) elif message.text not in [str(i) for i in range(1,101)]: self.bot.send_message(message.chat.id, "Вы ввели не по формату, попробуйте еще раз или введите <b>Отмена</b>", parse_mode = "HTML") else: self.bot.send_message(message.chat.id, f"Ваш новый процент для <b>{theme_text}</b> -- <b>{message.text}%</b>", parse_mode = "HTML") #тут нужен sql else: call = query if call.data == "add_operator": inst_id = #тут нужен sql #self.sql.get_inst(call.from_user.id) link = f"http://t.me/cashtestback_bot?start=o{inst_id}" self.bot.send_message(call.message.chat.id, f"Используйте эту ссылку, чтобы добавить в ваше предприятие оператора:\n{link}") elif call.data == "settings": keyboard = InlineKeyboardMarkup() button_referal = InlineKeyboardButton(text = "Проценты на рефералы", callback_data = "config|referal") button_reffer = InlineKeyboardButton(text = "Проценты на рефферы", callback_data = "config|reffer") button_bonus = InlineKeyboardButton(text = "Бонусы", callback_data = "config|bonus") keyboard.add(button_referal, button_reffer) keyboard.add(button_bonus, self.button_cancel) self.bot.send_message(call.message.chat.id, "Настроить:", reply_markup = keyboard) elif call.data == "buy": self.users_in_process.append({"user_id":call.from_user.id, "item":"buy"}) self.bot.send_message(call.message.chat.id, "Введите код: ") elif call.data.startswith("config"): item = call.data.split("|")[1] self.bot.send_message(call.message.chat.id, "Введите число от 1>100") self.users_in_process.append({"user_id":call.from_user.id, "item":item})
class BotUtil(TeleBot): def __init__(self, token, creator=None): super().__init__(token) self.bot = TeleBot(token) self.__group_admins = ['administrator', 'creator'] self.__creator = creator def edit_message(self, message_text, chat_id, message_id, reply_markup=None, parse_mode=None): return self.bot.edit_message_text(chat_id=chat_id, message_id=message_id, text=message_text, reply_markup=reply_markup, parse_mode=parse_mode) def reply(self, chat_id, message_text, message_id, reply_markup=None, parse_mode=None): return self.bot.send_message(chat_id, message_text, reply_to_message_id=message_id, reply_markup=reply_markup, parse_mode=parse_mode) @staticmethod def get_link(name, user_id): return '<a href="tg://user?id={}">{}</a>'.format(user_id, name) def is_admin(self, chat, user): chat_member = self.bot.get_chat_member(chat, user) if chat_member.status in self.__group_admins: return True else: return False def __admin_checks(self, chat, user, admin_user): if chat.type == "private": self.bot.send_message( chat.id, "Административные команды не работают в личных сообщениях.") return False if self.is_admin(chat.id, user.id): self.bot.send_message(chat.id, "Вы пытаетесь ограничить администратора.") return False if not self.is_admin(chat.id, admin_user.id): self.bot.send_message(chat.id, "Вы не администратор.") return False if not self.is_admin(chat.id, self.bot.get_me().id): self.bot.send_message(chat.id, "Я не администратор.") return False return True def mute(self, chat, user, admin_user, for_date=0, reason=""): if not self.__admin_checks(chat, user, admin_user): return now_time = int(time.time()) until_date = now_time + for_date time_text = "секунд" date_text = for_date if for_date > 60: date_text = "минут" time_text = str(for_date / 60) elif for_date > 3600: date_text = "часов" time_text = str(for_date / 3600) elif for_date > 86400: date_text = "дней" time_text = str(for_date / 86400) tts = 'Пользователь {} ограничен на {} {}.'.format( self.get_link(user.first_name, user.id), time_text, date_text) if for_date < 60: tts = "Пользователь {} ограничен навсегда.".format( self.get_link(user.first_name, user.id)) tts += "\nПричина: {}".format(reason) self.bot.restrict_chat_member(chat.id, user.id, until_date=until_date) self.bot.send_message(chat.id, tts, parse_mode="HTML") def ban(self, chat, user, admin_user, for_date=0, reason=""): if not self.__admin_checks(chat, user, admin_user): return now_time = int(time.time()) until_date = now_time + for_date time_text = "секунд" date_text = for_date if 60 < for_date < 3600: date_text = "минут" time_text = str(for_date / 60) elif 3600 < for_date < 86400: date_text = "часов" time_text = str(for_date / 3600) elif for_date > 86400: date_text = "дней" time_text = str(for_date / 86400) tts = 'Пользователь {} заблокирован на {} {}.'.format( self.get_link(user.first_name, user.id), time_text, date_text) if for_date < 60: tts = "Пользователь {} заблокирован навсегда.".format( self.get_link(user.first_name, user.id)) tts += "\nПричина: {}".format(reason) self.bot.kick_chat_member(chat.id, user.id, until_date=until_date) self.bot.send_message(chat.id, tts, parse_mode="HTML") def report(self, text, quiet=False): if self.__creator: if not quiet: print(text) return self.bot.send_message(self.__creator, text) def send_message(self, chat_id, text, disable_web_page_preview=None, reply_to_message_id=None, reply_markup=None, parse_mode="HTML", disable_notification=None, timeout=None): super().send_message(chat_id, text, disable_web_page_preview, reply_to_message_id, reply_markup, parse_mode, disable_notification, timeout)