예제 #1
0
def reward_g_def(player, reward, cost, *args, **kwargs):
    guild = Guild.get_guild(player.guild)
    if guild is None or guild.castle != HOME_CASTLE:
        if guild is None:
            text = "Гильдия не найдена. Вы должны состоять в гильдии.\nЖетоны возвращены."
        else:
            text = "Функция доступна только для гильдий из Скалы.\nЖетоны возвращены."
        dispatcher.bot.send_message(player.id, text=text)
        player.reputation += cost
        player.update()
        raise RewardRollbackException
    do_mailing(
        dispatcher.bot,
        "📣📣📣Вы слышите звуки рога! Это {} зазывает сынов и дочерей Скалы на защиту!\n"
        "/g_def {}".format(guild.tag, guild.tag))
    dispatcher.bot.send_message(
        chat_id=STATUSES_MODERATION_CHAT_ID,
        text="Не забудьте снять жетоны тем, "
        "кого не будет в дефе <b>{}</b> в ближайшую битву!".format(guild.tag),
        parse_mode='HTML')
    job.run_once(when=get_time_remaining_to_battle() +
                 datetime.timedelta(minutes=5),
                 callback=g_def_remind_after_battle,
                 context={"tag": guild.tag})
def parse_stats():
    data = castles_stats_queue.get()
    while data is not None:
        debug = data.get("debug", False)
        data = data.get("data")
        # logging.error("Got data in parse: {}".format(data))
        if 'Результаты сражений:' in data:
            # Результаты битвы замков
            if not debug:
                response_all = "Игроки, попавшие в топ:\n"
                for guild_id in Guild.guild_ids:
                    response = ""
                    guild = Guild.get_guild(guild_id=guild_id)
                    tag = guild.tag
                    for castle_results_string in data.split("\n\n"):
                        if tag in castle_results_string:
                            try:
                                attacked_castle = re.search(
                                    '[🍁☘🖤🐢🦇🌹🍆]',
                                    castle_results_string).group(0)
                            except TypeError:
                                attacked_castle = "???"
                            nicknames_list = re.findall(
                                ".\\[{}\\][^🍁☘🖤🐢🦇🌹🍆🎖\n]+".format(tag),
                                castle_results_string)
                            print(nicknames_list)
                            for nickname in nicknames_list:
                                if response == "":
                                    response = "Игроки, попавшие в топ:\n"
                                response += "{}{} <b>{}</b>\n".format(
                                    "🛡️" if nickname[0] == attacked_castle else
                                    "⚔️", attacked_castle, nickname[:-1])

                                response_all += "{}{} <b>{}</b>\n".format(
                                    "🛡️" if nickname[0] == attacked_castle else
                                    "⚔️", attacked_castle, nickname[:-1])

                    if response != "":
                        if guild.chat_id is None:
                            continue
                        dispatcher.bot.send_message(chat_id=guild.chat_id,
                                                    text=response,
                                                    parse_mode='HTML')
                if response_all != "Игроки, попавшие в топ:\n":
                    dispatcher.bot.send_message(chat_id=CENTRAL_SQUARE_CHAT_ID,
                                                text=response_all,
                                                parse_mode='HTML')
            worldtop_strings = data.split("\n\n")[-1].splitlines()
            worldtop = load_worldtop(battle_id=count_battle_id() - 1)
            old_worldtop = copy.deepcopy(worldtop)
            for string in worldtop_strings:
                parse = re.search("(.).* \\+(\\d+) 🏆 очков", string)
                if parse is None:
                    continue
                castle = parse.group(1)
                count = int(parse.group(2))
                score = worldtop.get(castle)
                score += count
                worldtop.update({castle: score})
                sort_worldtop(worldtop)
                logging.info("Worldtop updated: {}: {}".format(castle, count))
            save_worldtop(worldtop)
            if not debug:
                send_worldtop_update(old_worldtop, worldtop)
            logging.info("Worldtop at the end: {}".format(worldtop))
        elif data.startswith("🤝Headquarters news:") or data.startswith(
                "🗺State of map:"):
            # Итоги штабов альянсов
            logging.info("Got alliance news")
            parse_alliance_battle_results(data, debug)
        else:
            #  Сообщение о пиратстве
            response_by_tags = {}
            data = data.replace("Attackers:", "   🗡Атакующие:")
            data = data.replace("Defenders:", "   🛡Обороняющиеся:")
            guild_list = re.split("[⚔🛡] ..?Гильдия", data)
            for guild_str in guild_list:
                new_str = guild_str
                new_str = "{}".format('⚔️' if 'атакована' in
                                      new_str else '🛡') + new_str
                tags = re.findall("[🍁☘🖤🐢🦇🌹🍆](\\w+)", guild_str)
                tags = list(set(tags))
                for tag in tags:
                    new_str = new_str.replace(tag, "<b>{}</b>".format(tag))
                for tag in tags:
                    lst = response_by_tags.get(tag)
                    if lst is None:
                        lst = "Итоги гильдейских битв с вашим участием:\n\n"
                        response_by_tags.update({tag: lst})
                    lst += new_str + "\n"
                    response_by_tags.update({tag: lst})
                # dispatcher.bot.send_message(chat_id=SUPER_ADMIN_ID, text=guild_str, parse_mode='HTML')
            import json
            # logging.error("Guild list for parse_stats: {}".format(json.dumps(guild_list, indent=4, ensure_ascii=False)))
            logging.error("Response by tags: {}".format(
                json.dumps(response_by_tags, indent=4, ensure_ascii=False)))
            print(guild_list)
            print(json.dumps(response_by_tags, indent=4, ensure_ascii=False))
            for tag, string in list(response_by_tags.items()):
                guild = Guild.get_guild(guild_tag=tag)
                if guild is None:
                    continue
                dispatcher.bot.send_message(chat_id=guild.chat_id,
                                            text=string,
                                            parse_mode='HTML')
        data = castles_stats_queue.get()
def notify_guild_attack(bot, update):
    mes = update.message
    remaining_time = get_time_remaining_to_battle()
    forward_message_date = utc.localize(
        mes.forward_date).astimezone(tz=moscow_tz).replace(tzinfo=None)
    if forward_message_date - datetime.datetime.now() > datetime.timedelta(
            minutes=2):
        return 0
    if remaining_time > datetime.timedelta(minutes=30):
        pass
        return 0
    ready_to_battle = mes.text.count("[⚔]") + mes.text.count("[🛡]")
    sleeping = mes.text.count("[🛌]") + mes.text.count("[⚒]")
    response = "<b>{0}</b>\nГотово к битве: <b>{1}</b>\nНе готово к битве, но занято <b>{2}</b>\n" \
               "Спит: <b>{3}</b>\n\nВремя до битвы: {4}\n".format(mes.text.splitlines()[0], ready_to_battle,
                                                                  mes.text.count("\n") - ready_to_battle - sleeping,
                                                                  sleeping, ":".join(str(remaining_time).partition(".")[0].split(":")[0:3]))
    request = "select guild_id from guilds where chat_id = %s"
    cursor.execute(request, (mes.chat_id, ))
    row = cursor.fetchone()
    if row is None:
        return
    guild = Guild.get_guild(guild_id=row[0])
    set = guild.settings.get(
        "battle_notify") if guild.settings is not None else True
    if guild is None or set is False:
        return
    if mes.chat_id != guild.chat_id:
        return
    if mes.from_user.id not in get_admin_ids(
            bot, chat_id=mes.chat_id) and not check_access(mes.from_user.id):
        bot.send_message(chat_id=mes.chat_id,
                         text="Доступ только у админов",
                         parse_mode='HTML',
                         reply_to_message_id=mes.message_id)
        return
    do_not_ready = []
    sleeping = []
    for string in mes.text.splitlines()[1:]:
        if not ("[⚔]" in string or "[🛡]" in string):
            nickname = string.partition("]")[2][1:]
            do_not_ready.append(nickname)
            if "[🛌]" in string or "[⚒]" in string:
                sleeping.append(nickname)

    in_dict_do_not_ready = []
    in_dict_sleeping = []
    ping_dict = {
        "do not ready": in_dict_do_not_ready,
        "sleeping": in_dict_sleeping
    }
    for player_id in guild.members:
        player = Player.get_player(player_id, notify_on_error=False)
        if player is None:
            continue
        db_nickname = player.nickname.partition("]")[2]
        if db_nickname in do_not_ready:
            in_dict_do_not_ready.append(player.username)
            if db_nickname in sleeping:
                in_dict_sleeping.append(player.username)

    ping_by_chat_id.update({mes.chat_id: ping_dict})
    response += "Пингануть тех, кто спит: /notify_guild_sleeping\n" \
                "Пингануть всех, кто не готов: /notify_guild_not_ready"
    bot.send_message(chat_id=mes.chat_id, text=response, parse_mode='HTML')
