diff --git a/jarvis/cogs/admin.py b/jarvis/cogs/admin.py index 3b0f6ff..aca71a5 100644 --- a/jarvis/cogs/admin.py +++ b/jarvis/cogs/admin.py @@ -6,6 +6,7 @@ from discord.utils import get from discord_slash import cog_ext from discord_slash.utils.manage_commands import create_option, create_choice from jarvis.utils.db import DBManager +from jarvis.utils.permissions import admin_or_permissions class AdminCog(commands.Cog): @@ -30,53 +31,54 @@ class AdminCog(commands.Cog): ): if not user or user == ctx.author: await ctx.send("You cannot ban yourself.") - if not reason: - reason = ( - "Mr. Stark is displeased with your presence. Please leave." - ) - - mtype = type - if mtype == "perm": - mtype = "perma" - - guild_name = ctx.guild.name - user_message = ( - f"You have been {mtype}banned from {guild_name}." - + " Reason:\n{reason}" + return + if not reason: + reason = ( + "Mr. Stark is displeased with your presence. Please leave." ) - if mtype == "temp": - user_message += f"\nDuration: {length} hours" - await user.send(user_message) - await ctx.guild.ban(user, reason=reason) - if mtype == "soft": - await ctx.guild.unban(user, reason="Ban was softban") - await ctx.send( - f"{user.name} has been {mtype}banned from {guild_name}." - + f"Reason:\n{reason}" - ) - if type != "temp": - length = None - active = True - if type == "soft": - active = False - self.db.jarvis.bans.insert_one( - { - "user": user.id, - "reason": reason, - "admin": ctx.author.id, - "time": datetime.now(), - "guild": ctx.guild.id, - "type": type, - "length": length, - "active": active, - } - ) + mtype = type + if mtype == "perm": + mtype = "perma" + + guild_name = ctx.guild.name + user_message = ( + f"You have been {mtype}banned from {guild_name}." + + " Reason:\n{reason}" + ) + if mtype == "temp": + user_message += f"\nDuration: {length} hours" + + await user.send(user_message) + await ctx.guild.ban(user, reason=reason) + if mtype == "soft": + await ctx.guild.unban(user, reason="Ban was softban") + await ctx.send( + f"{user.name} has been {mtype}banned from {guild_name}." + + f"Reason:\n{reason}" + ) + if type != "temp": + length = None + active = True + if type == "soft": + active = False + self.db.jarvis.bans.insert_one( + { + "user": user.id, + "reason": reason, + "admin": ctx.author.id, + "time": datetime.now(), + "guild": ctx.guild.id, + "type": type, + "length": length, + "active": active, + } + ) @cog_ext.cog_slash( name="ban", description="Ban a user", - guild_ids=[578757004059738142], + guild_ids=[418094694325813248, 578757004059738142], options=[ create_option( name="user", @@ -109,7 +111,7 @@ class AdminCog(commands.Cog): ), ], ) - @commands.has_permissions(ban_members=True) + @admin_or_permissions(ban_members=True) async def _ban_slash( self, ctx, @@ -123,36 +125,37 @@ class AdminCog(commands.Cog): async def _kick(self, ctx, user: User, reason=None): if not user or user == ctx.author: await ctx.send("You cannot kick yourself.") - if not reason: - reason = ( - "Mr. Stark is displeased with your presence. Please leave." - ) - guild_name = ctx.guild.name - try: - await user.send( - f"You have been kicked from {guild_name}. Reason:\n{reason}" - ) - except Exception: - await ctx.send("Unable to message user.") - await ctx.guild.kick(user, reason=reason) - await ctx.send( - f"{user.name} has been kicked from {guild_name}." - + f"Reason:\n{reason}" + return + if not reason: + reason = ( + "Mr. Stark is displeased with your presence. Please leave." ) - self.db.jarvis.kicks.insert_one( - { - "user": user.id, - "reason": reason, - "admin": ctx.authod.id, - "time": datetime.now(), - "guild": ctx.guild.id, - } + guild_name = ctx.guild.name + try: + await user.send( + f"You have been kicked from {guild_name}. Reason:\n{reason}" ) + except Exception: + await ctx.send("Unable to message user.") + await ctx.guild.kick(user, reason=reason) + await ctx.send( + f"{user.name} has been kicked from {guild_name}." + + f"Reason:\n{reason}" + ) + self.db.jarvis.kicks.insert_one( + { + "user": user.id, + "reason": reason, + "admin": ctx.authod.id, + "time": datetime.now(), + "guild": ctx.guild.id, + } + ) @cog_ext.cog_slash( name="kick", description="Kick a user", - guild_ids=[578757004059738142], + guild_ids=[418094694325813248, 578757004059738142], options=[ create_option( name="user", @@ -168,7 +171,7 @@ class AdminCog(commands.Cog): ), ], ) - @commands.has_permissions(kick_members=True) + @admin_or_permissions(kick_members=True) async def _kick_slash(self, ctx, user: User, reason=None): await self._kick(ctx, user, reason) @@ -201,7 +204,7 @@ class AdminCog(commands.Cog): ) ], ) - @commands.has_permissions(manage_messages=True) + @admin_or_permissions(manage_messages=True) async def _purge_slash(self, ctx, amount: int = 10): if amount < 1: await ctx.send("Amount must be >= 1") @@ -212,7 +215,7 @@ class AdminCog(commands.Cog): @cog_ext.cog_slash( name="mute", description="Mute a user", - guild_ids=[578757004059738142], + guild_ids=[418094694325813248, 578757004059738142], options=[ create_option( name="user", @@ -234,7 +237,7 @@ class AdminCog(commands.Cog): ), ], ) - @commands.has_permissions(mute_members=True) + @admin_or_permissions(mute_members=True) async def _mute(self, ctx, user: Member, reason: str, length: int = 30): mute_setting = self.db.jarvis.settings.find_one( {"guild": ctx.guild.id, "setting": "mute"} diff --git a/jarvis/cogs/autoreact.py b/jarvis/cogs/autoreact.py index 1797af7..9533ce1 100644 --- a/jarvis/cogs/autoreact.py +++ b/jarvis/cogs/autoreact.py @@ -1,12 +1,11 @@ import jarvis import re from datetime import datetime -from discord import TextChannel, Emoji +from discord import TextChannel from discord.ext import commands from discord.utils import find from discord_slash import cog_ext from discord_slash.utils.manage_commands import create_option -from emoji import UNICODE_EMOJI from jarvis.config import get_config from jarvis.utils.db import DBManager @@ -54,6 +53,29 @@ class AutoReactCog(commands.Cog): self.db.jarvis.autoreact.insert_one(autoreact) await ctx.send(f"Autoreact created for {channel.mention}!") + @cog_ext.cog_subcommand( + base="autoreact", + name="remove", + description="Remove an autoreact from a channel", + guild_ids=[418094694325813248, 578757004059738142], + options=[ + create_option( + name="channel", + description="Channel to stop monitoring", + option_type=7, + required=True, + ) + ], + ) + async def _autoreact_remove(self, ctx, channel: TextChannel): + exists = self.db.jarvis.autoreact.delete_one( + {"guild": channel.guild.id, "channel": channel.id} + ) + if exists: + await ctx.send(f"Autoreact remove from {channel.mention}") + else: + await ctx.send(f"Autoreact not found on {channel.mention}") + @cog_ext.cog_subcommand( base="autoreact", name="add", @@ -103,6 +125,11 @@ class AutoReactCog(commands.Cog): f"Emote already added to {channel.mention} autoreactions." ) return + if len(exists["reactions"]) == 20: + await ctx.send( + "Max number of reactions hit. Remove a different one to add this one" + ) + return exists["reactions"].append(emote) self.db.jarvis.autoreact.update_one( {"_id": exists["_id"]}, diff --git a/jarvis/cogs/dev.py b/jarvis/cogs/dev.py index 7ade71a..3bfeb79 100644 --- a/jarvis/cogs/dev.py +++ b/jarvis/cogs/dev.py @@ -13,8 +13,9 @@ from bson import ObjectId from discord.ext import commands from discord_slash import cog_ext from inspect import getsource -from jarvis.utils import build_embed, convert_bytesize, user_is_bot_admin +from jarvis.utils import build_embed, convert_bytesize from jarvis.utils.field import Field +from jarvis.utils.permissions import user_is_bot_admin from time import time diff --git a/jarvis/cogs/owner.py b/jarvis/cogs/owner.py index 30ff35b..c77451d 100644 --- a/jarvis/cogs/owner.py +++ b/jarvis/cogs/owner.py @@ -3,7 +3,8 @@ import jarvis from discord import User from discord.ext import commands from jarvis.config import get_config, reload_config -from jarvis.utils import update, user_is_bot_admin, db +from jarvis.utils import update, db +from jarvis.utils.permissions import user_is_bot_admin class OwnerCog(commands.Cog): diff --git a/jarvis/cogs/settings.py b/jarvis/cogs/settings.py index 6f4d3fb..6d4fcbb 100644 --- a/jarvis/cogs/settings.py +++ b/jarvis/cogs/settings.py @@ -4,8 +4,9 @@ from discord import Role from discord.ext import commands from discord_slash import cog_ext from discord_slash.utils.manage_commands import create_option -from jarvis.config import get_config, reload_config -from jarvis.utils import update, user_is_bot_admin, db +from jarvis.config import get_config +from jarvis.utils import db +from jarvis.utils.permissions import admin_or_permissions class SettingsCog(commands.Cog): @@ -38,7 +39,7 @@ class SettingsCog(commands.Cog): ) ], ) - @commands.has_permissions(mute_members=True) + @admin_or_permissions(mute_members=True) async def _mute(self, ctx, role: Role): await ctx.defer() self.update_settings("mute", role.id, ctx.guild.id) diff --git a/jarvis/cogs/starboard.py b/jarvis/cogs/starboard.py index a63918a..90ef41a 100644 --- a/jarvis/cogs/starboard.py +++ b/jarvis/cogs/starboard.py @@ -11,6 +11,7 @@ from jarvis.config import get_config from jarvis.utils import build_embed from jarvis.utils.db import DBManager from jarvis.utils.field import Field +from jarvis.utils.permissions import admin_or_permissions supported_images = [ "image/png", @@ -40,7 +41,7 @@ class StarboardCog(commands.Cog): if starboards != []: message = "Available Starboards:\n" for s in starboards: - message += f"{s['name']}: <#{s['target']}>\n" + message += f"<#{s['target']}>\n" await ctx.send(message) else: await ctx.send("No Starboards available.") @@ -51,12 +52,6 @@ class StarboardCog(commands.Cog): description="Create a starboard", guild_ids=[418094694325813248, 578757004059738142], options=[ - create_option( - name="name", - description="Starboard name", - option_type=3, - required=True, - ), create_option( name="target", description="Target channel", @@ -66,33 +61,28 @@ class StarboardCog(commands.Cog): ], ) @commands.has_permissions(administrator=True) - async def _create(self, ctx, name: str, target: TextChannel): + async def _create(self, ctx, target: TextChannel): if target not in ctx.guild.channels: await ctx.send( "Target channel not in guild. Choose an existing channel." ) return exists = self.db.jarvis.starboard.find_one( - {"name": name, "guild": ctx.guild.id} + {"target": target.id, "guild": ctx.guild.id} ) if exists: - await ctx.send( - f"Starboard {name} already exists at <@{exists['channel']}>!" - ) + await ctx.send(f"Starboard already exists at {target.mention}.") return self.db.jarvis.starboard.insert_one( { - "name": name, "guild": ctx.guild.id, "target": target.id, "admin": ctx.author.id, "time": datetime.now(), } ) - await ctx.send( - f"Starboard `{name}` created! Check it out at {target.mention}." - ) + await ctx.send(f"Starboard created. Check it out at {target.mention}.") @cog_ext.cog_subcommand( base="starboard", @@ -101,112 +91,26 @@ class StarboardCog(commands.Cog): guild_ids=[418094694325813248, 578757004059738142], options=[ create_option( - name="name", - description="Starboard name", - option_type=3, - required=True, - ), - ], - ) - @commands.has_permissions(administrator=True) - async def _delete(self, ctx, name: str): - deleted = self.db.jarvis.starboard.delete_one( - { - "name": name, - "guild": ctx.guild.id, - } - ) - if deleted: - self.db.jarvis.stars.delete_many({"starboard": name}) - await ctx.send(f"Starboard `{name}` deleted!") - else: - await ctx.send(f"Starboard `{name}` not found!") - - @cog_ext.cog_subcommand( - base="starboard", - name="move", - description="Move a starboard", - guild_ids=[418094694325813248, 578757004059738142], - options=[ - create_option( - name="name", - description="Starboard name", - option_type=3, - required=True, - ), - create_option( - name="target", - description="New Starboard channel", + name="channel", + description="Starboard channel", option_type=7, required=True, ), ], ) @commands.has_permissions(administrator=True) - async def _move(self, ctx, name: str, target: TextChannel): - exists = self.db.jarvis.starboard.find_one( + async def _delete(self, ctx, target: TextChannel): + deleted = self.db.jarvis.starboard.delete_one( { - "name": name, + "target": target.id, "guild": ctx.guild.id, } ) - if not exists: - await ctx.send( - f"Good news! Starboard `{name}` doesn't exist!\n" - + f"Run `/starboard create {name} {target.mention}` " - + "to create it!" - ) - return - exists["target"] = target.id - self.db.jarvis.starboard.update_one( - {"_id": exists["_id"]}, {"$set": exists} - ) - await ctx.send(f"Starboard `{name}` moved to {target.mention}!") - - @cog_ext.cog_subcommand( - base="starboard", - name="rename", - description="Move a starboard", - guild_ids=[418094694325813248, 578757004059738142], - options=[ - create_option( - name="name", - description="Starboard name", - option_type=3, - required=True, - ), - create_option( - name="new", - description="New Starboard name", - option_type=3, - required=True, - ), - ], - ) - @commands.has_permissions(administrator=True) - async def _rename(self, ctx, name: str, new: str): - old_exists = self.db.jarvis.starboard.find_one( - {"name": name, "guild": ctx.guild.id} - ) - if not old_exists: - await ctx.send( - f"Good news! Starboard `{name}` doesn't exist!\n" - + f"Run `/starboard create {new} ` " - + "to create your new channel!" - ) - return - new_exists = self.db.jarvis.starboard.find_one( - {"name": new, "guild": ctx.guild.id} - ) - if new_exists: - await ctx.send(f"Starboard `{new}` already exists!") - return - - old_exists["name"] = new - self.db.jarvis.starboard.update_one( - {"_id": old_exists["_id"]}, {"$set": old_exists} - ) - await ctx.send(f"Starboard `{name}` moved renamed to `{name}`!") + if deleted: + self.db.jarvis.stars.delete_many({"starboard": target.id}) + await ctx.send(f"Starboard deleted from {target.mention}.") + else: + await ctx.send(f"Starboard not found in {target.mention}.") @cog_ext.cog_subcommand( base="star", @@ -223,7 +127,7 @@ class StarboardCog(commands.Cog): create_option( name="starboard", description="Starboard to send message to", - option_type=3, + option_type=7, required=True, ), create_option( @@ -240,40 +144,36 @@ class StarboardCog(commands.Cog): self, ctx: SlashContext, message: str, - starboard: str, + starboard: TextChannel, channel: TextChannel = None, ): if not channel: channel = ctx.channel exists = self.db.jarvis.starboard.find_one( - {"name": starboard, "guild": ctx.guild.id} + {"target": starboard.id, "guild": ctx.guild.id} ) if not exists: await ctx.send( - f"Starboard `{starboard}` does not exist! " + f"Starboard does not exist in {starboard.mention}. " + "Please create it first" ) return message = await channel.fetch_message(int(message)) - guild_channels = await ctx.guild.fetch_channels() - target = find(lambda x: x.id == exists["target"], guild_channels) - - if not target: - await ctx.send("Could not find Starboard channel!") - return exists = self.db.jarvis.stars.find_one( { "message": message.id, "channel": message.channel.id, "guild": message.guild.id, - "starboard": starboard, + "starboard": starboard.id, } ) if exists: - await ctx.send(f"Message already sent to Starboard `{starboard}`!") + await ctx.send( + f"Message already sent to Starboard {starboard.mention}" + ) return content = message.content @@ -306,14 +206,14 @@ class StarboardCog(commands.Cog): if image_url: embed.set_image(url=image_url) - star = await target.send(embed=embed) + star = await starboard.send(embed=embed) self.db.jarvis.stars.insert_one( { "message": message.id, "channel": message.channel.id, "guild": message.guild.id, - "starboard": starboard, + "starboard": starboard.id, "admin": ctx.author.id, "time": datetime.now(), "star": star.id, @@ -321,8 +221,7 @@ class StarboardCog(commands.Cog): ) await ctx.send( - f"Message saved to Starboard `{starboard}`!\n" - + f"See it in {target.mention}" + "Message saved to Starboard.\n" + f"See it in {starboard.mention}" ) diff --git a/jarvis/utils/__init__.py b/jarvis/utils/__init__.py index e3ed48a..7a5fa3e 100644 --- a/jarvis/utils/__init__.py +++ b/jarvis/utils/__init__.py @@ -86,13 +86,3 @@ def update(): def get_repo_hash(): repo = git.Repo(".") return repo.head.object.hexsha - - -def user_is_bot_admin(): - def predicate(ctx): - if getattr(jarvis.config.get_config(), "admins", None): - return ctx.author.id in jarvis.config.get_config().admins - else: - return False - - return commands.check(predicate) diff --git a/jarvis/utils/permissions.py b/jarvis/utils/permissions.py new file mode 100644 index 0000000..7d15267 --- /dev/null +++ b/jarvis/utils/permissions.py @@ -0,0 +1,23 @@ +import jarvis +from discord.ext import commands + + +def user_is_bot_admin(): + def predicate(ctx): + if getattr(jarvis.config.get_config(), "admins", None): + return ctx.author.id in jarvis.config.get_config().admins + else: + return False + + return commands.check(predicate) + + +def admin_or_permissions(**perms): + original = commands.has_permissions(**perms).predicate + + async def extended_check(ctx): + return await commands.has_permissions(administrator=True).predicate( + ctx + ) or await original(ctx) + + return commands.check(extended_check)