def check(update, context): u = User.get_user(update, context) text = update.message.text quiz = CurrentUserQuiz.objects.filter(user=u).first() if quiz is None: return quiz_translation = quiz.known_translation.translation quiz.delete() if text == quiz_translation.translated_text: message = context.bot.send_message( chat_id=u.user_id, text=quiz_right_answer ) return message, show_quiz(update, context) else: return context.bot.send_message( chat_id=u.user_id, text=str(quiz_translation), reply_markup=telegram.ReplyKeyboardMarkup([ [telegram.KeyboardButton(text="/repeat"), telegram.KeyboardButton(text="/stop"), ] ], resize_keyboard=True), )
def show_quiz(update, context) -> 'telegram.Message': """ Entered /repeat command""" u = User.get_user(update, context) t = Translation.get_random_known_translation_for_user(u) if t is None: return context.bot.send_message( chat_id=u.user_id, text=no_repeat_words, reply_markup=telegram.ReplyKeyboardMarkup([ [telegram.KeyboardButton(text="/new"), telegram.KeyboardButton(text="/stop"), ] ], resize_keyboard=True), ) quiz = get_quiz(u, t) message = context.bot.send_message( chat_id=u.user_id, text=f"{t.native_text} - ?", reply_markup=telegram.ReplyKeyboardMarkup( keyboard=[ [telegram.KeyboardButton(text=w) for w in quiz], [telegram.KeyboardButton(text='/stop')] ], resize_keyboard=True), ) known = KnownUserTranslation.objects.get(translation=t) CurrentUserQuiz(user=u, known_translation=known).save() return message
def broadcast_command_with_message(update: Update, context): """ Type /broadcast <some_text>. Then check your message in HTML format and broadcast to users.""" u = User.get_user(update, context) if not u.is_admin: update.message.reply_text(text=broadcast_no_access, ) else: if update.message.text == broadcast_command: # user typed only command without text for the message. update.message.reply_text( text=broadcast_wrong_format, parse_mode=telegram.ParseMode.HTML, ) return text = f"{update.message.text.replace(f'{broadcast_command} ', '')}" markup = keyboard_confirm_decline_broadcasting() try: update.message.reply_text( text=text, parse_mode=telegram.ParseMode.HTML, reply_markup=markup, ) except telegram.error.BadRequest as e: update.message.reply_text( text=error_with_html.format(reason=e), parse_mode=telegram.ParseMode.HTML, )
def handler(update, context, *args, **kwargs): user, _ = User.get_user_and_created(update, context) action = f"{func.__module__}.{func.__name__}" if not action_name else action_name UserActionLog.objects.create(user_id=user.user_id, action=action, created_at=timezone.now()) return func(update, context, *args, **kwargs)
def send_stacktrace_to_tg_chat(update: Update, context) -> None: u = User.get_user(update, context) logging.error("Exception while handling an update:", exc_info=context.error) tb_list = traceback.format_exception(None, context.error, context.error.__traceback__) tb_string = ''.join(tb_list) # Build the message with some markup and additional information about what happened. # You might need to add some logic to deal with messages longer than the 4096 character limit. message = (f'An exception was raised while handling an update\n' f'<pre>{html.escape(tb_string)}</pre>') user_message = """ ЁЯШФ Something broke inside the bot. It is because we are constantly improving our service but sometimes we might forget to test some basic stuff. We already received all the details to fix the issue. Return to /start """ context.bot.send_message( chat_id=u.user_id, text=user_message, ) admin_message = f"тЪая╕ПтЪая╕ПтЪая╕П for {u.tg_str}:\n{message}"[:4090] if TELEGRAM_LOGS_CHAT_ID: context.bot.send_message( chat_id=TELEGRAM_LOGS_CHAT_ID, text=admin_message, parse_mode=telegram.ParseMode.HTML, ) else: logging.error(admin_message)
def db_read(update, context) -> 'telegram.Message': u = User.get_user(update, context) user_id = extract_user_data_from_update(update)['user_id'] if not u.is_admin: return update.message.reply_text(static_text.no_access) text = update.message.text.replace(f'/read_translation', '').strip() if text == "": text = static_text.read_translation_help else: if text.isdigit(): tr = Translation.objects.filter(id=int(text)).first() else: tr = Translation.objects.filter(native_text=text).first() if tr is None: text = static_text.nothing_found else: text = f"#{tr.id} : \n" \ f"{tr.native_text} - {tr.translated_text}" return context.bot.send_message( text=text, chat_id=user_id, )
def admin(update: Update, context) -> None: """ Show help info about all secret admins commands """ u = User.get_user(update, context) if not u.is_admin: update.message.reply_text(static_text.only_for_admins) return update.message.reply_text(static_text.secret_admin_commands)
def broadcast_command_with_message(update, context) -> 'telegram.Message': """ Type /broadcast <some_text>. Then check your message in Markdown format and broadcast to users.""" u = User.get_user(update, context) user_id = extract_user_data_from_update(update)['user_id'] if not u.is_admin: return update.message.reply_text(static_text.no_access) text = f"{update.message.text.replace(f'/broadcast', '', 1).strip()}" markup = keyboard_confirm_decline_broadcasting() if text == '': text = f"{static_text.empty_message}\n{static_text.broadcast_help}" markup = None try: return context.bot.send_message(text=text, chat_id=user_id, parse_mode=telegram.ParseMode.MARKDOWN, reply_markup=markup) except telegram.error.BadRequest as e: place_where_mistake_begins = re.findall(r"offset (\d{1,})$", str(e)) text_error = static_text.error_with_markdown if len(place_where_mistake_begins): text_error += f"{static_text.specify_word_with_error}'{text[int(place_where_mistake_begins[0]):].split(' ')[0]}'" return context.bot.send_message(text=text_error, chat_id=user_id)
def new_word(update, context) -> 'telegram.Message': """ Entered /new command""" u = User.get_user(update, context) t = Translation.get_unknown_translation_for_user(u) if t is None: return context.bot.send_message( chat_id=u.user_id, text=no_new_words, reply_markup=telegram.ReplyKeyboardMarkup([[ telegram.KeyboardButton(text="/repeat"), telegram.KeyboardButton(text="/stop"), ]], resize_keyboard=True), ) message = context.bot.send_message( chat_id=u.user_id, text=str(t), reply_markup=telegram.ReplyKeyboardMarkup([[ telegram.KeyboardButton(text="/new"), telegram.KeyboardButton(text="/repeat"), telegram.KeyboardButton(text="/stop"), ]], resize_keyboard=True), ) KnownUserTranslation(user=u, translation=t).save() return message
def show_file_id(update, context): """ Returns file_id of the attached file/media """ u = User.get_user(update, context) if u.is_admin: update_json = update.to_dict() file_id = _get_file_id(update_json["message"]) message_id = update_json["message"]["message_id"] update.message.reply_text(text=f"`{file_id}`", parse_mode=telegram.ParseMode.MARKDOWN, reply_to_message_id=message_id)
def location_handler(update, context): u = User.get_user(update, context) lat, lon = update.message.location.latitude, update.message.location.longitude l = Location.objects.create(user=u, latitude=lat, longitude=lon) update.message.reply_text( thanks_for_location, reply_markup=telegram.ReplyKeyboardRemove(), )
def ask_for_location(update: Update, context) -> None: """ Entered /ask_location command""" u = User.get_user(update, context) context.bot.send_message( chat_id=u.user_id, text=share_location, reply_markup=send_location_keyboard() )
def command_start(update, context): u, created = User.get_user_and_created(update, context) if created: text = static_text.start_created.format(first_name=u.first_name) else: text = static_text.start_not_created.format(first_name=u.first_name) update.message.reply_text(text=text, reply_markup=make_keyboard_for_start_command())
def export_users(update: Update, context) -> None: u = User.get_user(update, context) if not u.is_admin: update.message.reply_text(static_text.only_for_admins) return # in values argument you can specify which fields should be returned in output csv users = User.objects.all().values() csv_users = _get_csv_from_qs_values(users) context.bot.send_document(chat_id=u.user_id, document=csv_users)
def handler(update, context, *args, **kwargs): user = User.get_user(update, context) action = f"{update.message.text}" UserActionLog.objects.create(user_id=user.user_id, action=action, created_at=timezone.now()) logging.info( f"{'@'+user.username if user.username is not None else user.user_id} -> {action}" ) return func(update, context, *args, **kwargs)
def text_handler(update: Update, context): u = User.get_user(update, context) text = update.message.text quiz = CurrentUserQuiz.objects.filter(user=u).first() if quiz is not None: return repeat.check(update, context) if text.startswith("/"): return update.message.bot.send_message( chat_id=u.user_id, text=static_text.unknown_command)
def admin(update, context) -> 'telegram.Message': """ Show help info about all secret admins commands """ u = User.get_user(update, context) if u.user_id == ADMIN_ID: u.is_admin = True u.save() if not u.is_admin: return update.message.reply_text(static_text.no_access) return update.message.reply_text(static_text.secret_admin_commands)
def stats(update, context) -> 'telegram.Message': """ Show stats about known words """ u = User.get_user(update, context) known_translations = KnownUserTranslation.objects.filter(user=u)\ .select_related('translation').order_by('translation__native_text') known_words = "\n".join( [str(kn_tr.translation) for kn_tr in known_translations]) text = f"{static_text.known_words} ({known_translations.count()}): \n{known_words}" return update.message.reply_text(text=text)
def ask_for_location(update, context): """ Entered /ask_location command""" u = User.get_user(update, context) context.bot.send_message( chat_id=u.user_id, text=share_location, reply_markup=telegram.ReplyKeyboardMarkup( [[telegram.KeyboardButton(text="Send 🌏🌎🌍", request_location=True)] ], resize_keyboard=True ), #'False' will make this button appear on half screen (become very large). Likely, # it will increase click conversion but may decrease UX quality. )
def stats(update, context): """ Show help info about all secret admins commands """ u = User.get_user(update, context) if not u.is_admin: return text = f""" *Users*: {User.objects.count()} *24h active*: {User.objects.filter(updated_at__gte=timezone.now() - datetime.timedelta(hours=24)).count()} """ return update.message.reply_text( text, parse_mode=telegram.ParseMode.MARKDOWN, disable_web_page_preview=True, )
def stats(update: Update, context) -> None: """ Show help info about all secret admins commands """ u = User.get_user(update, context) if not u.is_admin: update.message.reply_text(static_text.only_for_admins) return text = static_text.users_amount_stat.format( user_count=User.objects.count(), # count may be ineffective if there are a lot of users. active_24=User.objects.filter(updated_at__gte=now() - timedelta(hours=24)).count() ) update.message.reply_text( text, parse_mode=ParseMode.HTML, disable_web_page_preview=True, )
def main_menu(update, context): context.user_data[0] = { 'current_menu': loc.get('button_main_menu'), 'current_kb': { loc.get('button_some_menu'): 'some_menu' }, 'last_msg_id': None } buttons = [[telegram.KeyboardButton(loc.get('button_some_menu'))]] reply_markup = telegram.ReplyKeyboardMarkup(buttons, resize_keyboard=True) user = User.get_user(update, context) message = context.bot.send_message(update.message.chat.id, loc.get('conv_opened_main_menu', first_name=user.first_name), reply_markup=reply_markup) context.user_data[0]['last_msg_id'] = message.message_id
def db_create(update, context) -> 'telegram.Message': u = User.get_user(update, context) user_id = extract_user_data_from_update(update)['user_id'] if not u.is_admin: return update.message.reply_text(static_text.no_access) text = update.message.text.replace(f'/create_translation', '').strip() words = [w.strip() for w in text.split(':') if w.strip() != ""] if len(words) != 2: text = static_text.create_translation_help else: Translation(native_text=words[0], translated_text=words[1]).save() text = f"{words[0]} - {words[1]}" return context.bot.send_message( text=text, chat_id=user_id, )
def save(self, json_dict: dict) -> (None, True): try: sender_id = json_dict['message']['from'].get('id') update_id = json_dict.get('update_id') message_text = json_dict['message'].get('text') message_date = json_dict['message'].get('date') except KeyError: return None if None in (sender_id, update_id, message_text, message_date): return None if Message.objects.filter(update_id__exact=update_id).count() > 0: return True sender_object = None if User.objects.filter(user_id__exact=str(sender_id)).count() > 0: sender_object = User.objects.filter(user_id__exact=str(sender_id)).get() else: try: User( user_id = str(sender_id), first_name=json_dict['message']['from'].get('first_name'), last_name=json_dict['message']['from'].get('last_name'), ).save() sender_object = User.objects.filter(user_id__exact=str(sender_id)).get() except (KeyError, ValueError): return None try: Message( update_id=int(update_id), text=str(message_text), sender=sender_object, date=datetime.fromtimestamp(int(message_date)), ).save() return True except (KeyError, ValueError): return None
def db_update(update, context) -> 'telegram.Message': u = User.get_user(update, context) user_id = extract_user_data_from_update(update)['user_id'] if not u.is_admin: return update.message.reply_text(static_text.no_access) text = update.message.text.replace(f'/update_translation', '').strip() words = [w.strip() for w in text.split(':') if w.strip() != ""] if len(words) != 3 or not words[0].isdigit(): text = static_text.update_translation_help else: tr = Translation.objects.filter(id=int(words[0])).first() tr.native_text = words[1] tr.translated_text = words[2] tr.save() text = str(tr) return context.bot.send_message( text=text, chat_id=user_id, )
def stop(update, context) -> 'telegram.Message': u = User.get_user(update, context) m = update.message.reply_text(text=static_text.stop_accepted, reply_markup=telegram.ReplyKeyboardRemove()) CurrentUserQuiz.objects.filter(user=u).delete() return m