예제 #4
0
def mob(bot, update):
    mes = update.message
    link = re.search("/fight_(.*)$", mes.text)
    if link is None:
        bot.send_message(chat_id=mes.chat_id, text="Ошибка.")
        return
    link = link.group(1)
    names, lvls, buffs = [], [], []
    for string in mes.text.splitlines():
        parse = re.search("(.+) lvl\\.(\\d+)", string)
        if parse is not None:
            name = parse.group(1)
            lvl = int(parse.group(2))
            names.append(name)
            lvls.append(lvl)
            buffs.append("")
        else:
            parse = re.search("  ╰ (.+)", string)
            if parse is not None:
                buff = parse.group(1)
                buffs.pop()
                buffs.append(buff)
    try:
        forward_message_date = utc.localize(mes.forward_date).astimezone(tz=moscow_tz).replace(tzinfo=None)
    except Exception:
        forward_message_date = datetime.datetime.now(tz=moscow_tz).replace(tzinfo=None)
    # forward_message_date = datetime.datetime.now(tz=moscow_tz).replace(tzinfo=None) - datetime.timedelta(
    #     minutes=2, seconds=30)  # Test only
    request = "insert into mobs(link, mob_names, mob_lvls, date_created, created_player, on_channel, buffs, " \
              "minutes) values (" \
              "%s, %s, %s, %s, %s, %s, %s, %s)"
    is_pm = filter_is_pm(mes)
    minutes = AMBUSH_MINUTES if 'ambush' in mes.text else USUAL_MINUTES
    if "Вы нашли странное укрытие. Некоторые символы в дверном проёме выглядят знакомо" in mes.text:
        minutes = 7
    helpers = []
    try:
        cursor.execute(request, (link, names, lvls, forward_message_date, mes.from_user.id, is_pm, buffs, minutes))
    except psycopg2.IntegrityError:
        # logging.error(traceback.format_exc())
        request = "select on_channel, helpers from mobs where link = %s"
        cursor.execute(request, (link,))
        row = cursor.fetchone()
        helpers = row[1]
        if is_pm:
            if row[0]:
                bot.send_message(chat_id=mes.chat_id, text="Данный моб уже на канале",
                                 reply_to_message_id=mes.message_id)
                return
            request = "update mobs set on_channel = true where link = %s"
            cursor.execute(request, (link,))
    minutes = AMBUSH_MINUTES if 'ambush' in mes.text else USUAL_MINUTES
    response, buttons, avg_lvl, remaining_time = get_mobs_text_and_buttons(mes.chat_id, link, names, lvls, helpers,
                                                                           forward_message_date, buffs, minutes,
                                                                           mes.from_user.id)
    player: Player = Player.get_player(mes.from_user.id)
    if is_pm and (player is None or player.castle == '🖤'):
        if 'It\'s an ambush!'.lower() in mes.text.lower():
            bot.send_message(chat_id=mes.chat_id, text="Засады не отправляются на канал. "
                                                       "Зовите бойцов вашей гильдии на помощь!")
        elif remaining_time <= datetime.timedelta(0):
            bot.send_message(chat_id=mes.chat_id, text="Время истекло. На канал не отправлено.")
        # elif re.search("(boar|wolf|bear)", mes.text) is not None and 'resist' in mes.text:
        #     pass
        else:
            threading.Thread(target=send_mob_message_and_start_updating(bot, mes, player, response, buttons,
                                                                        is_pm, link, forward_message_date, [])).start()
            bot.send_message(chat_id=mes.chat_id, parse_mode='HTML',
                             text="Отправлено на <a href=\"https://t.me/mobs_skala_cw3\">канал</a>, а также в "
                                  "<a href=\"https://t.me/CwMobsNotifyBot\">бота</a>. Спасибо!")
            if player is not None and player.has_api_access:
                cwapi.update_player(player.id, player=player)
            try:
                # requests.post('http://127.0.0.1:5555/addMob',
                #               json=json.dumps({"castle": '🖤', "text": mes.text, "telegram_id": mes.from_user.id,
                #                                "forward_date": forward_message_date.timestamp()}, ensure_ascii=False),
                #               timeout=0.3)

                pass
                # Верно!
                requests.post('http://144.91.112.129:5555/addMob',
                              json=json.dumps({"castle": '🖤', "text": mes.text, "telegram_id": mes.from_user.id,
                                               "forward_date": forward_message_date.timestamp()}, ensure_ascii=False),
                              timeout=0.3)
            except Exception:
                logging.error(traceback.format_exc())
    else:
        ping, ping_list = [], []
        if remaining_time > datetime.timedelta(0):
            if not is_pm:
                minus, plus = get_suitable_lvls(mes.text)
                ping_list = get_chat_helpers(mes.chat_id, minus, plus, avg_lvl, player)
                if ping_list:
                    for pl in ping_list:
                        on = pl.settings.get("mobs_notify")
                        if on is None:
                            on = True
                        if on and pl.id != mes.from_user.id:
                            ping.append(pl.username)
                    if ping:
                        threading.Thread(target=send_notify, args=(link, mes.chat_id, ping)).start()

        guild = Guild.get_guild(player.guild)
        if guild is None or guild.settings.get("mobs_hunt", True) is True or mes.chat_id != guild.chat_id:
            threading.Thread(target=send_mob_message_and_start_updating,
                             args=(
                                 bot, mes, player, response, buttons, is_pm, link, forward_message_date, ping_list)
                             ).start()
    return
예제 #5
0
def stock(bot, update):
    """
    Выводит сток игрока (команда /stock)
    """
    mes = update.message
    player = Player.get_player(mes.from_user.id)
    if player is None:
        return
    is_guild = False
    guild = None
    if 'guild' in mes.text or mes.text.startswith("/g_stock"):
        is_guild = True
        if player.guild is None:
            bot.send_message(
                chat_id=mes.from_user.id,
                text=
                "Вы не состоите в гильдии. Попросите командира добавить вас")
            return
        guild = Guild.get_guild(guild_id=player.guild)
        if guild is None:
            bot.send_message(
                chat_id=mes.from_user.id,
                text=
                "Вы не состоите в гильдии. Попросите командира добавить вас")
            return
        curr_stock = guild.api_info.get("stock")
        if curr_stock is None:
            bot.send_message(
                chat_id=mes.from_user.id,
                text=
                "Отсутствует информация о стоке. Для обновления нажмите /update_guild. "
                "Требуется доступ к API.")
            return
    else:
        if not player.stock:
            bot.send_message(
                chat_id=mes.chat_id,
                text=
                "Отсутствует информация о стоке. Для обновления нажмите /update_stock. "
                "Требуется доступ к API.")
            return
        curr_stock = player.stock
    """
    res:   Ресурсы
    alch:  Травы
    misc:  Корм, Зелья, свитки
    other: Остальное
    """
    if 'res' in mes.text:
        stage = [0]
    elif 'alch' in mes.text:
        stage = [1]
    elif 'misc' in mes.text:
        stage = [2]
    elif 'equip' in mes.text:
        stage = [3]
    elif 'other' in mes.text:
        stage = [5]
    else:
        stage = []
    response = "<b>📦Склад:\nРесурсы:</b>\n"
    stages = {
        0: {
            "name": "Ресурсы:",
            "to_achieve": lambda code: True
        },
        1: {
            "name": "Травы",
            "to_achieve": lambda code: not code.isdigit() or int(code) >= 39
        },
        2: {
            "name": "Корм:",
            "to_achieve": lambda code: not code.isdigit() or int(code) >= 618
        },
        3: {
            "name": "Экипировка и крафт:",
            "to_achieve": lambda code: not code.isdigit()
        },
        4: {
            "name":
            "Зелья:",
            "to_achieve":
            lambda code: not code.isdigit() and code[0] not in ["k", "r", "w"]
        },
        5: {
            "name": "Другое:",
            "to_achieve": lambda code: not code.isdigit() and code[0] != "p"
        },
        6: {
            "name": "КОНЕЦ",
            "to_achieve": lambda code: False
        }
    }
    stage_num = 0
    next_stage = stages.get(stage_num + 1)
    total_gold = 0
    prices = cwapi.api_info.get("prices") or {}
    for code, count in list(curr_stock.items()):
        stage_changed = False
        new_response = ""
        while next_stage.get("to_achieve")(code):
            stage_changed = True
            stage_num += 1
            next_stage = stages.get(stage_num + 1)
        if stage and stage_num not in stage:
            continue
        if stage_changed:
            new_response += "\n<b>{}</b>\n".format(
                stages.get(stage_num).get("name"))
        price = prices.get(code) or "❔"
        if len(code) > 4:
            name = code
        else:
            name = get_item_name_by_code(code)
        new_response += "<a href=\"https://t.me/share/url?url=/{}\">{} x {}</a> ≈ {}" \
                        "\n".format("{} {} {}".format("g_withdraw" if is_guild else "g_deposit", code, count),
                                    "{} | {}".format(code, name) if code != name else
                                    name, count, "<b>{}</b>💰({}💰x{})".format(
                                    price * count, price, count) if isinstance(price, int) else price)
        total_gold += price * count if isinstance(price, int) else 0
        if len(response + new_response) > MAX_MESSAGE_LENGTH:
            bot.group_send_message(chat_id=mes.chat_id,
                                   text=response,
                                   parse_mode='HTML')
            response = ""
        response += new_response
    response += "\n\n<b>Всего: {}💰</b>\n".format(total_gold)
    if is_guild and guild is not None:
        stock_size, stock_limit = guild.api_info.get(
            "stock_size"), guild.api_info.get("stock_limit")
        if stock_size is not None and stock_limit is not None:
            response += "📦Сток гильдии: <b>{}</b> / <b>{}</b>\n".format(
                stock_size, stock_limit)
        response += "Последнее обновление: <em>{}</em>".format(
            guild.last_updated.strftime("%d/%m/%y %H:%M") if guild.
            last_updated is not None else "Неизвестно")
    elif not is_guild:
        response += "Последнее обновление: <em>{}</em>\n".format(
            player.api_info.get("stock_update") or "Неизвестно")
    bot.group_send_message(chat_id=mes.chat_id,
                           text=response,
                           parse_mode='HTML')
    bot.send_message_group(mes.chat_id)
예제 #6
0
def players_update_monitor():
    """
    Выполняется на всём протяжении функционирования бота. Раз в секунду запрашивает обновление
    MAX_PLAYERS_AUTO_UPDATE_PER_SECOND профилей игроков, ранее всего обновлявших свои профили.
    Раз в GUILD_UPDATE_INTERVAL_SECONDS секунд вызывает обновление гильдии, которая не обновлялась дольше всего.
    :return: None
    """
    cursor = conn.cursor()
    time.sleep(7)

    check_guilds_api_access()
    logging.info("Started updating profiles")
    i = 0
    while True:
        try:
            i += 1
            if not cwapi.active:
                return 0
            time_to_battle = get_time_remaining_to_battle()
            if time_to_battle < datetime.timedelta(minutes=30) or \
                    time_to_battle > datetime.timedelta(minutes=30, hours=7):
                time.sleep(1)
                continue
            if i % GUILD_UPDATE_INTERVAL_SECONDS == 0:
                # Обновление гильдии
                request = "select guild_id from guilds order by last_updated nulls first"
                cursor.execute(request)
                rows = cursor.fetchall()
                guild, player_id = None, None
                for row in rows:
                    guild_id = row[0]
                    guild = Guild.get_guild(guild_id=guild_id)
                    player_id = get_player_with_api_access_from_guild(guild)
                    if player_id is not None:
                        break
                if guild is None or player_id is None:
                    logging.error("No guild to update")
                    continue
                cwapi.update_guild_info(player_id)
                guild.api_info.update()
                logging.debug("Updating {} through CW3 API".format(guild.tag))

            request = "select id from players where api_info -> 'token' is not null order by last_updated limit %s"
            cursor.execute(request, (MAX_PLAYERS_AUTO_UPDATE_PER_SECOND, ))
            row = cursor.fetchone()
            while row is not None:
                if row is None:
                    logging.error("Request is None in players_update_monitor")
                    return 0
                player = Player.get_player(row[0])
                cwapi.update_player(player.id, player=player)
                logging.debug("Updating {} through CW3 API".format(
                    player.nickname))
                if not cwapi.active:
                    return 0
                access = player.api_info.get("access")
                if access is not None and "gear" in access:
                    cwapi.update_gear(player.id, player=player)
                row = cursor.fetchone()
            time.sleep(1)
        except Exception:
            logging.error(traceback.format_exc())
예제 #7
0
def mob(bot, update):
    mes = update.message
    link = re.search("/fight_(.*)$", mes.text)
    if link is None:
        bot.send_message(chat_id=mes.chat_id, text="Ошибка.")
        return
    link = link.group(1)
    names, lvls, buffs = [], [], []
    for string in mes.text.splitlines():
        parse = re.search("(.+) lvl\\.(\\d+)", string)
        if parse is not None:
            name = parse.group(1)
            lvl = int(parse.group(2))
            names.append(name)
            lvls.append(lvl)
            buffs.append("")
        else:
            parse = re.search("  ╰ (.+)", string)
            if parse is not None:
                buff = parse.group(1)
                buffs.pop()
                buffs.append(buff)
    try:
        forward_message_date = utc.localize(mes.forward_date).astimezone(tz=moscow_tz).replace(tzinfo=None)
    except Exception:
        forward_message_date = datetime.datetime.now(tz=moscow_tz).replace(tzinfo=None)
    request = "insert into mobs(link, mob_names, mob_lvls, date_created, created_player, on_channel, buffs, " \
              "minutes) values (" \
              "%s, %s, %s, %s, %s, %s, %s, %s)"
    is_pm = filter_is_pm(mes)
    minutes = 5 if 'ambush' in mes.text else 3
    helpers = []
    try:
        cursor.execute(request, (link, names, lvls, forward_message_date, mes.from_user.id, is_pm, buffs, minutes))
    except psycopg2.IntegrityError:
        # logging.error(traceback.format_exc())
        request = "select on_channel, helpers from mobs where link = %s"
        cursor.execute(request, (link,))
        row = cursor.fetchone()
        helpers = row[1]
        if is_pm:
            if row[0]:
                bot.send_message(chat_id=mes.chat_id, text="Данный моб уже на канале",
                                 reply_to_message_id=mes.message_id)
                return
            request = "update mobs set on_channel = true where link = %s"
            cursor.execute(request, (link,))
    minutes = 5 if 'ambush' in mes.text else 3
    response, buttons, avg_lvl, remaining_time = get_mobs_text_and_buttons(link, names, lvls, helpers,
                                                                           forward_message_date, buffs, minutes,
                                                                           mes.from_user.id)
    player = Player.get_player(mes.from_user.id)
    if is_pm and (player is None or player.castle == '🖤'):
        if 'It\'s an ambush!'.lower() in mes.text.lower():
            bot.send_message(chat_id=mes.chat_id, text="Засады не отправляются на канал. "
                                                       "Зовите бойцов вашей гильдии на помощь!")
        elif remaining_time <= datetime.timedelta(0):
            bot.send_message(chat_id=mes.chat_id, text="Время истекло. На канал не отправлено.")
        # elif re.search("(boar|wolf|bear)", mes.text) is not None and 'resist' in mes.text:
        #     pass
        else:
            threading.Thread(target=send_mob_message_and_start_updating(bot, mes, player, response, buttons,
                                                                        is_pm, link, forward_message_date)).start()
            bot.send_message(chat_id=mes.chat_id, parse_mode='HTML',
                             text="Отправлено на <a href=\"https://t.me/mobs_skala_cw3\">канал</a>, а также в "
                                  "<a href=\"https://t.me/CwMobsNotifyBot\">бота</a>. Спасибо!")
            try:
                # requests.post('http://127.0.0.1:5555/addMob',
                #               json=json.dumps({"castle": '🖤', "text": mes.text, "telegram_id": mes.from_user.id,
                #                                "forward_date": forward_message_date.timestamp()}, ensure_ascii=False),
                #               timeout=0.3)

                pass
                # Верно!
                requests.post('http://144.91.112.129:5555/addMob',
                              json=json.dumps({"castle": '🖤', "text": mes.text, "telegram_id": mes.from_user.id,
                                               "forward_date": forward_message_date.timestamp()}, ensure_ascii=False),
                              timeout=0.3)
            except Exception:
                logging.error(traceback.format_exc())
    else:
        if remaining_time > datetime.timedelta(0):
            ping_count = 0
            if not is_pm:
                barracks = Location.get_location(1)
                try:
                    ping_list = barracks.special_info.get("mobs_notify").get(str(mes.chat_id)).copy()
                except Exception:
                    ping_list = None
                if not ping_list:
                    ping_list = []
                if player.guild is not None or ping_list:
                    guild = Guild.get_guild(guild_id=player.guild)
                    if guild.is_academy() and mes.chat_id == guild.chat_id:
                        # Пинги для академки отключены
                        return
                    if guild is not None and guild.chat_id == mes.chat_id:
                        ping_list += guild.members
                    if ping_list:
                        minus, plus = get_suitable_lvls(mes.text)
                        ping = []
                        for pl_id in ping_list:
                            pl = Player.get_player(pl_id)
                            if avg_lvl - minus <= pl.lvl <= avg_lvl + plus:
                                on = pl.settings.get("mobs_notify")
                                if on is None:
                                    on = True
                                if on and pl.id != mes.from_user.id:
                                    ping.append(pl.username)
                        if ping:
                            text = "Мобы!\n"
                            for username in ping:
                                text += "@{} ".format(username)
                                ping_count += 1
                                if ping_count >= PING_LIMIT:
                                    bot.send_message(chat_id=mes.chat_id, text=text)
                                    text = "Мобы!\n"
                                    ping_count = 0
                            if text != "Мобы!\n":
                                bot.send_message(chat_id=mes.chat_id, text=text)
        threading.Thread(target=send_mob_message_and_start_updating(bot, mes, player, response, buttons, is_pm, link,
                                                                    forward_message_date)).start()
    return
