Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Many improvements and changes #85

Open
wants to merge 4 commits into
base: rewrite-slash
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
DISCORD_TOKEN = Your bot token
DISCORD_OWNER_IDS = 86477779717066752, 00000000000000000
DISCORD_OWNER_IDS = [86477779717066752, ...]
DISCORD_JOIN_MESSAGE = I has joined to do stuff 🌟

DISCORD_ACTIVITY_NAME = drunk as always 🍻
DISCORD_ACTIVITY_TYPE = playing/listening/watching/streaming/competing
DISCORD_STATUS_TYPE = online/idle/dnd
DISCORD_ACTIVITY_TYPE = playing/listening/watching/streaming/competing/custom
DISCORD_STATUS_TYPE = online/idle/dnd/offline/invisible

# The Guild ID that commands will be registered to
# DISCORD_GUILD_ID = 933704302252408853
# ID of the Guild to sync owner only commands to.
OWNER_GUILD_ID =

# The Twitch username to use if activity type is "streaming"
# DISCORD_STATUS_URL = TTVUserName (Uncomment to use it)
# The URL to a Twtich/YouTube stream if DISCORD_ACTIVITY_TYPE is set to streaming.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Twtich -> Twitch

STREAMING_STATUS_URL =
232 changes: 120 additions & 112 deletions cogs/admin.py
Original file line number Diff line number Diff line change
@@ -1,74 +1,25 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Literal, Optional, Union

import aiohttp
import discord
import importlib
import os

from discord import app_commands
from discord.ext import commands
from utils import permissions, default, http
from utils.data import DiscordBot


class Admin(commands.Cog):
def __init__(self, bot):
self.bot: DiscordBot = bot

group = app_commands.Group(name="change", description="Change the bot's appearances.")

@app_commands.command()
async def amiadmin(self, ctx: discord.Interaction):
""" Are you an admin? """
owners = self.bot.config.discord_owner_ids
if str(ctx.user.id) in owners:
return await ctx.response.send_message(
f"Yes **{ctx.user.name}** you are an admin! ✅"
)

# Please do not remove this part.
# I would love to be credited as the original creator of the source code.
# -- AlexFlipnote
if ctx.user.id == 86477779717066752:
return await ctx.response.send_message(
f"Well kinda **{ctx.user.name}**.. "
"you still own the source code"
)

await ctx.response.send_message(f"no, heck off {ctx.user.name}")
from utils import default, http

@app_commands.command()
@app_commands.check(permissions.is_owner)
async def load(self, ctx: discord.Interaction, name: str):
""" Loads an extension. """
try:
await self.bot.load_extension(f"cogs.{name}")
except Exception as e:
return await ctx.response.send_message(default.traceback_maker(e))
await ctx.response.send_message(f"Loaded extension **{name}.py**")
if TYPE_CHECKING:
from utils.data import DiscordBot

@app_commands.command()
@app_commands.check(permissions.is_owner)
async def unload(self, ctx: discord.Interaction, name: str):
""" Unloads an extension. """
try:
await self.bot.unload_extension(f"cogs.{name}")
except Exception as e:
return await ctx.response.send_message(default.traceback_maker(e))
await ctx.response.send_message(f"Unloaded extension **{name}.py**")

@app_commands.command()
@app_commands.check(permissions.is_owner)
async def reload(self, ctx: discord.Interaction, name: str):
""" Reloads an extension. """
try:
await self.bot.reload_extension(f"cogs.{name}")
except Exception as e:
return await ctx.response.send_message(default.traceback_maker(e))
await ctx.response.send_message(f"Reloaded extension **{name}.py**")
class Admin(commands.Cog):
def __init__(self, bot: DiscordBot) -> None:
self.bot: DiscordBot = bot

