class Example2(commands.Cog): def __init__(self, bot): self.bot = bot greetings = SlashCommandGroup("greetings", "Various greeting from cogs!") international_greetings = greetings.create_subgroup( "international", "International greetings") secret_greetings = SlashCommandGroup( "secret_greetings", "Secret greetings", permissions=[ CommandPermission( "owner", 2, True ) # Ensures the owner_id user can access this, and no one else ], ) @greetings.command() async def hello(self, ctx): await ctx.respond("Hello, this is a slash subcommand from a cog!") @international_greetings.command() async def aloha(self, ctx): await ctx.respond("Aloha, a Hawaiian greeting") @secret_greetings.command() async def secret_handshake(self, ctx, member: discord.Member): await ctx.respond(f"{member.mention} secret handshakes you")
class RepCommands(Cog): def __init__(self, bot): self.bot = bot repGroup = SlashCommandGroup('rep', 'Give out reputation points') @repGroup.command(name='lead', description='Rep leaderboards!') async def leaderboard(self, ctx): formatted = '\n'.join([f'{rank}: {details[0]} ({details[1]} points)' for rank, details in enumerate(leader_list(await ctx.guild.fetch_members().flatten()), start=1)]) embed = Embed(title='Current Rep Leaderboard:', description=formatted) await ctx.respond('', embed=embed) @repGroup.command(name='give', description='Give a reputation point!') async def give_rep(self, ctx, target: Option(Member, 'Who gets the rep?')): if ctx.user.id == target.id: return await self.rep_check(ctx, target) giver = load_user(ctx.user) if giver.get_pool() > 0: giver.spend_pool() receiver = load_user(target) receiver.received += 1 save_user(giver, ctx.user) save_user(receiver, target) await ctx.respond(f'{ctx.user.mention}, you gave a rep to {target.mention}!') else: await ctx.respond(f'Sorry {ctx.user.mention}, you have no rep to give!', ephemeral=True) @repGroup.command(name='check', description='Check the rep a user has accumulated.') async def rep_check(self, ctx, target: Option(Member, 'Whose rep do you want to view?', required=False)): if target: user = target else: user = ctx.user rep_info = load_user(user) await ctx.respond( f'{user.mention} has received {rep_info.received} rep and has {rep_info.get_pool()} rep available to give!')
class Music(commands.Cog, name="🎵 Muzyka (beta)"): def __init__(self, bot: Atorin): self.bot = bot if self.bot and not hasattr(self.bot, "lavalink"): lavalink.add_event_hook(self.track_hook) self.bot.lavalink = lavalink.Client( config["dashboard"]["client_id"]) self.bot.lavalink.add_node(address, port, password, region, node) self.bot.add_listener(self.bot.lavalink.voice_update_handler, "on_socket_response") def cog_unload(self): """Cog unload handler. This removes any event hooks that were registered.""" self.bot.lavalink._event_hooks.clear() async def cog_before_invoke(self, ctx): """Command before-invoke handler.""" guild_check = ctx.guild is not None # This is essentially the same as `@commands.guild_only()` # except it saves us repeating ourselves (and also a few lines). if guild_check: await self.ensure_voice(ctx) # Ensure that the bot and command author share a mutual voicechannel. return guild_check async def ensure_voice(self, ctx): # These are commands that doesn't require author to join a voicechannel if ctx.command.name in ("lyrics", ): return True """This check ensures that the bot and command author are in the same voicechannel.""" player = self.bot.lavalink.player_manager.create(ctx.guild.id, endpoint=str( ctx.guild.region)) # Create returns a player if one exists, otherwise creates. # These are commands that require the bot to join a voicechannel (i.e. initiating playback). if isinstance(ctx.command, str): should_connect = ctx.command in ("play", ) else: should_connect = ctx.command.name in ("play", ) if not ctx.author.voice or not ctx.author.voice.channel: raise commands.CommandError( "Musisz być połączony do kanału głosowego!") if not player.is_connected: if not should_connect: raise commands.CommandError("Atorin nie odtwarza muzyki!") permissions = ctx.author.voice.channel.permissions_for(ctx.me) if not permissions.connect or not permissions.speak: raise commands.CommandError( "Atorin nie ma uprawnień potrzebnych do odtwarzania muzyki." " Daj roli `Atorin` uprawnienia `Łączenie` oraz `Mówienie`" " i spróbuj ponownie.") player.store("channel", ctx.channel.id) await ctx.author.voice.channel.connect(cls=LavalinkVoiceClient) else: if int(player.channel_id) != ctx.author.voice.channel.id: raise commands.CommandError( "Nie jesteś połączony do kanału na którym jest Atorin!") async def track_hook(self, event): if isinstance(event, lavalink.events.QueueEndEvent): guild_id = int(event.player.guild_id) guild: discord.Guild = self.bot.get_guild(guild_id) player = self.bot.lavalink.player_manager.get(guild_id) if not player.is_connected: return player.queue.clear() await player.stop() await guild.voice_client.disconnect(force=True) if isinstance(event, lavalink.events.TrackStartEvent): song = event.track channel = self.bot.get_channel(event.player.fetch("channel")) embed = discord.Embed() embed.title = "Teraz odtwarzane" embed.add_field(name="🎧 Utwór", value=song.title, inline=False) if not song.duration == 9223372036854775807: embed.add_field( name="🛤️ Długość", value=str( timedelta(milliseconds=song.duration)).split(".")[0], ) else: embed.add_field(name="🛤️ Długość", value="🔴 Na żywo") embed.add_field(name="💃 Zaproponowany przez", value=f"<@{song.requester}>") embed.set_thumbnail( url= f"https://img.youtube.com/vi/{song.identifier}/maxresdefault.jpg" ) await channel.send(embed=embed) @slash_command( description= "Odtwarza utwór lub playlistę z YT/Twitch/MP3 na kanale głosowym", guild_ids=config["guild_ids"], ) async def play( self, ctx: discord.ApplicationContext, query: Option(str, "Tytuł lub link do Youtube/Twitch/MP3"), ): """Searches and plays a song from a given query.""" await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) query = query.strip("<>") if not url_rx.match(query): query = f"ytsearch:{query}" else: if "open.spotify.com/track/" in query: song = get_song_from_spotify( query.split("open.spotify.com/track/")[1].split("?")[0]) query = f"ytsearch:{song}" elif "spotify:track:" in query: song = get_song_from_spotify(query.split("spotify:track:")[1]) query = f"ytsearch:{song}" results = await player.node.get_tracks(query) if not results or not results["tracks"]: return await ctx.send_followup( "❌ Nie znaleziono utworu o podanej nazwie!") embed = discord.Embed() # Valid loadTypes are: # TRACK_LOADED - single video/direct URL) # PLAYLIST_LOADED - direct URL to playlist) # SEARCH_RESULT - query prefixed with either ytsearch: or scsearch:. # NO_MATCHES - query yielded no results # LOAD_FAILED - most likely, the video encountered an exception during loading. if results["loadType"] == "PLAYLIST_LOADED": tracks = results["tracks"] for track in tracks: player.add(requester=ctx.author.id, track=track) embed.title = "Dodano playlistę do kolejki!" embed.description = ( f'{results["playlistInfo"]["name"]} - {len(tracks)} utworów') else: track = results["tracks"][0] embed.title = "Dodano do kolejki" embed.description = f'[{track["info"]["title"]}]({track["info"]["uri"]})' embed.set_thumbnail( url= f"https://img.youtube.com/vi/{track['info']['identifier']}/maxresdefault.jpg" ) track = lavalink.models.AudioTrack(track, ctx.author.id) player.add(requester=ctx.author.id, track=track) await ctx.send_followup(embed=embed) if not player.is_playing: await player.play() @slash_command(description="Rozłącza bota z kanału głosowego", guild_ids=config["guild_ids"]) async def stop(self, ctx: discord.ApplicationContext): """Disconnects the player from the voice channel and clears its queue.""" await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if player.is_playing: player.queue.clear() await player.stop() await ctx.voice_client.disconnect(force=True) embed = discord.Embed() embed.description = "⏹ **Zatrzymano odtwarzanie.**" await ctx.send_followup(embed=embed) else: raise commands.CommandError("Atorin nie odtwarza muzyki!") @slash_command(description="Wstrzymuje odtwarzanie muzyki", guild_ids=config["guild_ids"]) async def pause(self, ctx: discord.ApplicationContext): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if not player.paused: await player.set_pause(True) embed = discord.Embed() embed.description = ( "⏸ **Wstrzymano odtwarzanie. Aby wznowić wpisz `/resume`.**") await ctx.send_followup(embed=embed) else: raise commands.CommandError("Atorin nie odtwarza muzyki!") @slash_command(description="Wznawia odtwarzanie muzyki", guild_ids=config["guild_ids"]) async def resume(self, ctx: discord.ApplicationContext): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if player.paused: await player.set_pause(False) embed = discord.Embed() embed.description = "▶️ **Wznowiono odtwarzanie.**" await ctx.send_followup(embed=embed) else: raise commands.CommandError("Atorin nie odtwarza muzyki!") @slash_command(description="Pomija aktualnie odtwarzany utwór", guild_ids=config["guild_ids"]) async def skip( self, ctx: discord.ApplicationContext, number: Option(int, "Podaj numer utworu który chcesz odtworzyć", min_value=1) = None, ): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if player.is_playing: if number: if number > len(player.queue): raise commands.BadArgument( "Podano niepoprawny numer utworu! Sprawdź kolejkę komendą `/queue view`" ) player.queue = player.queue[number - 1:] await player.skip() embed = discord.Embed() embed.description = "⏭ ️**Pominięto utwór.**" await ctx.send_followup(embed=embed) else: raise commands.CommandError("Atorin nie odtwarza muzyki!") @slash_command( description="Ustawia głośność aktualnie odtwarzanego utworu", guild_ids=config["guild_ids"], ) async def volume( self, ctx: discord.ApplicationContext, vol: Option(int, "Głośność od 1 do 100", min_value=1, max_value=100), ): await ctx.defer() if vol > 100 or vol < 0: raise commands.BadArgument( "Wartość musi być w przedziale od 1 do 100!") player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if player.is_playing: await player.set_volume(vol) embed = discord.Embed() embed.description = f"🔉 **Ustawiono glośność na {vol}%.**" await ctx.send_followup(embed=embed) else: raise commands.CommandError("Atorin nie odtwarza muzyki!") queue_group = SlashCommandGroup( "queue", "Komendy do zarządzania kolejką odtwarzania", guild_ids=config["guild_ids"], ) @queue_group.command( name="view", description="Wyświetla kolejkę utworów do odtworzenia", ) async def queue_view(self, ctx: discord.ApplicationContext): emoji_numbers = { 1: "1️⃣", 2: "2️⃣", 3: "3️⃣", 4: "4️⃣", 5: "5️⃣", 6: "6️⃣", 7: "7️⃣", 8: "8️⃣", 9: "9️⃣", 10: "🔟", } await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) embed = discord.Embed() if not player.queue: embed.description = "🕳️ **Kolejka jest pusta!**" return await ctx.send_followup(embed=embed) fmt = "\n".join(f"{emoji_numbers[i]} **{song.title}**" for i, song in enumerate(player.queue, start=1)) embed.title = f"Utwory w kolejce: {len(player.queue)}" embed.description = fmt await ctx.send_followup(embed=embed) @queue_group.command( name="clear", description="Czyści kolejkę", ) async def queue_clear(self, ctx: discord.ApplicationContext): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) embed = discord.Embed() if not player.queue: embed.description = "🕳️ **Kolejka jest pusta!**" return await ctx.send_followup(embed=embed) embed.title = "Wyczyszczono kolejkę" embed.description = ( f"✅ **Pomyślnie usunięto *{len(player.queue)}* utworów z kolejki.**" ) player.queue = [] await ctx.send_followup(embed=embed) @queue_group.command( name="remove", description="Usuwa z kolejki podany utwór", ) async def queue_remove( self, ctx: discord.ApplicationContext, number: Option(int, "Wpisz numer utworu w kolejce", min_value=1), ): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) embed = discord.Embed() if not player.queue: embed.description = "🕳️ **Kolejka jest pusta!**" return await ctx.send_followup(embed=embed) try: song: lavalink.AudioTrack = player.queue.pop(number - 1) except IndexError: raise commands.BadArgument( "Podano niepoprawny numer utworu! Sprawdź kolejkę komendą `/queue view`" ) embed.title = "Usunięto z kolejki" embed.description = f"🗑 {song.title}" await ctx.send_followup(embed=embed) @slash_command( description="Wyświetla aktualnie odtwarzany utwór", guild_ids=config["guild_ids"], ) async def nowplaying(self, ctx: discord.ApplicationContext): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if player.is_playing: song: lavalink.AudioTrack = player.current embed = discord.Embed() embed.title = "Teraz odtwarzane" embed.add_field(name="🎧 Utwór", value=song.title, inline=False) if not song.duration == 9223372036854775807: duration = str(timedelta(milliseconds=song.duration)) position = str(timedelta( milliseconds=round(player.position))).split(".")[0] progress = progress_bar( round(player.position) / song.duration * 100)[:-5] embed.add_field( name="🛤️ Postęp", value=f"```css\n{progress} {position}/{duration}```", inline=False, ) else: embed.add_field(name="🛤️ Postęp", value="🔴 Na żywo") embed.add_field( name="🔂 Powtarzanie utworu", value="✅ Włączone" if player.repeat else "❌ Wyłączone", ) embed.add_field(name="🔉 Głośność", value=f"{player.volume}%") embed.add_field( name="🎚 Bass Boost", value="✅ Włączony" if player.fetch("bassboost") else "❌ Wyłączony", ) embed.add_field( name="🔀 Losowo", value="✅ Włączony" if player.shuffle else "❌ Wyłączony") embed.add_field( name="💃 Zaproponowany przez", value=f"<@{song.requester}>", ) embed.set_thumbnail( url= f"https://img.youtube.com/vi/{song.identifier}/maxresdefault.jpg" ) await ctx.send_followup(embed=embed) else: raise commands.CommandError("Atorin nie odtwarza muzyki!") @slash_command( description="Ustawia powtarzanie aktualnie odtwarzanego utworu", guild_ids=config["guild_ids"], ) async def loop(self, ctx: discord.ApplicationContext): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if player.repeat: player.repeat = False else: player.repeat = True await ctx.send_followup( f"🔂 Powtarzanie aktualnego utworu zostało {'włączone' if player.repeat else 'wyłączone'}." ) @slash_command(description="Ustawia losowe odtwarzanie kolejki", guild_ids=config["guild_ids"]) async def shuffle(self, ctx: discord.ApplicationContext): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if player.shuffle: player.shuffle = False else: player.shuffle = True await ctx.send_followup( f"🔀 Losowe odtwarzanie kolejki zostało {'włączone' if player.shuffle else 'wyłączone'}." ) @slash_command(description="Bass Boost", guild_ids=config["guild_ids"]) async def bassboost(self, ctx: discord.ApplicationContext): await ctx.defer() player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) equalizer = lavalink.filters.Equalizer() if not player.fetch("bassboost"): bands = [(0, 0.25), (1, 0.25), (2, 0.25)] equalizer.update(bands=bands) await player.set_filter(equalizer) player.store("bassboost", True) else: await player.remove_filter(equalizer) player.store("bassboost", False) await ctx.send_followup( f"🎚 Bass boost został **{'włączony' if player.fetch('bassboost') else 'wyłączony'}**." ) @slash_command(description="Tekst piosenki", guild_ids=config["guild_ids"]) async def lyrics( self, ctx: discord.ApplicationContext, title: Option( str, "Podaj tytuł utworu lub pozostaw puste, jeśli chcesz tekst aktualnie odtwarzanego utworu", ) = None, ): await ctx.defer() from_player: bool = False if not title: player: lavalink.DefaultPlayer = self.bot.lavalink.player_manager.get( ctx.guild.id) if not player or not player.is_playing: raise commands.BadArgument( "Atorin nie odtwarza muzyki, musisz podać tytuł utworu!") song: lavalink.AudioTrack = player.current title: str = song.title.split(" (")[0] from_player = True search = requests.get( "https://genius.com/api/search/multi", params={"q": title}, headers={"User-agent": "Atorin"}, ) if not search.status_code == 200: raise commands.CommandError( f"Wystąpił błąd podczas wyszukiwania tekstu piosenki! [{search.status_code}]" ) search_data = search.json()["response"]["sections"] if not search_data: if from_player: raise commands.BadArgument( "Nie znaleziono tekstu odtwarzanego utworu! Spróbuj wpisać komendę jeszcze raz, podając tytuł utworu." ) else: raise commands.BadArgument( "Nie znaleziono tekstu podanego utworu!") for section in search_data: if section["type"] == "song": lyrics_data = section["hits"][0]["result"] lyrics_url = lyrics_data["path"] lyrics_artist = lyrics_data["artist_names"] lyrics_title = lyrics_data["title"] lyrics_thumbnail = lyrics_data["song_art_image_url"] r = requests.get(f"https://genius.com{lyrics_url}", headers={"User-agent": "Atorin"}) if not r.status_code == 200: raise commands.CommandError( f"Wystąpił błąd podczas pobierania tekstu piosenki! [{r.status_code}]" ) soup = BeautifulSoup(r.content, "html.parser") containers: list[Tag] = soup.find_all( "div", attrs={"data-lyrics-container": "true"}) if not containers: raise commands.CommandError( f"Wystąpił błąd podczas przetwarzania tekstu!") lyrics: str = "" for container in containers: i_tags: list[Tag] = container.find_all("i") for tag in i_tags: tag.replace_with(f"*{tag.text}*") b_tags: list[Tag] = container.find_all("b") for tag in b_tags: tag.replace_with(f"**{tag.text}**") lyrics += container.get_text("\n", strip=True) + "\n" splited_lyrics = lyrics.splitlines() for i, line in enumerate(splited_lyrics): if line.startswith("[") and line.endswith("]"): splited_lyrics[i] = f"\n**{line}**" lyrics = "\n".join(splited_lyrics) embed = discord.Embed() embed.title = f"🎶 {lyrics_artist} - {lyrics_title}" embed.set_thumbnail(url=lyrics_thumbnail) if len(lyrics) > 4096: splited_message = [] limit = 4096 for i in range(0, len(lyrics), limit): splited_message.append(lyrics[i:i + limit]) if i > 2: break embed.description = splited_message.pop(0) await ctx.send_followup(embed=embed) for message in splited_message: embed.description = message await ctx.send(embed=embed) else: embed.description = lyrics await ctx.send_followup(embed=embed)
class PageTest(commands.Cog): def __init__(self, bot): self.bot = bot self.pages = [ "Page 1", [ discord.Embed(title="Page 2, Embed 1"), discord.Embed(title="Page 2, Embed 2"), ], "Page Three", discord.Embed(title="Page Four"), discord.Embed(title="Page Five"), [ discord.Embed(title="Page Six, Embed 1"), discord.Embed(title="Page Seven, Embed 2"), ], ] self.pages[3].set_image( url="https://c.tenor.com/pPKOYQpTO8AAAAAM/monkey-developer.gif" ) self.pages[4].add_field( name="Example Field", value="Example Value", inline=False ) self.pages[4].add_field( name="Another Example Field", value="Another Example Value", inline=False ) self.more_pages = [ "Second Page One", discord.Embed(title="Second Page Two"), discord.Embed(title="Second Page Three"), ] self.even_more_pages = ["11111", "22222", "33333"] def get_pages(self): return self.pages pagetest = SlashCommandGroup("pagetest", "Commands for testing ext.pages") # These examples use a Slash Command Group in a cog for better organization - it's not required for using ext.pages. @pagetest.command(name="default") async def pagetest_default(self, ctx: discord.ApplicationContext): """Demonstrates using the paginator with the default options.""" paginator = pages.Paginator(pages=self.get_pages()) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="hidden") async def pagetest_hidden(self, ctx: discord.ApplicationContext): """Demonstrates using the paginator with disabled buttons hidden.""" paginator = pages.Paginator(pages=self.get_pages(), show_disabled=False) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="loop") async def pagetest_loop(self, ctx: discord.ApplicationContext): """Demonstrates using the loop_pages option.""" paginator = pages.Paginator(pages=self.get_pages(), loop_pages=True) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="strings") async def pagetest_strings(self, ctx: discord.ApplicationContext): """Demonstrates passing a list of strings as pages.""" paginator = pages.Paginator( pages=["Page 1", "Page 2", "Page 3"], loop_pages=True ) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="timeout") async def pagetest_timeout(self, ctx: discord.ApplicationContext): """Demonstrates having the buttons be disabled when the paginator view times out.""" paginator = pages.Paginator( pages=self.get_pages(), disable_on_timeout=True, timeout=30 ) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="remove_buttons") async def pagetest_remove(self, ctx: discord.ApplicationContext): """Demonstrates using the default buttons, but removing some of them.""" paginator = pages.Paginator(pages=self.get_pages()) paginator.remove_button("first") paginator.remove_button("last") await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="init") async def pagetest_init(self, ctx: discord.ApplicationContext): """Demonstrates how to pass a list of custom buttons when creating the Paginator instance.""" pagelist = [ pages.PaginatorButton( "first", label="<<-", style=discord.ButtonStyle.green ), pages.PaginatorButton("prev", label="<-", style=discord.ButtonStyle.green), pages.PaginatorButton( "page_indicator", style=discord.ButtonStyle.gray, disabled=True ), pages.PaginatorButton("next", label="->", style=discord.ButtonStyle.green), pages.PaginatorButton("last", label="->>", style=discord.ButtonStyle.green), ] paginator = pages.Paginator( pages=self.get_pages(), show_disabled=True, show_indicator=True, use_default_buttons=False, custom_buttons=pagelist, loop_pages=True, ) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="custom_buttons") async def pagetest_custom_buttons(self, ctx: discord.ApplicationContext): """Demonstrates adding buttons to the paginator when the default buttons are not used.""" paginator = pages.Paginator( pages=self.get_pages(), use_default_buttons=False, loop_pages=False, show_disabled=False, ) paginator.add_button( pages.PaginatorButton( "prev", label="<", style=discord.ButtonStyle.green, loop_label="lst" ) ) paginator.add_button( pages.PaginatorButton( "page_indicator", style=discord.ButtonStyle.gray, disabled=True ) ) paginator.add_button( pages.PaginatorButton( "next", style=discord.ButtonStyle.green, loop_label="fst" ) ) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="custom_view") async def pagetest_custom_view(self, ctx: discord.ApplicationContext): """Demonstrates passing a custom view to the paginator.""" view = discord.ui.View() view.add_item(discord.ui.Button(label="Test Button, Does Nothing", row=1)) view.add_item( discord.ui.Select( placeholder="Test Select Menu, Does Nothing", options=[ discord.SelectOption( label="Example Option", value="Example Value", description="This menu does nothing!", ) ], ) ) paginator = pages.Paginator(pages=self.get_pages(), custom_view=view) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="groups") async def pagetest_groups(self, ctx: discord.ApplicationContext): """Demonstrates using page groups to switch between different sets of pages.""" page_buttons = [ pages.PaginatorButton( "first", label="<<-", style=discord.ButtonStyle.green ), pages.PaginatorButton("prev", label="<-", style=discord.ButtonStyle.green), pages.PaginatorButton( "page_indicator", style=discord.ButtonStyle.gray, disabled=True ), pages.PaginatorButton("next", label="->", style=discord.ButtonStyle.green), pages.PaginatorButton("last", label="->>", style=discord.ButtonStyle.green), ] view = discord.ui.View() view.add_item(discord.ui.Button(label="Test Button, Does Nothing", row=2)) view.add_item( discord.ui.Select( placeholder="Test Select Menu, Does Nothing", options=[ discord.SelectOption( label="Example Option", value="Example Value", description="This menu does nothing!", ) ], ) ) page_groups = [ pages.PageGroup( pages=self.get_pages(), label="Main Page Group", description="Main Pages for Main Things", ), pages.PageGroup( pages=[ "Second Set of Pages, Page 1", "Second Set of Pages, Page 2", "Look, it's group 2, page 3!", ], label="Second Page Group", description="Secondary Pages for Secondary Things", custom_buttons=page_buttons, use_default_buttons=False, custom_view=view, ), ] paginator = pages.Paginator(pages=page_groups, show_menu=True) await paginator.respond(ctx.interaction, ephemeral=False) @pagetest.command(name="update") async def pagetest_update(self, ctx: discord.ApplicationContext): """Demonstrates updating an existing paginator instance with different options.""" paginator = pages.Paginator(pages=self.get_pages(), show_disabled=False) await paginator.respond(ctx.interaction) await asyncio.sleep(3) await paginator.update(show_disabled=True, show_indicator=False) @pagetest.command(name="target") async def pagetest_target(self, ctx: discord.ApplicationContext): """Demonstrates sending the paginator to a different target than where it was invoked.""" paginator = pages.Paginator(pages=self.get_pages()) await paginator.respond(ctx.interaction, target=ctx.interaction.user) @commands.command() async def pagetest_prefix(self, ctx: commands.Context): """Demonstrates using the paginator with a prefix-based command.""" paginator = pages.Paginator(pages=self.get_pages(), use_default_buttons=False) paginator.add_button( pages.PaginatorButton("prev", label="<", style=discord.ButtonStyle.green) ) paginator.add_button( pages.PaginatorButton( "page_indicator", style=discord.ButtonStyle.gray, disabled=True ) ) paginator.add_button( pages.PaginatorButton("next", style=discord.ButtonStyle.green) ) await paginator.send(ctx) @commands.command() async def pagetest_target(self, ctx: commands.Context): """Demonstrates sending the paginator to a different target than where it was invoked (prefix-command version).""" paginator = pages.Paginator(pages=self.get_pages()) await paginator.send(ctx, target=ctx.author, target_message="Paginator sent!")
class Dev(commands.Cog, name="🧑💻 Programowanie"): def __init__(self, bot: Atorin): self.bot = bot self.rtfm_cache = {} @slash_command(description="Informacje o bibliotekach z PyPi", guild_ids=config["guild_ids"]) async def pypi(self, ctx: discord.ApplicationContext, package: Option(str, "Nazwa biblioteki")): await ctx.defer() r = requests.get( f"https://pypi.org/pypi/{package}/json", headers={"User-agent": "Atorin"}, ) if r.status_code == 200: data = r.json() embed = discord.Embed() embed.title = f"PyPi - {data['info']['name']}" embed.add_field( name= f"{data['info']['summary'] if data['info']['summary'] else 'Brak opisu'}", value=f"```bash\npip install {data['info']['name']}```", inline=False, ) embed.add_field( name="👨💻 Autor", value=data["info"]["author"] if data["info"]["author"] else "Nieznany", ) embed.add_field( name="⚙️ Wersja", value=data["info"]["version"] if data["info"]["version"] else "Nieznana", ) embed.add_field( name="📜 Licencja", value=data["info"]["license"] if data["info"]["license"] else "Brak", ) if "project_urls" in data["info"]: links = [] if "Documentation" in data["info"]["project_urls"]: links.append( f"[Dokumentacja]({data['info']['project_urls']['Documentation']})" ) if "Homepage" in data["info"]["project_urls"]: links.append( f"[Strona]({data['info']['project_urls']['Homepage']})" ) if "package_url" in data["info"]: links.append(f"[PyPi]({data['info']['package_url']})") embed.add_field( name="🔗 Linki", value=f"**{' | '.join(links)}**", ) await ctx.send_followup(embed=embed) elif r.status_code == 404: raise commands.BadArgument( "Nie znaleziono biblioteki o podanej nazwie!") else: raise commands.CommandError(r.text) @slash_command(description="Informacje o bibliotekach z NPM", guild_ids=config["guild_ids"]) async def npm(self, ctx: discord.ApplicationContext, package: Option(str, "Nazwa biblioteki")): await ctx.defer() r = requests.get( f"https://registry.npmjs.org/{package}/", headers={"User-agent": "Atorin"}, ) if r.status_code == 200: data = r.json() embed = discord.Embed() embed.title = f"NPM - {data['name']}" embed.add_field( name= f"{data['description'] if data['description'] else 'Brak opisu'}", value=f"```bash\nnpm i {data['name']}```", inline=False, ) if "author" in data: embed.add_field( name="👨💻 Autor", value=data["author"] if type(data["author"]) is str else data["author"]["name"], ) embed.add_field(name="⚙️ Wersja", value=data["dist-tags"]["latest"]) embed.add_field( name="📜 Licencja", value=data["license"] if data["license"] else "Brak", ) links = [] if "homepage" in data: links.append(f"[Strona]({data['homepage']})") links.append(f"[NPM](https://npmjs.com/package/{data['name']})") embed.add_field( name="🔗 Linki", value=f"**{' | '.join(links)}**", ) await ctx.send_followup(embed=embed) elif r.status_code == 404: raise commands.BadArgument( "Nie znaleziono biblioteki o podanej nazwie!") else: raise commands.CommandError(r.text) @slash_command( description="Wyszukiwanie w dokumentacjach bibliotek do Pythona", guild_ids=config["guild_ids"], ) async def rtfm( self, ctx: discord.ApplicationContext, package: Option(str, "Nazwa biblioteki"), term: Option(str, "Szukana fraza"), ): package = package.lower() await ctx.defer() embed = discord.Embed() embed.title = "Znalezione w dokumentacji" pypi = requests.get( f"https://pypi.org/pypi/{package}/json", headers={"User-agent": "Atorin"}, ) if pypi.status_code == 200: data = pypi.json() embed.add_field(name="🔤 Biblioteka", value=data["info"]["name"]) embed.add_field(name="⚙️ Wersja", value=data["info"]["version"]) else: embed.add_field(name="🔤 Biblioteka", value=package) if not self.rtfm_cache.get(package): url = docs.get(package) if not url: if ("project_urls" in data["info"] and "Documentation" in data["info"]["project_urls"]): url = data["info"]["project_urls"]["Documentation"] if "readthedocs.io" in url and not "/en/latest" in url: url = os.path.join(url, "en", "latest") else: url = f"https://{package}.readthedocs.io/en/latest/" r = requests.get( os.path.join(url, "objects.inv"), headers={"User-agent": "Atorin"}, ) if r.status_code == 200: self.rtfm_cache[package] = SphinxObjectFileReader( r.content).parse_object_inv(url) elif r.status_code == 404: raise commands.BadArgument("Nie znaleziono dokumentacji!") else: raise commands.CommandError( f"Wystąpił błąd przy pobieraniu dokumentacji! ({r.status_code})" ) cache = self.rtfm_cache.get(package) results = finder(term, list(cache.items()), key=lambda x: x[0], lazy=False)[:5] if results: embed.description = "\n".join( [f"[`{key}`]({url})" for key, url in results]) else: embed.description = "Brak wyników wyszukiwania" await ctx.send_followup(embed=embed) @slash_command( description="Uruchamianie kodu", guild_ids=config["guild_ids"], ) async def exec( self, ctx: discord.ApplicationContext, language: Option( str, "Wybierz język programowania", choices=[ OptionChoice(name="Bash", value="bash"), OptionChoice(name="C#", value="csharp"), OptionChoice(name="C", value="c"), OptionChoice(name="C++", value="c++"), OptionChoice(name="Go", value="go"), OptionChoice(name="Java", value="java"), OptionChoice(name="JavaScript", value="javascript"), OptionChoice(name="PHP", value="php"), OptionChoice(name="PowerShell", value="powershell"), OptionChoice(name="Python", value="python"), OptionChoice(name="Rust", value="rust"), OptionChoice(name="Ruby", value="ruby"), OptionChoice(name="TypeScript", value="typescript"), ], ), ): class ExecModal(Modal): def __init__(self) -> None: super().__init__("Uruchamianie kodu") self.add_item( InputText( label="Twój kod", placeholder="print('Hello world!')", style=discord.InputTextStyle.multiline, )) async def callback(self, interaction: discord.Interaction): r = requests.post( "https://emkc.org/api/v1/piston/execute", json={ "language": language, "source": self.children[0].value, }, ) if r.status_code != 200: raise commands.CommandError(r.text) data = r.json() embed = discord.Embed() embed.title = f"Uruchamianie kodu {language.capitalize()}" embed.description = f"```{data['output'][:4000] if data['output'] else 'Program wykonany pomyślnie.'}```" await interaction.response.send_message(embeds=[embed]) modal = ExecModal() await ctx.interaction.response.send_modal(modal) base64_group = SlashCommandGroup( "base64", "Kodowanie/Dekodowanie tekstu/ciągu w Base64", guild_ids=config["guild_ids"], ) @base64_group.command( name="encode", description="Kodowanie tekstu w Base64", ) async def base64_encode( self, ctx: discord.ApplicationContext, content: Option(str, "Wprowadź tekst"), ): await ctx.defer() embed = discord.Embed() embed.title = "Base64" encoded = base64.b64encode(content.encode("utf-8", "ignore")).decode( "utf-8", "ignore") embed.add_field(name="📋 Tekst", value=f"```{content}```", inline=False) embed.add_field(name="🔠 Base64", value=f"```{encoded}```", inline=False) await ctx.send_followup(embed=embed) @base64_group.command( name="decode", description="Dekodowanie ciągu w Base64", ) async def base64_decode( self, ctx: discord.ApplicationContext, content: Option(str, "Wprowadź ciąg"), ): await ctx.defer() embed = discord.Embed() embed.title = "Base64" decoded = base64.b64decode(content.encode("utf-8", "ignore")).decode( "utf-8", "ignore") embed.add_field(name="🔠 Base64", value=f"```{content}```", inline=False) embed.add_field(name="📋 Tekst", value=f"```{decoded}```", inline=False) await ctx.send_followup(embed=embed)
class Sov(commands.Cog): """ All about sov! """ def __init__(self, bot): self.bot = bot sov_commands = SlashCommandGroup( "sov", "Commands for Managing/Attacking Sov", guild_ids=[int(settings.DISCORD_GUILD_ID)]) @sov_commands.command(name='lowadm', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def lowadm( self, ctx, adm: Option(float, description="Optional ADM Level to flag under.", required=False)): """ Systems with low ADMs. """ if not adm: adm = app_settings.get_low_adm() # @commands.command(pass_context=True) # @message_in_channels(settings.SOV_DISCORD_BOT_CHANNELS) if ctx.channel.id not in settings.SOV_DISCORD_BOT_CHANNELS: return await ctx.respond( f"You do not have permission to use this command here.", ephemeral=True) await ctx.defer() own_ids = settings.DISCORD_BOT_SOV_STRUCTURE_OWNER_IDS include_regions = settings.DISCORD_BOT_ADM_REGIONS include_systems = settings.DISCORD_BOT_ADM_SYSTEMS include_constel = settings.DISCORD_BOT_ADM_CONSTELLATIONS sov_structures = providers.esi.client.Sovereignty.get_sovereignty_structures( ).result() names = {} for s in sov_structures: if s.get('alliance_id') in own_ids: if s.get('vulnerability_occupancy_level'): if s.get('vulnerability_occupancy_level') < adm: names[s.get('solar_system_id')] = { "system_name": s.get('solar_system_id'), "adm": s.get('vulnerability_occupancy_level') } if len(names) == 0: await ctx.respond(f"All above {adm} :ok_hand:") return True systems = [k for k, v in names.items()] constelations = {} for n in systems: system = providers.esi.client.Universe.get_universe_systems_system_id( system_id=n).result() names[n]["system_name"] = system.get("name") names[n]["system_id"] = system.get("system_id") names[n]["constellation_id"] = system.get("constellation_id") if system.get("constellation_id") not in constelations: constelations[system.get("constellation_id")] = {} for c, v in constelations.items(): const = providers.esi.client.Universe.get_universe_constellations_constellation_id( constellation_id=c).result() region = providers.esi.client.Universe.get_universe_regions_region_id( region_id=const.get("region_id")).result() v["region_id"] = const.get("region_id") v["region_name"] = region.get("name") v["constellation_name"] = const.get("name") out_array = {} for k, v in names.items(): out_array[k] = {**v, **constelations[v["constellation_id"]]} output = {} base_str = "**{}** ADM:{}" urls = {} for k, h in sorted(out_array.items(), key=lambda e: e[1]['adm']): show = False if h['region_id'] in include_regions: show = True elif h['constellation_id'] in include_constel: show = True elif h['system_id'] in include_systems: show = True if show: if h['region_name'] not in output: output[h['region_name']] = [] output[h['region_name']].append( base_str.format(h['system_name'], h['adm'])) if h['region_name'].replace(" ", "_") not in urls: urls[h['region_name'].replace(" ", "_")] = [] urls[h['region_name'].replace(" ", "_")].append( h['system_name'].replace(" ", "_")) url = "https://evemaps.dotlan.net/map/{}/{}#adm" if len(output) > 0: embed = Embed(title="Low ADMs!") embed.set_thumbnail( url= "https://avatars3.githubusercontent.com/u/39349660?s=200&v=4") embed.colour = Color.red() embed.description = f"Showing systems with ADMs below {adm}. Due to an ESI bug this data might only update once a day at around 2200-2300 Eve Time. **YMMY**\n[For more info please see this issue](https://github.com/esi/esi-issues/issues/1092)" await ctx.respond(embed=embed) for k, v in output.items(): n = 25 chunks = [ list(v[i * n:(i + 1) * n]) for i in range((len(v) + n - 1) // n) ] for chunk in chunks: await ctx.send("__{}__\n{}".format(k, "\n".join(chunk))) _urls = [] for r, s in urls.items(): _urls.append(url.format(r, ",".join(s))) await ctx.send("\n\n".join(_urls)) else: await ctx.respond(f"No Systems with ADM below {adm}!") return True @sov_commands.command(name='vulnerable', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def vuln(self, ctx, name_search: Option( str, description="String to search against the sov database.")): """ Vulnerable Sov Structures for region/constelation/system/alliance """ if ctx.channel.id not in settings.SOV_DISCORD_BOT_CHANNELS: return await ctx.respond( f"You do not have permission to use this command here.", ephemeral=True) await ctx.defer() name_ids = providers.esi.client.Search.get_search( categories=['constellation', 'solar_system', 'region', 'alliance'], search=name_search).result() hit_ids = { "a": name_ids.get("alliance") or [], "c": name_ids.get("constellation") or [], "s": name_ids.get("solar_system") or [], "r": name_ids.get("region") or [], } for r in hit_ids['r']: constellations = providers.esi.client.Universe.get_universe_regions_region_id( region_id=r).result()["constellations"] for c in constellations: if c not in hit_ids["c"]: hit_ids["c"].append(c) for c in hit_ids['c']: systems = providers.esi.client.Universe.get_universe_constellations_constellation_id( constellation_id=c).result()["systems"] for s in systems: if s not in hit_ids["s"]: hit_ids["s"].append(s) sov_structures = providers.esi.client.Sovereignty.get_sovereignty_structures( ).result() hits = [] names = [] alliances = [] dt_comp = datetime.datetime.utcnow().replace(tzinfo=timezone.utc) + \ datetime.timedelta(hours=1) for s in sov_structures: start = s.get('vulnerable_start_time', False) if start: if start < dt_comp: if s.get('solar_system_id') in hit_ids["s"] or s.get( 'alliance_id') in hit_ids["a"]: alliances.append(s.get('alliance_id')) names.append(s.get('solar_system_id')) names.append(s.get('structure_type_id')) hits.append(s) if len(names) == 0: await ctx.respond( ":sad: Nothing found for '{}'".format(name_search)) return True names_alli = {} for a in set(alliances): res = providers.esi.client.Alliance.get_alliances_alliance_id( alliance_id=a).result() names_alli[a] = res.get("ticker") names = providers.esi.client.Universe.post_universe_names( ids=list(set(names))).result() nms = {} for n in names: nms[n.get("id")] = n.get("name") for hit in hits: hit['system_name'] = nms[hit.get('solar_system_id')] if hit.get("structure_type_id") == 32226: hit['structure'] = "TCU" elif hit.get("structure_type_id") == 32458: hit['structure'] = "IHUB" else: hit['structure'] = "¯\\_(ツ)_/¯" hit['alliance_name'] = names_alli[hit.get('alliance_id')] output = [] base_str = "**{}** {} (ADM {})[**{}**] Vulnerable{}" dt_now = pendulum.now(tz="UTC") for h in sorted(hits, key=lambda k: k['vulnerable_start_time']): time = "" if h['vulnerable_start_time'] > dt_now: time = " in **{}**".format( pendulum.now(tz="UTC").diff_for_humans( h['vulnerable_start_time'], absolute=True)) else: time = " for **{}**".format( pendulum.now(tz="UTC").diff_for_humans( h['vulnerable_end_time'], absolute=True)) output.append( base_str.format(h['system_name'], h['structure'], h['vulnerability_occupancy_level'], h['alliance_name'], time)) n = 10 chunks = [ list(output[i * n:(i + 1) * n]) for i in range((len(output) + n - 1) // n) ] overflow = "" if len(output) > 50: overflow = "Only showing first 50..." await ctx.respond( "Found {} Vunerable Structures for `{}`\n{}\n".format( len(output), name_search, overflow)) for c in chunks[:5]: await ctx.send("\n".join(c)) @sov_commands.command(name='search', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def sov(self, ctx, name_search: Option( str, description="String to search against the sov database.")): """ Sov Details for region/constelation/system/alliance """ if ctx.channel.id not in settings.SOV_DISCORD_BOT_CHANNELS: return await ctx.respond( f"You do not have permission to use this command here.", ephemeral=True) await ctx.defer() name_ids = providers.esi.client.Search.get_search( categories=['constellation', 'solar_system', 'region', 'alliance'], search=name_search).result() hit_ids = { "a": name_ids.get("alliance") or [], "c": name_ids.get("constellation") or [], "s": name_ids.get("solar_system") or [], "r": name_ids.get("region") or [], } for r in hit_ids['r']: constellations = providers.esi.client.Universe.get_universe_regions_region_id( region_id=r).result()["constellations"] for c in constellations: if c not in hit_ids["c"]: hit_ids["c"].append(c) for c in hit_ids['c']: systems = providers.esi.client.Universe.get_universe_constellations_constellation_id( constellation_id=c).result()["systems"] for s in systems: if s not in hit_ids["s"]: hit_ids["s"].append(s) sov_structures = providers.esi.client.Sovereignty.get_sovereignty_structures( ).result() hits = [] names = [] alliances = [] for s in sov_structures: start = s.get('vulnerable_start_time', False) if start: if s.get('solar_system_id') in hit_ids["s"] or s.get( 'alliance_id') in hit_ids["a"]: alliances.append(s.get('alliance_id')) names.append(s.get('solar_system_id')) names.append(s.get('structure_type_id')) hits.append(s) if len(names) == 0: await ctx.respond( ":sad: Nothing found for '{}'".format(name_search)) return True names_alli = {} for a in set(alliances): res = providers.esi.client.Alliance.get_alliances_alliance_id( alliance_id=a).result() names_alli[a] = res.get("ticker") names = providers.esi.client.Universe.post_universe_names( ids=list(set(names))).result() nms = {} for n in names: nms[n.get("id")] = n.get("name") for hit in hits: hit['system_name'] = nms[hit.get('solar_system_id')] if hit.get("structure_type_id") == 32226: hit['structure'] = "TCU" elif hit.get("structure_type_id") == 32458: hit['structure'] = "IHUB" else: hit['structure'] = "¯\\_(ツ)_/¯" hit['alliance_name'] = names_alli[hit.get('alliance_id')] output = [] base_str = "**{}** {} (ADM {})[**{}**] Vulnerable{}" dt_now = pendulum.now(tz="UTC") for h in sorted(hits, key=lambda k: k['vulnerable_start_time']): time = "" time = " for **{}**".format( pendulum.now(tz="UTC").diff_for_humans( h['vulnerable_end_time'], absolute=True)) if h['vulnerable_start_time']: if h['vulnerable_start_time'] > dt_now: time = " in **{}**".format( pendulum.now(tz="UTC").diff_for_humans( h['vulnerable_start_time'], absolute=True)) output.append( base_str.format(h['system_name'], h['structure'], h['vulnerability_occupancy_level'], h['alliance_name'], time)) n = 15 chunks = [ list(output[i * n:(i + 1) * n]) for i in range((len(output) + n - 1) // n) ] overflow = "" if len(output) > 50: overflow = "Only showing first 50..." await ctx.respond("Found {} Sov structures for `{}`\n{}\n".format( len(output), name_search, overflow)) for c in chunks[:5]: await ctx.send("\n".join(c))
class MoonsCog(commands.Cog): """ All about Moons! """ def __init__(self, bot): self.bot = bot pinger_commands = SlashCommandGroup( "moons", "Moon Module Commands", guild_ids=[int(settings.DISCORD_GUILD_ID)]) def sender_has_moon_perm(self, ctx): id = ctx.author.id try: has_perm = DiscordUser.objects.get( uid=id).user.has_perm("moons.view_all") if has_perm: return True else: return False except Exception as e: return False def sender_has_corp_moon_perm(self, ctx): id = ctx.author.id try: has_perm = DiscordUser.objects.get( uid=id).user.has_perm("moons.view_corp") if has_perm: return True else: return False except Exception as e: return False @pinger_commands.command(name='print_stats', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def info_slash(self, ctx): """ Print the Uninvocied Mining Stats! """ if not self.sender_has_moon_perm(ctx): return await ctx.respond( f"You do not have permision to use this command.", ephemeral=True) await ctx.respond(f"Calculating the Moon Stats.") last_date = InvoiceRecord.get_last_invoice_date() date_str = last_date.strftime('%Y/%m/%d') e = Embed(title=f"Last Invoice {date_str}") accounts_seen = 0 locations = set() data = InvoiceRecord.generate_invoice_data() total_mined = 0 total_taxed = 0 # run known people for u, d in data['knowns'].items(): try: total_mined += d['total_value'] total_taxed += d['tax_value'] accounts_seen += 1 for l in d['locations']: locations.add(l) except KeyError: pass # probably wanna ping admin about it. for u, d in data['unknowns'].items(): try: total_mined += d['totals_isk'] total_taxed += d['tax_isk'] for l in d['seen_at']: locations.add(l) except KeyError: pass # probably wanna ping admin about it. e.add_field(name="Known Members", value=f"{accounts_seen}", inline=False) e.add_field(name="Unknown Characters", value=f"{len(data['unknowns'])}", inline=False) e.add_field(name="Total Mined", value=f"${total_mined:,}", inline=False) e.add_field(name="Total Tax", value=f"${total_taxed:,}", inline=False) locations = "\n ".join(list(locations)) e.description = f'Locations tracked so far ({len(list(locations))})\n\n {locations}' await ctx.channel.send(embed=e) @pinger_commands.command(name='inactive', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def inactive_moons(self, ctx, own_corp: Optional[bool] = False): """ Print inactive Moons! """ if own_corp: if not self.sender_has_corp_moon_perm(ctx): return await ctx.respond( f"You do not have permission to use this command.", ephemeral=True) user = DiscordUser.objects.get( uid=ctx.author.id).user.profile.main_character corps = CorporationAudit.objects.filter( corporation__corporation_id=user.corporation_id) corp_names = [f"{c.corporation.corporation_name}" for c in corps] if corps.count() > 0: await ctx.respond( f"Printing Inactive Drills for {', '.join(corp_names)}", ephemeral=True) await ctx.author.send( f"Printing Inactive Drills for {', '.join(corp_names)}") else: await ctx.respond( f"Your corp is not setup in Audit, please contact an admin.", ephemeral=True) else: if not self.sender_has_moon_perm(ctx): return await ctx.respond( f"You do not have permission to use this command.", ephemeral=True) corps = CorporationAudit.objects.filter( corporation__corporation_id__in=app_settings.PUBLIC_MOON_CORPS) corp_names = [f"{c.corporation.corporation_name}" for c in corps] if corps.count() > 0: await ctx.respond( f"Printing Inactive Drills for {', '.join(corp_names)}") else: await ctx.respond( f"Public corp is not setup, please contact an admin.") tzactive = timezone.now() fracks = MoonFrack.objects.filter( arrival_time__gte=tzactive, corporation__in=corps).values_list('structure_id') structures = Structure.objects.filter( structureservice__name__in=["Moon Drilling"], corporation__in=corps).exclude(structure_id__in=fracks) messages = [f"{s.name}" for s in structures] n = 10 chunks = [ list(messages[i * n:(i + 1) * n]) for i in range((len(messages) + n - 1) // n) ] for chunk in chunks: message = "\n".join(chunk) if own_corp: await ctx.author.send(f"```{message}```") else: await ctx.send(f"```{message}```")
class Admin(commands.Cog): def __init__(self, bot): self.bot = bot admin_commands = SlashCommandGroup( "admin", "Server Admin Commands", guild_ids=[int(settings.DISCORD_GUILD_ID)]) @admin_commands.command(name='add_role', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def add_role_slash(self, ctx, channel: TextChannel, role: Role): """ Add a role as read/write to a channel.... """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer() await channel.set_permissions(role, read_messages=True, send_messages=True) await ctx.respond(f"Set Read/Write `{role.name}` in `{channel.name}`") @admin_commands.command(name='add_role_read', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def add_role_read_slash(self, ctx, channel: TextChannel, role: Role): """ Add a role as read only to a channel.... """ # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif if ctx.author.id not in app_settings.get_admins(): return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer() await channel.set_permissions(role, read_messages=True, send_messages=False) await ctx.respond(f"Set Readonly `{role.name}` in `{channel.name}`") @admin_commands.command(name='rem_role', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def rem_role_slash(self, ctx, channel: TextChannel, role: Role): """ Remove a role from a channel.... """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer() await channel.set_permissions(role, read_messages=False, send_messages=False) await ctx.respond(f"Removed `{role.name}` from `{channel.name}`") @admin_commands.command(name='new_channel', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def new_channel_slash(self, ctx, category: CategoryChannel, channel_name: str, first_role: Role): """ Create a new channel and add a role.... """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer() found_channel = False for channel in ctx.guild.channels: # TODO replace with channel lookup not loop if channel.name.lower() == channel_name.lower(): found_channel = True if not found_channel: channel = await ctx.guild.create_text_channel(channel_name.lower(), category=category ) # make channel await channel.set_permissions(ctx.guild.default_role, read_messages=False, send_messages=False) await channel.set_permissions(first_role, read_messages=True, send_messages=True) await ctx.respond( f"Created New Channel `{channel.name}` and added the `{first_role.name}` Role" ) @admin_commands.command(name='promote_to_god', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def promote_role_to_god(self, ctx, role: Role): """ set role as admin.... """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer(ephemeral=True) perms = role.permissions perms.administrator = True await role.edit(permissions=perms) await ctx.respond(f"Set `{role.name}` as admin", ephemeral=True) @admin_commands.command(name='demote_from_god', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def demote_role_from_god(self, ctx, role: Role): """ revoke role admin.... """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer(ephemeral=True) perms = role.permissions perms.administrator = False await role.edit(permissions=perms) await ctx.respond(f"Removed admin from `{role.name}`", ephemeral=True) @admin_commands.command(name='empty_roles', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def empty_roles(self, ctx): """ dump all roles with no members. """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer() empties = [] for role_model in ctx.guild.roles: if len(role_model.members) == 0: empties.append(role_model.name) await ctx.respond("\n".join(empties)) @admin_commands.command(name='clear_empty_roles', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def clear_empty_roles(self, ctx): """ delete all roles with no members. """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer() empties = 0 fails = [] for role_model in ctx.guild.roles: if len(role_model.members) == 0: try: await role_model.delete() empties += 1 except Exception as e: fails.append(role_model.name) await ctx.respond(f"Deleted {empties} Roles.") chunks = [fails[x:x + 50] for x in range(0, len(fails), 50)] for c in chunks: await ctx.respond("\n".join(c)) @admin_commands.command(name='orphans', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def orphans_slash(self, ctx): """ Returns a list of users on this server, who are not known to AA """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer() payload = "The following Users cannot be located in Alliance Auth \n" member_list = ctx.guild.members for member in member_list: id = member.id try: discord_exists = DiscordUser.objects.get(uid=id) discord_is_bot = member.bot except Exception as e: discord_exists = False discord_is_bot = False try: discord_is_bot = member.bot except Exception as e: discord_is_bot = False if discord_exists is not False: # nothing to do, the user exists. Move on with ur life dude. pass elif discord_is_bot is True: # lets also ignore bots here pass else: payload = payload + member.mention + "\n" try: await ctx.respond(payload) except Exception as e: await ctx.respond(payload[0:1999]) @admin_commands.command(name='get_webhooks', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def get_webhooks(self, ctx): """ Returns the webhooks for the channel """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) await ctx.defer(ephemeral=True) hooks = await ctx.channel.webhooks() if len(hooks) == 0: name = "{}_webhook".format(ctx.channel.name.replace(" ", "_")) hook = await ctx.channel.create_webhook(name=name) await ctx.respond("{} - {}".format(hook.name, hook.url), ephemeral=True) else: strs = [] for hook in hooks: strs.append("{} - {}".format(hook.name, hook.url)) await ctx.respond("\n".join(strs), ephemeral=True) @admin_commands.command(name='uptime', guild_ids=[int(settings.DISCORD_GUILD_ID)]) async def uptime(self, ctx): """ Returns the uptime of the bot """ if ctx.author.id not in app_settings.get_admins( ): # https://media1.tenor.com/images/1796f0fa0b4b07e51687fad26a2ce735/tenor.gif return await ctx.respond( f"You do not have permission to use this command", ephemeral=True) try: await ctx.respond(pendulum.now(tz="UTC").diff_for_humans( self.bot.currentuptime, absolute=True), ephemeral=True) except AttributeError: await ctx.respond("Still Booting up!", ephemeral=True)
class Admin(commands.Cog): def __init__(self, bot: Client): self.bot = bot self.init() self.votumTask.start() for server in session.query(Server): guilds.append(server.Id) settings = SlashCommandGroup( "setting", "Настройки бота. Admin only!", permissions=[CommandPermission("owner", 2, True)], guild_ids=guilds) @staticmethod def init(): for votum in session.query(Votum): votumList[votum.ServerId, votum.MessageId] = votum @tasks.loop(seconds=60, reconnect=True) async def votumTask(self): keys = votumList.keys() for i in keys: votum = votumList[i] if datetime.datetime.utcnow() >= votum.EndTime: try: channel = await self.bot.fetch_channel(votum.ChannelId) message = await channel.fetch_message(votum.MessageId) await message.delete() except discord.errors.NotFound: pass session.delete(votum) session.commit() votumList.pop(i) @slash_command( name='votum', description= "Начинает голосование по выдачи Вотума недовольства (Мута) пользователю.", ) async def votum(self, ctx, member: Option( discord.Member, "Выберите пользователя, которому выдаём Вотум")): if member.bot: emb = discord.Embed( title="Некорректный вызов", description="Пользователь {0} - это Бот".format(member.name)) return await ctx.send(embed=emb) # Проверяем не идёт ли уже голосование за мут votum = session.query(Votum) \ .filter(Votum.ServerId == ctx.guild.id) \ .filter(Votum.MemberId == member.id).first() if votum: emb = discord.Embed( title="Некорректный вызов", description= "{1}, голосование по выдачи Вотума пользователю {0} уже идёт". format(member.name, ctx.author.name)) return await ctx.send(embed=emb) # Создаём голование emb = discord.Embed( title="Голосование за выдачу Вотума Недовольства пользователю {0}". format(member.name), description= "Если это собщение наберёт 6 голосов (:thumbsup:) в течении 1 часа, тогда пользователю {0} " "будет выдан мут на 24 часа".format(member.name)) msg = await ctx.send(embed=emb) votum = Votum(channelId=ctx.channel.id, serverId=ctx.guild.id, memberId=member.id, messageId=msg.id) session.add(votum) session.commit() votumList[ctx.guild.id, msg.id] = votum await msg.add_reaction('\N{THUMBS UP SIGN}') return msg @commands.Cog.listener() async def on_reaction_add(self, reaction: discord.Reaction, user): if reaction.count >= 6: hours = 24 message = reaction.message votum = votumList[reaction.message.guild.id, reaction.message.id] member = await message.guild.fetch_member(votum.MemberId) await member.timeout(datetime.datetime.now() + datetime.timedelta(days=1), reason="Большинство проголосовало за мут") votumList.pop((votum.ServerId, votum.MessageId)) session.delete(votum) session.commit() await message.delete() return await message.channel.send( content="Пользователь {} заглушен на {} часа".format( member.name, hours)) # Кол-во пришедших @slash_command( name='count', description= 'Выводит статистику посещения сервера, а сколько пришло или ушло') async def count(self, ctx): members = session.query(Member).filter(Member.ServerId == ctx.guild.id) all = members.count() alive = members.filter(Member.IsAlive).count() dead = members.filter(Member.IsAlive == False).count() embed = discord.Embed(title="Я запомнила " + str(all) + " чел.", description="На данный момент") embed.add_field(name="Ушло", value=str(dead) + " чел.") embed.add_field(name="Осталось", value=str(alive) + " чел.") await ctx.send(embed=embed) # Устанавливает информационный канал @settings.command( name="info", guild_id=guilds, default_permission=False, permissions=[CommandPermission("owner", 2, True)], description= "Задаёт канал для вывода сообщений об приходе/уходе/возвращение пользователей." ) async def setInfo(self, ctx, channel: Option(discord.TextChannel, "Выбрите текстовый канал", required=False, default=None)): server = session.query(Server).filter( Server.Id == ctx.guild.id).first() if channel: server.InfoChannel = channel.id else: server.InfoChannel = "" session.commit() await ctx.send("InfoChannel: {}".format(channel.name)) # Устанавливает роль новичков @settings.command( name="joinrole", guild_id=guilds, permissions=[CommandPermission("owner", 2, True)], default_permission=False, description= "Задаёт роль для пользовтелей который только-что присоединились.") async def setJoinRole(self, ctx, role: Option(discord.Role, "Выберите роль для новичков", required=False, default=None)): server = session.query(Server).filter( Server.Id == ctx.guild.id).first() if role: server.JoinRole = role.id await ctx.send("Join role changed to: {}".format(role.name)) else: server.JoinRole = "" await ctx.send("Join role cleared") session.commit() # Устанавливает название участника сервера @settings.command( name="memname", guild_id=guilds, permissions=[CommandPermission("owner", 2, True)], default_permission=False, description= "Устанавливает называние при приходе/уходе/возвращение пользователей на сервер." ) async def setMemName(self, ctx, name: Option( str, "Строка обозначающее имя участника канала", default="Member", required=False)): server = session.query(Server).filter( Server.Id == ctx.guild.id).first() server.MemberName = name session.commit() await ctx.send("Member name changed to: {}".format(name)) # Устанавливает текст при бане пользователя на сервере @slash_command( name="bantext", permissions=[CommandPermission("owner", 2, True)], guild_id=guilds, default_permission=False, description="Устанавливает текст при бане пользователя на сервере.") @permissions.is_owner() async def setBanText(self, ctx, bantext: Option( str, "Сроки обозначающие, что пользовтатель был забанен", default="has been banned.", required=False)): server = session.query(Server).filter( Server.Id == ctx.guild.id).first() server.BanText = bantext session.commit() await ctx.send("Ban text changed for: {}".format(bantext)) # Подключение к серверу @commands.Cog.listener() async def on_guild_join(self, guild): logging.info("Join to: {} {}".format(guild.id, guild.name)) server = session.query(Server).filter(Server.Id == guild.id).first() if not server: common.createServerFolder(guild) server = Server(id=guild.id) session.add(server) session.commit() common.addMembersOnServer(guild) guilds.append(guild.id) else: common.checkMembersOnServer(guild) common.addRoles(guild) common.addEmojies(guild) # аudit @settings.command( name="audit", guild_id=guilds, permissions=[CommandPermission("owner", 2, True)], default_permission=False, description= "Производит аудит пользователей сервера и синхронизирует с бд бота.") async def audit(self, ctx): server = session.query(Server).filter( Server.Id == ctx.guild.id).first() if not server: common.createServerFolder(ctx.guild) server = Server(id=ctx.guild.id) session.add(server) session.commit() common.addMembersOnServer(ctx.guild) else: await common.checkMembersOnServer(ctx.guild) common.addRoles(ctx.guild) common.addEmojies(ctx.guild) await ctx.send("Audit completed!") @settings.command( name="ignor", guild_id=guilds, permissions=[CommandPermission("owner", 2, True)], default_permission=False, description= "Игнор-лист, для того чтобы бот не защитывал XP, упоминания или эмодзи в каналах." ) async def ignor(self, ctx, action: Option(str, "Выберите раздел", required=True, choices=["Список", "Добавить", "Удалить"], default="Список"), channel: Option(discord.TextChannel, "Канал который добавить/удалить из списка", required=False, default=None)): if action == "Список": embed = await ignorChannels.list(ctx) await ctx.send(embed=embed) elif action == "Добавить": if channel: embed = await ignorChannels.add(ctx, channel) await ctx.send(embed=embed) else: await ctx.send("Не указан канал!") elif action == "Удалить": if channel: embed = await ignorChannels.remove(ctx, channel) await ctx.send(embed=embed) else: await ctx.send("Не указан канал!") else: await ctx.send("Неизвестное действие.") @settings.command( name="boost", guild_id=guilds, permissions=[CommandPermission("owner", 2, True)], default_permission=False, description="Boost-лист каналов где присваивается х2 опыт.") async def boost(self, ctx, action: Option(str, "Выберите раздел", required=True, choices=["Список", "Добавить", "Удалить"], default="Список"), channel: Option(discord.TextChannel, "Канал который добавить/удалить из списка", required=False, default=None)): if action == "Список": embed = await boostChannels.list(ctx) await ctx.send(embed=embed) elif action == "Добавить": if channel: embed = await boostChannels.add(ctx, channel) await ctx.send(embed=embed) else: await ctx.send("Не указан канал!") elif action == "Удалить": if channel: embed = await boostChannels.remove(ctx, channel) await ctx.send(embed=embed) else: await ctx.send("Не указан канал!") else: await ctx.send("Неизвестное действие.") @slash_command( name="emojistat", description="Выводит статистику использования серверных эмоджи.") async def emojiStat(self, ctx: discord.ApplicationContext): pages = [] emojies = {} for i in ctx.guild.emojis: emojies.update({i.id: i}) iter = 0 for emojie in session.query(Emojie).filter( Emojie.ServerId == ctx.guild.id).order_by( desc(Emojie.CountUsage)): emoji = emojies.get(emojie.Id) if emoji: iter += 1 embed = discord.Embed(title=emoji.name) embed.set_thumbnail(url=emoji.url) embed.add_field(name="Кол-во:", value=emojie.CountUsage, inline=True) embed.add_field(name="Последнее использование:", value=str(emojie.LastUsage), inline=True) if iter == 1: page = Page(embeds=[embed]) else: page.embeds.append(embed) if iter == 5: pages.append(page) iter = 0 try: if pages.count(page) == 0: pages.append(page) except UnboundLocalError: return if len(pages) == 0: return paginator = Paginator(pages=pages, loop_pages=True, disable_on_timeout=True, timeout=360) await paginator.respond(ctx.interaction)