예제 #8
0
def get_player_and_guild_and_alliance(player_id: int):
    player = Player.get_player(player_id, notify_on_error=False)
    guild = Guild.get_guild(player.guild) if player is not None else None
    alliance = Alliance.get_alliance(guild.alliance_id) if guild is not None else None
    return player, guild, alliance
예제 #9
0
def hero(bot, update, user_data):
    mes = update.message
    text = mes.text
    castle = re.search("([🍁☘️🖤🐢🦇🌹🍆🎖]+)(.+)", text)
    nickname = castle.group(2)
    castle = castle.group(1)
    if castle != '🖤':
        pass
        # Игрок не из Скалы
        # bot.send_message(chat_id=mes.from_user.id, text="Пользователям не из Скалы запрещена регистрация!")
        # return
    player = Player.get_player(mes.from_user.id, notify_on_error=False)
    if player is not None and player.id == 402027858 and player.castle != '🖤' and castle == '🖤':
        # Рыбак вернулся!
        bot.send_message(
            chat_id=player.id,
            text=
            "Стражи с гулким стуком ударяют копьями о землю. Врата медленно "
            "отворяются, открывая взору такие знакомые, но в то же время изменившиеся улицы.\n"
            "<b>С возвращением домой!</b>",
            parse_mode='HTML')
    if player is None and mes.chat_id != mes.from_user.id:
        # Добавление новых пользователей только в личке у бота
        return
    forward_message_date = utc.localize(
        mes.forward_date).astimezone(tz=moscow_tz).replace(tzinfo=None)
    print(forward_message_date)
    if datetime.datetime.now() - forward_message_date > datetime.timedelta(seconds=30) and \
            mes.from_user.id not in urned_players:
        bot.send_message(chat_id=mes.chat_id,
                         text="Это устаревший профиль.",
                         reply_to_message_id=mes.message_id)
        return
    # Парсинг хиро
    guild_tag = re.search("[🍁☘🖤🐢🦇🌹🍆🎖]\\[(.+)\\]", text)
    if guild_tag:
        guild_tag = guild_tag.group(1)
    lvl = int(re.search("🏅Уровень: (\\d+)", text).group(1))
    attack = int(re.search("⚔Атака: (\\d+)", text).group(1))
    defense = int(re.search("🛡Защита: (\\d+)", text).group(1))
    stamina = int(re.search("🔋Выносливость: \\d+/(\\d+)", text).group(1))
    pet = re.search("Питомец:\n.(\\s.+\\(\\d+ lvl\\))", text)
    exp = int(re.search("🔥Опыт: (\\d+)", text).group(1))
    last_updated = datetime.datetime.now(tz=moscow_tz).replace(tzinfo=None)
    if pet:
        pet = pet.group(1)
    # Парсинг экипировки
    print("parsing eq")
    player_equipment = {
        "main_hand": None,
        "second_hand": None,
        "head": None,
        "gloves": None,
        "armor": None,
        "boots": None,
        "cloaks": None
    }
    equip_strings = text.partition("🎽Экипировка")[2].splitlines()[1:]
    for string in equip_strings:
        # clear_name = re.search("\\+?\\d?\\s?(.+?)\\s\\+", string)
        clear_name = re.search(
            "(⚡?\\+?\\d*\\s?(.+?))\\s\\+((\\d*)⚔)?\\s*\\+?(\\d*)🛡?", string)
        if clear_name is None:
            # logging.warning("Error while parsing item_string\n{}".format(string))
            continue
        else:
            pass
            # logging.info("successful parsed {},, Got: {}".format(string, clear_name.group(1)))
        full_name = clear_name.group(1)
        eq_attack = int(clear_name.group(4)) if clear_name.group(
            4) is not None and clear_name.group(4) != "" else 0
        eq_defense = int(
            clear_name.group(5)) if clear_name.group(5) != "" else 0
        clear_name = clear_name.group(2)
        eq = get_equipment_by_name(clear_name)
        if eq is None:
            logging.warning(
                "Equipment with name {} is None".format(clear_name))
            continue
        eq.name = full_name
        eq.attack = eq_attack
        eq.defense = eq_defense
        player_equipment.update({eq.place: eq})
    if player is None:
        if mes.from_user.username is None:
            bot.send_message(
                chat_id=mes.chat_id,
                text=
                "Регистрация без имени пользователя невозможна. Пожалуйста, "
                "установите его в настройках аккаунта Telegram")
            return
        player = Player(mes.from_user.id,
                        mes.from_user.username,
                        nickname,
                        guild_tag,
                        None,
                        lvl,
                        attack,
                        defense,
                        stamina,
                        pet,
                        player_equipment,
                        castle=castle,
                        last_updated=last_updated,
                        created=last_updated,
                        exp=exp)
        # Добавляем игрока в бд
        player.insert_into_database()
        player = player.reload_from_database()

        user_data.update({"status": DEFAULT_CASTLE_STATUS, "location_id": 0})
        bot.send_message(
            chat_id=mes.chat_id,
            text=
            "Добро пожаловать в 🖤Скалу, <b>{}</b>!\n\n<a href=\"https://t.me/joinchat/DdKE7kUfsmDVIC2DJymw_A\">Чат центральной площади</a>\n\nДля добавления информации о классе "
            "необходимо прислать ответ @ChatWarsBot на кнопку \"🏅Герой\" (рекомендуется сделать для "
            "получения доступа к некоторых дополнительным фишкам, особенно стражникам).\n\n"
            "<em>Вы всегда можете отключить рп составляющую бота командой </em>/change_rp.<em> "
            "Обратите внимание, что это сделает недоступными некоторые функции "
            "бота.</em>".format(player.nickname),
            parse_mode='HTML')
        if filter_is_pm(mes):
            send_general_buttons(mes.from_user.id, user_data)
        auth(bot, update)

    else:
        # Обновляем существующую информацию
        player.username = mes.from_user.username
        player.nickname = nickname
        player.guild_tag = guild_tag
        player.lvl = lvl
        player.attack = attack
        player.defense = defense
        player.stamina = stamina
        player.pet = pet
        player.equipment = player_equipment
        player.castle = castle
        player.last_updated = last_updated
        player.exp = exp
        player.update()
        bot.send_message(chat_id=mes.chat_id,
                         text="Профиль успешно обновлён, <b>{}</b>!".format(
                             player.nickname),
                         parse_mode='HTML')
        if player.guild is not None:
            guild = Guild.get_guild(player.guild)
            guild.calculate_attack_and_defense()
            guild.sort_players_by_exp()
