def __init__(self, bot: telegram.Bot, alerts_chat_id: int = config.DEFAULT_CAPTCHA_ALERTS_CHAT_ID): self._minecraft = Minecraft() self._bot = bot self._alerts_chat_id = alerts_chat_id self._captcha_sample = None
class MinecraftServerReconnector(metaclass=Singleton): """Monitors minecraft for disconnections and crashes.""" MAX_RECONNECT_TRIES = 5 def __init__(self): self._minecraft = Minecraft() self._crash_event_handler = CrashDirEventHandler() self._init_crash_dir_observer() self._reconnect_tries = 0 def keep_connected(self): logging.info("Starting minecraft server reconnector.") self._init_observer_if_stopped() self._crash_dir_observer.start() self._detect_and_handle_disconnections() def stop(self): logging.info("Stopping minecraft server reconnector.") self._crash_dir_observer.stop() def is_up(self): return self._crash_dir_observer.is_alive() def _init_observer_if_stopped(self): if not self.is_up(): # Observer start method can only be invoked once per instance. self._init_crash_dir_observer() def _init_crash_dir_observer(self): self._crash_dir_observer = Observer() self._crash_dir_observer.schedule(self._crash_event_handler, config.MINECRAFT_CRASH_DIR) @threaded def _detect_and_handle_disconnections(self): with open(config.MINECRAFT_LOG_FILE) as log_file: for log_line in tailer.follow(log_file, LOG_LINE_READ_DELAY): if not self.is_up(): break self._process_log_line(log_line) def _process_log_line(self, line): if re.match(DISCONNECTION_LOG, line): logging.warning("Disconnection from hypixel detected.") self._handle_disconnection() elif re.match(JOIN_SERVER_LOG, line): logging.info("Successfully reconnected.") self._reconnect_tries = 0 def _handle_disconnection(self): if self._reconnect_tries < self.MAX_RECONNECT_TRIES: self._minecraft.connect() self._reconnect_tries += 1 else: logging.warning("Max retries exceeded, relaunching minecraft.") self._minecraft.relaunch() self._reconnect_tries = 0
class CrashDirEventHandler(FileSystemEventHandler): """Handles file system events in crash reports directory.""" def __init__(self): super().__init__() self._minecraft = Minecraft() def on_created(self, event): """Relaunch minecraft when a new crash report is detected.""" logging.warning("Crash report detected.") self._minecraft.relaunch()
class UpdateCobbleMiner(UpdateCommand): """Update minecraft macro scripts.""" SERVER_LOAD_TIME_SECS = 5 def __init__(self): super().__init__('CobbleMiner', config.COBBLEMINER_MACROS_DIR) self._minecraft = Minecraft() @auth def run(self, update, context): try: self._reply(update, context, ReplyMsg.UPDATE_COBBLEMINER.value) self._repo_installer.install_latest_files() self._apply_macro_changes() self._reply(update, context, ReplyMsg.MACROS_INSTALLED.value) except RepoInstallError: self._reply(update, context, ReplyMsg.UPDATE_FAILED.value) def _apply_macro_changes(self): self._minecraft.reconnect() time.sleep(self.SERVER_LOAD_TIME_SECS)
class CaptchaDetector(metaclass=Singleton): def __init__(self, bot: telegram.Bot, alerts_chat_id: int = config.DEFAULT_CAPTCHA_ALERTS_CHAT_ID): self._minecraft = Minecraft() self._bot = bot self._alerts_chat_id = alerts_chat_id self._captcha_sample = None def set_alerts_target_chat(self, chat_id): self._alerts_chat_id = chat_id @threaded def run_forever(self): logging.info("Starting captcha detector.") with open(config.CAPTCHA_ALERTS_FILE) as captcha_file: for _ in tailer.follow(captcha_file, LOG_LINE_READ_DELAY): self._save_captcha_sample() self._send_alert() def _save_captcha_sample(self): self._captcha_sample = self._build_captcha_save_path() self._minecraft.save_live_image(self._captcha_sample) @staticmethod def _build_captcha_save_path(): if not os.path.exists(config.CAPTCHA_SAMPLES_DIR): os.makedirs(config.CAPTCHA_SAMPLES_DIR) curr_dir = pathlib.Path().absolute() curr_time = datetime.now().strftime("%d-%m-%Y %H;%M;%S") return f"{curr_dir}\\{config.CAPTCHA_SAMPLES_DIR}\\{curr_time}.png" def _send_alert(self): logging.warning("Captcha detected! Sending alert via telegram.") with open(self._captcha_sample, "rb") as img: self._bot.send_photo(chat_id=self._alerts_chat_id, photo=img) self._bot.send_message(chat_id=self._alerts_chat_id, text=commands.ReplyMsg.CAPTCHA_ALERT.value)
def __init__(self): self._minecraft = Minecraft() self._crash_event_handler = CrashDirEventHandler() self._init_crash_dir_observer() self._reconnect_tries = 0
def __init__(self): super().__init__() self._minecraft = Minecraft()
def __init__(self): super().__init__('CobbleMiner', config.COBBLEMINER_MACROS_DIR) self._minecraft = Minecraft()
def __init__(self): self._minecraft = Minecraft()