async def ensure_client(self): if self.client is None: self.client = mc.Client(ADRESS, PASS) try: await self.client.setup() except: self.client = None raise RCONUnavailableException("Could not reach the Minecraft server")
async def get_client(*args, **kwargs): client = rc.Client(*args, **kwargs) try: yield client except rc.ConnectionFailedError: print("Connection failed", file=sys.stderr) except rc.InvalidAuthError: print("Invalid password", file=sys.stderr) except EOFError: pass finally: await client.close()
async def rcon_command(self, ctx, *, cmd): dm_check = (lambda m: ctx.author.id == m.author.id and ctx.author.dm_channel.id == m.channel.id) db_guild = await self.db.fetch_guild(ctx.guild.id) if db_guild['mcserver'] is None: await self.bot.send(ctx, ctx.l.minecraft.rcon.stupid_1) return db_user_rcon = await self.db.fetch_user_rcon(ctx.author.id, db_guild['mcserver']) if db_user_rcon is None: try: await self.bot.send(ctx.author, ctx.l.minecraft.rcon.port) except Exception: await self.bot.send(ctx, ctx.l.minecraft.rcon.dm_error) return try: port_msg = await self.bot.wait_for('message', check=dm_check, timeout=60) except asyncio.TimeoutError: try: await self.bot.send(ctx.author, ctx.l.minecraft.rcon.msg_timeout) except Exception: pass return try: rcon_port = int(port_msg.content) if 0 > rcon_port > 65535: rcon_port = 25575 except Exception: rcon_port = 25575 try: await self.bot.send(ctx.author, ctx.l.minecraft.rcon.passw) except Exception: await self.bot.send(ctx, ctx.l.minecraft.rcon.dm_error) return try: auth_msg = await self.bot.wait_for('message', check=dm_check, timeout=60) except asyncio.TimeoutError: try: await self.bot.send(ctx.author, ctx.l.minecraft.rcon.msg_timeout) except Exception: pass return password = auth_msg.content else: rcon_port = db_user_rcon['rcon_port'] password = Fernet(self.k.fernet).decrypt(db_user_rcon['password'].encode('utf-8')).decode('utf-8') # decrypt to plaintext await ctx.trigger_typing() try: rcon_con = self.d.rcon_cache.get((ctx.author.id, db_guild['mcserver'])) if rcon_con is None: rcon_con = rcon.Client((db_guild['mcserver'].split(':')[0] + f':{rcon_port}'), password, 2.5, loop=self.bot.loop) self.d.rcon_cache[(ctx.author.id, db_guild['mcserver'])] = (rcon_con, arrow.utcnow()) else: rcon_con = rcon_con[0] self.d.rcon_cache[(ctx.author.id, db_guild['mcserver'])] = (rcon_con, arrow.utcnow()) await rcon_con.setup() except Exception as e: if isinstance(e, rcon.errors.InvalidAuthError): await self.bot.send(ctx, ctx.l.minecraft.rcon.stupid_2) else: await self.bot.send(ctx, ctx.l.minecraft.rcon.err_con) await self.db.delete_user_rcon(ctx.author.id, db_guild['mcserver']) await rcon_con.close() self.d.rcon_cache.pop((ctx.author.id, db_guild['mcserver']), None) return if db_user_rcon is None: encrypted_password = Fernet(self.k.fernet).encrypt(password.encode('utf-8')).decode('utf-8') await self.db.add_user_rcon(ctx.author.id, db_guild['mcserver'], rcon_port, encrypted_password) try: resp = await rcon_con.send_cmd(cmd[:1445]) except Exception: await self.bot.send(ctx, ctx.l.minecraft.rcon.err_cmd) await rcon_con.close() self.d.rcon_cache.pop((ctx.author.id, db_guild['mcserver']), None) return resp_text = '' for i in range(0, len(resp[0])): if resp[0][i] != '§' and (i == 0 or resp[0][i-1] != '§'): resp_text += resp[0][i] await ctx.send('```\uFEFF{}```'.format(resp_text.replace('\\n', '\n')[:2000-7]))
async def rcon_command(self, ctx, *, cmd): author_check = (lambda m: ctx.author.id == m.author.id and ctx.author.dm_channel.id == m.channel.id) db_guild = await self.db.fetch_guild(ctx.guild.id) if db_guild['mcserver'] is None: await self.bot.send(ctx, 'You have to set a Minecraft server for this guild via the `/config mcserver` command first.') return key = (ctx.guild.id, ctx.author.id, db_guild['mcserver']) cached = self.d.rcon_connection_cache.get(key) if cached is None: try: await self.bot.send(ctx.author, 'Type in the remote console password (rcon.password in the server.properties file) here. This password can be stored for up to 10 minutes past the last rcon command.') except Exception: await self.bot.send(ctx, 'I need to be able to DM you, either something went wrong or I don\'t have the permissions to.') return try: auth_msg = await self.bot.wait_for('message', check=author_check, timeout=60) except asyncio.TimeoutError: await self.bot.send(ctx.author, 'I\'ve stopped waiting for a response.') return if db_guild['mcserver_rcon'] is None: try: await self.bot.send(ctx.author, 'Now type in the RCON port (rcon.port in the server.properties file)') except Exception: await self.bot.send(ctx, 'I need to be able to DM you, either something went wrong or I don\'t have the permissions to.') return try: port_msg = await self.bot.wait_for('message', check=author_check, timeout=60) except asyncio.TimeoutError: await self.bot.send(ctx.author, 'I\'ve stopped waiting for a response.') return port = 25575 try: port = int(port_msg.content) except Exception: port = 25575 if 0 > port > 65535: port = 25575 await self.db.set_guild_attr(ctx.guild.id, 'mcserver_rcon', port) # update value in db else: port = db_guild['mcserver_rcon'] try: s = db_guild['mcserver'].split(':')[0]+f':{port}' self.d.rcon_connection_cache[key] = (rcon.Client(s, auth_msg.content, 2.5, loop=self.bot.loop), arrow.utcnow()) await self.d.rcon_connection_cache[key][0].setup() except rcon.Errors.ConnectionFailedError: await self.bot.send(ctx, 'Connection to the server failed, is RCON enabled?') await self.close_rcon_con(key, ctx.guild.id) return except rcon.Errors.InvalidAuthError: await self.bot.send(ctx.author, 'The provided RCON password/authentication is invalid') await self.close_rcon_con(key, ctx.guild.id) return rcon_con = self.d.rcon_connection_cache[key][0] else: rcon_con = cached[0] self.d.rcon_connection_cache[key] = (rcon_con, arrow.utcnow()) # update time try: resp = await rcon_con.send_cmd(cmd[:1446]) # shorten to avoid unecessary timeouts except asyncio.TimeoutError: await self.bot.send(ctx, 'A timeout occurred while sending that command to the server') await self.close_rcon_con(key, ctx.guild.id) except Exception: await self.bot.send(ctx, f'For some reason, an error ocurred while sending that command to the server') await self.close_rcon_con(key, ctx.guild.id) else: resp_text = '' for i in range(0, len(resp[0])): if resp[0][i] != '§' and (i == 0 or resp[0][i-1] != '§'): resp_text += resp[0][i] await ctx.send('```{}```'.format(resp_text.replace('\\n', '\n')))
async def rcon_command(self, ctx, *, cmd): db_guild = await self.db.fetch_guild(ctx.guild.id) if db_guild["mc_server"] is None: await self.bot.reply_embed(ctx, ctx.l.minecraft.rcon.stupid_1.format(ctx.prefix)) return db_user_rcon = await self.db.fetch_user_rcon(ctx.author.id, db_guild["mc_server"]) if db_user_rcon is None: try: await self.bot.send_embed(ctx.author, ctx.l.minecraft.rcon.port) except Exception: await self.bot.reply_embed(ctx, ctx.l.minecraft.rcon.dm_error, True) return try: if 0 in self.bot.shard_ids: port_msg = await self.bot.wait_for("message", check=dm_check(ctx), timeout=60) else: port_msg = await asyncio.wait_for( self.ipc.request({"type": "dm-message-request", "user_id": ctx.author.id}), 60 ) except asyncio.TimeoutError: try: await self.bot.send_embed(ctx.author, ctx.l.minecraft.rcon.msg_timeout) except (discord.Forbidden, discord.HTTPException): pass return try: rcon_port = int(port_msg.content) if 0 > rcon_port > 65535: rcon_port = 25575 except (ValueError, TypeError): rcon_port = 25575 try: await self.bot.send_embed(ctx.author, ctx.l.minecraft.rcon.passw) except Exception: await self.bot.reply_embed(ctx, ctx.l.minecraft.rcon.dm_error, True) return try: if 0 in self.bot.shard_ids: auth_msg = await self.bot.wait_for("message", check=dm_check(ctx), timeout=60) else: auth_msg = await asyncio.wait_for( self.ipc.request({"type": "dm-message-request", "user_id": ctx.author.id}), 60 ) except asyncio.TimeoutError: try: await self.bot.send_embed(ctx.author, ctx.l.minecraft.rcon.msg_timeout) except (discord.Forbidden, discord.HTTPException): pass return password = auth_msg.content else: rcon_port = db_user_rcon["rcon_port"] password = self.fernet.decrypt(db_user_rcon["password"].encode("utf-8")).decode("utf-8") # decrypt to plaintext await ctx.trigger_typing() try: rcon_con = self.bot.rcon_cache.get((ctx.author.id, db_guild["mc_server"])) if rcon_con is None: rcon_con = rcon.Client(db_guild["mc_server"].split(":")[0], rcon_port, password) self.bot.rcon_cache[(ctx.author.id, db_guild["mc_server"])] = (rcon_con, arrow.utcnow()) else: rcon_con = rcon_con[0] self.bot.rcon_cache[(ctx.author.id, db_guild["mc_server"])] = (rcon_con, arrow.utcnow()) await rcon_con.connect(timeout=2.5) except Exception as e: if isinstance(e, rcon.IncorrectPasswordError): await self.bot.reply_embed(ctx, ctx.l.minecraft.rcon.stupid_2) else: await self.bot.reply_embed(ctx, ctx.l.minecraft.rcon.err_con) await self.db.delete_user_rcon(ctx.author.id, db_guild["mc_server"]) await rcon_con.close() self.bot.rcon_cache.pop((ctx.author.id, db_guild["mc_server"]), None) return if db_user_rcon is None: encrypted_password = Fernet(self.k.fernet).encrypt(password.encode("utf-8")).decode("utf-8") await self.db.add_user_rcon(ctx.author.id, db_guild["mc_server"], rcon_port, encrypted_password) try: resp = await rcon_con.send_cmd(cmd[:1445]) except Exception: await self.bot.reply_embed(ctx, ctx.l.minecraft.rcon.err_cmd) await rcon_con.close() self.bot.rcon_cache.pop((ctx.author.id, db_guild["mc_server"]), None) return resp_text = "" for i in range(0, len(resp[0])): if resp[0][i] != "§" and (i == 0 or resp[0][i - 1] != "§"): resp_text += resp[0][i] await ctx.reply("```\uFEFF{}```".format(resp_text.replace("\\n", "\n")[: 2000 - 7]), mention_author=False)