예제 #10
0
def view_profile(bot, update):
    mes = update.message
    requested_player_id = mes.from_user.id
    requested_player = Player.get_player(requested_player_id)
    if requested_player is None:
        return
    has_access = True
    guild = Guild.get_guild(guild_id=requested_player.guild)
    if not check_whois_access(requested_player_id):
        if guild is None or not guild.check_high_access(requested_player_id):
            # bot.send_message(chat_id=mes.chat_id, text="Право распоряжаться людьми необходимо заслужить.",
            #                  reply_to_message_id=mes.message_id)
            has_access = False
    # Доступ к хуизу есть
    reply = False
    if mes.text.startswith("/dok") or mes.text.startswith("/doc"):
        if mes.reply_to_message is not None:
            #  Реплай в чате
            reply = True
            player_ids = [mes.reply_to_message.from_user.id]
        elif has_access is False:
            return
        elif "@" in update.message.text:
            # Поиск по юзерке
            player_ids = []
            for username in mes.text.split()[1:]:
                request = "select id from players where username = %s"
                cursor.execute(request, (username.partition("@")[2], ))
                row = cursor.fetchone()
                if row is None:
                    bot.send_message(
                        chat_id=mes.chat_id,
                        text="Игрок {} не найден.".format(username))
                    continue
                player_ids.append(row[0])
            if not player_ids:
                return
        else:
            # Поиск по нику в игре
            request = "select id from players where lower(nickname) = %s or lower(nickname) like %s"
            # print(request % mes.text.partition(" ")[2] % "%]" + mes.text.partition(" ")[2])
            cursor.execute(request,
                           (mes.text.partition(" ")[2].lower(),
                            "%]" + mes.text.partition(" ")[2].lower()))
            row = cursor.fetchone()
            if row is None:
                bot.send_message(chat_id=mes.chat_id, text="Игрок не найден.")
                return
            player_ids = [row[0]]
    else:
        player_id = re.search("_(\\d+)", mes.text)
        player_ids = [int(player_id.group(1))]
    if not player_ids:
        bot.send_message(chat_id=mes.chat_id, text="Неверный синтаксис.")
        return
    for player_id in player_ids:
        player = Player.get_player(player_id)
        if player is None or (mes.text.startswith("/view_profile") and
                              (guild is None or player.guild != guild.id)):
            if player is not None and player.guild is not None:
                guild = Guild.get_guild(player.guild)
                if guild is not None:
                    if requested_player_id in guild.assistants or requested_player_id == guild.commander_id:
                        pass
                    else:
                        bot.send_message(chat_id=mes.chat_id,
                                         text="Игрок не найден.")
                        return
        if reply and player.status is not None:
            # Сообщение со статусом
            bot.send_message(chat_id=mes.chat_id,
                             text=get_status_message_by_text(
                                 get_status_text_by_id(player.status,
                                                       player.id)),
                             parse_mode='HTML',
                             reply_to_message_id=mes.message_id)
            on_doc_status(requested_player)
        if not has_access:
            bot.send_message(
                chat_id=mes.chat_id,
                text="Право распоряжаться людьми необходимо заслужить.",
                reply_to_message_id=mes.message_id)
            return
        buttons = get_profile_buttons(player)
        if (player.guild is None or player.guild != requested_player.guild
            ) and not check_whois_access(requested_player_id):
            guild = Guild.get_guild(guild_id=player.guild)
            bot.send_message(
                chat_id=mes.from_user.id,
                text=
                "Вы не знаете этого человека, однако его форма позволяет вам сделать вывод, что он "
                "служит {}".format(
                    "в гильдии <b>{}</b>".format(guild.tag) if guild
                    is not None else "как вольный наёмник (без гильдии)"),
                parse_mode='HTML',
                reply_markup=buttons)
            return
        buttons = get_profile_buttons(player, whois_access=True)
        response = get_profile_text(player,
                                    self_request=False,
                                    requested_player=requested_player)
        bot.send_message(chat_id=mes.from_user.id,
                         text=response,
                         parse_mode='HTML',
                         reply_markup=buttons)
예제 #11
0
def check_whois_access(user_id):
    try:
        return check_access(user_id) or user_id == MERC_ID or user_id in trade_divisions_access_list or \
               Guild.get_guild(guild_tag="АКАДЕМИЯ").check_high_access(user_id)
    except Exception:
        return False
