class SlashCommands(commands.Cog): def __init__(self, client): self.client = client #on_ready event example @commands.Cog.listener() async def on_ready(self): print('<SlashCommands> Test module loaded!') #fill with id's of guilds where you want to use slash commands guild_id = [320574287046115328] @cog_ext.cog_slash( name="test", guild_ids=guild_id, description="Test command.", options=[ manage_commands.create_option("option1", "Member example.", discord.Member, True), manage_commands.create_option("option2", "Bool example.", bool, True), manage_commands.create_option( "option3", "String example.", str, False) #if set to False it't optional ]) @commands.has_permissions(administrator=True ) #right now we have to use discord.ext check async def _test(self, ctx, member: discord.Member): try: await ctx.respond(True) #do something except Exception as E: print(E) #error handler @commands.Cog.listener() async def on_slash_command_error(self, ctx: SlashContext, error): try: await ctx.respond(True) if isinstance(error, MissingPermissions): mess = await ctx.send( f":exclamation: Missing permissions: `{','.join(error.missing_perms)}`!" ) await asyncio.sleep(5) await mess.delete() except Exception as E: print(E)
class Guild(commands.Cog): def __init__(self, bot): self.bot = bot # slash commands slash_guilds = [773042619734687766] @cog_ext.cog_slash( name="guild", description= "Checks if you are in the guild, and gives you the guild member role", options=[ manage_commands.create_option( name="username", description="Your username on hypixel", option_type=3, required=True) ], guild_ids=slash_guilds) async def _guild(self, ctx: SlashContext, username): req_player = await self.bot.session.get( f"https://api.slothpixel.me/api/players/{username}") res_player = await req_player.json() if "error" in res_player: return await ctx.send( "An error happened! Please check if the username you provided is correct", hidden=True) if res_player['links']['DISCORD'] != str(ctx.author): return await ctx.send( f"Your Minecraft and Discord accounts are not linked! Please update your discord link on hypixel from {res_player['links']['DISCORD']} to {str(ctx.author)}", hidden=True) req_guild = await self.bot.session.get( f"https://api.slothpixel.me/api/guilds/{username}") res_guild = await req_guild.json() if not res_guild['name'] == "Galaxy Crusaders": return await ctx.send(f"You are not in the guild!", hidden=True) role = ctx.guild.get_role(828657324877021204) await ctx.author.add_roles(role) await ctx.send( "Welcome to the guild! I have sucessfully added your guild role. Enjoy!", hidden=True) #normal commands start here @commands.command() async def scammer(self, ctx, ign: str): uuid_data = await self.bot.session.get( f"https://api.mojang.com/users/profiles/minecraft/{ign}") if uuid_data.status == 204: return await ctx.send("Ign Invalid!") uuid_json = await uuid_data.json() uuid = uuid_json['id'] scammer_data = await self.bot.session.get( "https://raw.githubusercontent.com/skyblockz/pricecheckbot/master/scammer.json" ) scammer_json = json.loads(await scammer_data.text()) if uuid in scammer_json: embed = discord.Embed( title="USER IS A SCAMMER!!", description=f"This user has been found on the scammers list!") embed.add_field( name="Details", value=f"{scammer_json[uuid]['reason']}\nUser's UUID: {uuid}") embed.set_author( name=f"JERRY SCAMMER LIST", url= "https://raw.githubusercontent.com/skyblockz/pricecheckbot/master/scammer.json" ) embed.set_footer(text=scammer_json[uuid]['operated_staff']) await ctx.send(embed=embed) else: embed = discord.Embed( title="Not a Scammer", description= "this user isn't a scammer, however, always be careful trading!" ) await ctx.send(embed=embed) @commands.has_any_role(828661477606817824, 828662244652220436) @commands.command(name='addguildrole', aliases=['agr', 'add-guild-role']) async def add_guild_role(self, ctx, user: discord.Member): """Manually adds the guild role to a user""" guild_role = ctx.guild.get_role(828657324877021204) await user.add_roles(guild_role) await ctx.send(f"I have added the guild role to {str(user)}!") @commands.command(name='inguild') async def inguild(self, ctx, username: str): """Checks if the given username is in the guild""" resp = await self.bot.session.get( f"https://api.mojang.com/users/profiles/minecraft/{username}") if resp.status == 204: return await ctx.send("Invalid username!") uuid_data = await resp.json() uuid = uuid_data['id'] guild_resp = await self.bot.session.get( f"https://api.slothpixel.me/api/guilds/{uuid}") guild_data = await guild_resp.json() if guild_data['name'] == "Galaxy Crusaders": await ctx.send(f"{uuid_data['name']} is in the guild!") else: await ctx.send(f"{uuid_data['name']} is not in the guild :(") @commands.has_role(828662244652220436) @commands.command(name="gexpcheck", aliases=['gexp-check']) async def gexp_check(self, ctx): async with ctx.typing(): req = await self.bot.session.get( f"https://api.slothpixel.me/api/guilds/zeromomentum?populatePlayers=true" ) res = await req.json() ending_string = "" for member in res['members']: gexp = calc(member['exp_history']) if gexp >= 30000: ending_string += f"+ {member['profile']['username']} has 30k+ gexp ({gexp:,})\n" if len(ending_string) >= 2000: hb = await self.bot.session.post("https://hst.sh/documents", data=ending_string.encode('utf8')) url = f"https://hst.sh/{(await hb.json())['key']}" return await ctx.send(f"Here is the GEXP overview! {url}") else: return await ctx.send("```diff\n" + ending_string + "```") @commands.has_role(828662244652220436) @commands.command(name="choppingblock", aliases=['chopping-block', 'no-gexp']) async def chopping_block(self, ctx): async with ctx.typing(): req = await self.bot.session.get( f"https://api.slothpixel.me/api/guilds/zeromomentum?populatePlayers=true" ) res = await req.json() ending_string = "" for member in res['members']: gexp = calc(member['exp_history']) if gexp <= 30000: ending_string += f"- {member['profile']['username']} has less than 30k gexp ({gexp:,})\n" if len(ending_string) >= 2000: hb = await self.bot.session.post("https://hst.sh/documents", data=ending_string.encode('utf8')) url = f"https://hst.sh/{(await hb.json())['key']}" return await ctx.send(f"Here is the GEXP overview! {url}") else: return await ctx.send("```diff\n" + ending_string + "```")
class SlashCmds(commands.Cog): def __init__(self, bot): self.bot: Skybot = bot async def shortcut_error(self, ctx): embed = await Embed( self.bot, ctx.author, title="Error", description= "You can only use this shortcut if you link a username to your Discord account." ).set_requested_by_footer() await ctx.send(embeds=[embed]) # await ctx.invoke(self.bot.get_command("help show_command"), arg=ctx.command.name) async def profile_not_found_error(self, ctx: commands.Context, player): embed = await Embed( self.bot, ctx.author, title="Error", description= "Couldn't find the provided profile in your Skyblock account. Your profiles: " + ", ".join(player.profiles.keys())).set_requested_by_footer() await ctx.send(embeds=[embed]) async def get_uname(self, ctx, uname): if not uname: uname, profile = await get_uuid_profileid(self.bot, ctx.author) if uname is None: return await self.shortcut_error(ctx) return uname async def make_player(self, ctx, uname, profile): if uname and uname.lower() == "me": uname, rest = await get_uuid_profileid(self.bot, ctx.author) if not uname and not profile: uname, profile = await get_uuid_profileid(self.bot, ctx.author) if uname is None: await self.shortcut_error(ctx) return None uname, uuid = await skypy.fetch_uuid_uname(uname) if not uname: raise exceptions.BadNameError(uname) player = await skypy.Player(keys=self.bot.api_keys, uname=uname) if not profile: await player.set_profile_automatically() elif profile and profile.capitalize() in player.profiles.keys(): await player.set_profile(player.profiles[profile.capitalize()]) else: try: await player.set_profile(profile) except exceptions.DataError: await self.profile_not_found_error(ctx, player) return None return player def format_name(self, name): return name + "'s" if name[-1] != "s" else name profiles = [ manage_commands.create_choice("apple", "Apple"), manage_commands.create_choice("banana", "Banana"), manage_commands.create_choice("blueberry", "Blueberry"), manage_commands.create_choice("coconut", "Coconut"), manage_commands.create_choice("cucumber", "Cucumber"), manage_commands.create_choice("grapes", "Grapes"), manage_commands.create_choice("kiwi", "Kiwi"), manage_commands.create_choice("lemon", "Lemon"), manage_commands.create_choice("lime", "Lime"), manage_commands.create_choice("mango", "Mango") ] @cog_ext.cog_slash( name="dungeons", description="Shows you Catacomb stats.", options=[ manage_commands.create_option( "username", "Minecraft username/Discord user if linked.", SlashCommandOptionType.STRING, False), manage_commands.create_option( "profile", "Profile name (There are more profile names then suggested!)", SlashCommandOptionType.STRING, False, choices=profiles) ]) async def dungeons(self, ctx: SlashContext, username=None, profile=None): await ctx.defer() player = await self.make_player(ctx, username, profile) if not player: return embeds = await Player.get_dungeon_embeds(self, ctx, player) if isinstance(embeds, Embed): return await ctx.send(embed=embeds) elif len(embeds) == 1: return await ctx.send(embed=embeds[0]) msg = await ctx.send(embed=embeds[0]) await Paginator(self.bot, msg, embeds=embeds, timeout=60, only=ctx.author).start() @cog_ext.cog_slash( name="networth", description= "View a more in-depth breakdown of your estimated networth.", options=[ manage_commands.create_option( "username", "Minecraft username/Discord user if linked.", SlashCommandOptionType.STRING, False), manage_commands.create_option( "profile", "Profile name (There are more profile names then suggested!)", SlashCommandOptionType.STRING, False, choices=profiles) ]) async def networth(self, ctx: SlashContext, username=None, profile=None): await ctx.defer() player = await self.make_player(ctx=ctx, uname=username, profile=profile) if not player: return success = await player.skylea_stats(self.bot.stats_api) if success: embeds = await Player.get_networth_embeds(self, ctx=ctx, player=player) msg = await ctx.send(embed=embeds[0]) await Expander(self.bot, msg, embeds=embeds, timeout=120, only=ctx.author).start() else: await ctx.send( content= f"An error occurred, perhaps this user has not played skyblock." ) @cog_ext.cog_slash( name="skills", description="Shows you Skyblock skill levels and xp.", options=[ manage_commands.create_option( "username", "Minecraft username/Discord user if linked.", SlashCommandOptionType.STRING, False), manage_commands.create_option( "profile", "Profile name (There are more profile names then suggested!)", SlashCommandOptionType.STRING, False, choices=profiles) ]) async def skills(self, ctx: SlashContext, username=None, profile=None): await ctx.defer() player = await self.make_player(ctx=ctx, uname=username, profile=profile) if not player: return embed = await Player.get_skills_embed(self, ctx=ctx, player=player) await ctx.send(embeds=[embed]) @cog_ext.cog_slash( name="stats", description= "Shows you Skyblock profile stats like health, strength and more.", options=[ manage_commands.create_option( "username", "Minecraft username/Discord user if linked.", SlashCommandOptionType.STRING, False), manage_commands.create_option( "profile", "Profile name (There are more profile names then suggested!)", SlashCommandOptionType.STRING, False, choices=profiles) ]) async def stats(self, ctx: SlashContext, username=None, profile=None): await ctx.defer() player = await self.make_player(ctx=ctx, uname=username, profile=profile) if not player: return success = await player.skylea_stats(self.bot.stats_api) if success: embed = await Player.get_stats_embed(self, ctx=ctx, player=player) await ctx.send(embeds=[embed]) else: await ctx.send( content= f"An error occurred, perhaps this user has not played skyblock." ) @cog_ext.cog_slash( name="slayer", description="Shows you Slayer stats.", options=[ manage_commands.create_option( "username", "Minecraft username/Discord user if linked.", SlashCommandOptionType.STRING, False), manage_commands.create_option( "profile", "Profile name (There are more profile names then suggested!)", SlashCommandOptionType.STRING, False, choices=profiles) ]) async def slayer(self, ctx: SlashContext, username=None, profile=None): await ctx.defer() player = await self.make_player(ctx=ctx, uname=username, profile=profile) if not player: return embed = await Player.get_slayer_embed(self, ctx=ctx, player=player) await ctx.send(embeds=[embed]) @cog_ext.cog_slash( name="profiles", description="Shows you all your available profiles on Skyblock.", options=[ manage_commands.create_option( "username", "Minecraft username/Discord user if linked.", SlashCommandOptionType.STRING, False) ]) async def profiles(self, ctx: SlashContext, username=None): await ctx.defer() uname = await self.get_uname(ctx, username) if not uname: return embed: Embed = await Player.get_profiles_embed(self, ctx=ctx, uname=uname) await ctx.send(embeds=[embed]) # @cog_ext.cog_slash(name="auctions", description="Shows you Skyblock auctions and information about them.", options=[manage_commands.create_option("username", "Minecraft username/Discord user if linked.", SlashCommandOptionType.STRING, False), # manage_commands.create_option("profile", "Profile name (There are more profile names then suggested!)", SlashCommandOptionType.STRING, False, choices=profiles)]) # async def auctions(self, ctx : SlashContext, username=None, profile=None): # player = await self.make_player(ctx=ctx, uname=username, profile=profile) # if not player: return # embeds = await Player.get_auctions_embeds(self, ctx=ctx, player=player) # if not embeds: # return await ctx.send(content=f"{player.uname} has no auctions running.") # msg = await ctx.send(embeds=[embeds[0]]) # if len(embeds) > 1: # pages = Paginator(self.bot, msg, embeds=embeds, only=ctx.author, use_more=True) # await pages.start() async def get_help_embed(self, ctx): staff = is_staff(ctx) list_embed = Embed(title="Categories", bot=self.bot, user=ctx.author) # list_embed.set_author(name=f"Use {ctx.prefix}help [Command/Category]") await list_embed.set_requested_by_footer() for name, cog in self.bot.cogs.items(): if name == "Admin" or name == "Help": continue if not cog.get_commands(): continue commands = [] for command in cog.get_commands(): if has_is_staff(command) and not staff: continue commands.append(f"`{command.name}`") list_embed.add_field(name=name, value=", ".join(commands), inline=False) list_embed.add_field( name="Links", value= "[Contribute](https://discord.gg/zqRsduD2JN) | [Vote](https://top.gg/bot/630106665387032576/vote) | [Invite the Bot to your server](https://discordapp.com/oauth2/authorize?client_id=630106665387032576&scope=bot&permissions=8) | [Support Server](https://discord.gg/7fPv2uY2Tf) | [Todos](https://trello.com/b/2yBAtx82/skybot-rewrite) | [GitHub repo](https://github.com/Skybot-dev/Skybot-rewrite)", inline=False) return list_embed @cog_ext.cog_slash(name="help", description="List commands and command info.", guild_ids=[636937988248436736]) async def help(self, ctx: SlashContext): await ctx.defer() embed = await self.get_help_embed(ctx) await ctx.send(embeds=[embed])
class SlashCommands(commands.Cog): """Class to use slash commands in guilds.""" __slots__ = ("bot") def __init__(self, bot): self.bot = bot @cog_ext.cog_slash( name="help", description="Shows information about Coronavirus bot", options=[ manage_commands.create_option( name="help_type", description="Options about how to use the bot", option_type=3, required=False, choices=[ manage_commands.create_choice( name="📈Statistics", value="stats" ), manage_commands.create_choice( name="⚙️Bot utilities", value="utilities" ) ] ) ] ) async def _help(self, ctx: SlashContext, help_type=""): await help.help_command(self.bot, ctx, help_type) @cog_ext.cog_slash( name="getprefix", description="Shows current guild prefix" ) async def _getg_prefix(self, ctx: SlashContext): await help.get_guild_prefix_command(self.bot, ctx) @cog_ext.cog_slash( name="setprefix", description="Set new prefix for your guild", ) async def _set_prefix(self, ctx: SlashContext, new_prefix): await help.setprefix_command(self.bot, ctx, new_prefix) @cog_ext.cog_slash( name="list", description="List all the countries that the bot can find" ) async def _list_countries(self, ctx): await data.list_countries_command(self.bot, ctx) @cog_ext.cog_slash( name="info", description="Shows some symbolic numbers about the pandemic" ) async def _info(self, ctx): await data.info_command(self.bot, ctx) @cog_ext.cog_slash( name="country", description="Shows information about country.ies" ) async def _country(self, ctx, countries): countries = countries.split(" ") # TODO: adapt the aux func to avoid split usage # temporary fix to use slash commands await data.country_command(self.bot, ctx, countries) @cog_ext.cog_slash( name="stats", description="Shows statistics about a country" ) async def _stats(self, ctx, country): country = country.split(" ") await data.stats_command(self.bot, ctx, country) @cog_ext.cog_slash( name="notification", description="Shows statistics about a country", options=[ manage_commands.create_option( name="country", description="Country to set the notification for", option_type=3, required=True ), manage_commands.create_option( name="interval", description="Interval between each updates", option_type=3, required=True ), manage_commands.create_option( name="interval_type", description="Interval type", option_type=3, required=True, choices=[ manage_commands.create_choice( name="Hours", value="hours" ), manage_commands.create_choice( name="Days", value="days" ), manage_commands.create_choice( name="Weeks", value="weeks" ) ] ) ] ) async def _notification(self, ctx: SlashContext, country, interval, interval_type): logger.info(interval_type) await data.notification_command( self.bot, ctx, country=country, interval=interval, interval_type=interval_type ) @cog_ext.cog_slash( name="track", description="Track a specific country" ) async def _track(self, ctx, country): country = country.split(" ") await data.track_command(self.bot, ctx, *country) @cog_ext.cog_slash( name="region", description="Get stats about a region" ) async def _region(self, ctx, country): country = country.split(" ") await data.region_command(self.bot, ctx, country) @cog_ext.cog_slash( name="daily", description="Daily stats" ) async def _daily(self, ctx, country): country = country.split(" ") await data.daily_command(self.bot, ctx, *country) @cog_ext.cog_slash( name="news", description="Get the latest news about Covid 19" ) async def _news(self, ctx: SlashContext): await data.news_command(self.bot, ctx)
class Slash(commands.Cog): def __init__(self, client): self.bot = client @cog_ext.cog_slash(name="charts", description='Returns PDF chart for given airport ICAO', options=[ manage_commands.create_option( name='icao', description='Required airport ICAO code', option_type=3, required=True) ]) async def _charts(self, ctx: SlashContext, icao: str): # prfx = get_prefix(client=self, message=ctx.message) prfx = '/' print(f"Requested charts for {icao.upper()}") if len(icao) != 4: await ctx.send("ICAO code must be composed of 4 characters") return url = f"http://www.uvairlines.com/admin/resources/{icao.upper()}.pdf" request = requests.get(url) if request.status_code != 200: print( f'Failed to retrieve charts for {icao.upper()}, error: {request.status_code}' ) await ctx.send( f"Error {request.status_code} while retrieving charts for {icao.upper()}, either the website is down or the airport you chose is not available" ) else: charts = discord.Embed( title=f"Requested charts for {icao.upper()}", description=f"Download or view the charts at: [Link]({url})") charts.set_footer( text= "You can also check the METAR for this airport with `{}metar {}`" .format(prfx, icao.upper())) charts.set_thumbnail( url= "https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif" ) await ctx.send(embed=charts) @cog_ext.cog_slash(name='metar', description='Fetches METAR for given airport ICAO', options=[ manage_commands.create_option( name='icao', description='Required airport ICAO code', option_type=3, required=True) ]) async def metar(self, ctx: SlashContext, icao: str): global gustbool if len(icao) != 4: await ctx.send("ICAO code must be composed of 4 characters") return try: req = requests.get( 'https://api.checkwx.com/metar/{}/decoded'.format(icao), headers=hdr, timeout=5) except Exception as err: await ctx.send( "Timeout error while requesting METAR, API servers are probably offline. Please try again later" ) return print(err) print(f"Requested METAR for {icao.upper()}") if req.status_code != 200: print( f"Failed to retrieve METAR for {icao.upper()}, error {req.status_code}" ) return await ctx.send( f"Error {req.status_code} while retrieving info for {icao.upper()}, either the website is down or the airport you chose is not available" ) else: resp = req.json() if resp["results"] == 0: await ctx.send( "No results, please check for typos or try a different ICAO" ) return # with open('./Utils/wx.json', 'w') as f: # json.dump(resp, f, indent=4) layerint = len(resp["data"][0] ["clouds"]) # integer for number of cloud layers wxint = 0 if "conditions" in resp["data"][0]: wxint = len( resp["data"][0]["conditions"]) # presence of wx conditions visbool = "visibility" in resp["data"][0] # presence of vis data if 'wind' in resp['data'][0]: gustbool = "gust_kts" in resp["data"][0][ "wind"] # presence of gusts wind_bool = True else: wind_bool = False name = resp["data"][0]["station"]["name"] if wind_bool: degrees = resp["data"][0]["wind"]["degrees"] speed = resp["data"][0]["wind"]["speed_kts"] temp = resp["data"][0]["temperature"]["celsius"] dew = resp["data"][0]["dewpoint"]["celsius"] humidity = resp["data"][0]["humidity"]["percent"] inhg = resp["data"][0]["barometer"]["hg"] hpa = resp["data"][0]["barometer"]["hpa"] obs = resp["data"][0]["observed"] cond = resp["data"][0]["flight_category"] raw = resp["data"][0]["raw_text"] points = [] lat: float = resp["data"][0]["station"]["geometry"]["coordinates"][ 1] long: float = resp["data"][0]["station"]["geometry"][ "coordinates"][0] points.append(tuple([lat, long])) marker_outline = CircleMarker((long, lat), 'white', 18) marker = CircleMarker((long, lat), '#0036FF', 12) icon_flag = IconMarker((long + 0.008, lat), './Utils/icon-flag.png', 12, 32) m = StaticMap(700, 300, 10, 10) m.add_marker(marker_outline) m.add_marker(marker) m.add_marker(icon_flag) image = m.render(zoom=8) image.save('Utils/metar.png') file = discord.File('Utils/metar.png') metar = discord.Embed(title="Requested METAR for {} - {}".format( icao.upper(), name), description="Raw: {}".format(raw), colour=discord.Colour.from_rgb(97, 0, 215)) if wind_bool: if not gustbool: metar.add_field(name="Wind:", value="{}° at {} kts".format( degrees, speed)) else: gust = resp["data"][0]["wind"]["gust_kts"] metar.add_field(name="Wind:", value="{}° at {} kts, gusts {} kts".format( degrees, speed, gust)) else: metar.add_field(name="Wind:", value="Calm") metar.add_field(name="Temp/Dewpoint:", value="{}°C/ {}°C".format(temp, dew)) metar.add_field(name="Altimeter:", value="{} hPa/ {} inHg".format(hpa, inhg)) if visbool: vismil = resp["data"][0]["visibility"]["miles"] vismet = resp["data"][0]["visibility"]["meters"] metar.add_field(name="Visibility:", value="{} meters/ {} miles".format( vismet, vismil)) metar.add_field(name="Humidity:", value="{}%".format(humidity)) metar.set_thumbnail( url= "https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif" ) metar.set_footer( text="Observed at {}. Flight category: {}".format(obs, cond)) if wxint > 0: weather = resp["data"][0]["conditions"][0]["text"] metar.add_field(name="Weather condition:", value="{}".format(weather)) if layerint == 1: clouds = resp["data"][0]["clouds"][0]["text"] if 'feet' in resp["data"][0]["clouds"][0]: clofeet = resp["data"][0]["clouds"][0]["feet"] metar.add_field(name="Cloud condition:", value="{}ft {}".format(clofeet, clouds)) else: metar.add_field(name="Cloud condition:", value="{}".format(clouds)) elif layerint == 2: clouds = resp["data"][0]["clouds"][0]["text"] clofeet = resp["data"][0]["clouds"][0]["feet"] clouds1 = resp["data"][0]["clouds"][1]["text"] clofeet1 = resp["data"][0]["clouds"][1]["feet"] metar.add_field(name="Cloud condition:", value="{}ft {}/ {}ft {}".format( clofeet, clouds, clofeet1, clouds1)) elif layerint == 3: clouds = resp["data"][0]["clouds"][0]["text"] clofeet = resp["data"][0]["clouds"][0]["feet"] clouds1 = resp["data"][0]["clouds"][1]["text"] clofeet1 = resp["data"][0]["clouds"][1]["feet"] clouds2 = resp["data"][0]["clouds"][2]["text"] clofeet2 = resp["data"][0]["clouds"][2]["feet"] metar.add_field(name="Cloud condition:", value="{}ft {}/ {}ft {}/ {}ft {}".format( clofeet, clouds, clofeet1, clouds1, clofeet2, clouds2)) else: metar.add_field(name="Cloud condition:", value="Not Specified / Cloud data error") metar.set_image(url='attachment://metar.png') await ctx.send(embed=metar, file=file) @cog_ext.cog_slash( name='flightplan', description='Calculates a flight plan between two given airports', options=[ manage_commands.create_option( name='dep', description='Departure airport ICAO code', option_type=3, required=True), manage_commands.create_option( name='arr', description='Arrival airport ICAO code', option_type=3, required=True) ]) async def flightplan(self, ctx: SlashContext, dep='lmfao', arr='lmfao'): if len(dep) != 4 or len(arr) != 4: await ctx.send( 'You need to specify two valid airport ICAO codes to create a flight plan' ) return # loading = discord.Embed( # title='Your flight plan is loading', # description='Creating flight plan...' # ) # loading.set_thumbnail( # url='https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif') # loading.set_footer(text='Using data from the Flight Plan Database (https://flightplandatabase.com)') # message = await ctx.send(embed=loading) headers = { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + fpd_api } data = '{"fromICAO":"immensecock","toICAO":"giganticpenis"}' data = data.replace("immensecock", dep) data = data.replace("giganticpenis", arr) print( f'Requested flight plan: {dep.upper()} to {arr.upper()}, generating...' ) response = requests.post( 'https://api.flightplandatabase.com/auto/generate', headers=headers, data=data) if response.status_code != 201: # await message.delete() await ctx.send( f"Error {response.status_code} while generating the flight plan, try with different ICAO codes```{response.json()['errors'][0]['message']}```" ) return plan = (str(response.json()))[7:14] print('Requesting...') # loading1 = discord.Embed( # title='Your flight plan is loading', # description='Flight plan created successfully, uploading...' # ) # loading1.set_thumbnail( # url='https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif') # loading1.set_footer(text='Using data from the Flight Plan Database (https://flightplandatabase.com)') # await message.delete() # message1 = await ctx.send(embed=loading1) retrieve = requests.get( f'https://api.flightplandatabase.com/plan/{plan}') if retrieve.status_code != 200: # await message1.delete() await ctx.send( f'There was an error while processing the flight plan: **{retrieve.status_code}**, try with different ICAO codes' ) # self.flightplan.reset_cooldown(ctx) return print('Received flight plan') flp = retrieve.json() flpid = flp['id'] dep_icao = flp['fromICAO'] arr_icao = flp['toICAO'] dep_name = flp['fromName'] arr_name = flp['toName'] dist = int(flp['distance']) cr_alt = flp['maxAltitude'] wpt_num = flp['waypoints'] # important link = f'https://flightplandatabase.com/plan/{flpid}' airac = flp['cycle']['ident'] global fltplan_id fltplan_id = flpid i = 1 route = f'***{dep_icao}***' route += ' ' + '[SID]' while i <= wpt_num: if flp['route']['nodes'][i]['ident'] != f'{arr_icao}': if flp['route']['nodes'][i]['ident'] == flp['route']['nodes'][ i + 1]['ident']: i += 1 continue elif flp['route']['nodes'][i]['via'] is None: del flp['route']['nodes'][i]['via'] flp['route']['nodes'][i]['via'] = {} flp['route']['nodes'][i]['via']['ident'] = 'None' if i != 1: if flp['route']['nodes'][i - 1]['via']['ident'] == 'None': route += ' ' + '**DCT**' + ' ' + flp['route'][ 'nodes'][i]['ident'] else: route += ' ' + flp['route']['nodes'][i - 1]['ident'] + ' ' + '**DCT**' + ' ' + \ flp['route']['nodes'][i]['ident'] else: route += ' ' + flp['route']['nodes'][i]['ident'] i += 1 continue elif flp['route']['nodes'][i]['via']['ident'] != flp['route'][ 'nodes'][i - 1]['via']['ident']: if flp['route']['nodes'][i - 1]['via']['ident'] == 'None': route += ' ' + '**DCT**' + ' ' + flp['route']['nodes'][i]['ident'] + ' ' + '**' + \ flp['route']['nodes'][i]['via']['ident'] + '**' else: route += ' ' + flp['route']['nodes'][i][ 'ident'] + ' ' + '**' + flp['route']['nodes'][i][ 'via']['ident'] + '**' i += 1 continue else: i += 1 else: route += ' ' + flp['route']['nodes'][ i - 1]['ident'] + ' ' + '[STAR]' + ' ' route += f'***{arr_icao}***' break base_url = 'https://www.flightplandatabase.com/plan/{fltplan_id}/download/' flp_embed = discord.Embed( title=f"Here's your flight plan: **{dep_icao} → {arr_icao}**", description=f"Flight plan: {route}") flp_embed.set_thumbnail( url= 'https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif' ) flp_embed.add_field(name='Departure Airport:', value=dep_name) flp_embed.add_field(name='Arrival Airport:', value=arr_name) flp_embed.add_field(name='Distance / Cruise Altitude:', value=f'{dist}nm/{cr_alt}ft') flp_embed.add_field( name='Downloads:', value= f'[X-PLane 11]({base_url}xplane11) | [X-Plane 10/9]({base_url}xplane) | [FSX]({base_url}fsx) | [FS9]({base_url}fs9) | [PMDG]({base_url}pmdg) | [PDF]({base_url}pdf)' ) flp_embed.add_field(name='Link to full flight plan:', value=link) flp_embed.set_footer( text= f'Using data from the Flight Plan Database (https://flightplandatabase.com), AIRAC Cycle: {airac[3:]}' ) print('Success!') # await message1.delete() await ctx.send(embed=flp_embed) @cog_ext.cog_slash( name='checklist', description='Returns checklist for supported a aircraft', options=[ manage_commands.create_option( name='plane', description='Required aircraft ICAO code', option_type=3, required=False) ]) async def checklist(self, ctx: SlashContext, plane='avail'): # prfx = get_prefix(client=self, message=ctx.message) prfx = '/' if plane == 'avail': avplanes = ', '.join(avail_checklists) await ctx.send( f'Checklists are currenly available for these planes: **{avplanes}**' ) elif len(plane) != 4: await ctx.send( f"You must input a correct 4 character ICAO code for your plane, check available checklists with {prfx}checklist (empty argument)" ) elif plane.upper() in avail_checklists: clfile = discord.File(f'./Utils/Checklists/{plane.upper()}.pdf') await ctx.send( content= f"Here's your requested checklist for the {plane.upper()}:", files=[clfile]) else: await ctx.send( f"Unfortunately the checklist you requested is not available, check a list of available checklists with {prfx}checklist (empty argument)" ) # @cog_ext.cog_slash(name='download', # description='Downloads a generated FMS plan in a given format, requires a flight plan to be created (/flightplan)', # options=[manage_commands.create_option( # name='sim_type', # description='Required file format for the flight plan, leave blank for a list of options', # option_type=3, # required=False)], # guild_ids=guild_ids) # async def download(self, ctx: SlashContext, sim_type='None'): # # # prfx = get_prefix(client=self, message=ctx.message) # prfx = '/' # # if fltplan_id == 0: # await ctx.send(f'You need to first create a flight plan with {prfx}flightplan') # return # elif sim_type.lower() not in correct_sim_types: # await ctx.send( # 'You need to specify a correct file format, supported formats are: xplane11 [X-Plane 11], xplane [X-Plane 10], fsx [FSX], fs9 [FS2004], pmdg [PMDG], pdf [PDF]') # return # else: # download_embed = discord.Embed( # title=f'Requested flight plan for {sim_type.upper()}', # description=f'To download the file click [here](https://www.flightplandatabase.com/plan/{fltplan_id}/download/{sim_type.lower()})' # ) # download_embed.set_thumbnail( # url='https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif') # download_embed.set_footer(text=f'Using data from the Flight Plan Database (https://flightplandatabase.com)') # await ctx.send(embed=download_embed) @cog_ext.cog_slash( name='info', description='Fetches information for given airport ICAO', options=[ manage_commands.create_option( name='icao', description='Required airport ICAO code', option_type=3, required=True) ]) @commands.command() async def info(self, ctx: SlashContext, icao: str = 'NO INPUT'): await ctx.defer() if len(icao) != 4: await ctx.send("Please input a correct ICAO code") return request = requests.get( f'https://api.flightplandatabase.com/nav/airport/{icao.upper()}') if request.status_code != 200: print( f'Failed to fetch info for {icao.upper()}, error {request.status_code}' ) return await ctx.send( f"Error {request.status_code} while retrieving info for {icao.upper()}, either the website is down or the airport you chose is not available ```{request.json()['message']}```" ) else: info = request.json() # with open('./Utils/info.json', 'w') as f: # json.dump(info, f, indent=4) json_icao = info['ICAO'] iata = info['IATA'] name = info['name'] lat: float = info["lat"] lon: float = info["lon"] runway_int = info['runwayCount'] elevation = int(info['elevation']) mag_var = round(info['magneticVariation'], 2) timezone = info['timezone']['name'] metar = info['weather']['METAR'] taf = info['weather']['TAF'] offset = str(info['timezone']['offset'] / 3600) offset = offset.replace('.', ':') offset += '0' if -10 < info['timezone']['offset'] / 3600 < 10: if '-' not in offset: offset = '+0' + offset else: offset = list(offset) del offset[0] offset = "".join(offset) offset = '-0' + offset if '-' not in offset and '+' not in offset: offset = '+' + offset offset = list(offset) if len(offset) == 7: del offset[6] if offset[4] != 0: if offset[4] == '5': offset[4] = '3' elif offset[4] == '7': offset[4] = '4' offset = "".join(offset) epoch = datetime.datetime.now().timestamp() local = epoch + info['timezone']['offset'] utc = datetime.datetime.fromtimestamp(epoch).strftime( '%d-%m-%Y %H:%M:%S') local = datetime.datetime.fromtimestamp(local).strftime( '%d-%m-%Y %H:%M:%S') marker_outline = CircleMarker((lon, lat), 'white', 18) marker = CircleMarker((lon, lat), '#0036FF', 12) m = StaticMap( 500, 300, 10, 10, url_template= 'https://tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png') m.add_marker(marker_outline) m.add_marker(marker) image = m.render(zoom=13) image.save('Utils/info.png') info_embed = discord.Embed(title=f'{json_icao} - {iata}', description=name, colour=discord.Colour.from_rgb( 97, 0, 215)) runways = '' i = 0 # j = 0 if runway_int == 1: runways += f"{info['runways'][i]['ends'][0]['ident']} / {info['runways'][i]['ends'][1]['ident']}" len_width = f"{int(info['runways'][0]['length'])}ft x {int(info['runways'][0]['width'])}ft" hdg = int(info['runways'][0]['bearing']) if hdg + 180 > 360: rwy_hdg = f'{hdg} - {hdg - 180}' else: rwy_hdg = f'{hdg}°/{hdg + 180}°' info_embed.add_field(name='Runways:', value=runways) info_embed.add_field(name='Airport Elevation:', value=f'{str(elevation)}ft') info_embed.add_field(name='Magnetic Variation:', value=f'{str(mag_var)}°') info_embed.add_field(name='Timezone:', value=f'{offset} UTC, {timezone}') # for ils in info['runways'][i]['navaids']: # if ils == "LOC-ILS": # print(info['runways'][i]['navaids'][j]['name']) # break # else: # j += 1 img = Image.open('Utils/info.png') draw = ImageDraw.Draw(img) font = ImageFont.truetype('./Utils/font.ttf', 25) draw.text((0, 275), f'{runways} - {len_width} - {rwy_hdg}', fill=(0, 0, 0), font=font) img.save('Utils/info_done.png') else: img = Image.open('Utils/info.png') draw = ImageDraw.Draw(img) font = ImageFont.truetype('./Utils/font.ttf', 20) while i < runway_int: px = 280 - i * 19 curr_rwy = f"{info['runways'][i]['ends'][0]['ident']} / {info['runways'][i]['ends'][1]['ident']}" runways += f"{info['runways'][i]['ends'][0]['ident']} / {info['runways'][i]['ends'][1]['ident']} - " len_width = f"{int(info['runways'][i]['length'])}ft x {int(info['runways'][i]['width'])}ft" draw.text((0, px), f'{curr_rwy} - {len_width}', (0, 0, 0), font=font) i += 1 info_embed.add_field(name='Runways:', value=runways[:-3]) info_embed.add_field(name='Airport Elevation:', value=f'{str(elevation)}ft') info_embed.add_field(name='Magnetic Variation:', value=f'{str(mag_var)}°') info_embed.add_field(name='Timezone:', value=f'{offset} UTC, {timezone}') img.save('Utils/info_done.png') info_embed.add_field(name='Zulu/Local Time:', value=f'Zulu: {utc}\nLocal: {local}') info_embed.add_field(name='METAR:', value=metar) info_embed.add_field(name='TAF:', value=taf) info_embed.set_image(url='attachment://info_done.png') info_embed.set_footer( text= f'Using data from the Flight Plan Database (https://flightplandatabase.com), check the full weather for this airport with /metar {icao.upper()}' ) file = discord.File('Utils/info_done.png') await ctx.send(embed=info_embed, file=file) @cog_ext.cog_slash(name='notam', description='Fetches NOTAMs for given airport ICAO', options=[ manage_commands.create_option( name='icao', description='Required airport ICAO code', option_type=3, required=True), manage_commands.create_option( name='page', description='Required airport ICAO code', option_type=4, required=False) ]) @commands.command() async def notam(self, ctx: SlashContext, icao: str = 'NO INPUT', page=1): if len(icao) != 4: return await ctx.send("Please input a correct ICAO code") if not isinstance(page, int): return await ctx.send('Please insert a number for the embed page') request = requests.get( f'https://api.autorouter.aero/v1.0/notam?itemas=["{icao.upper()}"]&offset=0&limit=200' ) if request.status_code != 200: print( f'Failed to fetch info for {icao.upper()}, error {request.status_code}' ) return await ctx.send( f"Error {request.status_code} while retrieving NOTAMs for {icao.upper()}, either the website is down or the airport you chose is not available" ) else: notam = request.json() notamemb = discord.Embed( title=f'NOTAM list for **{icao.upper()}**', description=f"Number of active NOTAMs: {notam['total']}", colour=discord.Colour.from_rgb(97, 0, 215)) # with open('./Utils/notam.json', 'w') as f: # json.dump(notam, f, indent=4) total = notam['total'] numb = 0 page -= 1 i = page * 5 for _ in notam['rows']: numb += 1 total_pages = math.ceil(total / 5) if total_pages == 0: return await ctx.send( f'No NOTAMs were found for {icao.upper()}!') if page + 1 > total_pages: return await ctx.send( f'Please select a page number between 1 and {total_pages}') try: while page * 5 <= i < (page * 5) + 5: lon = (notam['rows'][i]['lon'] * 90) / (1 << 30) lat = (notam['rows'][i]['lat'] * 90) / (1 << 30) radius = str(notam['rows'][i]['radius']) lon_str = str(int(abs(lon))) lat_str = str(int(abs(lat))) if len(radius) < 3: radius = '0' + radius if len(radius) < 3: radius = '0' + radius if len(lon_str) == 2: lon_str = '0' + lon_str elif len(lon_str) == 1: lon_str = '00' + lon_str elif len(lat_str) == 1: lat_str = '0' + lat_str if lon < 0: lon = abs(lon) lon_str += str(int(round((lon - int(lon)) * 60, 0))) lon_str += 'W' else: lon_str += str(int(round((lon - int(lon)) * 60, 0))) lon_str += 'E' if lat < 0: lat = abs(lat) lat_str += str(int(round((lat - int(lat)) * 60, 0))) lat_str += 'S' else: lat_str += str(int(round((lat - int(lat)) * 60, 0))) lat_str += 'N' coordinates = lat_str + lon_str + radius first_line = str(notam['rows'][i]['series']) + str( notam['rows'][i]['number']) + '/' + str( notam['rows'][i]['year']) + ' ' + 'NOTAM' + str( notam['rows'][i]['type']) + ' ' if notam['rows'][i]['lower'] == 0: notam['rows'][i]['lower'] = '000' line_q = 'Q) ' + notam['rows'][i]['fir'] + '/' + notam['rows'][i]['code23'] + notam['rows'][i][ 'code45'] + '/' + notam['rows'][i]['traffic'] + '/' + notam['rows'][i]['purpose'] + '/' + \ notam['rows'][i]['scope'] + '/' + str(notam['rows'][i]['lower']) + '/' + str( notam['rows'][i]['upper']) + '/' + coordinates if notam['rows'][i]['estimation'] is not None: line_abc = f'A) {icao.upper()}' + ' B) ' + datetime.datetime.fromtimestamp( notam['rows'][i]['startvalidity']).strftime( '%Y-%m-%d %H:%M' ) + ' C) ' + datetime.datetime.fromtimestamp( notam['rows'][i]['endvalidity']).strftime( '%Y-%m-%d %H:%M' ) + ' ' + notam['rows'][i]['estimation'] else: line_abc = f'A) {icao.upper()}' + ' B) ' + datetime.datetime.fromtimestamp( notam['rows'][i]['startvalidity']).strftime( '%Y-%m-%d %H:%M' ) + ' C) ' + datetime.datetime.fromtimestamp( notam['rows'][i]['endvalidity']).strftime( '%Y-%m-%d %H:%M') if notam['rows'][i]['referredseries'] is not None: first_line += str( notam['rows'][i]['referredseries']) + str( notam['rows'][i]['referrednumber'] ) + '/' + str(notam['rows'][i]['referredyear']) notamemb.add_field( name= f"{notam['rows'][i]['id']} | Modified at {datetime.datetime.fromtimestamp(notam['rows'][i]['modified']).strftime('%Y-%m-%d %H:%M')}", value=f'{first_line}\n' f'{line_q}\n' f'{line_abc}\n' f"E) {notam['rows'][i]['iteme']}", inline=False) i += 1 except IndexError: print('index') notamemb.set_thumbnail( url= 'https://cdn.discordapp.com/attachments/356779184393158657/729351510974267513/plane-travel-icon-rebound2.gif' ) notamemb.set_footer( text= f'Page {page + 1} of {total_pages}, use /notam {icao.upper()} [page number] to select different pages' ) try: await ctx.send(embed=notamemb) except discord.HTTPException: await ctx.send( f'Unfortunately this page has more characters than the max allowed limit of 2000, please try with a different ICAO or a different page' ) @cog_ext.cog_slash( name='simbrief', description='Returns the last flight plan created in SimBrief', options=[ manage_commands.create_option(name='username', description='Your username', option_type=3, required=True) ]) async def simbrief(self, ctx: SlashContext, username: str): request = requests.get( f'https://www.simbrief.com/api/xml.fetcher.php?username={username}&json=1' ) if request.status_code == 400: print( f'Failed to fetch latest flight plan for {username}, error {request.status_code}' ) error = request.json() return await ctx.send( f"Error {request.status_code} while retrieving flight plan for {username}, make sure you entered a correct username ```{error['fetch']['status']}```" ) else: info = request.json() # with open('./Utils/simbrief.json', 'w') as f: # json.dump(info, f, indent=4) # print(info) i = 0 toc = False for _ in info: if info['navlog']['fix'][i]['name'] == 'TOP OF CLIMB': toc = True break else: i += 1 desc = f"Generated at: **{datetime.datetime.fromtimestamp(int(info['params']['time_generated'])).strftime('%H:%M %Y-%m-%d')}** | AIRAC: **{info['params']['airac']}** | Units: **{info['params']['units']}**\n\n" \ f"FL STEPS: **{info['general']['stepclimb_string']}**\n\n" \ f"ROUTE: **{info['origin']['icao_code']}/{info['origin']['plan_rwy']}** {info['general']['route']} **{info['destination']['icao_code']}/{info['destination']['plan_rwy']}**" fuel = f"TRIP {info['fuel']['enroute_burn']}\n" \ f"CONT {info['fuel']['contingency']}\n" \ f"ALTN {info['fuel']['alternate_burn']}\n" \ f"FINRES {info['fuel']['reserve']}\n" \ f"EXTRA {info['fuel']['extra']}\n" \ f"TAXI {info['fuel']['taxi']}\n" \ f"BLOCK FUEL {info['fuel']['plan_ramp']}\n" payload = f"PAX {info['weights']['pax_count']}\n" \ f"CARGO {round((int(info['weights']['cargo']) / 1000), 1)}\n" \ f"PAYLOAD {round((int(info['weights']['payload']) / 1000), 1)}\n" \ f"ZFW {round((int(info['weights']['est_zfw']) / 1000), 1)}\n" \ f"FUEL {round((int(info['fuel']['plan_ramp']) / 1000), 1)}\n" \ f"TOW {round((int(info['weights']['est_tow']) / 1000), 1)}\n" \ f"LAW {round((int(info['weights']['est_ldw']) / 1000), 1)}\n" if toc: general = f"Cost Index: {info['general']['cruise_profile']}\n" \ f"Route Distance: {info['general']['route_distance']}nm\n" \ f"Average Wind: {info['general']['avg_wind_dir']}°/{info['general']['avg_wind_comp']}kt\n" \ f"Aircraft: {info['aircraft']['name']}\n" \ f"Est. Time Enroute: {round((int(info['times']['est_time_enroute']) / 3600), 2)}hrs\n" \ f"TOC Conditions: {info['navlog']['fix'][i]['wind_dir']}°/{info['navlog']['fix'][i]['wind_spd']}kt | OAT: {info['navlog']['fix'][i]['oat']} | ISA DEV: {info['navlog']['fix'][i]['oat_isa_dev']}\n" else: general = f"Cost Index: {info['general']['cruise_profile']}\n" \ f"Route Distance: {info['general']['route_distance']}\n" \ f"Average Wind: {info['general']['avg_wind_dir']}°/{info['general']['avg_wind_comp']}kt\n" \ f"Aircraft: {info['aircraft']['name']}\n" \ f"Est. Time Enroute: {info['times']['est_time_enroute']}\n" directory = info['files']['directory'] files = f"[X-Plane 11]({directory}{info['fms_downloads']['xpe']['link']}) | [MSFS 2020]({directory}{info['fms_downloads']['mfs']['link']}) | " \ f"[FSX/P3D]({directory}{info['fms_downloads']['fsx']['link']}) | [PMDG]({directory}{info['fms_downloads']['pmr']['link']})" sb_embed = discord.Embed( title= f"Retrieved SimBrief flight plan: **{info['origin']['icao_code']} → {info['destination']['icao_code']}** ALTN: {info['alternate']['icao_code']}", description=desc, colour=discord.Colour.from_rgb(97, 0, 215)) # sb_embed.set_thumbnail( # url="https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif") sb_embed.set_footer( text= 'If you prefer to keep your username private, you can use this command in a private chat' ) sb_embed.add_field(name='Fuel:', value=fuel) sb_embed.add_field(name='Weights:', value=payload) sb_embed.add_field(name='Info:', value=general) sb_embed.add_field(name='Departure METAR:', value=info['weather']['orig_metar'], inline=False) sb_embed.add_field(name='Destination METAR:', value=info['weather']['dest_metar'], inline=False) sb_embed.add_field(name='FMC Files:', value=files, inline=False) try: sb_embed.set_image( url= f"{info['images']['directory']}{info['images']['map'][0]['link']}" ) except Exception as err: print(err) await ctx.send(embed=sb_embed) return print('Sent SimBrief flight plan')
class RussianRoulette(commands.Cog): def __init__(self, bot): self.bot = bot def players_description(self, players): desc = "\n" for i, player in enumerate(players, start=1): desc += f"{i}. {str(player.member)}\n" return desc async def handle_reactions(self, ctx: SlashContext, msg: discord.Message, player: discord.Member): try: reaction, user = await self.bot.wait_for( "reaction_add", check=lambda react, usr: react.message.id == msg.id and usr == player, timeout=30) kill_decision = EmojiUtils.get_emoji_value(reaction.emoji) return kill_decision except asyncio.TimeoutError: # Gdy nie zdąży dodać reakcji - 30 sekund await ctx.send(embed=discord.Embed( title="⏰ Upływ czasu ⏰", description= f"{player.mention} nie zdążył strzelić!\nZa kare dostał kulkę od barmana", color=discord.Color.red())) return -1 @cog_ext.cog_slash(name="rr", description="Rosyjska ruletka", guild_ids=guild_ids, options=[ manage_commands.create_option( name="bet", description="Wartość zakładu", option_type=SlashCommandOptionType.INTEGER, required=True) ]) async def __rr(self, ctx: SlashContext, bet: int): if bet <= 0: return start_embed = discord.Embed( title="Rosyjska ruletka", description= f"Czy podejmiesz się wyzwaniu?\nKliknij 🔫 aby dołączyć\n🏁 aby wystartować\nKoszt wstępu: `{bet}` chillcoinsów", color=discord.Color.red()) start_embed.set_image(url=self.bot.user.avatar_url) start_embed.set_footer( text=f"Komenda wyłołana przez {ctx.author.name}", icon_url=ctx.author.avatar_url) start_message: discord.Message = await ctx.send(embed=start_embed) await start_message.add_reaction("🔫") await start_message.add_reaction("🏁") try: await self.bot.wait_for( "reaction_add", check=lambda react, usr: usr == ctx.author and str(react.emoji) == "🏁" and react.message.id == start_message.id, timeout=120) except asyncio.TimeoutError: await ctx.send(embed=discord.Embed( title="Upływ czasu", description= f"Upłynął czas na dodanie 🏁 przez {ctx.author.name}", color=discord.Color.red()), delete_after=20) await start_message.delete() start_message: discord.Message = await ctx.fetch_message( start_message.id) players: List[Player] = [ Player(player) for player in await start_message.reactions[0].users().flatten() if player.display_name != self.bot.user.display_name ] if len(players) <= 1: return for player in players: member: TeinfMember = db_session.query(TeinfMember).filter_by( discordId=player.id).first() money = member.money if money < bet: players.remove(player) await player.member.send( "Niestety nie możesz zagrać w rosyjską ruletkę - masz za mało pieniędzy! - {}" .format(money)) else: member.money -= bet if len(players) <= 1: return random.shuffle(players) start_players_amount = len(players) revolver = Gun(ctx) while len(players) > 1: for player in players: embed = discord.Embed( title="🤔 Wybór 🤔", description= f"{player.member.mention}\n1. Strzał w siebie\n2. Strzał w innego", color=discord.Color.purple()) embed.set_footer(text=f"{str(player.member)}", icon_url=player.member.avatar_url) msg = await ctx.send(embed=embed, delete_after=20) await EmojiUtils.add_digits(msg, 2) kill_decision = await self.handle_reactions( ctx, msg, player.member) if kill_decision == -1: players.remove(player) elif kill_decision == 1: # strzelanie w siebie target = player target_killed = await player.shot(ctx, target, revolver, self_shot=True) if target_killed: players.remove(target) elif kill_decision == 2: message = await ctx.send(embed=discord.Embed( title="Strzał!", description= f"{player.member.mention} wybierz osobę w którą chcesz strzelić" + self.players_description(players), color=discord.Color.green())) await EmojiUtils.add_digits(message, len(players)) response = await self.handle_reactions( ctx, message, player.member) target = players[response - 1] target_killed = await player.shot(ctx, target, revolver) if not target_killed: await ctx.send(embed=discord.Embed( title="Strzał w siebie", description= f"{player.member.mention} niestety teraz musisz strzelać do siebie...", color=discord.Color.red())) target = player target_killed = await player.shot(ctx, target, revolver, self_shot=True) if target_killed: players.remove(target) else: players.remove(target) winning_player = players[0] embed = discord.Embed( title="🏆 Wygrana! 🏆", description=f"Gratulacje {winning_player} wygrałeś rozgrywkę!", color=discord.Color.green()) money_gained = start_players_amount * bet exp_gained = money_gained // 2 embed.set_footer(text=f"+{money_gained}cc, +{exp_gained}exp") await ctx.send(embed=embed) winning_player: TeinfMember = db_session.query(TeinfMember).filter_by( discordId=winning_player.id).first() winning_player.money += money_gained winning_player.exp += exp_gained
class Music(commands.Cog): def __init__(self, bot: commands.Bot): global pillow_installed # aiya global eyed3_installed # aiya x2 self.bot = bot self.log = bot.log self.voice_state = VoiceState(self.bot) # read configuration self.log.debug("Reading music configuration") if "music" in bot.config.config: conf = bot.config.config["music"] self.root_path = conf.get("MusicPath", fallback="/media/Moosic") self.show_song_status = conf.getboolean( "CurrentSongAsStatus", fallback=False ) ignored_paths = conf.get("IgnoredPaths", fallback="").split(",") self.ignored_paths = ignored_paths if ignored_paths[0] != "" else [] pillow_installed = conf.getboolean("DominantColorEmbed", pillow_installed) eyed3_installed = conf.getboolean("Id3Metadata", eyed3_installed) else: self.root_path = "/media/Moosic" self.show_song_status = False # process all songs self.get_files() def get_files(self): self.songs = [] self.log.info(f"Searching for songs from {self.root_path}.") ignored: int = 0 for root, _, files in os.walk(self.root_path): for name in files: if name.endswith(".mp3"): for query in self.ignored_paths: if query in root: ignored += 1 break else: try: self.songs.append(Song(os.path.join(root, name), self.log)) except IOError: # expected if file not found pass self.log.info(f"Found {len(self.songs)} songs, ignored {ignored}.") async def get_voice_state(self, ctx): await self.voice_state.connect(ctx) def find_songs(self, query) -> list: args = query.lower().split() sources = [] for song in self.songs: for q in args: if not (q in song.path_lower or q in song.get_name().lower()): break else: sources.append(song) return sources @cog_ext.cog_slash( name="play", description="Play a moosic", options=[ manage_commands.create_option( name="query", description="Tags to search for", option_type=3, required=False, ), manage_commands.create_option( name="number", description="Song number from search, or 0 for all songs that match search", option_type=4, required=False, ), ], guild_ids=DEBUG_GUILDS, ) @commands.command() async def play( self, ctx, query="", number: int = 1, play_random: bool = False, show_lyrics: bool = True, ): await self._play(ctx, query, number, play_random, show_lyrics) async def _play( self, ctx, query="", number: int = 1, play_random: bool = False, show_lyrics: bool = True, return_to_function: bool = False, ) -> list: # treat numbers <= 0 as play all play_all = number <= 0 if query and not play_random: # if there is a query try: sources = self.find_songs(query) if not play_all: sources = [sources[number - 1]] except IndexError: return await ctx.send( f"No songs matching '{query}' were found at the specified index." ) else: # if query is empty play a random song if play_all: sources = self.songs.copy() else: sources = [random.choice(self.songs)] # if there's only one it doesn't matter if more we want to shuffle them random.shuffle(sources) try: await self.get_voice_state(ctx) except AttributeError: print(traceback.format_exc()) return await ctx.send("You are not in a voice channel.") if return_to_function: return sources for s in sources: await self.voice_state.add(s, lyrics=show_lyrics) if len(sources) > 1: await ctx.send(f"Added {len(sources)} songs to the queue.") else: await ctx.send(f"Added **{sources[0].get_name()}** to the queue.") @cog_ext.cog_slash( name="playnow", description="Play a moosic now", options=[ manage_commands.create_option( name="query", description="Tags to search for", option_type=3, required=False, ), manage_commands.create_option( name="number", description="Song number from search, or 0 for all songs that match search", option_type=4, required=False, ), ], guild_ids=DEBUG_GUILDS, ) @commands.command(name="playnow") async def play_now( self, ctx, query="", number: int = 1, play_random: bool = False, show_lyrics: bool = True, ): sources = await self._play( ctx, query, number, play_random, show_lyrics, return_to_function=True ) for s in sources: await self.voice_state.add(s, True, show_lyrics) if len(sources) > 1: await ctx.send( f"Playing **{sources[0].get_name()}**, added {len(sources)-1} songs to the queue." ) else: await ctx.send(f"Playing **{sources[0].get_name()}**.") await self.voice_state.skip() @cog_ext.cog_slash( name="playnext", description="Play a moosic right after", options=[ manage_commands.create_option( name="query", description="Tags to search for", option_type=3, required=False, ), manage_commands.create_option( name="number", description="Song number from search, or 0 for all songs that match search", option_type=4, required=False, ), ], guild_ids=DEBUG_GUILDS, ) async def play_next( self, ctx, query="", number: int = 1, play_random: bool = False, show_lyrics: bool = True, ): sources = await self._play( ctx, query, number, play_random, show_lyrics, return_to_function=True ) for s in sources: await self.voice_state.add(s, True, show_lyrics) if len(sources) > 1: await ctx.send(f"Added {len(sources)} songs to the queue.") else: await ctx.send(f"Added **{sources[0].get_name()}** to the queue.") @cog_ext.cog_slash( name="skip", description="Skip a number of tracks (default 1)", options=[ manage_commands.create_option( name="number", description="The number of tracks to skip / the track number to skip to", option_type=4, required=False, ) ], guild_ids=DEBUG_GUILDS, ) async def skip(self, ctx, number: int = 1): await self.voice_state.skip(number) await ctx.send("Skipped track.") @cog_ext.cog_slash( name="search", description="Searches local files for music", options=[ manage_commands.create_option( name="query", description="Query to search for in tags", option_type=3, required=True, ), manage_commands.create_option( name="page", description="Page number to show", option_type=4, required=False, ), ], guild_ids=DEBUG_GUILDS, ) async def search(self, ctx, query, page: int = 1): page -= 1 sources = self.find_songs(query) offset = page * ITEMS_PER_PAGE if len(sources) < offset: return await ctx.send(f"Page not found for query '{query}'.") embed = discord.Embed(title=f"Moosic containing '{query}'", description="") for i, n in enumerate(sources[offset : offset + ITEMS_PER_PAGE]): embed.description += ( f"{offset+i+1}. {n.get_name()}{' [LRC]' if n.lyrics else ''}\n" ) embed.description += ( f"\nPage {page+1} of {math.ceil(len(sources) / ITEMS_PER_PAGE)}" ) await ctx.send(embed=embed) @cog_ext.cog_slash( name="stop", description="Stop playback and disconnect", options=[], guild_ids=DEBUG_GUILDS, ) async def stop(self, ctx): await self.voice_state.stop() await ctx.send("Goodbye!") @cog_ext.cog_slash( name="clear", description="Clear the queue", options=[], guild_ids=DEBUG_GUILDS ) async def clear_queue(self, ctx): self.voice_state.queue.clear() await ctx.send("Cleared the queue!") @cog_ext.cog_slash( name="queue", description="Show the queue", options=[ manage_commands.create_option( name="page", description="The page number to view", option_type=4, required=False, ) ], guild_ids=DEBUG_GUILDS, ) async def show_queue(self, ctx, page: int = 1): page -= 1 if len(self.voice_state.queue) < 1: return await ctx.send("Nothing in the queue on this page.") offset = page * ITEMS_PER_PAGE embed = discord.Embed(title="Queue", description="") for i, s in enumerate(self.voice_state.queue[offset : offset + ITEMS_PER_PAGE]): embed.description += ( f"{offset+i+1}. {s[0].get_name()}{' [LRC]' if s[0].lyrics else ''}\n" ) embed.description += f"\nPage {page+1} of {math.ceil(len(self.voice_state.queue) / ITEMS_PER_PAGE)}" await ctx.send(embed=embed)
class Admin(commands.Cog): def __init__(self, bot): self.bot = bot @commands.command(brief='Turns on/off my Master\'s PC') async def power(self, ctx, arg=None): await self._power(ctx, arg) @cog_ext.cog_slash( name="power", description='Turns on/off my Master\'s PC', #guild_ids=[207481917975560192, 572648167573684234], options=[ manage_commands.create_option( name="arg", description="\"on\" to switch on, \"off\" to switch off", option_type=3, required=True, choices=[ create_choice(name="On", value="on"), create_choice(name="Off", value="off") ]), ], ) async def powers(self, ctx: SlashContext, arg: str): await self._power(ctx, arg) async def _power(self, ctx, arg: str): logger.debug("PRE: {}".format(ctx)) try: if not arg: if isinstance(ctx, discord.ext.commands.context.Context): await ctx.send('```Usage:(ADMIN ONLY)\n' '{}power on : to switch on PC\n' '{}power off : to shutdown PC\n```'.format( COMMAND_PREFIX, COMMAND_PREFIX)) elif arg.lower() == "on": if ctx.author.id == int(ADMIN_ID): ''' api way ''' ''' session = aiohttp.ClientSession() data = {"action": "on"} api_path = os.path.join(ROOT_DIR, "keys/api") try: # read API endpoint from file # with open(api_path) as f: # pc_api = f.read().strip() # res = await session.post(pc_api, data=json.dumps(data), headers={'content-type': 'application/json'}) # await session.close() await ctx.send('```Done```') except Exception as e: logger.exception(e) ''' ''' direct call ''' master_mac_path = os.path.join(ROOT_DIR, "keys/master_mac") with open(master_mac_path) as f: master_mac = f.read().strip() logger.debug("Powering on PC") os.system("wakeonlan {}".format(master_mac)) await ctx.send("```Powering on PC```") else: await ctx.send("```Only my master can use this command```") elif arg.lower() == "off": admin_id_path = os.path.join(ROOT_DIR, "keys/admin_id") with open(admin_id_path) as f: admin_id = f.read().strip() if ctx.author.id == int(admin_id): master_ip_path = os.path.join(ROOT_DIR, "keys/master_ip") with open(master_ip_path) as f: master_ip = f.read().strip() logger.debug("Shutting down PC") os.system("ssh preetham@{} shutdown /s".format(master_ip)) await ctx.send('```Shutting down PC```') else: await ctx.send('```Only my master can use this command.```' ) else: await ctx.send('```Invalid entry```') if isinstance(ctx, discord.ext.commands.context.Context): await ctx.send('```Usage:(ADMIN ONLY)\n' '{}power on : to switch on PC\n' '{}power off : to shutdown PC\n```'.format( COMMAND_PREFIX, COMMAND_PREFIX)) except Exception as e: logger.exception(e) await ctx.send('```Zzzzz```') @commands.command(brief='', hidden=True) async def post(self, ctx, *args): if args[0] == 'gb': channel = self.bot.get_channel(TEST2_CHANNEL_ID) message = ' '.join(args[1:]) elif args[0] == 'test': channel = self.bot.get_channel(TEST_CHANNEL_ID) message = ' '.join(args[1:]) else: channel = self.bot.get_channel(GENERAL_CHANNEL_ID) message = ' '.join(args) logger.debug("{} {}".format(len(args), message)) await channel.send(message) @commands.command(brief='Shows my host hardware-software info') async def sysinfo(self, ctx): await self._sysinfo(ctx) @cog_ext.cog_slash( name="sysinfo", description='Shows my host hardware-software info', #guild_ids=[207481917975560192, 572648167573684234], ) async def sysinfos(self, ctx: SlashContext): await self._sysinfo(ctx) async def _sysinfo(self, ctx): try: if ctx.author.id == int(ADMIN_ID): # wait_message = await ctx.send("Processing... Please wait. This might take sometime") # async with ctx.typing(): embed = discord.Embed( title="System Info", description="Showing my host hardware/software information", colour=discord.Color.gold()) embed.set_footer(text="Hope that was helpful, bye!") embed.set_author(name="Bro Bot", icon_url=self.bot.user.avatar_url) embed.set_thumbnail(url=ctx.guild.icon_url) result = subprocess.Popen(['neofetch', '--stdout'], stdout=subprocess.PIPE) for line in result.stdout: line = line.decode('utf-8').strip('\n').split(':') if len(line) == 2: if line[0] == "OS" or line[0] == "Host": embed.add_field(name=line[0], value=line[1], inline=False) else: embed.add_field(name=line[0], value=line[1], inline=True) # Raspberry Pi Only!!! if os.uname()[1] == "raspberrypi": temp = subprocess.Popen( ['/opt/vc/bin/vcgencmd', 'measure_temp'], stdout=subprocess.PIPE) for line in temp.stdout: line = line.decode('utf-8').strip('\n').split('=') if len(line) == 2: embed.add_field(name="CPU Temp", value=line[1], inline=True) url = await get_public_url() embed.add_field(name="Public URL", value=url, inline=False) # await wait_message.edit(content='', embed=embed) await embed_send(ctx, embed) else: await ctx.send('```Only my master can use this command.```') except Exception as e: logger.exception(e) @commands.command(brief='', hidden=True) async def runcmd(self, ctx, *args): logger.debug(args) if ctx.message.author.id == int(ADMIN_ID): try: result = subprocess.Popen(args, stdout=subprocess.PIPE) logger.debug(result.stdout) out = "" for line in result.stdout: out += line.decode('utf-8') logger.debug(out) await ctx.send("```{}```".format(out)) except Exception as e: logger.exception(e) else: await ctx.send('```Only my master can use this command.```')