def update_daily_quests(bot, job): cursor = conn.cursor() request = "select id from players" cursor.execute(request) row = cursor.fetchone() while row is not None: player = Player.get_player(row[0]) if player is None: continue daily_quests: [Quest] = player.quests_info.get("daily_quests") if daily_quests is None: daily_quests = [] player.quests_info.update({"daily_quests": daily_quests}) else: daily_quests.clear() forbidden_list = [] for i in range(3): quest = copy.deepcopy(random.choice(list(quests.values()))) limit = 0 while (quest.id in forbidden_list or quest.skip_selection) and limit < 5: quest = copy.deepcopy(random.choice(list(quests.values()))) limit += 1 quest.start(player) if quest.daily_unique: forbidden_list.append(quest.id) daily_quests.append(quest) player.update_to_database() row = cursor.fetchone() time.sleep(1) plan_update_daily_quests()
def count_reputation_sum(bot, update): """ Функция для отлавливания багов и их использования. Команда /count_reputation_sum Выводит разницу между полученными "легально" жетонами и текущими жетонами у игроков. """ request = "select action, player_id from castle_logs" cursor.execute(request) rep = {} action_to_rep = {"collect_resources": 3, "construction": 5} row = cursor.fetchone() while row is not None: action, player_id = row cur_rep = rep.get(player_id) or 0 cur_rep += action_to_rep.get(action) rep.update({player_id: cur_rep}) row = cursor.fetchone() lst = list(rep.items()) lst.sort(key=lambda x: Player.get_player(x[0]).reputation - x[1], reverse=True) response = "Статистика по жетонам:\n" for obj in lst: id, reputation = obj player = Player.get_player(id) new_response = "<code>{:<20}</code> 🔘: <code>{:4<}</code>, всего 🔘: <code>{:<4}</code>, <code>{}</code>\n" \ "".format(player.username, reputation, player.reputation, player.reputation - reputation) if len(response + new_response) > 4000: bot.send_message(chat_id=update.message.chat_id, text=response, parse_mode='HTML') response = "" response += new_response bot.send_message(chat_id=update.message.chat_id, text=response, parse_mode='HTML')
def fill_allowed_list(): request = "select id from players" cursor.execute(request) row = cursor.fetchone() allowed_list.clear() while row is not None: allowed_list.append(row[0]) row = cursor.fetchone()
def fill_union_chats(): request = "select name, chat_id from trade_unions where chat_id is not null" cursor.execute(request) row = cursor.fetchone() union_chats.clear() while row is not None: union_chats.update({row[0]: row[1]}) row = cursor.fetchone()
def rangers_notify_start(bot, update): cursor = conn.cursor() time_to_battle = get_time_remaining_to_battle() print("time_to_battle", time_to_battle) try: callback_chat_id = update.message.chat_id except AttributeError: try: callback_chat_id = int(update) except TypeError: return count = 0 request = "select id from players where class_skill_lvl is not NULL" cursor.execute(request) row = cursor.fetchone() while row is not None: player = Player.get_player(row[0]) if player is None: row = cursor.fetchone() continue if player.settings is not None and player.settings.get( "rangers_notify") is False: row = cursor.fetchone() continue guild = Guild.get_guild(guild_id=player.guild) if guild is None: row = cursor.fetchone() continue telegram_username = player.username username = player.nickname class_skill_lvl = player.class_skill_lvl context = [telegram_username, username, guild.chat_id] print(class_skill_lvl) time_to_aim_mins = ranger_aiming_minutes[class_skill_lvl] if \ class_skill_lvl < len(ranger_aiming_minutes) else 40 time_to_aim = datetime.timedelta(minutes=time_to_aim_mins) print("time_to_aim", time_to_aim) time_to_notify = time_to_battle - time_to_aim - datetime.timedelta( minutes=1) print(time_to_notify) # time_to_notify = datetime.timedelta(minutes=1) # TEST if time_to_notify >= datetime.timedelta(minutes=0): job.run_once(ranger_notify, time_to_notify, context=context) row = cursor.fetchone() count += 1 cursor.close() bot.send_message( chat_id=callback_chat_id, text="Запланировано оповещение <b>{0}</b> бедных лучников".format( count), parse_mode='HTML')
def get_rangers(bot, update): mes = update.message if not check_whois_access(mes.from_user.id): return response = "Лучники 🖤Скалы:\n" request = "select '@' || username, nickname, lvl from players where game_class = 'Ranger' order by lvl desc" cursor.execute(request) row = cursor.fetchone() while row is not None: response += "{} <b>{}</b> 🏅:{}\n".format(*row) row = cursor.fetchone() bot.send_message(chat_id=mes.from_user.id, text=response, parse_mode='HTML')
def insert_to_database(self): request = "insert into alliance_locations(link, name, type, lvl, owner_id, can_expired, expired) VALUES " \ "(%s, %s, %s, %s, %s, %s, %s) returning id" cursor.execute(request, (self.link, self.name, self.type, self.lvl, self.owner_id, self.can_expired, self.expired)) self.id = cursor.fetchone()[0]
def get_mobs_info_by_link(link): cursor = conn.cursor() request = "select mob_names, mob_lvls, date_created, helpers, buffs, minutes, created_player from mobs where link = %s" cursor.execute(request, (link,)) row = cursor.fetchone() cursor.close() return row
def info_trigger(bot, update): mes = update.message if filter_is_pm(mes): return if mes.from_user.id not in get_admin_ids(bot=bot, chat_id=mes.chat_id): bot.send_message(chat_id=mes.chat_id, text="Доступ только у админов.", reply_to_message_id=mes.message_id) return text = mes.text.partition(" ")[2].lower() list_triggers = triggers_in.get(mes.chat_id) chat_id = mes.chat_id if list_triggers is None: list_triggers = [] triggers_in.update({mes.chat_id: list_triggers}) if text not in list_triggers: if text not in global_triggers_in: bot.send_message(chat_id=mes.chat_id, text="Триггер не найден", reply_to_message_id=mes.message_id) return chat_id = 0 request = "select creator, date_created from triggers where text_in = %s and chat_id = %s" cursor.execute(request, (text, chat_id)) row = cursor.fetchone() response = "<code>{}</code> — создал <code>{}</code> {}".format( text, row[0], row[1].strftime("%d/%m/%y %H:%M:%S")) bot.send_message(chat_id=mes.chat_id, text=response, parse_mode='HTML', reply_to_message_id=mes.message_id)
def get_alliance_by_link(link: str) -> 'Alliance': request = "select id from alliances where lower(link) = lower(%s) limit 1" cursor.execute(request, (link, )) row = cursor.fetchone() if row is None: return None return Alliance.get_alliance(row[0])
def view_vote(bot, update): mes = update.message if not check_access(mes.from_user.id): return vote_id = re.search("_(\\d+)", mes.text) if vote_id is None: bot.send_message(chat_id=mes.chat_id, text="Неверный синтаксис.") return vote_id = int(vote_id.group(1)) request = "select name, text, variants, started, duration, classes from votes where id = %s" cursor.execute(request, (vote_id,)) row = cursor.fetchone() if row is None: bot.send_message(chat_id=mes.chat_id, text="Голосование не найдено.") return response = "Голосование <b>{}</b>\n".format(row[0]) response += row[1] + "\n\n" response += "Начало: <code>{}</code>\n".format(row[3].strftime("%d/%m/%y %H:%M:%S") if row[3] is not None else "Не началось.") response += "Длительность: <code>{}</code>\n".format(row[4] if row[4] is not None else "Не задано.") cl_text = "" if all(row[5]) or not row[5]: cl_text = "ВСЕ" else: for i, b in enumerate(row[5]): cl_text += classes_list[i] if b else "" response += "Классы: <code>{}</code>\n".format(cl_text) if row[3] is None: response += "Изменить длительность: /change_vote_duration_{}\n".format(vote_id) response += "Начать голосование: /start_vote_{}\n".format(vote_id) response += "\nИзменить классы для голосований: /set_vote_classes_{} [Классы, которые ПРИНИМАЮТ участие " \ "в голосовании]\n\n<em>Классы ТОЛЬКО как в списке: {}</em>".format(vote_id, classes_list) print(response) bot.send_message(chat_id=mes.chat_id, text=response, parse_mode='HTML')
def finish_vote(bot, update, user_data): mes = update.message if not check_access(mes.from_user.id): return name, variants, text = user_data.get("vote_name"), user_data.get("vote_variants"), user_data.get("vote_text") if not all([name, variants, text]): bot.send_message(chat_id=mes.chat_id, text="Все этапы должны быть заполнены перед запуском голосования") choices = {} for i in range(len(variants)): choices.update({i: []}) choices = json.dumps(choices) request = "insert into votes(name, text, variants, choices) VALUES (%s, %s, %s, %s) returning id" cursor.execute(request, (name, text, variants, choices)) row = cursor.fetchone() if row is None: bot.send_message(chat_id=mes.chat_id, text="Произошла ошибка. Возможно, голосование всё же создалось, " "проверьте: /vote") return bot.send_message(chat_id=mes.chat_id, text="Голосование <b>{}</b> успешно создано.\n" "Просмотреть голосование: /view_vote_{}".format(name, row[0]), parse_mode='HTML') user_data.pop("vote_name") user_data.pop("vote_variants") user_data.pop("vote_text") user_data.pop("status")
def get_reward_combo(reward_name: str) -> int: reward = rewards.get(reward_name) request = "select count(*) from castle_logs where action = %s and date > %s" cursor.execute(request, ("reward_{}".format(reward_name), get_current_datetime() - datetime.timedelta(weeks=REWARD_PRICE_RESET_WEEKS))) count, *skip = cursor.fetchone() return count
def fill_triggers_lists(): global_triggers_in.clear() triggers_in.clear() request = "select text_in, chat_id from triggers" cursor.execute(request) row = cursor.fetchone() while row is not None: text, chat_id = row if chat_id == 0: global_triggers_in.append(text) else: triggers_list = triggers_in.get(chat_id) if triggers_list is None: triggers_list = [] triggers_in.update({chat_id: triggers_list}) triggers_list.append(text) row = cursor.fetchone()
def get_or_create_alliance_by_name(name: str) -> 'Alliance': request = "select id from alliances where lower(name) = lower(%s)" cursor.execute(request, (name, )) row = cursor.fetchone() if row is None: alliance = Alliance(None, None, name, None, None, None) alliance.insert_to_database() return alliance return Alliance.get_alliance(row[0])
def get_location_by_link(link: str) -> 'AllianceLocation': if link is None: return None request = "select id from alliance_locations where lower(link) = lower(%s) and expired is false limit 1" cursor.execute(request, (link, )) row = cursor.fetchone() if row is None: return None return AllianceLocation.get_location(row[0])
def get_location(location_id: int) -> 'AllianceLocation': request = "select link, name, type, lvl, owner_id, turns_owned, can_expired, expired from alliance_locations where id = %s " \ "limit 1" cursor.execute(request, (location_id, )) row = cursor.fetchone() if row is None: return None link, name, location_type, lvl, owner_id, turns_owned, can_expired, expired = row return AllianceLocation(location_id, link, name, location_type, lvl, owner_id, turns_owned, can_expired, expired)
def fight_club(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) player = Player.get_player(mes.from_user.id) 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 = "select mob_lvls, helpers from mobs where link = %s" cursor.execute(request, (link,)) row = cursor.fetchone() helpers = [] lvl = player.lvl if row is not None: lvls, helpers = row lvl = lvls[0] response = get_fight_club_txt(link, lvl, helpers, forward_message_date) buttons = [[InlineKeyboardButton(text="⚔ {}-{}🏅".format(int(lvl - 5), int(lvl + 10)), url=u"https://t.me/share/url?url=/fight_{}".format(link)), InlineKeyboardButton(text="🤝Помогаю!", callback_data="fight_club_partify_{}".format(link))]] guild = Guild.get_guild(chat_id=mes.chat_id) if guild is not None: ping = [] for player_id in guild.members: cur_player = Player.get_player(player_id) if cur_player is None: continue if cur_player.settings.get("pretend") and cur_player.lvl in range(lvl - 5, lvl + 11) and \ player.username not in ping: ping.append(player.username) if len(ping) >= 4: text = "Подпольный бой!\n" for username in ping: text += "@{} ".format(username) bot.send_message(chat_id=mes.chat_id, text=text) ping.clear() if ping: text = "Подпольный бой!\n" for username in ping: text += "@{} ".format(username) bot.send_message(chat_id=mes.chat_id, text=text) if guild is not None: response += "\n\n<em>Подписаться на уведомления о клубах в чате ги:</em> /pretend" bot.send_message(chat_id=mes.chat_id, text=response, reply_markup=InlineKeyboardMarkup(buttons), parse_mode='HTML') request = "insert into mobs(link, mob_names, mob_lvls, date_created, created_player) values (" \ "%s, %s, %s, %s, %s)" try: cursor.execute(request, (link, ["Fight Club"], [lvl], forward_message_date, mes.from_user.id)) except psycopg2.IntegrityError: pass
def get_alliance(alliance_id: int) -> 'Alliance': if alliance_id is None: return None request = "select link, name, creator_id, assistants, hq_chat_id from alliances where id = %s " \ "limit 1" cursor.execute(request, (alliance_id, )) row = cursor.fetchone() if row is None: return None link, name, creator_id, assistants, hq_chat_id = row return Alliance(alliance_id, link, name, creator_id, assistants, hq_chat_id)
def get_or_create_location_by_name_and_lvl(name: str, lvl: int) -> 'AllianceLocation': request = "select id from alliance_locations where expired is false and lower(name) = lower(%s) and lvl = %s " \ "limit 1" cursor.execute(request, (name, lvl)) row = cursor.fetchone() if row is None: location = AllianceLocation(None, None, name, None, lvl, None, 0, False, False) location.insert_to_database() return location return AllianceLocation.get_location(row[0])
def king_cabinet_construction(bot, update): request = "select location_id from locations where state is false and building_process = -1" cursor.execute(request) row = cursor.fetchone() response = "Здания, которые можно начать строить:\n" while row is not None: location = Location.get_location(row[0]) if location is None: row = cursor.fetchone() continue response += "<b>{}</b>\nСтоимость: 🌲: <code>{}</code>, ⛰: <code>{}</code>\nНачать строительство: " \ "/begin_construction_{}\n".format(location.name, location.need_res_to_construct.get("wood") or 0, location.need_res_to_construct.get("stone") or 0, location.id) row = cursor.fetchone() response += "\n----------------------\nСтройка в процессе:\n" request = "select location_id from locations where state is false and building_process >= 0" cursor.execute(request) row = cursor.fetchone() while row is not None: location = Location.get_location(row[0]) if location is None: row = cursor.fetchone() continue response += "<b>{}</b>\nПрогресс: <code>{}</code> из <code>{}</code>\n" \ "\n".format(location.name, location.building_process, location.need_clicks_to_construct) row = cursor.fetchone() treasury = Location.get_location(6) response += "\n----------------------\nСостояние казны: 🌲Дерево: <b>{}</b>, " \ "⛰Камень: <b>{}</b>".format(treasury.wood, treasury.stone) bot.send_message(chat_id=update.message.chat_id, text=response, parse_mode='HTML')
def reports_history(bot, update): data = update.callback_query.data mes = update.callback_query.message player = Player.get_player(player_id=update.callback_query.from_user.id) if player is None: return requested_player_id = re.search("_(\\d+)", data) if requested_player_id is None: bot.send_message( chat_id=mes.chat_id, text="Произошла ошибка. Попробуйте вызвать сообщение заного.") return requested_player_id = int(requested_player_id.group(1)) requested_player = Player.get_player(requested_player_id, notify_on_error=False) if requested_player is None: bot.send_message(chat_id=mes.chat_id, text="Игрок не найден.") return if player.id != requested_player.id and not check_whois_access( player.id) and (requested_player.guild is None or requested_player.guild != player.guild): bot.answerCallbackQuery(callback_query_id=update.callback_query.id) bot.send_message(chat_id=mes.chat_id, text="Доступ запрещён.") return response = "Отчёты по последним битвам <b>{}</b>:\n".format( requested_player.nickname) request = "select battle_id, attack, defense, exp, gold, stock from reports where player_id = %s order by " \ "battle_id desc limit 30" cursor.execute(request, (requested_player.id, )) row = cursor.fetchone() while row is not None: response += "🕒{} ⚔️:<code>{:<3},🛡:{:<3},🔥:{:<4},💰:{:<3},📦:{:<3}</code>" \ "\n".format(count_battle_time(row[0]).strftime("%H:%M %d/%m"), row[1], row[2], row[3], row[4], row[5]) row = cursor.fetchone() bot.send_message(chat_id=mes.chat_id, text=response, parse_mode='HTML') bot.answerCallbackQuery(callback_query_id=update.callback_query.id)
def votes(bot, update): mes = update.message response = "Доступные голосования в замке:\n\n" request = "select id, name, text, classes from votes where started is not null and started + duration > now() " \ "AT TIME ZONE 'Europe/Moscow'" cursor.execute(request) row = cursor.fetchone() player = Player.get_player(mes.from_user.id) if player is None: return while row is not None: try: if row[3] is not None and row[3] and (player.game_class is None or row[3][classes_list.index(player.game_class)] is False): row = cursor.fetchone() continue except Exception: logging.error(traceback.format_exc()) response += "<b>{}</b>\n{}\n<code>Принять участие в голосовании:</code> /vote_{}" \ "\n\n".format(row[1], row[2], row[0]) row = cursor.fetchone() bot.send_message(chat_id=mes.chat_id, text=response, parse_mode='HTML')
def add_alliance_location(bot, update): mes = update.message player, guild, alliance = get_player_and_guild_and_alliance(mes.from_user.id) try: parse = re.search("simple combination: (\\w+)", mes.text) link = parse.group(1) parse = re.search("You found hidden (location (.+) lvl.(\\d+)|headquarter (.+))", mes.text) if parse.group(4) is not None: return add_alliance_link(parse.group(4), link) name, lvl = parse.group(2), int(parse.group(3)) except Exception: logging.error(traceback.format_exc()) if filter_is_pm(mes): bot.send_message(chat_id=mes.chat_id, text="Произошла ошибка") return request = "select id from alliance_locations where link = %s and expired is false" cursor.execute(request, (link,)) row = cursor.fetchone() if row is not None: return request = "select id from alliance_locations where name = %s and lvl = %s and link is null " \ "and expired is false limit 1" cursor.execute(request, (name, lvl)) row = cursor.fetchone() if row is not None: location = AllianceLocation.get_location(row[0]) location.link = link location.update() else: location = AllianceLocation(None, link, name, None, lvl, None, 0, False, False) location.figure_type() location.insert_to_database() for alli in Alliance.get_all_alliances(): if alli.hq_chat_id is not None: bot.send_message(chat_id=alli.hq_chat_id, parse_mode='HTML', text="Новая локация: <b>{} Lvl.{}</b>\n{}".format(name, lvl, link)) bot.send_message(chat_id=mes.chat_id, text="Спасибо! Новая локация!", reply_to_message_id=mes.message_id)
def add_union(bot, update): mes = update.message name = re.search("Trade Union: (.*)", mes.text) creator_nick = re.search("🏅Owner:['🍆🍁☘🌹🐢🦇🖤](.*)", mes.text) if name is None: bot.send_message(chat_id=mes.chat_id, text="Ошибка распознавания имени") return if creator_nick is None: bot.send_message(chat_id=mes.chat_id, text="Ошибка распознавания ника создателя") return name = name.group(1) creator_nick = creator_nick.group(1) request = "select id from players where nickname = %s" cursor.execute(request, (creator_nick, )) row = cursor.fetchone() if row is None: bot.send_message(chat_id=mes.chat_id, text="Создатель профсоюза не зарегистрирован в боте. " "Регистрация необходима для работы.") # return creator = Player.get_player(row[0], notify_on_error=False) view_link = re.search("View: /tu_view_(.*)", mes.text) view_link = view_link.group(1) if view_link is not None else None request = "select id from trade_unions where name = %s" cursor.execute(request, (name, )) row = cursor.fetchone() if row is not None: bot.send_message(chat_id=mes.chat_id, text="Этот профсоюз уже зарегистрирован!") return request = "insert into trade_unions(creator_id, name, players, view_link) values (%s, %s, %s, %s)" cursor.execute(request, (creator.id, name, [creator.id], view_link)) bot.send_message( chat_id=mes.chat_id, text="Профсоюз <b>{}</b> успешно зарегистрирован!".format(name), parse_mode='HTML')
def load_worldtop(battle_id: int = None) -> dict: """ Загружает /worldtop после битвы с battle_id :return: { str: int } """ if battle_id is None: battle_id = count_battle_id() request = "select ferma, amber, oplot, rassvet, tortuga, night, skala from worldtop where battle_id = %s" cursor.execute(request, (battle_id, )) row = cursor.fetchone() if not row: return {} worldtop = {k: v for k, v in zip(castles, row)} sort_worldtop(worldtop) return worldtop
def send_trigger(bot, update): mes = update.message if filter_is_pm(mes): return chat_id = mes.chat_id trigger_list = triggers_in.get(mes.chat_id) if trigger_list is None: trigger_list = [] triggers_in.update({mes.chat_id: trigger_list}) if mes.text.lower() not in trigger_list: chat_id = 0 request = "select type, data_out from triggers where text_in = %s and chat_id = %s limit 1" cursor.execute(request, (mes.text.lower(), chat_id)) row = cursor.fetchone() trigger_type, data = row send_trigger_with_type_and_data(bot, update.message.chat_id, trigger_type, data)
def get_king_audience(bot, update): mes = update.message audience_id = re.search("_(\\d+)", mes.text) if audience_id is None: bot.send_message(chat_id=mes.chat_id, text="Неверный синтаксис.") return [-1] audience_id = int(audience_id.group(1)) request = "select request_player_id from king_audiences where audience_id = %s and accepted is null" cursor.execute(request, (audience_id, )) row = cursor.fetchone() if row is None: bot.send_message( chat_id=mes.chat_id, text= "Невозможно найти заявку. Проверьте id. Возможно, вы уже рассмотрели её" ) return [-1] return [row[0], audience_id]
def union_list(bot, update): mes = update.message union = TradeUnion.get_union(creator_id=update.message.from_user.id) if union is None: bot.send_message( chat_id=update.message.chat_id, text="Только создатель и замы профсоюза могут вносить его состав.") return for string in update.message.text.splitlines(): if string[0] in castles: request = "select id from players where nickname = %s" cursor.execute(request, (string[1:].partition(" /")[0], )) row = cursor.fetchone() if row is None: continue if row[0] not in union.players: union.players.append(row[0]) union.update_to_database() bot.send_message(chat_id=mes.chat_id, text="Список <b>{}</b> успешно обновлён!".format( union.name), parse_mode='HTML')
def fight_club_help(bot, update): data = update.callback_query.data mes = update.callback_query.message link = re.search("fight_club_partify_(.+)", data) if link is None: bot.send_message(chat_id=update.callback_query.from_user.id, text="Произошла ошибка.") return link = link.group(1) request = "select mob_lvls, date_created, helpers from mobs where link = %s" cursor.execute(request, (link,)) row = cursor.fetchone() if row is None: bot.send_message(chat_id=update.callback_query.from_user.id, text="Событие не найдено") return lvls, forward_message_date, helpers = row lvl = lvls[0] player = Player.get_player(update.callback_query.from_user.id) if player is None: bot.answerCallbackQuery(callback_query_id=update.callback_query.id, text="Для помощи необходима регистрация!", show_alert=True) return helper_row = "@{} 🏅:{}".format(player.username, player.lvl) if helper_row in helpers: bot.answerCallbackQuery(callback_query_id=update.callback_query.id, text="Ты уже помогаешь!", show_alert=True) return helpers.append(helper_row) response = get_fight_club_txt(link, lvl, helpers, forward_message_date) buttons = [[InlineKeyboardButton(text="⚔ {}-{}🏅".format(int(player.lvl - 5), int(player.lvl + 10)), url=u"https://t.me/share/url?url=/fight_{}".format(link)), InlineKeyboardButton(text="🤝Помогаю!", callback_data="fight_club_partify_{}".format(link))]] try: bot.editMessageText(chat_id=mes.chat_id, message_id=mes.message_id, text=response, reply_markup=InlineKeyboardMarkup(buttons), parse_mode='HTML') except Exception: logging.error(traceback.format_exc()) bot.answerCallbackQuery(callback_query_id=update.callback_query.id, text="Успешно добавлено") request = "update mobs set helpers = %s where link = %s" cursor.execute(request, (helpers, link))