Пример #1
0
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)
Пример #2
0
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))
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
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)
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
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)
Пример #11
0
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)