@app_commands.command()
@app_commands.check(permissions.is_owner)
async def reloadall(self, ctx: discord.Interaction):
""" Reloads all extensions. """
async def reload_all_extensions(self, interaction: discord.Interaction[DiscordBot]) -> None:
error_collection = []
for file in os.listdir("cogs"):
if not file.endswith(".py"):
Expand All @@ -78,92 +29,149 @@ async def reloadall(self, ctx: discord.Interaction):
try:
await self.bot.reload_extension(f"cogs.{name}")
except Exception as e:
error_collection.append(
[file, default.traceback_maker(e, advance=False)]
)
error_collection.append([file, default.traceback_maker(e, advance=False)])

if error_collection:
output = "\n".join([
f"**{g[0]}** ```diff\n- {g[1]}```"
for g in error_collection
])
output = "\n".join([f"**{g[0]}** ```diff\n- {g[1]}```" for g in error_collection])

return await ctx.response.send_message(
return await interaction.response.send_message(
f"Attempted to reload all extensions, was able to reload, "
f"however the following failed...\n\n{output}"
f"however the following failed...\n\n{output}",
ephemeral=True,
)

await interaction.response.send_message("Successfully reloaded all extensions")

change = app_commands.Group(name="change", description="Change the bot's appearances.")

@app_commands.command()
@app_commands.describe(action="The action to perform.", name="The extension to perform the action on. If any.")
async def extensions(
self,
interaction: discord.Interaction[DiscordBot],
action: Literal[
"list",
"load",
"unload",
"reload",
"reloadall",
],
name: Optional[str] = None,
):
if action == "list":
exts = "\n".join(e for e in self.bot.extensions.keys())
embed = discord.Embed(
title="Extensions",
description=f"fHere are all the extensions:\n\n{exts}",
color=discord.Color.blurple(),
)
await interaction.response.send_message(embed=embed)
elif action in ("load", "unload", "reload"):
if not name:
return await interaction.response.send_message("You need to specify an extension name.", ephemeral=True)

await ctx.response.send_message("Successfully reloaded all extensions")
to_call = getattr(self.bot, action)
try:
await to_call(f"cogs.{name}")
except Exception as e:
return await interaction.response.send_message(default.traceback_maker(e))
else:
await interaction.response.send_message(
f"Successfully {action}ed **{name}.py**",
)
elif action == "reloadall":
return await self.reload_all_extensions(interaction)

@app_commands.command()
@app_commands.check(permissions.is_owner)
async def reloadutils(self, ctx: discord.Interaction, name: str):
""" Reloads a utils module. """
@app_commands.describe(name="The utils module to reload.")
async def reloadutils(self, interaction: discord.Interaction[DiscordBot], name: str):
"""Reloads a utils module."""
name_maker = f"utils/{name}.py"
try:
module_name = importlib.import_module(f"utils.{name}")
importlib.reload(module_name)
except ModuleNotFoundError:
return await ctx.response.send_message(f"Couldn't find module named **{name_maker}**")
return await interaction.response.send_message(
f"Couldn't find module named **{name_maker}**", ephemeral=True
)
except Exception as e:
error = default.traceback_maker(e)
return await ctx.response.send_message(f"Module **{name_maker}** returned error and was not reloaded...\n{error}")
await ctx.response.send_message(f"Reloaded module **{name_maker}**")
return await interaction.response.send_message(
f"Module **{name_maker}** returned error and was not reloaded...\n{error}", ephemeral=True
)

await interaction.response.send_message(f"Reloaded module **{name_maker}**")

@app_commands.command()
@app_commands.check(permissions.is_owner)
async def dm(self, ctx: discord.Interaction, user: discord.User, *, message: str):
""" DM the user of your choice """
async def dm(
self, interaction: discord.Interaction[DiscordBot], user: Union[discord.Member, discord.User], message: str
):
"""DM the user of your choice"""
if user.bot:
return await interaction.response.send_message(f"Bot users can't be DMed!", ephemeral=True)

try:
await user.send(message)
await ctx.response.send_message(f"✉️ Sent a DM to **{user}**")
await interaction.response.send_message(f"✉️ Sent a DM to **{user}**")
except discord.Forbidden:
await ctx.response.send_message("This user might be having DMs blocked or it's a bot account...")
await interaction.response.send_message("This user might have blocked our bot.", ephemeral=True)
except discord.HTTPException:
await interaction.response.send_message("Looks like this user's DMs are not open.", ephemeral=True)

@group.command(name="username")
@app_commands.check(permissions.is_owner)
async def change_username(self, ctx: discord.Interaction, *, name: str):
""" Change username. """
@change.command(name="username")
async def change_username(self, interaction: discord.Interaction[DiscordBot], name: Optional[str] = None):
"""Change username."""
try:
await self.bot.user.edit(username=name)
await ctx.response.send_message(f"Successfully changed username to **{name}**")
await self.bot.user.edit(username=name) # type: ignore # can't be None here
except discord.HTTPException as err:
await ctx.response.send_message(err)
await interaction.response.send_message(f"Failed to change username: {err}", ephemeral=True)
else:
await interaction.response.send_message(
f"Successfully changed username to **{name}**.\nYou may have to wait a few minutes for the change to be visible."
)

@group.command(name="nickname")
@app_commands.check(permissions.is_owner)
async def change_nickname(self, ctx: discord.Interaction, *, name: str = None):
""" Change nickname. """
@change.command(name="nickname")
async def change_nickname(self, interaction: discord.Interaction[DiscordBot], name: Optional[str] = None):
"""Change nickname."""
try:
await ctx.guild.me.edit(nick=name)
await interaction.guild.me.edit(nick=name) # type: ignore # can't be None here
if name:
return await ctx.response.send_message(f"Successfully changed nickname to **{name}**")
await ctx.response.send_message("Successfully removed nickname")
return await interaction.response.send_message(f"Successfully changed nickname to **{name}**")
await interaction.response.send_message("Successfully removed nickname")
except Exception as err:
await ctx.response.send_message(err)

@group.command(name="avatar")
@app_commands.check(permissions.is_owner)
async def change_avatar(self, ctx: discord.Interaction, url: str = None):
""" Change avatar. """
if url is None and len(ctx.message.attachments) == 1:
url = ctx.message.attachments[0].url
await interaction.response.send_message(f"Failed to change nickname: {err}", ephemeral=True)

@change.command(name="avatar")
async def change_avatar(
self,
interaction: discord.Interaction[DiscordBot],
url: Optional[str] = None,
attachment: Optional[discord.Attachment] = None,
):
"""Change avatar."""
url = attachment.url if attachment else url
if url:
url = url.strip("<>")
else:
url = url.strip("<>") if url else None
return await interaction.response.send_message(
"You need to provide an image URL or upload one with the command", ephemeral=True
)

try:
bio = await http.get(url, res_method="read")
await self.bot.user.edit(avatar=bio.response)
await ctx.response.send_message(f"Successfully changed the avatar. Currently using:\n{url}")
await self.bot.user.edit(avatar=bio.response) # type: ignore # can't be None here
await interaction.response.send_message(f"Successfully changed the avatar. Currently using:\n{url}")
except aiohttp.InvalidURL:
await ctx.response.send_message("The URL is invalid...")
except discord.InvalidArgument:
await ctx.response.send_message("This URL does not contain a useable image")
await interaction.response.send_message("The URL is invalid...")
except ValueError:
await interaction.response.send_message("This URL does not contain a useable image")
except discord.HTTPException as err:
await ctx.response.send_message(err)
await interaction.response.send_message(err)
except TypeError:
await ctx.response.send_message("You need to either provide an image URL or upload one with the command")
await interaction.response.send_message(
"You need to either provide an image URL or upload one with the command"
)


async def setup(bot):
await bot.add_cog(Admin(bot))
async def setup(bot: DiscordBot) -> None:
await bot.add_cog(Admin(bot), guild=discord.Object(gid) if (gid := bot.config.owner_guild_id) else None)