예제 #12
0
def get_profile_text(player,
                     self_request=True,
                     user_data=None,
                     requested_player=None):
    barracks = Location.get_location(1)
    class_links = barracks.special_info.get("class_links")
    if class_links is None:
        class_links = {}
        barracks.special_info.update({"class_links": class_links})
    try:
        class_format = (classes_to_emoji.get(player.game_class) + player.game_class) if \
            player.game_class is not None else "Воин"
    except Exception:
        class_format = "Воин"
        logging.error(traceback.format_exc())
        logging.error("id:{} nickname:{} class:{} username:{}".format(
            player.id, player.nickname, player.game_class, player.username))
    response = "<b>{}</b> - {} {}\n".format(
        player.nickname, class_format,
        "🖤Скалы" if player.castle == '🖤' else player.castle)
    response += "{}id: <code>{}</code>, ".format(
        "@{}, ".format(player.username) if player.username is not None else "",
        player.id)
    if user_data is None:
        user_data = dispatcher.user_data.get(player.id)
    if player.status is not None:
        response += "Статус: <b>{}</b>\n".format(
            get_status_text_by_id(player.status, player.id))
    response += "🏅: <code>{}</code>, 🔥: <code>{}</code> ⚔: <code>{}</code>, 🛡: <code>{}</code>" \
                "\n".format(player.lvl, player.exp or "???", player.attack, player.defense)
    response += ("👝: {}, ".format(player.pogs) if player.pogs is not None else "") + \
        "🔘: <code>{}</code>\n".format(player.reputation)
    guild = Guild.get_guild(
        guild_id=player.guild) if player.guild is not None else None
    response += "Гильдия: {} | {}🔋\n".format(
        "<code>{}</code>".format(guild.tag) if guild is not None else "нет",
        player.stamina)
    if guild is not None and self_request:
        response += "Покинуть гильдию: /leave_guild\n"
    elif guild is not None and guild.check_high_access(requested_player.id) and \
            (requested_player.guild == guild.id or guild.is_academy()):
        response += "Удалить из гильдии: /remove_player_{}\n".format(player.id)
    if self_request:
        if player.game_class is not None and player.castle == '🖤' and player.game_class not in [
                'Master', 'Esquire'
        ]:
            try:
                if class_links.get(player.game_class) is None:
                    revoke_class_link(player.game_class)
                invite_link = class_links.get(player.game_class)
                response += "<a href=\"{}\">\n📚Классовый чат</a>\n".format(
                    "https://t.me/joinchat/" + invite_link)
            except Exception:
                logging.error(traceback.format_exc())
    response += "\nЭкипировка:\n"
    eq_list = list(player.equipment.values())
    for equipment in eq_list:
        if equipment is None:
            continue
        response += equipment.format()

    r1, r2, r3 = player.get_reports_count()

    try:
        if guild is not None and guild.commander_id == player.id:
            response += "\n<b>🎗Командир гильдии</b>\n"
        if guild is not None and player.id in guild.assistants:
            response += "\n<b>🎗Зам командира гильдии</b>\n"
    except Exception:
        logging.error(traceback.format_exc())

    response += "\nРепорты(эта неделя / прошлая / всего): <code>{}</code> / <code>{}</code> / <code>{}</code>" \
                "\n".format(r1, r2, r3)
    response += "Регистрация в боте: <code>{}</code>\n".format(
        player.created.strftime("%d/%m/%y %H:%M:%S") if player.
        created is not None else "Оппозит")
    response += "Последнее обновление профиля: " \
                "<code>{}</code>\n".format(player.last_updated.strftime("%d/%m/%y %H:%M:%S") if
                                           player.last_updated is not None else "неизвестно")
    if user_data is None:
        return response
    status = user_data.get("status")
    if status is not None and status in ["sawmill", "quarry", "construction"
                                         ] or "quest_name" in user_data:
        if "quest_name" in user_data:
            quest_name = user_data.get("quest_name")
            response += "\n<b>Вы {}. Это займёт несколько минут.</b>" \
                        "".format("на разведке" if quest_name == 'exploration' else
                                  "копаете котлован" if quest_name == 'pit' else "")
        else:
            if player is not None:
                j = construction_jobs.get(player.id)
                if j is not None:
                    seconds_left = j.get_time_left()
                    response += "\nВы заняты делом. Окончание через <b>{:02.0f}:{:02.0f}</b>" \
                                "".format(seconds_left // 60, (seconds_left % 60) // 1)
    return response
예제 #13
0
def battle_stats(bot, update):
    mes = update.message
    cursor1 = conn.cursor()
    battle_id = re.search("_(\\d+)", mes.text)
    battle_id = int(
        battle_id.group(1)) if battle_id is not None else count_battle_id(mes)

    guilds = []
    for guild_id in Guild.guild_ids:
        guild = Guild.get_guild(guild_id=guild_id)
        if guild is None or guild.division in SKIPPED_DIVISIONS:
            continue
        guild.clear_counted_reports()
        guilds.append(guild)
    guilds.sort(key=lambda x: x.division or "")
    guilds.append(
        Guild(-1, "Без гильдии", None, None, None, None, None, None, None,
              None, None, None, None, None))
    request = "select player_id, attack, defense, gold from reports where battle_id = %s"
    cursor1.execute(request, (battle_id, ))
    row = cursor1.fetchone()
    response = "Статистика по битве {} - {}:\n".format(
        battle_id,
        count_battle_time(battle_id).strftime("%d/%m/%y %H:%M:%S"))
    while row is not None:
        player = Player.get_player(row[0])
        if player.castle != '🖤':
            row = cursor1.fetchone()
            continue
        if player.guild is None:
            guild = guilds[-1]
        else:
            guild = Guild.get_guild(player.guild)
        guild.add_count_report(row[1], row[2], row[3])
        row = cursor1.fetchone()
    total_reports = 0
    total_attack = 0
    total_defense = 0
    total_gold = 0
    guilds.sort(key=lambda x:
                (x.division or "", x.get_counted_report_values()[1]),
                reverse=True)
    current_division = guilds[0].division
    division_reports, division_attack, division_defense, division_gold = 0, 0, 0, 0
    for guild in guilds:
        if guild.division != current_division:
            response += "Дивизион {}:\nВсего: {} репортов, ⚔️: <b>{}</b>, 🛡: <b>{}</b>, 💰: <b>{}</b>\n\n" \
                        "".format(current_division, division_reports, division_attack, division_defense, division_gold)
            total_attack += division_attack
            total_defense += division_defense
            total_gold += division_gold
            total_reports += division_reports
            division_reports, division_attack, division_defense, division_gold = 0, 0, 0, 0

            current_division = guild.division

        values = guild.get_counted_report_values()
        division_reports += values[0]
        division_attack += values[1]
        division_defense += values[2]
        division_gold += values[3]
        response += "<code>{:<3}</code>-👣{} ⚔️{} 🛡{} 💰{}" \
                    "\n".format(guild.tag, values[0], values[1], values[2], values[3])


    response += "\nВсего: {} репортов, ⚔️: <b>{}</b>, 🛡: <b>{}</b>, " \
                    "💰: <b>{}</b>\n".format(total_reports, total_attack, total_defense, total_gold)
    bot.send_message(chat_id=mes.chat_id, text=response, parse_mode='HTML')
예제 #14
0
 def get_alliance_guilds(self):
     request = "select guild_id from guilds where alliance_id = %s"
     cursor.execute(request, (self.id, ))
     return list(
         map(lambda guild_id: Guild.get_guild(guild_id[0]),
             cursor.fetchall()))
예제 #15
0
def get_general_buttons(user_data, player=None, only_buttons=False):
    status = user_data.get("status")
    rp_off = user_data.get("rp_off")
    buttons = None
    if rp_off and status in ["central_square", "rp_off"]:
        buttons = [[
            KeyboardButton("👀 Профиль"),
            KeyboardButton("👥 Гильдия"),
            KeyboardButton("📈Топы"),
        ],
                   [
                       KeyboardButton("🔖Связь с МИД"),
                       KeyboardButton("🗂Обновления"),
                       KeyboardButton("📰Инструкция"),
                   ]]
        if player is not None:
            if player.guild is not None:
                guild = Guild.get_guild(player.guild)
                if guild is not None:
                    if guild.check_high_access(player.id):
                        pass
                        # buttons[0].append(KeyboardButton("📜Список гильдий"))
    elif status is None or status in ["default", "central_square"]:
        status = "central_square"
        user_data.update({"status": status})
        buttons = [
            [
                KeyboardButton(Location.get_location(1).name),
                KeyboardButton(Location.get_location(2).name),
                KeyboardButton("⛩ Врата замка"),
            ],
            [
                KeyboardButton("🔭 Башня ТехМаг наук"),  # ❗
                KeyboardButton("🏤Мандапа Славы"),
                # KeyboardButton("📈Топы"),
                # KeyboardButton("🏚 Не построено"),
            ],
            [
                KeyboardButton("↔️ Подойти к указателям"),
                KeyboardButton("🏚 Стройплощадка"),
                # KeyboardButton("↩️ Назад"),
            ]
        ]
        # Стройка Мандапы Славы окончена
        # hall = Location.get_location(8)
        # if hall is not None and hall.is_constructed():
        #     buttons[1].insert(1, KeyboardButton("🏤Мандапа Славы"))

        tea_party = Location.get_location(9)
        if tea_party is not None and tea_party.is_constructed():
            buttons[1].insert(2, KeyboardButton("🍵Чайная лига"))

    elif status == 'barracks':
        buttons = [[
            KeyboardButton("👀 Посмотреть в зеркало"),
            KeyboardButton("👥 Посмотреть ведомость гильдии"),
        ], [
            KeyboardButton("↩️ Назад"),
        ]]
        if player is not None:
            if player.guild is not None:
                guild = Guild.get_guild(player.guild)
                if guild is not None:
                    if guild.alliance_id is not None:
                        buttons.insert(1, [KeyboardButton(" 🤝Альянс")])
                    if guild.check_high_access(player.id):
                        pass
                        # buttons.insert(1, [KeyboardButton("📜Изучить список гильдий")])
    elif status == 'throne_room':
        buttons = [
            [
                KeyboardButton("Обратиться к командному составу"),
                KeyboardButton("Попросить аудиенции у 👑Короля"),
            ],
            [
                KeyboardButton("🎇Посмотреть на портреты"),
                # KeyboardButton("💰Сокровищница"),
            ],
            [
                KeyboardButton("↩️ Назад"),
            ]
        ]
        if player is not None and check_access(player.id):
            buttons[1].append(KeyboardButton("Штаб"))
        if player is not None and player.id in [king_id, SUPER_ADMIN_ID]:
            buttons[1].append(KeyboardButton("Кабинет Короля"))
    elif status in [
            'mid_feedback', 'duty_feedback', 'sending_guild_message',
            'editing_debrief', 'changing_castle_message',
            'sending_bot_guild_message', 'editing_update_message', "treasury",
            "awaiting_roulette_bet"
    ]:
        buttons = [[
            KeyboardButton("↩️ Назад"),
        ]]
    elif status in ["sawmill", "quarry", "construction", "exploration", "pit"]:
        buttons = [[
            KeyboardButton("👀 Профиль"),
        ], [
            KeyboardButton("↩️ Отмена"),
        ]]
    elif status == 'castle_gates':
        on_duty = user_data.get("on_duty")
        print(on_duty, user_data)
        if on_duty:
            buttons = [
                [
                    KeyboardButton("Покинуть вахту"),
                ],
            ]
        else:
            buttons = [[
                KeyboardButton("🌲Лесопилка"),
                KeyboardButton("⛰Каменоломня"),
            ], [
                KeyboardButton("Обратиться к 💂‍♂Стражам"),
            ], [
                KeyboardButton("↩️ Назад"),
            ]]
            print(player, player.game_class if player is not None else "")
            if player is not None and player.game_class == "Sentinel":  # Только для стражей, захардкожено
                buttons[0].append(KeyboardButton("Заступить на вахту"))
    elif status == 'king_cabinet':
        buttons = [[
            KeyboardButton("Добавить генерала"),
            KeyboardButton("Изменить сообщение"),
        ], [
            KeyboardButton("Начать стройку"),
        ], [
            KeyboardButton("↩️ Назад"),
        ]]
    elif status == 'headquarters':
        buttons = [[
            KeyboardButton("📜Выкатить дебриф"),
            KeyboardButton("📣Рассылка по гильдиям"),
        ], [
            KeyboardButton("↩️ Назад"),
        ]]
    elif status == 'technical_tower':
        buttons = [
            [
                # KeyboardButton("🔖Обратиться к магу"),
                KeyboardButton("📰Манускрипт"),
                KeyboardButton("🗂Архив объявлений"),
            ],
            [
                KeyboardButton("🧾История коммитов"),
            ],
            [
                KeyboardButton("↩️ Назад"),
            ]
        ]
        if player is not None and player.id == SUPER_ADMIN_ID:
            buttons[1].insert(1, KeyboardButton("💻Кабинет ботодела"))
    elif status == 'my_cabinet':
        buttons = [[
            KeyboardButton("📈Выкатить обнову"),
            KeyboardButton("📣Рассылка по гильдиям"),
        ], [
            KeyboardButton("↩️ Назад"),
        ]]
    elif status == 'construction_plate':
        location = Location.get_location(status_to_location.get(status))
        buttons = location.buttons
    elif status == 'hall_of_fame':
        buttons = [
            [
                KeyboardButton("📈Топы"),
                # KeyboardButton("📣Ещё кнопка, хз что"),
            ],
            [
                KeyboardButton("↩️ Назад"),
            ]
        ]
    elif status == 'tops':
        buttons = [[
            KeyboardButton("⚔️Атака"),
            KeyboardButton("🛡Защита"),
            KeyboardButton("🔥Опыт"),
        ], [
            KeyboardButton("↩️ Назад"),
        ]]
        if not rp_off:
            buttons.insert(1, [
                KeyboardButton("🌲Дерево"),
                KeyboardButton("⛰Камень"),
                KeyboardButton("🏚Стройка"),
            ])
    elif status == 'manuscript':
        buttons = [
            [
                KeyboardButton("👤Игроки"),
                KeyboardButton("👥Гильдии"),
                KeyboardButton("📓Гайды"),
            ],
            [
                KeyboardButton("🖋Триггеры"),
                KeyboardButton("📦Сток"),
                # KeyboardButton("🏠Профсоюзы"),
            ],
            [
                KeyboardButton("↩️ Назад"),
            ]
        ]
        if not rp_off:
            buttons[1].insert(0, KeyboardButton("↔️Указатели"))
    elif status == 'guides':
        buttons = [[
            KeyboardButton("⚗️Алхимик"),
            KeyboardButton("⚒Кузнец"),
            KeyboardButton("📦Добытчик"),
        ],
                   [
                       KeyboardButton("🏹Лучник"),
                       KeyboardButton("⚔Рыцарь"),
                       KeyboardButton("🛡Защитник"),
                   ], [
                       KeyboardButton("↩️ Назад"),
                   ]]
    elif status == 'tea_party':
        buttons = [
            # [
            # KeyboardButton("Разведка"),
            # KeyboardButton("Рыть котлован"),
            # ],
            [
                KeyboardButton("🎰Рулетка"),
                KeyboardButton("💲Магазин статусов"),
            ],
            [
                KeyboardButton("🧳Контрабандист"),
            ],
            [
                KeyboardButton("↩️ Назад"),
            ],
        ]
    elif status == 'roulette':
        buttons = [
            [
                KeyboardButton("🔸Сделать ставку"),
                KeyboardButton("📈Топы в рулетке"),
            ],
            [KeyboardButton("↩️ Назад")],
        ]
    if only_buttons or buttons is None:
        return buttons
    return ReplyKeyboardMarkup(buttons, resize_keyboard=True)
예제 #16
0
def send_withdraw(bot, update, *args):
    manual = False
    if args and args[0] == "custom_request":
        manual = True
        give = args[1]
        chat_id = update
        player = Player.get_player(chat_id)
    else:
        chat_id = update.message.chat_id
        player = Player.get_player(update.message.from_user.id)
        give = {}
    mes = update.message if not isinstance(update, int) else None
    response, response_full = "/g_withdraw ", "/g_withdraw "
    res_count = 0
    if player is None:
        return
    guild_stock = None
    if player.guild is not None:
        guild = Guild.get_guild(guild_id=player.guild)
        if guild.settings is not None:
            if guild.settings.get("withdraw") is False:
                if guild.chat_id == mes.chat_id:
                    return
        guild_stock = guild.api_info.get("stock")
    if manual:
        pass
    elif "дай" in mes.text.lower():
        # Выдача ресурсов по Дай x y
        potions_dict = {
            "фр": ["p01", "p02", "p03"],
            "фд": ["p04", "p05", "p06"],
            "грид": ["p07", "p08", "p09"],
            "натуру": ["p10", "p11", "p12"],
            "ману": ["p13", "p14", "p15"],
            "твайлайт": ["p16", "p17", "p18"],
            "морф": ["p19", "p20", "p21"]
        }
        parse = mes.text.lower().split()[1:]
        mode = "name"
        names = []
        for string in parse:
            if mode == "quantity":
                mode = "name"
                try:
                    quantity = int(string)
                    if quantity > 0:
                        if not names:
                            continue
                        for name in names:
                            give.update({name: quantity})
                        continue
                except ValueError:
                    pass
            if mode == "name":
                mode = "quantity"
                potions = potions_dict.get(string)
                if potions is None:
                    if string not in list(resources) and string not in list(equipment_names) and string not in \
                            list(resources_reverted) and re.match("[rkp]\\d\\d?", string) is None:
                        mode = "name"
                        continue
                    names = [
                        string
                    ]  # Список из имён, к которым далее следует количество для выдачи
                    give.update({string: 1})
                else:
                    names = []
                    for p in potions:
                        give.update({p: 1})
                        names.append(p)
    else:
        text = update.message.text.partition("In your stock:")
        text = text[2] or text[0]
        for string in text.splitlines():
            if "Нет нужных материалов" in mes.text:
                parse = re.search("([^\n$]+) x (\\d+)", string)
                if parse is None:
                    continue
                count = int(parse.group(2))
                name = parse.group(1)
                code = resources.get(name)
            else:
                parse = re.search("(\\d+) x ([^\n$]+)", string)
                if parse is None:
                    continue
                count = int(parse.group(1))
                name = parse.group(2)
                code = resources.get(name)
            if code is None:
                code = get_item_code_by_name(name)
            if code is None:
                continue
            give.update({code: count})
    not_enough = ""
    for code, count in list(give.items()):
        if guild_stock is not None:
            # Есть данные о стоке, проверка наличия ресурсов
            in_stock = guild_stock.get(code) or 0
            if in_stock > 0:
                response += "{} {} ".format(code, min(count, in_stock))
            if in_stock < count:
                not_enough += "{} x {}\n".format(get_item_name_by_code(code),
                                                 count - in_stock)
        response_full += "{} {} ".format(code, count)
        res_count += 1
        if res_count >= WITHDRAW_MESSAGE_LIMIT:
            response = format_all_withdraws(response, response_full,
                                            not_enough)
            bot.send_message(chat_id=chat_id, text=response, parse_mode='HTML')
            response, response_full, not_enough = "/g_withdraw ", "/g_withdraw ", ""
            res_count = 0
    if res_count > 0:
        response = format_all_withdraws(response, response_full, not_enough)
        bot.send_message(chat_id=chat_id, text=response, parse_mode='HTML')
예제 #17
0
 def check_vote_ability(self):
     """
     Метод проверки возможности игрока голосовать
     """
     from castle_files.libs.guild import Guild
     return self.castle == HOME_CASTLE and self.guild is not None and not Guild.get_guild(self.guild).is_academy()
예제 #18
0
    def on_guild_info(self, body):
        """
        Метод, который вызывается при получении информации о гильдии (в том числе и её стока)
        :param body: dict - Message body
        """
        try:
            payload = body.get("payload")
            if payload is None:
                logger.debug("Payload is None in guild info: {}".format(body))
                return
            player_id = payload.get("userId")
            player = Player.get_player(player_id, notify_on_error=False)
            guild = Guild.get_guild(player.guild)
            if body.get("result") != "Ok":
                logging.error(
                    "error while requesting guild info, {}".format(body))
                if body.get("result") == "Forbidden":
                    try:
                        self.remove_player_from_guild_access(guild, player)
                    except ValueError:
                        pass
                    except Exception:
                        logging.error(
                            "Can not remove guild api access: {}".format(
                                traceback.format_exc()))
                return
            # print(body)
            # print(json.dumps(body, sort_keys=1, indent=4, ensure_ascii=False))
            name, glory, lvl, members, stock_size, stock_limit, \
                tag, castle = payload.get("name"), payload.get("glory"), payload.get("level"), \
                payload.get("members"),  payload.get("stockSize"), payload.get("stockLimit"), \
                payload.get("tag"), payload.get("castle")
            got_stock = payload.get("stock")
            codes = payload.get("itemCodes")
            stock, equipment_temp, equipment = {}, {}, []
            for i_name, count in list(got_stock.items()):
                code = get_item_code_by_name(i_name)
                eq = get_equipment_by_name(i_name)
                if eq is not None:
                    lst = equipment_temp.get(eq.name)
                    if lst is None:
                        lst = []
                        equipment_temp.update({eq.name: lst})
                    for i in range(count):
                        lst.append(copy.deepcopy(eq))
                stock.update({code or i_name: count})
            stock = {
                k: stock[k]
                for k in sorted(stock, key=stock_sort_comparator)
            }
            self.__set_guild_equipment_codes(codes, equipment_temp, equipment)
            player = Player.get_player(player_id, notify_on_error=False)
            if player is None or player.guild is None:
                logging.warning(
                    "Received guild info, but player is None (or guild) for id {}"
                    .format(player_id))
                return
            if guild is None or guild.tag != tag:
                logging.warning(
                    "Received guild info, but guild is None or not euqal for"
                    " {} (@{})".format(player.nickname, player.username))
                return
            old_stock, old_glory, change_send = guild.api_info.get("stock") or {}, guild.api_info.get("glory") or 0, \
                                                guild.api_info.get("change_stock_send") or False
            if change_send:
                self.guild_changes.update({guild.tag: glory - old_glory})
                if self.guild_changes_work is None:
                    self.guild_changes_work = threading.Timer(
                        60, self.send_guild_changes_to_mid)
                    self.guild_changes_work.start()
                response = "Итоги битвы {}<b>{}</b>\n".format(
                    guild.castle, guild.tag)
                response += "<b>🎖Glory:</b> <code>{}</code>\n\n".format(
                    glory - old_glory)
                response += self.get_stock_change_text(old_stock, stock)
                attack, defense, exp, gold, total_stock = guild.count_battle_stats(
                )
                response += "\nПредыдущая битва:\n<code>Атака: {:>5}⚔\nЗащита:{:>5}🛡\nОпыт: {:>6}🔥\nЗолото:{:>5}💰\n" \
                            "Сток:  {:>5}📦</code>\n".format(attack, defense, exp, gold, total_stock)
                self.bot.send_message(chat_id=guild.chat_id,
                                      text=response,
                                      parse_mode='HTML')
                guild.api_info.pop("change_stock_send")
                guild.update_to_database(need_order_recashe=False)

            guild.name = name
            api_players = guild.api_info.get("api_players")
            if api_players is None:
                api_players = []
                guild.api_info.update({"api_players": api_players})
            if player_id not in api_players:
                api_players.append(player_id)
            guild.api_info.update({
                "stock": stock,
                "glory": glory,
                "lvl": lvl,
                "members": members,
                "stock_size": stock_size,
                "stock_limit": stock_limit,
                "equipment": equipment
            })
            guild.castle = castle
            guild.last_updated = datetime.datetime.now(tz=moscow_tz).replace(
                tzinfo=None)
            guild.update_to_database(need_order_recashe=False)
        except Exception:
            logging.error(traceback.format_exc())
예제 #19
0
def set_vote_variant(bot, update):
    data = update.callback_query.data
    mes = update.callback_query.message
    player = Player.get_player(update.callback_query.from_user.id)
    if player is None:
        return
    if player.castle != '🖤':
        bot.send_message(chat_id=mes.chat_id, text="Голосование доступно только жителям 🖤Скалы!")
        return
    if player.guild is None and player.id not in ALLOWED_LIST:
        bot.send_message(chat_id=mes.chat_id, text="Голосование доступно только членам гильдий.")
        return
        pass
    if Guild.get_guild(player.guild).is_academy():
        bot.send_message(chat_id=mes.chat_id, text="Ученикам Академии запрещено голосовать.")
        return
    parse = re.search("_(\\d+)_(\\d+)", data)
    if parse is None:
        bot.send_message(chat_id=mes.chat_id, text="Неверный синтаксис.")
        return
    vote_id = int(parse.group(1))
    variant = int(parse.group(2))
    vote = Vote.get_vote(vote_id)
    if vote is None:
        bot.send_message(chat_id=mes.chat_id, text="Голосование не найдено.")
        return
    if player.last_updated < vote.started:
        bot.send_message(chat_id=mes.chat_id, text="Для принятия участия в этом голосовании необходимо обновить "
                                                   "профиль после его начала.")
        return
    try:
        if vote.classes is not None and vote.classes and (player.game_class is None or
                                        vote.classes[classes_list.index(player.game_class)] is False):
            bot.send_message(chat_id=mes.chat_id, text="Голосование недоступно для вашего класса.\n\n<em>В случае, "
                                                       "если ваш класс указан неверно, его можно обновить, "
                                                       "прислав форвард ответа </em>@ChatWarsBot<em> на </em>/me",
                             parse_mode='HTML')
            bot.answerCallbackQuery(callback_query_id=update.callback_query.id)
            return
    except Exception:
        logging.error(traceback.format_exc())
    if vote.started + vote.duration < datetime.datetime.now(tz=moscow_tz).replace(tzinfo=None):
        bot.send_message(chat_id=mes.chat_id, text="Голосование уже завершено.")
        return
    for ch in vote.choices:
        if player.id in ch:
            ch.remove(player.id)
    vote.choices[variant].append(player.id)
    vote.update()
    choice = None
    for i, ch in enumerate(vote.choices):
        if player.id in ch:
            choice = i
            break
    response = get_vote_text(vote, choice=choice)
    buttons = get_vote_buttons(vote, choice=choice)
    try:
        bot.editMessageText(chat_id=mes.chat_id, message_id=mes.message_id, text=response,
                            reply_markup=buttons, parse_mode='HTML')
    # except Exception:
        # logging.error(traceback.format_exc())
    except BadRequest:
        pass
    except TelegramError:
        pass
    bot.answerCallbackQuery(callback_query_id=update.callback_query.id)