def run(self): """Run the main program's logic.""" # Change into the server's directory. os.chdir(self.args.server) # If we're only culling backups, do that and exit. if self.args.clean: return self.cull_backups() # Backups directory. backups = os.path.join(self.args.server, "backups") if not os.path.isdir(backups): log.info("Creating backups directory: {}".format(backups)) os.mkdir(backups) # Connect to the Minecraft-Control server. log.info("Connecting to Minecraft control server...") self.client = MinecraftClient( host=self.config["host"], port=self.config["port"], password=self.config["password"], methods=[self.config["method"]], ) self.client.add_handler("auth_ok", self.on_auth_ok) self.client.add_handler("auth_error", self.on_auth_error) self.client.add_handler("server_message", self.on_message) self.client.connect() self.client.start()
debug = False host, port, password = None, None, None whitelist = [] if sys.argv[1] == "--debug": debug = True host, port, password = sys.argv[2:5] whitelist = [x.lower() for x in sys.argv[5:]] else: host, port, password = sys.argv[1:4] whitelist = [x.lower() for x in sys.argv[4:]] # Connect to the server. client = MinecraftClient( debug=debug, host=host, port=port, password=password, ) def on_authed(client): print("Authentication successful!") client.sendline("say 01-gamemode.py demo started. Whitelist: {}".format( str(whitelist))) def on_error(client, error): print("Failed to authenticate: {}".format(error)) def on_message(client, message):
class Application: def __init__(self, args): """Initialize the application.""" self.args = args # Verify settings. self.verify_args() self.config = dict() # minecraft-control configuration self.client = None # MinecraftClient instance self.today = datetime.datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") self.world = self.get_world_name() log.info("Today's date/time: {}".format(self.today)) # Load the minecraft-control configuration. self.load_mc_config() def verify_args(self): """Do some sanity checking on input arguments.""" # The minecraft-control config file. if not os.path.isfile(self.args.config): log.error("{}: not a file".format(self.args.config)) sys.exit(1) # The server directory. if not os.path.isfile("{}/server.properties".format(self.args.server)): log.error("{}: not a Minecraft server directory (no " "server.properties file present)".format( self.args.server)) sys.exit(1) def load_mc_config(self): """Load the configuration from minecraft-control.""" log.debug("Loading minecraft-control settings from {}".format( args.config)) parser = RawConfigParser() with open(self.args.config, "r") as fh: parser.readfp(fh) self.config["host"] = parser.get("tcp-server", "address") self.config["port"] = parser.get("tcp-server", "port") self.config["password"] = parser.get("auth", "password") self.config["method"] = parser.get("auth", "method") def get_world_name(self): """Load the server.properties to find the world name.""" with open("{}/server.properties".format(self.args.server), "r") as fh: for line in fh: if not "=" in line: continue parts = line.split("=", 1) key = parts[0].strip() value = parts[1].strip() if key == "level-name": return value raise ValueError("No level-name found in server.properties!") def run(self): """Run the main program's logic.""" # Change into the server's directory. os.chdir(self.args.server) # If we're only culling backups, do that and exit. if self.args.clean: return self.cull_backups() # Backups directory. backups = os.path.join(self.args.server, "backups") if not os.path.isdir(backups): log.info("Creating backups directory: {}".format(backups)) os.mkdir(backups) # Connect to the Minecraft-Control server. log.info("Connecting to Minecraft control server...") self.client = MinecraftClient( host=self.config["host"], port=self.config["port"], password=self.config["password"], methods=[self.config["method"]], ) self.client.add_handler("auth_ok", self.on_auth_ok) self.client.add_handler("auth_error", self.on_auth_error) self.client.add_handler("server_message", self.on_message) self.client.connect() self.client.start() def on_auth_ok(self, mc): """Handle successful authentication.""" log.info("Connection to server established and authenticated!") # Target file name. fname = self.today + ".tar.gz" target = os.path.join("backups", fname) # Turn off saving and save the world now. log.info("Turning off auto-saving and saving the world now!") self.client.sendline("save-off") self.client.sendline("save-all") time.sleep(5) # Archive the world. log.info("Backing up the world as: {}".format(target)) subprocess.call(["tar", "czvf", target, self.world]) # Turn saving back on. time.sleep(5) log.info("Turning auto-saving back on!") self.client.sendline("save-on") # Cull old backups. self.cull_backups() quit() def cull_backups(self): """Trim the backup copies and remove older backups.""" log.info("Culling backups...") # Date cut-off for daily backups. daily_cutoff = ( datetime.datetime.utcnow() - datetime.timedelta(days=DAILY_BACKUPS)).strftime("%Y-%m-%d") log.debug("Daily cutoff date: {}".format(daily_cutoff)) # Number of weekly backups spared. weekly_spared = 0 # Check all the existing backups. for tar in sorted(os.listdir("backups"), reverse=True): if not tar.endswith(".tar.gz"): continue try: dt = datetime.datetime.strptime(tar, "%Y-%m-%d_%H-%M-%S.tar.gz") weekday = dt.weekday() date = dt.strftime("%Y-%m-%d") except Exception as e: log.error("Error parsing datetime from existing backup {}: {}". format( tar, e, )) continue # If this is within the daily cutoff, we keep it. if date > daily_cutoff: log.debug( "DAILY KEEP: {} is within the daily cutoff".format(tar)) continue # Now we're at backups older than our daily threshhold, so we only # want to keep one backup per week until we have WEEKLY_BACKUPS # copies, and only for backups taken on WEEKLY_WEEKDAY day-of-week. if weekday == WEEKLY_WEEKDAY and weekly_spared < WEEKLY_BACKUPS: log.debug("WEEKLY KEEP: {} is being kept".format(tar)) weekly_spared += 1 continue # All other old backups get deleted. log.info("Cull old backup: {}".format(tar)) os.unlink("backups/{}".format(tar)) def on_auth_error(self, mc, error): """Handle unsuccessful authentication.""" log.error(error) sys.exit(1) def on_message(self, mc, message): """Handle a Minecraft server message.""" log.info("Minecraft server says: {}".format(message))
class Application: def __init__(self, args): """Initialize the application.""" self.args = args # Verify settings. self.verify_args() self.config = dict() # minecraft-control configuration self.client = None # MinecraftClient instance self.today = datetime.datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") self.world = self.get_world_name() log.info("Today's date/time: {}".format(self.today)) # Load the minecraft-control configuration. self.load_mc_config() def verify_args(self): """Do some sanity checking on input arguments.""" # The minecraft-control config file. if not os.path.isfile(self.args.config): log.error("{}: not a file".format(self.args.config)) sys.exit(1) # The server directory. if not os.path.isfile("{}/server.properties".format(self.args.server)): log.error( "{}: not a Minecraft server directory (no " "server.properties file present)".format(self.args.server) ) sys.exit(1) def load_mc_config(self): """Load the configuration from minecraft-control.""" log.debug("Loading minecraft-control settings from {}".format(args.config)) parser = RawConfigParser() with open(self.args.config, "r") as fh: parser.readfp(fh) self.config["host"] = parser.get("tcp-server", "address") self.config["port"] = parser.get("tcp-server", "port") self.config["password"] = parser.get("auth", "password") self.config["method"] = parser.get("auth", "method") def get_world_name(self): """Load the server.properties to find the world name.""" with open("{}/server.properties".format(self.args.server), "r") as fh: for line in fh: if not "=" in line: continue parts = line.split("=", 1) key = parts[0].strip() value = parts[1].strip() if key == "level-name": return value raise ValueError("No level-name found in server.properties!") def run(self): """Run the main program's logic.""" # Change into the server's directory. os.chdir(self.args.server) # If we're only culling backups, do that and exit. if self.args.clean: return self.cull_backups() # Backups directory. backups = os.path.join(self.args.server, "backups") if not os.path.isdir(backups): log.info("Creating backups directory: {}".format(backups)) os.mkdir(backups) # Connect to the Minecraft-Control server. log.info("Connecting to Minecraft control server...") self.client = MinecraftClient( host=self.config["host"], port=self.config["port"], password=self.config["password"], methods=[self.config["method"]], ) self.client.add_handler("auth_ok", self.on_auth_ok) self.client.add_handler("auth_error", self.on_auth_error) self.client.add_handler("server_message", self.on_message) self.client.connect() self.client.start() def on_auth_ok(self, mc): """Handle successful authentication.""" log.info("Connection to server established and authenticated!") # Target file name. fname = self.today + ".tar.gz" target = os.path.join("backups", fname) # Turn off saving and save the world now. log.info("Turning off auto-saving and saving the world now!") self.client.sendline("save-off") self.client.sendline("save-all") time.sleep(5) # Archive the world. log.info("Backing up the world as: {}".format(target)) subprocess.call(["tar", "czvf", target, self.world]) # Turn saving back on. time.sleep(5) log.info("Turning auto-saving back on!") self.client.sendline("save-on") # Cull old backups. self.cull_backups() quit() def cull_backups(self): """Trim the backup copies and remove older backups.""" log.info("Culling backups...") # Date cut-off for daily backups. daily_cutoff = (datetime.datetime.utcnow() - datetime.timedelta(days=DAILY_BACKUPS)).strftime("%Y-%m-%d") log.debug("Daily cutoff date: {}".format(daily_cutoff)) # Number of weekly backups spared. weekly_spared = 0 # Check all the existing backups. for tar in sorted(os.listdir("backups"), reverse=True): if not tar.endswith(".tar.gz"): continue try: dt = datetime.datetime.strptime(tar, "%Y-%m-%d_%H-%M-%S.tar.gz") weekday = dt.weekday() date = dt.strftime("%Y-%m-%d") except Exception as e: log.error("Error parsing datetime from existing backup {}: {}".format(tar, e)) continue # If this is within the daily cutoff, we keep it. if date > daily_cutoff: log.debug("DAILY KEEP: {} is within the daily cutoff".format(tar)) continue # Now we're at backups older than our daily threshhold, so we only # want to keep one backup per week until we have WEEKLY_BACKUPS # copies, and only for backups taken on WEEKLY_WEEKDAY day-of-week. if weekday == WEEKLY_WEEKDAY and weekly_spared < WEEKLY_BACKUPS: log.debug("WEEKLY KEEP: {} is being kept".format(tar)) weekly_spared += 1 continue # All other old backups get deleted. log.info("Cull old backup: {}".format(tar)) os.unlink("backups/{}".format(tar)) def on_auth_error(self, mc, error): """Handle unsuccessful authentication.""" log.error(error) sys.exit(1) def on_message(self, mc, message): """Handle a Minecraft server message.""" log.info("Minecraft server says: {}".format(message))
debug = False host, port, password = None, None, None whitelist = [] if sys.argv[1] == "--debug": debug = True host, port, password = sys.argv[2:5] whitelist = map(lambda x: x.lower(), sys.argv[5:]) else: host, port, password = sys.argv[1:4] whitelist = map(lambda x: x.lower(), sys.argv[4:]) # Connect to the server. client = MinecraftClient( debug = debug, host = host, port = port, password = password, ) def on_authed(client): print("Authentication successful!") client.sendline("say 01-gamemode.py demo started. Whitelist: {}".format(str(whitelist))) def on_error(client, error): print("Failed to authenticate: {}".format(error)) def on_message(client, message): print("Saw server message: {}".format(message)) # Look for people joining the game. if "joined the game" in message: