""" eBot Copyright (C) 2022 Eriks K This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ import copy import os import random import sys from datetime import timedelta from typing import Dict, List, Union import httpx import sentry_sdk from erepublik import Citizen, classes, utils from ebot import __version__ from ebot.helpers import BotRestart, BotStop from ebot.player import Player from ebot.utils import _norm VERSION = __version__ EVERSION = utils.VERSION def main(config: Dict[str, Union[int, bool, str, List[str], Dict[str, Union[str, int]]]]): player = Player("", "", False) try: # If errors before player is initialized while True: has_dump = os.path.isfile("Player__dump.json") if has_dump: player = Player.load_from_dump("Player__dump.json") else: player = Player(email=config["email"], password=config["password"], auto_login=False) player.setup_citizen(config) player.login() if player.logged_in: sentry_sdk.set_user(dict(id=player.details.citizen_id, username=player.name, email=player.config.email)) try: import setproctitle setproctitle.setproctitle(f"eBot - {player}") except ImportError: pass break else: utils.silent_sleep(2) while True: try: player.update_all() if not player.restricted_ip: player.dump_instance() break except Exception as e: # noqa player.report_error(f"Error updating all data on initial update {e}") utils.silent_sleep(2) player.write_log( f"View Your stats at:\n" f"'https://erep.lv/player/{player.name.replace(' ', '%20')}'\n" f"Your password is '{player.reporter.key}'" ) # if player.reporter.allowed: report = copy.deepcopy(config) report.pop("email", None) report.pop("password", None) report.update(VERSION=VERSION, eRepublik_version=EVERSION) player.reporter.report_action("ACTIVE_CONFIG", json_val=report) player.setup_tasks(config) _run_main_loop(player) player.set_locks() player.logger.warning("Too many errors.") except BotStop as bs: raise bs except BotRestart: pass except httpx.ConnectError as conn_err: raise conn_err except Exception as e: # noqa if isinstance(player, Citizen): name = player.name elif config.get("email", None): name = config["email"] else: name = "Uninitialized" sentry_sdk.capture_exception(e) player.report_error( f"Fatal error. {e}", extra=dict(player_name=name, ebot_version=VERSION, erep_version=EVERSION) ) finally: if isinstance(player, Citizen): player.set_locks() def _run_main_loop(player: Player): error_count = 0 while error_count < 3 and not player.stop_threads.is_set(): try: player.update_all() player.do_tasks() next_task = player.get_next_task() player.travel_to_residence() random_seconds = random.randint(0, 121) if player.tasks.get_default("random_sleep", True) else 0 sleep_seconds = int(utils.get_sleep_seconds(next_task.time)) if sleep_seconds <= 0: player.write_warning(f"Loop detected! Offending task: '{next_task.name}'") next_time = _norm(next_task.time + timedelta(seconds=random_seconds)).strftime("%F %T") tasks = player.tasks.as_dict["tasks"] player.write_log("My next Tasks and there time:\n" + "\n".join((str(t) for t in tasks))) player.write_log( f"Sleeping until (eRep): {next_time} " f"(sleeping for {sleep_seconds}s + random {random_seconds}s)" ) seconds_to_sleep = sleep_seconds + random_seconds player.stop_threads.wait(seconds_to_sleep) except (classes.ErepublikNetworkException, httpx.ConnectError) as exc: sentry_sdk.capture_exception(exc) player.write_warning("Network ERROR detected. Sleeping for 1min...") player.sleep(60) except BotRestart: player.set_locks() return except classes.ErepublikException as exc: sentry_sdk.capture_exception(exc) player.report_error(f"Known error detected! {exc}") except (KeyboardInterrupt, BotStop): player.set_locks() sys.exit(0) except Exception as exc: sentry_sdk.capture_exception(exc) player.report_error( f"Unknown error! {exc}", extra=dict(player_name=player.name, ebot_version=VERSION, erep_version=EVERSION), ) error_count += 1 if error_count < 3: player.sleep(60)