def variable_message(message: telegram.Message, assignment_list: List[Assignment]): send_text = '' for assignment in assignment_list: send_text += assignment.display(message.from_user.language_code) + '\n' send_message(message.chat_id, send_text, delete_after=40) delete_message(message.chat_id, message.message_id, 25)
def handle_clear_variables(message: telegram.Message, player: Player, **_): _ = partial(get_by_user, user=message.from_user) player.variable_set.all().delete() send_text = _( Text.VARIABLE_CLEARED).format(character=player.character_name) send_message(message.chat_id, send_text, delete_after=20) delete_message(message.chat_id, message.message_id)
def handle_initiative(message: telegram.Message, name: str, text: str, **__): language_code = get_language(message.from_user) def _(t): return get(t, language_code) text = text.strip() match = INITIATIVE_REGEX.match(text) number = text if match is not None: name = match.group(1).strip() number = match.group(2) elif not text.isnumeric() or len(text) > 4: usage = _(Text.INIT_USAGE) error_message(message, usage) return game_round = Round.objects.filter(chat_id=message.chat_id).first() if not isinstance(game_round, Round): error_message(message, _(Text.INIT_WITHOUT_ROUND)) Actor.objects.create(belong_id=message.chat_id, name=name, value=int(number)) update_round_message(game_round, language_code, refresh=True) delete_message(message.chat_id, message.message_id)
def handle_add_tag(bot: telegram.Bot, chat, message: telegram.Message, **_kwargs): target = message.reply_to_message _ = partial(get_by_user, user=message.from_user) if not chat.recording: return error_message(message, _(Text.RECORD_NOT_FOUND)) elif not isinstance(target, telegram.Message): return error_message(message, _(Text.NEED_REPLY)) elif target.from_user.id != bot.id: return error_message(message, _(Text.NEED_REPLY_PLAYER_RECORD)) assert isinstance(message.from_user, telegram.User) user_id = message.from_user.id log = Log.objects.filter(chat=chat, message_id=target.message_id).first() if log is None: error_message(message, _(Text.RECORD_NOT_FOUND)) return elif log.user_id != user_id: error_message(message, _(Text.HAVE_NOT_PERMISSION)) return assert isinstance(log, Log) tag_list = [] if message.caption: text = message.caption entities = message.caption_entities else: text = message.text entities = message.entities for entity in entities: if isinstance(entity, telegram.MessageEntity) and entity.type == entity.HASHTAG: tag = text[entity.offset+1:entity.offset+entity.length] if tag: tag = get_tag(chat, tag) if tag not in log.tag.all(): tag_list.append(tag) if not tag_list: return error_message(message, _(Text.NOT_TAG)) tag_text = ''.join([' #{}'.format(tag.name) for tag in tag_list]) if target.photo: edit_text = str(target.caption_html) + tag_text bot.edit_message_caption( chat_id=target.chat_id, message_id=target.message_id, caption=edit_text, parse_mode='HTML', ) else: edit_text = str(target.text_html) + tag_text target.edit_text(edit_text, parse_mode='HTML') for tag in tag_list: log.tag.add(tag) log.save() chat.save() delete_message(message.chat_id, message.message_id)
def finish_gm_mode(message: telegram.Message, chat: Chat): _ = partial(get_by_user, user=message.from_user) if chat.gm_mode: if chat.gm_mode_notice: delete_message(chat.chat_id, chat.gm_mode_notice, 20) chat.gm_mode = False chat.gm_mode_notice = None chat.save() send_message(chat.chat_id, _(Text.FINISH_GM_MODE), delete_after=20) delete_message(message.chat_id, message.message_id)
def public_round(update: telegram.Update, _context): message: telegram.Message = update.message game_round = get_round(update) language_code = get_language(update.message.from_user) if not game_round: return if not is_gm(update.message.chat_id, update.message.from_user.id): error_text = get_by_user(Text.NOT_GM, update.message.from_user) return error_message(update.message, error_text) game_round.hide = False game_round.save() update_round_message(game_round, language_code, refresh=True) delete_message(message.chat_id, message.message_id)
def handle_set_dice_face(message: telegram.Message, text: str, **_kwargs): _ = partial(get_by_user, user=message.from_user) chat = get_chat(message.chat) try: face = int(text.strip()) except ValueError: return error_message( message, _(Text.SET_DEFAULT_FACE_SYNTAX).format( face=chat.default_dice_face)) chat.default_dice_face = face chat.save() delete_message(message.chat_id, message.message_id) send_message(message.chat_id, _(Text.DEFAULT_FACE_SETTLED).format(face))
def next_turn(update: telegram.Update, _context): game_round = get_round(update) if not game_round: return actors = game_round.get_actors() next_count = game_round.counter + 1 if next_count >= len(actors): next_count = 0 game_round.round_counter += 1 game_round.counter = next_count game_round.save() language_code = get_language(update.message.from_user) update_round_message(game_round, language_code, refresh=False) delete_message(update.message.chat_id, update.message.message_id)
def handle_start_round(message: telegram.Message, job_queue, **_kwargs): _ = partial(get_by_user, user=message.from_user) if not is_group_chat(message.chat): return error_message(job_queue, message, _(Text.NOT_GROUP)) chat = message.chat text = '{} #round\n\n\n{}'.format(_(Text.ROUND_INDICATOR), _(Text.ROUND_INDICATOR_INIT)) delete_message(job_queue, message.chat_id, message.message_id) sent = chat.send_message(text, parse_mode='HTML') message_id = sent.message_id chat_id = sent.chat_id remove_round(job_queue, chat_id) Round.objects.create(chat_id=chat_id, message_id=message_id, hide=False)
def handle_list_variables(message: telegram.Message, name: str, player: Player, **_): _ = partial(get_by_user, user=message.from_user) content = '' have_variable = False for variable in player.variable_set.order_by('updated').all(): have_variable = True content += '<code>${}</code> {}\n'.format(variable.name, variable.value) if not have_variable: content = _(Text.VARIABLE_LIST_EMPTY) send_text = '<b>{}</b>\n\n{}'.format( _(Text.VARIABLE_LIST_TITLE).format(character=name), content) send_message(message.chat_id, send_text, delete_after=30) delete_message(message.chat_id, message.message_id)
def send_and_record(job_queue: JobQueue, chat, gm, kind, message: telegram.Message, name, reply_log, rpg_message, send_text, temp_name, content, with_photo): reply_to_message_id = None if isinstance(reply_log, Log): reply_to_message_id = reply_log.message_id # send message if isinstance(with_photo, telegram.PhotoSize): sent = message.chat.send_photo( photo=with_photo, caption=send_text, reply_to_message_id=reply_to_message_id, parse_mode='HTML', ) else: sent = message.chat.send_message( send_text, reply_to_message_id=reply_to_message_id, parse_mode='HTML', ) if not chat.recording: return # record log created_log = Log.objects.create( message_id=sent.message_id, source_message_id=message.message_id, chat=chat, user_id=message.from_user.id, user_fullname=message.from_user.full_name, kind=kind, reply=reply_log, entities=rpg_message.entities.to_object(), character_name=name, temp_character_name=temp_name or '', content=content, gm=gm, created=message.date, ) for name in rpg_message.tags: created_log.tag.add(get_tag(chat, name)) created_log.save() # download and write photo file if with_photo: set_photo(job_queue, created_log.id, with_photo.file_id) delete_message(job_queue, message.chat_id, message.message_id, 10) chat.save()
def hide_round(update: telegram.Update, _context): game_round = get_round(update) message = update.message assert isinstance(message, telegram.Message) language_code = get_language(message.from_user) def _(x): return get(x, language_code) if not game_round: return if not is_gm(message.chat_id, message.from_user.id): return error_message(message, _(Text.NOT_GM)) game_round.hide = True game_round.save() update_round_message(game_round, language_code, refresh=True) delete_message(message.chat_id, message.message_id)
def start_round(update: telegram.Update, _context): message: telegram.Message = update.message assert isinstance(message, telegram.Message) _ = partial(get_by_user, user=message.from_user) if not is_group_chat(message.chat): return error_message(message, _(Text.NOT_GROUP)) chat = message.chat text = '{} #round\n\n\n{}'.format(_(Text.ROUND_INDICATOR), _(Text.ROUND_INDICATOR_INIT)) delete_message(message.chat_id, message.message_id) sent = chat.send_message(text, parse_mode='HTML') message_id = sent.message_id chat_id = sent.chat_id remove_round(chat_id) Round.objects.create(chat_id=chat_id, message_id=message_id, hide=False)
def handle_roll(job_queue: JobQueue, message: telegram.Message, name: str, entities: Entities, chat: Chat, hide=False): _ = partial(get_by_user, user=message.from_user) kind = LogKind.ROLL.value result_text = entities.telegram_html() if hide: hide_roll = HideRoll(message.chat_id, result_text) hide_roll.set() keyboard = [[ InlineKeyboardButton(_(Text.GM_LOOKUP), callback_data=hide_roll.key()) ]] reply_markup = InlineKeyboardMarkup(keyboard) text = '<b>{}</b> {}'.format(name, _(Text.ROLL_HIDE_DICE)) kind = LogKind.HIDE_DICE.value else: text = '{} 🎲 {}'.format(name, result_text) reply_markup = None if not chat.recording: text = '[{}] '.format(_(Text.NOT_RECORDING)) + text sent = message.chat.send_message(text, reply_markup=reply_markup, parse_mode='HTML') user = message.from_user assert isinstance(user, telegram.User) if chat.recording: Log.objects.create( user_id=user.id, message_id=sent.message_id, chat=chat, content=result_text, entities=entities.to_object(), user_fullname=user.full_name, character_name=name, gm=is_gm(message.chat_id, user.id), kind=kind, created=message.date, ) chat.save() delete_message(job_queue, message.chat_id, message.message_id, 25)
def handle_delete_callback(_bot: telegram.Bot, query: telegram.CallbackQuery): def _(t: Text): return get_by_user(t, user=query.from_user) message = query.message assert isinstance(message, telegram.Message) deletion = Deletion.get(message.chat_id, message.message_id) if not deletion: query.answer(_(Text.INTERNAL_ERROR), alert=True) delete_message(message.chat_id, message.message_id) return if deletion.user_id != query.from_user.id: query.answer(_(Text.MUST_SAME_USER)) return delete_message(message.chat_id, message.message_id) if query.data == 'delete:cancel': query.answer(_(Text.CANCELED)) elif query.data == 'delete:confirm': deletion.do() query.answer(_(Text.DELETED))
def handle_lift(message: telegram.Message, chat: Chat, **_kwargs): assert isinstance(message, telegram.Message) reply_to = message.reply_to_message user_id = message.from_user.id _ = partial(get_by_user, user=message.from_user) if not chat.recording: return error_message(message, _(Text.RECORD_NOT_FOUND)) elif not isinstance(reply_to, telegram.Message): return error_message(message, _(Text.NEED_REPLY)) elif reply_to.from_user.id == message.bot.id: return error_message(message, _(Text.NEED_REPLY_PLAYER_RECORD)) elif reply_to.from_user.id != user_id and not is_gm(message.chat_id, user_id): return error_message(message, _(Text.HAVE_NOT_PERMISSION)) name = get_name(reply_to) if not name: return error_message(message, _(Text.INVALID_TARGET)) with_photo = get_maximum_photo(reply_to) handle_say(chat, reply_to, name, with_photo=with_photo) delete_message(reply_to.chat_id, reply_to.message_id) delete_message(message.chat_id, message.message_id)
def set_name(update: telegram.Update, context: CallbackContext): bot = context args = context.args message = update.message assert isinstance(message, telegram.Message) _ = partial(get_by_user, user=message.from_user) if len(args) == 0: return error_message(message, _(Text.NAME_SYNTAX_ERROR)) user = message.from_user assert isinstance(user, telegram.User) name = ' '.join(args).strip() player = create_player(bot, message, name) if player.is_gm: template = _(Text.NAME_SUCCESS_GM) else: template = _(Text.NAME_SUCCESS) send_text = template.format(player=user.full_name, character=name) send_message(message.chat_id, send_text) delete_message(message.chat_id, message.message_id)
def handle_set_timer(message: telegram.Message, text: str, job_queue: JobQueue, **_kwargs): _ = partial(get_by_user, user=message.from_user) text = text.strip() args = text.split(' ', 1) if len(args) == 0: return error_message(job_queue, message, _(Text.TIMER_SYNTAX_ERROR)) try: timer = args[0] if len(timer) > 10: raise ValueError() timer = int(args[0]) except ValueError: return error_message(job_queue, message, _(Text.TIMER_SYNTAX_ERROR)) if len(args) > 1: comment = args[1].strip() if len(comment) > 128: return error_message(job_queue, message, "timer comment too long.") else: comment = "" delete_message(job_queue, message.chat_id, message.message_id) timer_message(job_queue, message.chat_id, timer, comment)
def on_edit(chat: Chat, edit_log: Log, kind, message, rpg_message: RpgMessage, send_text, text, with_photo): assert isinstance(edit_log, Log) chat_id = message.chat_id message_id = edit_log.message_id if edit_log.media: if isinstance(with_photo, telegram.PhotoSize): edit_message_photo(chat_id, message_id, with_photo.file_id) set_photo(edit_log.id, with_photo.file_id) edit_message_caption(chat_id, message_id, send_text) else: edit_message(chat_id, message_id, send_text) edit_log.tag.clear() for tag_name in rpg_message.tags: tag = get_tag(chat, tag_name) edit_log.tag.add(tag) edit_log.content = text edit_log.entities = rpg_message.entities.to_object() edit_log.kind = kind edit_log.save() delete_message(message.chat_id, message.message_id, 25) chat.save() return
def handle_message(update: telegram.Update, context: CallbackContext): bot = context .bot message: telegram.Message = update.message edit_log = None if update.edited_message: message = update.edited_message edit_log = Log.objects.filter(chat__chat_id=message.chat_id, source_message_id=message.message_id).first() cancel_delete_message(message.chat_id, message. message_id) elif not isinstance(message, telegram.Message): return elif not isinstance(message.from_user, telegram.User): return language_code: str = message.from_user.language_code def _(x: Text): return get(x, language_code) with_photo = get_maximum_photo(message) text = message.text if with_photo: text = message.caption if not isinstance(text, str): return # ignore ellipsis elif is_ellipsis(text): return if not is_group_chat(message.chat): message.reply_text(_(Text.NOT_GROUP)) return chat = get_chat(message.chat) player = get_player_by_id(message.chat_id, message.from_user.id) # handle GM mode if player and player.is_gm and (is_start_gm_mode(text) or is_finish_gm_mode(text)): if is_start_gm_mode(text): start_gm_mode(bot, message, chat) if len(text.rstrip()) == 1: delete_message(message.chat_id, message.message_id) return elif is_finish_gm_mode(text): finish_gm_mode(message, chat) return # not start with . / 。, ignore elif not is_command(text): return # user hasn't set name if not player: error_message(message, _(Text.NOT_SET_NAME)) return # in the GM mode if chat.gm_mode and not player.is_gm and not edit_log: if is_command(text): send_message( chat.chat_id, _(Text.PLAYER_IN_THE_GM_MODE), reply_to=message.message_id, delete_after=5 ) return name = player.character_name for pattern, handler in message_handlers: result = patterns.split(pattern, text) if not result: continue command, start = result rest = text[start:] if handler is not handle_as_say and edit_log: after_edit_delete_previous_message(edit_log.id) handler( bot=bot, chat=chat, player=player, command=command, start=start, name=name, text=rest, message=message, job_queue=context.job_queue, with_photo=with_photo, language_code=language_code, edit_log=edit_log, context=Context(bot, chat, player, command, name, start, rest, message, context.job_queue, language_code, with_photo, edit_log) ) return handle_say(chat, message, name, edit_log=edit_log, with_photo=with_photo, start=1)
def handle_delete( bot: telegram.Bot, chat: Chat, message: telegram.Message, player: Player, **_): target = message.reply_to_message variables = patterns.VARIABLE_REGEX.findall(message.text) _ = partial(get_by_user, user=message.from_user) # delete variable if len(variables) > 0: target_player: Player = player if isinstance(target, telegram.Message): if not player.is_gm: return error_message(message, _(Text.NOT_GM)) if bot.id == target.from_user.id: log = Log.objects.filter(chat=chat, message_id=target.message_id, deleted=False).first() if not log: return error_message(message, _(Text.RECORD_NOT_FOUND)) target_player = get_player_by_id(chat.chat_id, log.user_id) else: target_player = get_player_by_id(message.chat_id, target.from_user.id) if not target_player: return error_message(message, _(Text.INVALID_TARGET)) delete_log = '' variable_id_list = [] for variable_name in variables: variable = Variable.objects.filter(name__iexact=variable_name, player=target_player).first() if not variable: continue if variable.value: delete_log += '${} = {}\n'.format(variable.name, variable.value) else: delete_log += '${}'.format(variable.name) variable_id_list.append(variable.id) if not variable_id_list: return error_message(message, _(Text.NOT_FOUND_VARIABLE_TO_DELETE)) delete_message(message.chat_id, message.message_id) check_text = _(Text.CHECK_DELETE_VARIABLE).format(character=target_player.character_name) check_text += '\n<pre>{}</pre>'.format(delete_log) reply_markup = delete_reply_markup(message.from_user.language_code) deletion = Deletion(chat_id=message.chat_id, user_id=message.from_user.id, variable_id_list=variable_id_list) # delete message else: user_id = message.from_user.id if isinstance(target, telegram.Message): log = Log.objects.filter(chat=chat, message_id=target.message_id).first() else: log = Log.objects.filter(chat=chat, user_id=user_id).order_by('-created').first() if log is None: error_message(message, get_by_user(Text.RECORD_NOT_FOUND, message.from_user)) return elif log.user_id != user_id and not is_gm(message.chat_id, user_id): error_message(message, get_by_user(Text.HAVE_NOT_PERMISSION, message.from_user)) return character_name = "<b>{}</b>".format(log.temp_character_name or log.character_name) check_text = _(Text.DELETE_CHECK) + '\n\n[{}] {}'.format(character_name, log.content) reply_markup = delete_reply_markup(message.from_user.language_code) deletion = Deletion(message.chat_id, message.from_user.id, message_list=[log.message_id]) delete_message(message.chat_id, message.message_id) sent = message.chat.send_message(check_text, parse_mode='HTML', reply_markup=reply_markup) deletion.set(sent.message_id) delete_message(message.chat_id, sent.message_id, 30)
def remove_round(chat_id): for game_round in Round.objects.filter(chat_id=chat_id).all(): message_id = game_round.message_id game_round.delete() delete_message(chat_id, message_id)