def public_round(update: telegram.Update, context: CallbackContext): message: telegram.Message = update.message game_round = get_round(context.job_queue, 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(context.job_queue, update.message, error_text) game_round.hide = False game_round.save() update_round_message(context.job_queue, game_round, language_code, refresh=True) delete_message(context.job_queue, message.chat_id, message.message_id)
def handle_set_dice_face(message: telegram.Message, text: str, job_queue, **_kwargs): _ = partial(get_by_user, user=message.from_user) chat = get_chat(message.chat) try: face = int(text.strip()) except ValueError: return error_message( job_queue, message, _(Text.SET_DEFAULT_FACE_SYNTAX).format( face=chat.default_dice_face)) chat.default_dice_face = face chat.save() delete_message(job_queue, message.chat_id, message.message_id) send_message(job_queue, message.chat_id, _(Text.DEFAULT_FACE_SETTLED).format(face))
def set_password(update, context: CallbackContext): message = update.message assert isinstance(message, telegram.Message) args = context.args _ = partial(get_by_user, user=message.from_user) if len(args) > 1: text = _(Text.PASSWORD_USAGE) return error_message(message, text) chat = get_chat(message.chat) if args: password = str(args[0]) chat.password = sha256(password.encode()).hexdigest() else: chat.password = '' chat.save() send_message(message.chat_id, _(Text.PASSWORD_SUCCESS), 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 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 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_normal_roll(message: telegram.Message, command: str, name: str, start: int, chat: Chat, **_): rpg_message = RpgMessage(message, start) hide = command[-1] == 'h' entities = rpg_message.entities.list roll_counter = 0 next_entities = [] try: for entity in entities: if isinstance(entity, Span): result_entities = dice.roll_entities(entity.value, chat.default_dice_face) local_roll_counter = 0 for result_entity in result_entities: if isinstance(result_entity, RollResult): local_roll_counter += 1 if local_roll_counter > 0: next_entities.extend(result_entities) roll_counter += local_roll_counter else: next_entities.append(entity) else: next_entities.append(entity) if roll_counter == 0: default_roll_entities = dice.roll_entities('1d', chat.default_dice_face) default_roll_entities.extend(next_entities) next_entities = default_roll_entities except dice.RollError as e: error_text = Text.ERROR if len(e.args) > 0: error_kind = e.args[0] try: error_text = Text[error_kind.value] except KeyError: pass return error_message(message, get_by_user(error_text, message.from_user)) handle_roll(message, name, Entities(next_entities), chat, hide)
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 handle_variable_assign(bot: telegram.Bot, message: telegram.Message, start: int, player: Player, **_): _ = partial(get_by_user, user=message.from_user) is_gm = player.is_gm assign_player_list = [] text = message.caption or message.text if is_gm: for entity in message.entities: assert isinstance(entity, telegram.MessageEntity) offset = entity.offset length = entity.length end = offset + length assign_player = None if entity.type == entity.MENTION: assign_player = get_player_by_username(message.chat_id, text[offset:end]) elif entity.type == entity.TEXT_MENTION: assign_player = get_player_by_id(message.chat_id, entity.user.id) if assign_player: assign_player_list.append(assign_player) start = end else: error_text = '{}\n\n{}'.format( _(Text.VARIABLE_ASSIGN_USAGE), _(Text.VARIABLE_ASSIGN_GM_USAGE)) error_message(message, error_text) return if not assign_player_list: user_id = message.from_user.id # when reply to a message if isinstance(message.reply_to_message, telegram.Message) and is_gm: reply_to = message.reply_to_message user_id = reply_to.from_user.id # reply to a bot message if user_id == bot.id: log = Log.objects.filter( message_id=reply_to.message_id, chat__chat_id=message.chat_id).first() if not log: error_message(message, _(Text.RECORD_NOT_FOUND)) return user_id = log.user_id if user_id != player.user_id: player = get_player_by_id(message.chat_id, user_id) if not player: return error_message( message, _(Text.REPLY_TO_NON_PLAYER_IN_VARIABLE_ASSIGNMENT)) assign_player_list.append(player) text = text[start:] assert isinstance(text, str) assignment_list = [] for line in text.splitlines(): line = line.strip() # .set $VARIABLE + 42 matched = patterns.VARIABLE_MODIFY_REGEX.match(line) if matched: var_name = matched.group(1) operator = matched.group(2) value = value_processing(line[matched.end():]) for assign_player in assign_player_list: variable = Variable.objects.filter( player=assign_player, name__iexact=var_name).first() if not variable: variable = Variable.objects.create(player=assign_player, name=var_name, value=value) old_value = None else: old_value = variable.value if old_value.isdigit() and value.isdigit( ) and len(old_value) < 6 and len(value) < 6: if operator == '+': variable.value = str(int(old_value) + int(value)) elif operator == '-': variable.value = str(int(old_value) - int(value)) elif operator == '+': variable.value = old_value + ', ' + value else: continue variable.save() assignment_list.append( Assignment(assign_player, variable, old_value)) else: matched = patterns.VARIABLE_NAME_REGEX.search(line) if not matched: continue var_name = matched.group(1).strip() value = value_processing(line[matched.end():]) for assign_player in assign_player_list: variable = Variable.objects.filter( player=assign_player, name__iexact=var_name).first() old_value = None if not variable: variable = Variable.objects.create(player=assign_player, name=var_name, value=value) else: old_value = variable.value variable.value = value variable.save() assignment_list.append( Assignment(assign_player, variable, old_value)) if len(assignment_list) == 0: return error_message(message, _(Text.VARIABLE_ASSIGN_USAGE)) variable_message(message, assignment_list)
def handle_add_tag(bot: telegram.Bot, chat, message: telegram.Message, job_queue: JobQueue, **_kwargs): target = message.reply_to_message _ = partial(get_by_user, user=message.from_user) if not chat.recording: return error_message(job_queue, message, _(Text.RECORD_NOT_FOUND)) elif not isinstance(target, telegram.Message): return error_message(job_queue, message, _(Text.NEED_REPLY)) elif target.from_user.id != bot.id: return error_message(job_queue, 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(job_queue, message, _(Text.RECORD_NOT_FOUND)) return elif log.user_id != user_id: error_message(job_queue, 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(job_queue, 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(job_queue, message.chat_id, message.message_id)