def plan_academy_guilds_stats_send(): today = datetime.date.today() target = datetime.datetime.combine(today + datetime.timedelta(days=SUNDAY_INDEX - today.weekday()), datetime.time(ACADEMY_NOTIFY_HOUR)) if target - datetime.datetime.now(tz=moscow_tz).replace(tzinfo=None) < datetime.timedelta(0): # Время уже прошло, планируем на следующую неделю target += datetime.timedelta(days=7) job.run_once(send_guilds_stats, target) logging.info("Academy guild stats notify planned on {}".format(great_format_time(target)))
def castle_hello(bot, update): cp = Location.get_location(0) mes = update.message notified = cp.special_info.get("notified_on_join") if notified is None: notified = [] cp.special_info.update({"notified_on_join": notified}) if mes.from_user.id not in notified: notified.append(mes.from_user.id) cp.update_location_to_database() job.run_once(hello_check, 2, context={"mes": mes})
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 plan_work_week(callback, day: int, hour: int, context={}): today = datetime.date.today() target = datetime.datetime.combine( today + datetime.timedelta(days=day - today.weekday()), datetime.time(hour)) if target - datetime.datetime.now(tz=moscow_tz).replace( tzinfo=None) < datetime.timedelta(0): # Время уже прошло, планируем на следующую неделю target += datetime.timedelta(days=7) job.run_once(callback, target, context=context) logging.info("Academy guild stats notify planned on {}".format( great_format_time(target)))
def plan_mid_notifications(): time_before_battle_to_notify = [ datetime.timedelta(minutes=2), datetime.timedelta(minutes=1), datetime.timedelta(seconds=30), datetime.timedelta(seconds=20), datetime.timedelta(seconds=15), datetime.timedelta(seconds=10), ] battle_time = count_next_battle_time() for time in time_before_battle_to_notify: job.run_once(message_before_battle, battle_time - time)
def plan_work(callback, hour, minute, second, context={}): time_to_send = datetime.time(hour=hour, minute=minute, second=second) time_now = get_current_datetime().time() day_to_send = get_current_datetime().date() date_to_send = datetime.datetime.combine(day_to_send, datetime.time(hour=0)) if time_to_send < time_now: date_to_send += datetime.timedelta(days=1) date_to_send = date_to_send.date() send_time = datetime.datetime.combine(date_to_send, time_to_send) # Время в мск send_time = moscow_tz.localize(send_time).astimezone(tz=local_tz).replace( tzinfo=None) # Локальное время job.run_once(callback, when=send_time, context=context)
def load_construction_jobs(): """ Запускается при старте, перезапускает работы для квестов и стройки - помещает их в сллварь quest_players """ try: f = open('castle_files/backup/construction_jobs', 'rb') up = pickle.load(f) print(up) for k, v in list(up.items()): now = time.time() remaining_time = v[1] - now print("remaining", remaining_time) callback = statuses_to_callbacks.get(v[0]) if callback is None: logging.error("Callback is None for status {}".format(v[0])) continue if v[2] is None or True: # Always get user_data from dispatcher.user_data - it must be changed in callback context = [k, dispatcher.user_data.get(k)] else: context = v[2] if remaining_time < 0: try: job.run_once(callback, 0.1, context=context) print("Job started in 0.1 seconds...") except Exception: logging.error(traceback.format_exc()) pass continue try: construction_jobs.update({ k: MyJob( job.run_once(callback, remaining_time, context=context), remaining_time) }) print("Job started") except Exception: logging.error(traceback.format_exc()) f.close() f = open('castle_files/backup/quest_players', 'rb') t = pickle.load(f) with quest_lock: quest_players.clear() quest_players.update(t) f.close() except FileNotFoundError: pass except Exception: logging.error(traceback.format_exc())
def construct(bot, update, user_data): mes = update.message location_id = None for loc in list(locations.values()): if loc.name == mes.text: location_id = loc.id break if mes.text == '/build_teaparty': location_id = 9 if location_id is None: send_general_buttons(mes.from_user.id, user_data=user_data, bot=bot) return location = Location.get_location(location_id) if location is None: bot.send_message(chat_id=mes.chat_id, text="Локация не найдена.") return if location.state is True or location.building_process < 0: bot.send_message(chat_id=mes.chat_id, text="Локация уже построена или стройка не начиналась.") return context = [update.message.from_user.id, user_data] j = job.run_once(callback=construction_return, when=CONSTRUCTION_DURATION_SECONDS, context=context) old_j = construction_jobs.get(update.message.from_user.id) if old_j is not None: old_j.job.schedule_removal() construction_jobs.update({update.message.from_user.id: MyJob(j, CONSTRUCTION_DURATION_SECONDS)}) user_data.update({"status": "construction", "construction_id": location.id}) buttons = get_general_buttons(user_data) bot.send_message(chat_id=update.message.chat_id, text="Вы отправились на стройку. Это займёт 5 минут.", reply_markup=buttons)
def plan_roulette_games(): """ Планирует ближайшую игру в рулетке. Запускается снова каждый раз по окончанию игры. """ logging.error("Planning roulette game") now = datetime.datetime.now(tz=moscow_tz).replace(tzinfo=None) roulette_time = now.replace(hour=9, minute=0, second=0) limit_time = now.replace(hour=21, minute=0, second=0) while roulette_time < now and roulette_time <= limit_time: roulette_time += datetime.timedelta(hours=3, minutes=0) if roulette_time > limit_time: roulette_time = datetime.datetime.combine( now.date() + datetime.timedelta(days=1), datetime.time(hour=9)) tea_party = Location.get_location(9) if tea_party.is_constructed(): job.run_once(roulette_game, when=roulette_time) logging.error("Roulette planned on {}".format(roulette_time))
def safe_job_create(callback, when, player_id, context=None, cancel_old=True): j = job.run_once(callback=callback, when=when, context=context) if cancel_old: old_j = construction_jobs.get(player_id) if old_j is not None: old_j.job.schedule_removal() construction_jobs.update({player_id: MyJob(j, when)}) return j
def quarry(bot, update, user_data): user_data.update({"status": "quarry"}) buttons = get_general_buttons(user_data) bot.send_message(chat_id=update.message.chat_id, text="Вы отправились добывать камень. Это займёт примерно 3 минуты", reply_markup=buttons) context = [update.message.from_user.id, user_data] j = job.run_once(callback=resource_return, when=MINING_QUEST_DURATION_SECONDS, context=context) old_j = construction_jobs.get(update.message.from_user.id) if old_j is not None: old_j.job.schedule_removal() construction_jobs.update({update.message.from_user.id: MyJob(j, MINING_QUEST_DURATION_SECONDS)})
def sawmill(bot, update, user_data): user_data.update({"status": "sawmill"}) buttons = get_general_buttons(user_data) bot.send_message(chat_id=update.message.chat_id, text="Вы отправились добывать дерево. Это займёт примерно 3 минуты.\n\nВы можете вернуться " "мгновенно. В этом случае вся добыча будет утеряна.", reply_markup=buttons) context = [update.message.from_user.id, user_data] j = job.run_once(callback=resource_return, when=MINING_QUEST_DURATION_SECONDS, context=context) old_j = construction_jobs.get(update.message.from_user.id) if old_j is not None: old_j.job.schedule_removal() construction_jobs.update({update.message.from_user.id: MyJob(j, MINING_QUEST_DURATION_SECONDS)})
def reward_g_def(player, reward, cost, *args, **kwargs): guild = Guild.get_guild(player.guild) if guild is None: dispatcher.bot.send_message( player.id, text="Гильдия не найдена. Вы должны состоять в гильдии. " "Жетоны возвращены.") player.reputation += cost player.update() return 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 plan_clear_alliance_results(*args): job.run_once(clear_results, get_time_remaining_to_battle())
def clear_guilds_api_players(bot, update): job.run_once(check_guilds_api_access, 1, context={"reset": True}) bot.send_message( chat_id=update.message.from_user.id, text="Запущен процесс переопределения игроков с АПИ в гильдиях")
def plan_battle_jobs(): plan_mid_notifications() next_battle_time = moscow_tz.localize( count_next_battle_time()).astimezone(tz=local_tz).replace(tzinfo=None) job.run_once(after_battle, next_battle_time) job.run_once( grassroots_update_players, next_battle_time - datetime.timedelta(hours=1, minutes=41, seconds=30)) job.run_once(grassroots_update_stock, next_battle_time - datetime.timedelta(hours=0, minutes=37, seconds=39), context={"change_send": False}) job.run_once(grassroots_update_stock, next_battle_time - datetime.timedelta(hours=0, minutes=15, seconds=39), context={"change_send": False}) job.run_once(grassroots_update_stock, next_battle_time - datetime.timedelta(hours=0, minutes=7, seconds=39), context={"change_send": False}) job.run_once(grassroots_update_stock, next_battle_time - datetime.timedelta(hours=0, minutes=3, seconds=12), context={"change_send": False}) job.run_once(grassroots_update_stock, next_battle_time + datetime.timedelta(hours=0, minutes=4, seconds=0), context={"change_send": True}) # job.run_once(grassroots_update_stock, next_battle_time + datetime.timedelta(hours=0, minutes=0, seconds=1), # context={"change_send": False}) job.run_once(update_stock_for_fails, next_battle_time + datetime.timedelta(hours=0, minutes=12, seconds=0), context={"change_send": True}) job.run_once(update_stock_for_fails, next_battle_time + datetime.timedelta(hours=0, minutes=20, seconds=0), context={"change_send": True}) job.run_once( autospend_start, next_battle_time - datetime.timedelta(hours=0, minutes=14, seconds=00)) # job.run_once(grassroots_update_stock, 0.1, context={"change_send": True}) # job.run_once(update_stock_for_fails, 5, context={"change_send": True}) time_to_send = next_battle_time - datetime.timedelta(hours=1) now = datetime.datetime.now(tz=moscow_tz).replace(tzinfo=None) if time_to_send > now: job.run_once(send_potion_stats, time_to_send, context=[False]) time_to_send = next_battle_time - datetime.timedelta(minutes=30) if time_to_send > now: job.run_once(send_potion_stats, time_to_send, context=[False]) time_to_send = next_battle_time - datetime.timedelta(minutes=7, seconds=30) if time_to_send > now: job.run_once(send_potion_stats, time_to_send, context=[True]) rangers_notify_start(bot=dispatcher.bot, update=SUPER_ADMIN_ID) plan_clear_alliance_results()