Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
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))
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
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)
Пример #11
0
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()
Пример #12
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)
Пример #13
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)
Пример #14
0
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)
Пример #15
0
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))
Пример #16
0
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)
Пример #17
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)
Пример #18
0
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)
Пример #19
0
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
Пример #20
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)
Пример #21
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)
Пример #22
0
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)