commit
269020de56
19 changed files with 727 additions and 687 deletions
|
@ -1,10 +1,12 @@
|
||||||
from discord import Intents
|
from discord import Intents
|
||||||
|
from discord_slash import SlashCommand
|
||||||
|
|
||||||
from administrator.config import config
|
from administrator.config import config
|
||||||
import db
|
import db
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
|
||||||
bot = commands.Bot(command_prefix=config.get("prefix"), intents=Intents.all())
|
bot = commands.Bot(command_prefix=config.get("prefix"), intents=Intents.all())
|
||||||
|
slash = SlashCommand(bot, auto_register=True, auto_delete=True)
|
||||||
|
|
||||||
import extensions
|
import extensions
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
import functools
|
||||||
|
|
||||||
|
from discord import Permissions
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
from discord.ext.commands import NoPrivateMessage, NotOwner, MissingPermissions
|
||||||
|
|
||||||
import db
|
import db
|
||||||
|
|
||||||
|
@ -8,12 +12,62 @@ class ExtensionDisabled(commands.CheckFailure):
|
||||||
|
|
||||||
|
|
||||||
def is_enabled():
|
def is_enabled():
|
||||||
async def check(ctx: commands.Context):
|
def check(func):
|
||||||
if ctx.command.cog and ctx.guild:
|
@functools.wraps(func)
|
||||||
|
async def wrapped(*args):
|
||||||
|
ctx = args[1]
|
||||||
|
if ctx.guild:
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
es = s.query(db.ExtensionState).get((ctx.command.cog.qualified_name, ctx.guild.id))
|
es = s.query(db.ExtensionState).get((args[0].qualified_name, ctx.guild.id))
|
||||||
s.close()
|
s.close()
|
||||||
if es and not es.state:
|
if es and not es.state:
|
||||||
raise ExtensionDisabled()
|
return
|
||||||
return True
|
# raise ExtensionDisabled()
|
||||||
return commands.check(check)
|
return await func(*args)
|
||||||
|
return wrapped
|
||||||
|
return check
|
||||||
|
|
||||||
|
|
||||||
|
def is_owner():
|
||||||
|
def check(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
async def wrapped(*args):
|
||||||
|
ctx = args[1]
|
||||||
|
if not await ctx._discord.is_owner(ctx.author):
|
||||||
|
raise NotOwner('You do not own this bot.')
|
||||||
|
return await func(*args)
|
||||||
|
return wrapped
|
||||||
|
return check
|
||||||
|
|
||||||
|
|
||||||
|
def guild_only():
|
||||||
|
def check(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
async def wrapped(*args):
|
||||||
|
if args[1].guild is None:
|
||||||
|
raise NoPrivateMessage()
|
||||||
|
return await func(*args)
|
||||||
|
return wrapped
|
||||||
|
return check
|
||||||
|
|
||||||
|
|
||||||
|
def has_permissions(**perms):
|
||||||
|
invalid = set(perms) - set(Permissions.VALID_FLAGS)
|
||||||
|
if invalid:
|
||||||
|
raise TypeError('Invalid permission(s): %s' % (', '.join(invalid)))
|
||||||
|
|
||||||
|
def check(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
async def wrapped(*args):
|
||||||
|
ctx = args[1]
|
||||||
|
ch = ctx.channel
|
||||||
|
permissions = ch.permissions_for(ctx.author)
|
||||||
|
|
||||||
|
missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value]
|
||||||
|
|
||||||
|
if not missing or permissions.administrator:
|
||||||
|
return await func(*args)
|
||||||
|
|
||||||
|
raise MissingPermissions(missing)
|
||||||
|
return wrapped
|
||||||
|
return check
|
||||||
|
|
|
@ -1,12 +1,32 @@
|
||||||
import re
|
import re
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from discord import Message
|
||||||
from discord.ext.commands import BadArgument
|
from discord.ext.commands import BadArgument
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
import db
|
import db
|
||||||
|
|
||||||
|
|
||||||
|
msg_url_re = re.compile(r"^https://.*discord.*\.com/channels/[0-9]+/([0-9+]+)/([0-9]+)$")
|
||||||
|
|
||||||
|
|
||||||
|
async def get_message_by_url(ctx, url: str) -> Message:
|
||||||
|
r = msg_url_re.fullmatch(url)
|
||||||
|
if not r:
|
||||||
|
raise BadArgument()
|
||||||
|
r = r.groups()
|
||||||
|
|
||||||
|
c = ctx.guild.get_channel(int(r[0]))
|
||||||
|
if not c:
|
||||||
|
raise BadArgument()
|
||||||
|
|
||||||
|
m = await c.fetch_message(int(r[1]))
|
||||||
|
if not m or m.is_system():
|
||||||
|
raise BadArgument()
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
def time_pars(s: str) -> timedelta:
|
def time_pars(s: str) -> timedelta:
|
||||||
match = re.fullmatch(r"(?:([0-9]+)W)*(?:([0-9]+)D)*(?:([0-9]+)H)*(?:([0-9]+)M)*(?:([0-9]+)S)*",
|
match = re.fullmatch(r"(?:([0-9]+)W)*(?:([0-9]+)D)*(?:([0-9]+)H)*(?:([0-9]+)M)*(?:([0-9]+)S)*",
|
||||||
s.upper().replace(" ", "").strip())
|
s.upper().replace(" ", "").strip())
|
||||||
|
|
|
@ -2,9 +2,13 @@ from traceback import format_exc
|
||||||
|
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import Embed, Guild
|
from discord import Embed, Guild
|
||||||
from discord.ext.commands import MissingPermissions, BadArgument, CommandError
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import cog_ext, SlashContext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
import db
|
import db
|
||||||
|
from administrator import slash
|
||||||
|
from administrator.check import has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,69 +19,66 @@ logger = logger.getChild(extension_name)
|
||||||
class Extension(commands.Cog):
|
class Extension(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Manage bot's extensions"
|
return "Manage bot's extensions"
|
||||||
|
|
||||||
@commands.group("extension", pass_context=True)
|
@cog_ext.cog_subcommand(base="extension", name="list", description="List all enabled extensions")
|
||||||
async def extension(self, ctx: commands.Context):
|
@has_permissions(administrator=True)
|
||||||
if ctx.invoked_subcommand is None:
|
async def extension_list(self, ctx: SlashContext):
|
||||||
await ctx.invoke(self.extension_help)
|
|
||||||
|
|
||||||
@extension.group("help", pass_context=True)
|
|
||||||
async def extension_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Extension help")
|
|
||||||
for c, n, v in [[self.extension_list, "extension list", "List all enabled extensions"],
|
|
||||||
[self.extension_enable, "extension enable", "Enable an extensions"],
|
|
||||||
[self.extension_disable, "extension disable", "Disable an extensions"],
|
|
||||||
[self.extension_loaded, "extension loaded", "List all loaded extensions"],
|
|
||||||
[self.extension_load, "extension load <name>", "Load an extension"],
|
|
||||||
[self.extension_unload, "extension unload <name>", "Unload an extension"],
|
|
||||||
[self.extension_reload, "extension reload <name>", "Reload an extension"]]:
|
|
||||||
try:
|
|
||||||
if await c.can_run(ctx):
|
|
||||||
embed.add_field(name=n, value=v, inline=False)
|
|
||||||
except CommandError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not embed.fields:
|
|
||||||
raise MissingPermissions("")
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@extension.group("list", pass_context=True)
|
|
||||||
@commands.has_guild_permissions(administrator=True)
|
|
||||||
async def extension_list(self, ctx: commands.Context):
|
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
embed = Embed(title="Extensions list")
|
embed = Embed(title="Extensions list")
|
||||||
for es in s.query(db.ExtensionState).filter(db.ExtensionState.guild_id == ctx.guild.id):
|
for es in s.query(db.ExtensionState).filter(db.ExtensionState.guild_id == ctx.guild.id):
|
||||||
embed.add_field(name=es.extension_name, value="Enable" if es.state else "Disable")
|
embed.add_field(name=es.extension_name, value="Enable" if es.state else "Disable")
|
||||||
await ctx.send(embed=embed)
|
s.close()
|
||||||
|
await ctx.send(embeds=[embed])
|
||||||
|
|
||||||
@extension.group("enable", pass_context=True)
|
@cog_ext.cog_subcommand(base="extension",
|
||||||
@commands.has_guild_permissions(administrator=True)
|
name="enable",
|
||||||
async def extension_enable(self, ctx: commands.Context, name: str):
|
description="Enable an extensions",
|
||||||
|
options=[manage_commands.create_option("extension", "The extension to enable",
|
||||||
|
SlashCommandOptionType.STRING, True)])
|
||||||
|
@has_permissions(administrator=True)
|
||||||
|
async def extension_enable(self, ctx: SlashContext, name: str):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
es = s.query(db.ExtensionState).get((name, ctx.guild.id))
|
es = s.query(db.ExtensionState).get((name, ctx.guild.id))
|
||||||
if not es or es.state:
|
if not es:
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
elif es.state:
|
||||||
|
message = "Extension already enabled"
|
||||||
|
else:
|
||||||
es.state = True
|
es.state = True
|
||||||
s.add(es)
|
s.add(es)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
message = "\U0001f44d"
|
||||||
|
await ctx.send(content=message)
|
||||||
|
|
||||||
@extension.group("disable", pass_context=True)
|
@cog_ext.cog_subcommand(base="extension",
|
||||||
@commands.has_guild_permissions(administrator=True)
|
name="disable",
|
||||||
async def extension_disable(self, ctx: commands.Context, name: str):
|
description="Disable an extensions",
|
||||||
|
options=[manage_commands.create_option("extension", "The extension to disable",
|
||||||
|
SlashCommandOptionType.STRING, True)])
|
||||||
|
@has_permissions(administrator=True)
|
||||||
|
async def extension_disable(self, ctx: SlashContext, name: str):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
es = s.query(db.ExtensionState).get((name, ctx.guild.id))
|
es = s.query(db.ExtensionState).get((name, ctx.guild.id))
|
||||||
if not es or not es.state:
|
if not es:
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
elif not es.state:
|
||||||
|
message = "Extension already disabled"
|
||||||
|
else:
|
||||||
es.state = False
|
es.state = False
|
||||||
s.add(es)
|
s.add(es)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
message = "\U0001f44d"
|
||||||
|
await ctx.send(content=message)
|
||||||
|
|
||||||
|
@commands.group("extension", pass_context=True)
|
||||||
|
async def extension(self, ctx: commands.Context):
|
||||||
|
pass
|
||||||
|
|
||||||
@extension.group("loaded", pass_context=True)
|
@extension.group("loaded", pass_context=True)
|
||||||
@commands.is_owner()
|
@commands.is_owner()
|
||||||
|
@ -152,6 +153,9 @@ class Extension(commands.Cog):
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
def cog_unload(self):
|
||||||
|
slash.remove_cog_commands(self)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
logger.info(f"Loading...")
|
logger.info(f"Loading...")
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import Member, Embed, Forbidden
|
from discord import Member, Embed, Forbidden
|
||||||
from discord.ext.commands import BadArgument
|
from discord_slash import cog_ext, SlashContext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
from administrator.check import is_enabled
|
from administrator.check import is_enabled, guild_only, has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator import db, config
|
from administrator import db, slash
|
||||||
from administrator.utils import event_is_enabled
|
from administrator.utils import event_is_enabled
|
||||||
|
|
||||||
|
|
||||||
def check_greetings_message_type(message_type):
|
|
||||||
if message_type not in ["join", "leave"]:
|
|
||||||
raise BadArgument()
|
|
||||||
|
|
||||||
|
|
||||||
extension_name = "greetings"
|
extension_name = "greetings"
|
||||||
logger = logger.getChild(extension_name)
|
logger = logger.getChild(extension_name)
|
||||||
|
|
||||||
|
@ -20,67 +16,74 @@ logger = logger.getChild(extension_name)
|
||||||
class Greetings(commands.Cog):
|
class Greetings(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Setup join and leave message"
|
return "Setup join and leave message"
|
||||||
|
|
||||||
@commands.group("greetings", pass_context=True)
|
@cog_ext.cog_subcommand(base="greetings", name="set",
|
||||||
|
description="Set the greetings message\n`{}` will be replace by the username",
|
||||||
|
options=[
|
||||||
|
manage_commands.create_option("type", "The join or leave message",
|
||||||
|
SlashCommandOptionType.STRING, True,
|
||||||
|
[manage_commands.create_choice("join", "join"),
|
||||||
|
manage_commands.create_choice("leave", "leave")]),
|
||||||
|
manage_commands.create_option("message", "The message", SlashCommandOptionType.STRING,
|
||||||
|
True)
|
||||||
|
])
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
@commands.guild_only()
|
@guild_only()
|
||||||
@commands.has_permissions(manage_guild=True)
|
@has_permissions(manage_guild=True)
|
||||||
async def greetings(self, ctx: commands.Context):
|
async def greetings_set(self, ctx: SlashContext, message_type: str, message: str):
|
||||||
if ctx.invoked_subcommand is None:
|
|
||||||
await ctx.invoke(self.greetings_help)
|
|
||||||
|
|
||||||
@greetings.group("help", pass_context=True)
|
|
||||||
async def greetings_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Greetings help")
|
|
||||||
embed.add_field(name="set <join/leave> <message>", value="Set the greetings message\n"
|
|
||||||
"`{}` will be replace by the username",
|
|
||||||
inline=False)
|
|
||||||
embed.add_field(name="show <join/leave>", value="Show the greetings message", inline=False)
|
|
||||||
embed.add_field(name="toggle <join/leave>", value="Enable or disable the greetings message", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@greetings.group("set", pass_context=True)
|
|
||||||
async def greetings_set(self, ctx: commands.Context, message_type: str):
|
|
||||||
check_greetings_message_type(message_type)
|
|
||||||
message = ctx.message.content.replace(config.get("prefix")+"greetings set " + message_type, "").strip()
|
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
m = s.query(db.Greetings).filter(db.Greetings.guild == ctx.guild.id).first()
|
m = s.query(db.Greetings).filter(db.Greetings.guild == ctx.guild.id).first()
|
||||||
if not m:
|
if not m:
|
||||||
m = db.Greetings(ctx.guild.id)
|
m = db.Greetings(ctx.guild.id)
|
||||||
s.add(m)
|
s.add(m)
|
||||||
setattr(m, message_type+"_enable", True)
|
setattr(m, message_type+"_enable", True)
|
||||||
setattr(m, message_type+"_message", message)
|
setattr(m, message_type+"_message", message.replace("\\n", '\n'))
|
||||||
s.commit()
|
s.commit()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@greetings.group("show", pass_context=True)
|
@cog_ext.cog_subcommand(base="greetings", name="show",
|
||||||
async def greetings_show(self, ctx: commands.Context, message_type: str):
|
description="Show the greetings message",
|
||||||
check_greetings_message_type(message_type)
|
options=[manage_commands.create_option("type", "The join or leave message",
|
||||||
|
SlashCommandOptionType.STRING, True,
|
||||||
|
[manage_commands.create_choice("join", "join"),
|
||||||
|
manage_commands.create_choice("leave", "leave")])])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(manage_guild=True)
|
||||||
|
async def greetings_show(self, ctx: SlashContext, message_type: str):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
m = s.query(db.Greetings).filter(db.Greetings.guild == ctx.guild.id).first()
|
m = s.query(db.Greetings).filter(db.Greetings.guild == ctx.guild.id).first()
|
||||||
s.close()
|
s.close()
|
||||||
if not m:
|
if not m:
|
||||||
await ctx.send(f"No {message_type} message set !")
|
await ctx.send(content=f"No {message_type} message set !")
|
||||||
else:
|
else:
|
||||||
if message_type == "join":
|
if message_type == "join":
|
||||||
await ctx.send(embed=m.join_embed(ctx.guild.name, str(ctx.message.author)))
|
await ctx.send(embeds=[m.join_embed(ctx.guild.name, str(ctx.author))])
|
||||||
else:
|
else:
|
||||||
await ctx.send(m.leave_msg(str(ctx.message.author)))
|
await ctx.send(content=m.leave_msg(str(ctx.author)))
|
||||||
|
|
||||||
@greetings.group("toggle", pass_context=True)
|
@cog_ext.cog_subcommand(base="greetings", name="toggle",
|
||||||
async def greetings_toggle(self, ctx: commands.Context, message_type: str):
|
description="Enable or disable the greetings message",
|
||||||
check_greetings_message_type(message_type)
|
options=[manage_commands.create_option("type", "The join or leave message",
|
||||||
|
SlashCommandOptionType.STRING, True,
|
||||||
|
[manage_commands.create_choice("join", "join"),
|
||||||
|
manage_commands.create_choice("leave", "leave")])])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(manage_guild=True)
|
||||||
|
async def greetings_toggle(self, ctx: SlashContext, message_type: str):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
m = s.query(db.Greetings).filter(db.Greetings.guild == ctx.guild.id).first()
|
m = s.query(db.Greetings).filter(db.Greetings.guild == ctx.guild.id).first()
|
||||||
if not m:
|
if not m:
|
||||||
await ctx.send(f"No {message_type} message set !")
|
await ctx.send(content=f"No {message_type} message set !")
|
||||||
else:
|
else:
|
||||||
setattr(m, message_type+"_enable", not getattr(m, message_type+"_enable"))
|
setattr(m, message_type+"_enable", not getattr(m, message_type+"_enable"))
|
||||||
s.commit()
|
s.commit()
|
||||||
await ctx.send(f"{message_type.title()} message is " +
|
await ctx.send(content=f"{message_type.title()} message is " +
|
||||||
("enable" if getattr(m, message_type+"_enable") else "disable"))
|
("enable" if getattr(m, message_type+"_enable") else "disable"))
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
@ -108,6 +111,9 @@ class Greetings(commands.Cog):
|
||||||
if m and m.leave_enable:
|
if m and m.leave_enable:
|
||||||
await member.guild.system_channel.send(m.leave_msg(str(member)))
|
await member.guild.system_channel.send(m.leave_msg(str(member)))
|
||||||
|
|
||||||
|
def cog_unload(self):
|
||||||
|
slash.remove_cog_commands(self)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
logger.info(f"Loading...")
|
logger.info(f"Loading...")
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from discord import Embed
|
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord.ext.commands import CommandNotFound, MissingRequiredArgument, BadArgument, MissingPermissions, \
|
from discord.ext.commands import CommandNotFound, MissingRequiredArgument, BadArgument, MissingPermissions, \
|
||||||
NoPrivateMessage, CommandError, NotOwner
|
NoPrivateMessage, NotOwner
|
||||||
|
from discord_slash import SlashContext
|
||||||
|
|
||||||
from administrator import config
|
|
||||||
from administrator.check import ExtensionDisabled
|
from administrator.check import ExtensionDisabled
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
|
|
||||||
|
@ -19,38 +18,35 @@ class Help(commands.Cog):
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Give help and command list"
|
return "Give help and command list"
|
||||||
|
|
||||||
@commands.command("help", pass_context=True)
|
|
||||||
async def help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Help")
|
|
||||||
|
|
||||||
for c in filter(lambda x: x != "Help", self.bot.cogs):
|
|
||||||
cog = self.bot.cogs[c]
|
|
||||||
try:
|
|
||||||
if await getattr(cog, c.lower()).can_run(ctx):
|
|
||||||
embed.add_field(name=c,
|
|
||||||
value=cog.description() + "\n" +
|
|
||||||
f"`{config.get('prefix')}{c.lower()} help` for more information",
|
|
||||||
inline=False)
|
|
||||||
except CommandError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_command_error(self, ctx: commands.Context, error):
|
async def on_command_error(self, ctx: commands.Context, error):
|
||||||
|
await self.error_handler(ctx, error)
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_slash_command_error(self, ctx: SlashContext, error: Exception):
|
||||||
|
await self.error_handler(ctx, error)
|
||||||
|
|
||||||
|
async def error_handler(self, ctx, error: Exception):
|
||||||
if isinstance(error, CommandNotFound):
|
if isinstance(error, CommandNotFound):
|
||||||
await ctx.message.add_reaction("\u2753")
|
await self.reaction(ctx, "\u2753")
|
||||||
elif isinstance(error, MissingRequiredArgument) or isinstance(error, BadArgument):
|
elif isinstance(error, MissingRequiredArgument) or isinstance(error, BadArgument):
|
||||||
await ctx.message.add_reaction("\u274C")
|
await self.reaction(ctx, "\u274C")
|
||||||
elif isinstance(error, NotOwner) or isinstance(error, MissingPermissions) \
|
elif isinstance(error, NotOwner) or isinstance(error, MissingPermissions) \
|
||||||
or isinstance(error, NoPrivateMessage):
|
or isinstance(error, NoPrivateMessage):
|
||||||
await ctx.message.add_reaction("\U000026D4")
|
await self.reaction(ctx, "\U000026D4")
|
||||||
elif isinstance(error, ExtensionDisabled):
|
elif isinstance(error, ExtensionDisabled):
|
||||||
await ctx.message.add_reaction("\U0001F6AB")
|
await self.reaction(ctx, "\U0001F6AB")
|
||||||
else:
|
else:
|
||||||
await ctx.send("An error occurred !")
|
await ctx.send(content="An error occurred !")
|
||||||
raise error
|
raise error
|
||||||
await ctx.message.delete(delay=30)
|
|
||||||
|
@staticmethod
|
||||||
|
async def reaction(ctx, react: str):
|
||||||
|
m = getattr(ctx, "message", None)
|
||||||
|
if m:
|
||||||
|
await m.add_reaction(react)
|
||||||
|
else:
|
||||||
|
await ctx.send(content=react)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from discord import Embed, Member, Guild
|
from discord import Embed, Member, Guild, Role, CategoryChannel
|
||||||
|
from discord.abc import GuildChannel
|
||||||
from discord.errors import Forbidden
|
from discord.errors import Forbidden
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord.ext.commands import BadArgument
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import cog_ext, SlashContext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
import db
|
import db
|
||||||
from administrator.check import is_enabled
|
from administrator import slash
|
||||||
|
from administrator.check import is_enabled, guild_only, has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator.utils import event_is_enabled
|
from administrator.utils import event_is_enabled
|
||||||
|
|
||||||
|
@ -20,41 +24,31 @@ class Invite(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.invites = {}
|
self.invites = {}
|
||||||
|
slash.get_cog_commands(self)
|
||||||
self.bot.loop.create_task(self.update_invites())
|
self.bot.loop.create_task(self.update_invites())
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Get role from a special invite link"
|
return "Get role from a special invite link"
|
||||||
|
|
||||||
@commands.group("invite", pass_context=True)
|
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
@commands.guild_only()
|
@guild_only()
|
||||||
@commands.has_guild_permissions(administrator=True)
|
@has_permissions(administrator=True)
|
||||||
async def invite(self, ctx: commands.Context):
|
async def invite_add(self, ctx: SlashContext, channel: GuildChannel, role: Role):
|
||||||
if ctx.invoked_subcommand is None:
|
if isinstance(channel, CategoryChannel):
|
||||||
await ctx.invoke(self.invite_help)
|
|
||||||
|
|
||||||
@invite.group("help", pass_context=True)
|
|
||||||
async def invite_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Invite help")
|
|
||||||
embed.add_field(name="invite create <#channel> <@role>", value="Create a invite link to a role", inline=False)
|
|
||||||
embed.add_field(name="invite delete <code>", value="Remove a invite", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@invite.group("create", pass_context=True)
|
|
||||||
async def invite_add(self, ctx: commands.Context, channel: str, role: str):
|
|
||||||
if not channel_mention_re.fullmatch(channel) or len(ctx.message.channel_mentions) != 1 or\
|
|
||||||
not role_mention_re.fullmatch(role) or len(ctx.message.role_mentions) != 1:
|
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
inv = await channel.create_invite()
|
||||||
inv = await ctx.message.channel_mentions[0].create_invite()
|
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
s.add(db.InviteRole(ctx.guild.id, inv.code, ctx.message.role_mentions[0].id))
|
s.add(db.InviteRole(ctx.guild.id, inv.code, role.id))
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.send(f"Invite created: `{inv.url}`")
|
await ctx.send(content=f"Invite created: `{inv.url}`")
|
||||||
|
|
||||||
@invite.group("delete", pass_context=True)
|
@cog_ext.cog_subcommand(base="invite", name="delete", description="Remove a invite", options=[
|
||||||
async def invite_delete(self, ctx: commands.Context, code: str):
|
manage_commands.create_option("code", "The invitation code", SlashCommandOptionType.STRING, True)])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(administrator=True)
|
||||||
|
async def invite_delete(self, ctx: SlashContext, code: str):
|
||||||
inv = next(filter(lambda i: i.code == code, await ctx.guild.invites()), None)
|
inv = next(filter(lambda i: i.code == code, await ctx.guild.invites()), None)
|
||||||
if not inv:
|
if not inv:
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
@ -68,7 +62,7 @@ class Invite(commands.Cog):
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await inv.delete()
|
await inv.delete()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
async def update_invites(self):
|
async def update_invites(self):
|
||||||
for g in self.bot.guilds:
|
for g in self.bot.guilds:
|
||||||
|
|
|
@ -1,105 +1,74 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from discord import Embed, Member
|
from discord import Member, Role
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord.ext.commands import BadArgument, MissingPermissions, CommandError
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import cog_ext, SlashCommandOptionType, SlashContext
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
import db
|
import db
|
||||||
|
from administrator import slash
|
||||||
|
from administrator.check import guild_only, has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
|
from administrator.utils import get_message_by_url
|
||||||
|
|
||||||
extension_name = "PCP"
|
extension_name = "PCP"
|
||||||
logger = logger.getChild(extension_name)
|
logger = logger.getChild(extension_name)
|
||||||
msg_url_re = re.compile(r"^https://.*discord.*\.com/channels/[0-9]+/([0-9+]+)/([0-9]+)$")
|
|
||||||
role_mention_re = re.compile(r"^<@&[0-9]+>$")
|
|
||||||
user_mention_re = re.compile(r"^<@![0-9]+>$")
|
|
||||||
|
|
||||||
|
|
||||||
class PCP(commands.Cog):
|
class PCP(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "PCP Univ Lyon 1"
|
return "PCP Univ Lyon 1"
|
||||||
|
|
||||||
@commands.group("pcp", pass_context=True)
|
@cog_ext.cog_subcommand(base="pcp", name="join", description="Join your group", options=[
|
||||||
@commands.guild_only()
|
manage_commands.create_option("group", "The target group to join", SlashCommandOptionType.ROLE, True)])
|
||||||
async def pcp(self, ctx: commands.Context):
|
@guild_only()
|
||||||
group = ctx.message.content.replace(f"{ctx.prefix}{ctx.command} ", "").upper()
|
async def pcp(self, ctx: SlashContext, role: Role):
|
||||||
if group:
|
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
p = s.query(db.PCP).get(ctx.guild.id)
|
p = s.query(db.PCP).get(ctx.guild.id)
|
||||||
s.close()
|
s.close()
|
||||||
if p and re.fullmatch(p.roles_re, group):
|
if p and re.fullmatch(p.roles_re, role.name.upper()):
|
||||||
await ctx.message.add_reaction("\U000023f3")
|
await ctx.send(content="\U000023f3")
|
||||||
role = next(filter(lambda r: r.name.upper() == group, ctx.guild.roles), None)
|
|
||||||
|
|
||||||
def roles() -> list:
|
async def roles() -> list:
|
||||||
return list(filter(
|
return list(filter(
|
||||||
lambda r: re.fullmatch(p.roles_re, r.name.upper()) or
|
lambda r: re.fullmatch(p.roles_re, r.name.upper()) or
|
||||||
(p.start_role_re and re.fullmatch(p.start_role_re, r.name.upper())),
|
(p.start_role_re and re.fullmatch(p.start_role_re, r.name.upper())),
|
||||||
ctx.author.roles
|
(await ctx.guild.fetch_member(ctx.author.id)).roles
|
||||||
))
|
))
|
||||||
|
|
||||||
if not role or role.name in map(lambda r: r.name, roles()):
|
if not role or role.name in map(lambda r: r.name, await roles()):
|
||||||
await ctx.message.remove_reaction("\U000023f3", self.bot.user)
|
await ctx.delete()
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
|
||||||
while roles():
|
while await roles():
|
||||||
await ctx.author.remove_roles(*roles())
|
await ctx.author.remove_roles(*(await roles()))
|
||||||
|
|
||||||
while role not in ctx.author.roles:
|
while role not in (await ctx.guild.fetch_member(ctx.author.id)).roles:
|
||||||
await ctx.author.add_roles(role)
|
await ctx.author.add_roles(role)
|
||||||
await ctx.message.remove_reaction("\U000023f3", self.bot.user)
|
await ctx.edit(content="\U0001f44d")
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
|
||||||
return
|
|
||||||
|
|
||||||
if ctx.invoked_subcommand is None:
|
@cog_ext.cog_subcommand(base="pcp", name="pin", description="Pin a message with the url", options=[
|
||||||
await ctx.invoke(self.pcp_help)
|
manage_commands.create_option("url", "message URL", SlashCommandOptionType.STRING, True)
|
||||||
|
])
|
||||||
@pcp.group("help", pass_context=True)
|
@guild_only()
|
||||||
async def pcp_help(self, ctx: commands.Context):
|
async def pcp_pin(self, ctx: SlashContext, url: str):
|
||||||
embed = Embed(title="PCP help")
|
|
||||||
s = db.Session()
|
|
||||||
p = s.query(db.PCP).get(ctx.guild.id)
|
|
||||||
s.close()
|
|
||||||
if p:
|
|
||||||
embed.add_field(name="pcp <group>", value="Join your group", inline=False)
|
|
||||||
for c, n, v in [[self.pcp_group, "pcp group", "Manage PCP group"],
|
|
||||||
[self.pcp_pin, "pcp pin <url>", "Pin a message with the url"],
|
|
||||||
[self.pcp_unpin, "pcp unpin <url>", "Unpin a message with the url"]]:
|
|
||||||
try:
|
|
||||||
if await c.can_run(ctx):
|
|
||||||
embed.add_field(name=n, value=v, inline=False)
|
|
||||||
except CommandError:
|
|
||||||
pass
|
|
||||||
if not embed.fields:
|
|
||||||
raise MissingPermissions("")
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@pcp.group("pin", pass_context=True)
|
|
||||||
async def pcp_pin(self, ctx: commands.Context, url: str):
|
|
||||||
await self.pin(ctx, url, True)
|
await self.pin(ctx, url, True)
|
||||||
|
|
||||||
@pcp.group("unpin", pass_context=True)
|
@cog_ext.cog_subcommand(base="pcp", name="unpin", description="Unpin a message with the url", options=[
|
||||||
async def pcp_unpin(self, ctx: commands.Context, url: str):
|
manage_commands.create_option("url", "message URL", SlashCommandOptionType.STRING, True)
|
||||||
|
])
|
||||||
|
@guild_only()
|
||||||
|
async def pcp_unpin(self, ctx: SlashContext, url: str):
|
||||||
await self.pin(ctx, url, False)
|
await self.pin(ctx, url, False)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def pin(ctx: commands.Context, url: str, action: bool):
|
async def pin(ctx: SlashContext, url: str, action: bool):
|
||||||
r = msg_url_re.fullmatch(url)
|
m = await get_message_by_url(ctx, url)
|
||||||
if not r:
|
|
||||||
raise BadArgument()
|
|
||||||
r = r.groups()
|
|
||||||
|
|
||||||
c = ctx.guild.get_channel(int(r[0]))
|
|
||||||
if not c:
|
|
||||||
raise BadArgument()
|
|
||||||
|
|
||||||
m = await c.fetch_message(int(r[1]))
|
|
||||||
if not m:
|
|
||||||
raise BadArgument()
|
|
||||||
|
|
||||||
if action:
|
if action:
|
||||||
await m.pin()
|
await m.pin()
|
||||||
msg = "pinned a message"
|
msg = "pinned a message"
|
||||||
|
@ -107,35 +76,23 @@ class PCP(commands.Cog):
|
||||||
await m.unpin()
|
await m.unpin()
|
||||||
msg = "unpinned a message"
|
msg = "unpinned a message"
|
||||||
|
|
||||||
await ctx.send(f"{ctx.author.mention} {msg}")
|
await ctx.send(content=f"{ctx.author.mention} {msg}")
|
||||||
|
|
||||||
@pcp.group("group", pass_context=True)
|
@cog_ext.cog_subcommand(base="pcp", subcommand_group="group", name="fix_vocal",
|
||||||
@commands.has_permissions(administrator=True)
|
description="Check all text channel permissions to reapply vocal permissions")
|
||||||
async def pcp_group(self, ctx: commands.Context):
|
@has_permissions(administrator=True)
|
||||||
if ctx.invoked_subcommand is None:
|
async def pcp_group_fix_vocal(self, ctx: SlashContext):
|
||||||
await ctx.invoke(self.pcp_group_help)
|
|
||||||
|
|
||||||
@pcp_group.group("help", pass_context=True)
|
|
||||||
async def pcp_group_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="PCP group help")
|
|
||||||
embed.add_field(name="pcp group set <role Regex> [Welcome role Regex]",
|
|
||||||
value="Set regex for group role", inline=False)
|
|
||||||
embed.add_field(name="pcp group unset", value="Unset regex for group role", inline=False)
|
|
||||||
embed.add_field(name="pcp group subject", value="Manage subjects for group", inline=False)
|
|
||||||
embed.add_field(name="pcp group fix_vocal",
|
|
||||||
value="Check all text channel permissions to reapply vocal permissions", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@pcp_group.group("fix_vocal", pass_context=True)
|
|
||||||
async def pcp_group_fix_vocal(self, ctx: commands.Context):
|
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
p = s.query(db.PCP).get(ctx.guild.id)
|
p = s.query(db.PCP).get(ctx.guild.id)
|
||||||
s.close()
|
s.close()
|
||||||
if not p:
|
if not p:
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
|
||||||
|
message = "\U000023f3"
|
||||||
|
await ctx.send(content=message)
|
||||||
for cat in filter(lambda c: re.fullmatch(p.roles_re, c.name.upper()), ctx.guild.categories):
|
for cat in filter(lambda c: re.fullmatch(p.roles_re, c.name.upper()), ctx.guild.categories):
|
||||||
await ctx.send(f"{cat.name}...")
|
message += f"\n{cat.name}..."
|
||||||
|
await ctx.edit(content=message)
|
||||||
teachers = []
|
teachers = []
|
||||||
for t in cat.text_channels:
|
for t in cat.text_channels:
|
||||||
for p in t.overwrites:
|
for p in t.overwrites:
|
||||||
|
@ -144,11 +101,20 @@ class PCP(commands.Cog):
|
||||||
voc = next(filter(lambda c: c.name == "vocal-1", cat.voice_channels), None)
|
voc = next(filter(lambda c: c.name == "vocal-1", cat.voice_channels), None)
|
||||||
for t in teachers:
|
for t in teachers:
|
||||||
await voc.set_permissions(t, view_channel=True)
|
await voc.set_permissions(t, view_channel=True)
|
||||||
await ctx.send(f"{cat.name} done")
|
message += f"\n{cat.name} done"
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.edit(content=message)
|
||||||
|
message += "\n\U0001f44d"
|
||||||
|
await ctx.edit(content=message)
|
||||||
|
|
||||||
@pcp_group.group("set", pass_context=True)
|
@cog_ext.cog_subcommand(base="pcp", subcommand_group="group", name="set", description="Set regex for group role",
|
||||||
async def pcp_group_set(self, ctx: commands.Context, roles_re: str, start_role_re: str = None):
|
options=[
|
||||||
|
manage_commands.create_option("role", "Roles regex",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("role2", "Start roles regex",
|
||||||
|
SlashCommandOptionType.STRING, False)
|
||||||
|
])
|
||||||
|
@has_permissions(administrator=True)
|
||||||
|
async def pcp_group_set(self, ctx: SlashContext, roles_re: str, start_role_re: str = None):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
p = s.query(db.PCP).get(ctx.guild.id)
|
p = s.query(db.PCP).get(ctx.guild.id)
|
||||||
if p:
|
if p:
|
||||||
|
@ -159,9 +125,11 @@ class PCP(commands.Cog):
|
||||||
s.add(p)
|
s.add(p)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@pcp_group.group("unset", pass_context=True)
|
@cog_ext.cog_subcommand(base="pcp", subcommand_group="group", name="unset",
|
||||||
|
description="Unset regex for group role")
|
||||||
|
@has_permissions(administrator=True)
|
||||||
async def pcp_group_unset(self, ctx: commands.Context):
|
async def pcp_group_unset(self, ctx: commands.Context):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
p = s.query(db.PCP).get(ctx.guild.id)
|
p = s.query(db.PCP).get(ctx.guild.id)
|
||||||
|
@ -173,33 +141,21 @@ class PCP(commands.Cog):
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.message.add_reaction("\U0001f44d")
|
||||||
|
|
||||||
@pcp_group.group("subject", pass_context=True)
|
@cog_ext.cog_subcommand(base="pcp", subcommand_group="subject", name="add", description="Add a subject to a group",
|
||||||
async def pcp_group_subject(self, ctx: commands.Context):
|
options=[
|
||||||
if ctx.invoked_subcommand is None:
|
manage_commands.create_option("name", "The subject name",
|
||||||
await ctx.invoke(self.pcp_group_subject_help)
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("group", "The group",
|
||||||
@pcp_group_subject.group("help", pass_context=True)
|
SlashCommandOptionType.ROLE, True),
|
||||||
async def pcp_group_subject_help(self, ctx: commands.Context):
|
manage_commands.create_option("teacher", "The teacher",
|
||||||
embed = Embed(title="PCP group subject help")
|
SlashCommandOptionType.USER, False)
|
||||||
embed.add_field(name="pcp group subject add <name> <@group> [@teacher]", value="Add a subject to a group",
|
])
|
||||||
inline=False)
|
@has_permissions(administrator=True)
|
||||||
embed.add_field(name="pcp group subject bulk <@group> [subject1] [subject2] ...", value="Bulk subject add",
|
async def pcp_group_subject_add(self, ctx: SlashContext, name: str, group: Role, teacher: Member = None):
|
||||||
inline=False)
|
if teacher and not next(filter(lambda r: r.name == "professeurs", teacher.roles), None):
|
||||||
embed.add_field(name="pcp group subject remove <name> <@group>", value="Remove a subject to a group",
|
|
||||||
inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@pcp_group_subject.group("add", pass_context=True)
|
|
||||||
async def pcp_group_subject_add(self, ctx: commands.Context, name: str, group: str, teacher: str = None):
|
|
||||||
if not role_mention_re.fullmatch(group):
|
|
||||||
raise BadArgument()
|
|
||||||
if teacher and not user_mention_re.fullmatch(teacher):
|
|
||||||
raise BadArgument()
|
|
||||||
elif teacher and\
|
|
||||||
not next(filter(lambda r: r.name == "professeurs", ctx.message.mentions[0].roles), None):
|
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
|
||||||
cat = next(filter(lambda c: c.name.upper() == ctx.message.role_mentions[0].name.upper(),
|
cat = next(filter(lambda c: c.name.upper() == group.name.upper(),
|
||||||
ctx.guild.categories), None)
|
ctx.guild.categories), None)
|
||||||
if not cat:
|
if not cat:
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
@ -210,26 +166,32 @@ class PCP(commands.Cog):
|
||||||
voc = next(filter(lambda c: c.name == "vocal-1", cat.voice_channels), None)
|
voc = next(filter(lambda c: c.name == "vocal-1", cat.voice_channels), None)
|
||||||
if not voc:
|
if not voc:
|
||||||
voc = await cat.create_voice_channel("vocal-1")
|
voc = await cat.create_voice_channel("vocal-1")
|
||||||
if ctx.message.mentions:
|
if teacher:
|
||||||
await chan.set_permissions(ctx.message.mentions[0], read_messages=True)
|
await chan.set_permissions(teacher, read_messages=True)
|
||||||
await voc.set_permissions(ctx.message.mentions[0], view_channel=True)
|
await voc.set_permissions(teacher, view_channel=True)
|
||||||
|
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@pcp_group_subject.group("bulk", pass_context=True)
|
@cog_ext.cog_subcommand(base="pcp", subcommand_group="subject", name="bulk",
|
||||||
async def pcp_group_subject_bulk(self, ctx: commands.Context, mention, *names):
|
description="Remove a subject to a group", options=[
|
||||||
if not role_mention_re.fullmatch(mention):
|
manage_commands.create_option("group", "The group", SlashCommandOptionType.ROLE, True),
|
||||||
raise BadArgument()
|
manage_commands.create_option("names", "Subjects names", SlashCommandOptionType.STRING, True)
|
||||||
for n in names:
|
])
|
||||||
await ctx.invoke(self.pcp_group_subject_add, n, mention)
|
@has_permissions(administrator=True)
|
||||||
|
async def pcp_group_subject_bulk(self, ctx: SlashContext, group: Role, names: str):
|
||||||
|
for n in names.split(" "):
|
||||||
|
await self.pcp_group_subject_add.invoke(ctx, n, group)
|
||||||
|
|
||||||
@pcp_group_subject.group("remove", pass_context=True)
|
@cog_ext.cog_subcommand(base="pcp", subcommand_group="subject", name="remove",description="Bulk subject add",
|
||||||
async def pcp_group_subject_remove(self, ctx: commands.Context, name: str, group: str):
|
options=[
|
||||||
if not role_mention_re.fullmatch(group):
|
manage_commands.create_option("name", "The subject name",
|
||||||
raise BadArgument()
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("group", "The group",
|
||||||
cat = next(filter(lambda c: c.name.upper() == ctx.message.role_mentions[0].name.upper(),
|
SlashCommandOptionType.ROLE, True)
|
||||||
ctx.guild.categories), None)
|
])
|
||||||
|
@has_permissions(administrator=True)
|
||||||
|
async def pcp_group_subject_remove(self, ctx: SlashContext, name: str, group: Role):
|
||||||
|
cat = next(filter(lambda c: c.name.upper() == group.name.upper(), ctx.guild.categories), None)
|
||||||
if not cat:
|
if not cat:
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
|
||||||
|
@ -239,7 +201,7 @@ class PCP(commands.Cog):
|
||||||
|
|
||||||
await chan.delete()
|
await chan.delete()
|
||||||
|
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
|
import shlex
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from discord.abc import GuildChannel
|
from discord.abc import GuildChannel
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import Embed, RawReactionActionEvent, RawMessageDeleteEvent, RawBulkMessageDeleteEvent, TextChannel, Guild
|
from discord import Embed, RawReactionActionEvent, RawMessageDeleteEvent, RawBulkMessageDeleteEvent, TextChannel, Guild
|
||||||
from discord.ext.commands import BadArgument
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import cog_ext, SlashCommandOptionType, SlashContext
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
import db
|
import db
|
||||||
from administrator.check import is_enabled
|
from administrator import slash
|
||||||
|
from administrator.check import is_enabled, guild_only
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator.utils import event_is_enabled
|
from administrator.utils import event_is_enabled
|
||||||
|
|
||||||
|
@ -21,47 +25,41 @@ REACTIONS.append("\U0001F51F")
|
||||||
class Poll(commands.Cog):
|
class Poll(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Create poll with a simple command"
|
return "Create poll with a simple command"
|
||||||
|
|
||||||
@commands.group("poll", pass_context=True)
|
@cog_ext.cog_slash(name="poll",
|
||||||
|
description="Create a poll",
|
||||||
|
options=[
|
||||||
|
manage_commands.create_option("name", "Poll name",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("choices", "All pool choice",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("multi", "Allow multiple choice",
|
||||||
|
SlashCommandOptionType.BOOLEAN, False)
|
||||||
|
])
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
@commands.guild_only()
|
@guild_only()
|
||||||
async def poll(self, ctx: commands.Context, name: str, *choices):
|
async def poll(self, ctx: SlashContext, name: str, choices: str, multi: bool = False):
|
||||||
if name == "help":
|
choices = shlex.split(choices)
|
||||||
await ctx.invoke(self.poll_help)
|
if len(choices) > 11:
|
||||||
else:
|
|
||||||
multi = False
|
|
||||||
if choices and choices[0] in ["multi", "m"]:
|
|
||||||
multi = True
|
|
||||||
choices = choices[1:]
|
|
||||||
if len(choices) == 0 or len(choices) > 11:
|
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
else:
|
else:
|
||||||
embed = Embed(title=f"Poll: {name}")
|
embed = Embed(title=f"Poll: {name}")
|
||||||
embed.set_author(name=str(ctx.author), icon_url=ctx.author.avatar_url)
|
embed.set_author(name=str(ctx.author), icon_url=ctx.author.avatar_url)
|
||||||
embed.set_footer(text=f"Created: {ctx.message.created_at.strftime('%d/%m/%Y %H:%M')}")
|
embed.set_footer(text=f"Created: {datetime.now().strftime('%d/%m/%Y %H:%M')}")
|
||||||
for i, choice in enumerate(choices):
|
for i, choice in enumerate(choices):
|
||||||
embed.add_field(name=REACTIONS[i], value=choice, inline=False)
|
embed.add_field(name=REACTIONS[i], value=choice, inline=False)
|
||||||
message = await ctx.send(embed=embed)
|
message = await ctx.channel.send(embed=embed)
|
||||||
reactions = REACTIONS[0:len(choices)] + ["\U0001F5D1"]
|
reactions = REACTIONS[0:len(choices)] + ["\U0001F5D1"]
|
||||||
for reaction in reactions:
|
for reaction in reactions:
|
||||||
await message.add_reaction(reaction)
|
await message.add_reaction(reaction)
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
s.add(db.Polls(message.id, ctx.channel.id, ctx.guild.id, ctx.message.author.id, reactions, multi))
|
s.add(db.Polls(message.id, ctx.channel.id, ctx.guild.id, ctx.author.id, reactions, multi))
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.delete()
|
|
||||||
|
|
||||||
@poll.group("help", pass_context=True)
|
|
||||||
async def poll_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Poll help")
|
|
||||||
embed.add_field(name="poll <name> [multi|m] <Choice N°1> <Choice N°2> ... <Choice N°11>",
|
|
||||||
value="Create a poll, the argument multi (or m) after the name allow multiple response\n"
|
|
||||||
"User the \U0001F5D1 to close the poll",
|
|
||||||
inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_raw_reaction_add(self, payload: RawReactionActionEvent):
|
async def on_raw_reaction_add(self, payload: RawReactionActionEvent):
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
|
from discord.abc import GuildChannel
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import Embed, Message
|
from discord import Message, Role, TextChannel
|
||||||
from discord.ext.commands import BadArgument
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import cog_ext, SlashCommandOptionType, SlashContext
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
from administrator.check import is_enabled
|
from administrator.check import is_enabled, guild_only, has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator import db
|
from administrator import db, slash
|
||||||
from administrator.utils import event_is_enabled
|
from administrator.utils import event_is_enabled
|
||||||
|
|
||||||
extension_name = "presentation"
|
extension_name = "presentation"
|
||||||
|
@ -14,51 +17,49 @@ logger = logger.getChild(extension_name)
|
||||||
class Presentation(commands.Cog):
|
class Presentation(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Give role to user who make a presentation in a dedicated channel"
|
return "Give role to user who make a presentation in a dedicated channel"
|
||||||
|
|
||||||
@commands.group("presentation", pass_context=True)
|
@cog_ext.cog_subcommand(base="presentation", name="set",
|
||||||
|
description="Set the presentation channel and the role to give",
|
||||||
|
options=[
|
||||||
|
manage_commands.create_option("channel", "The presentation channel",
|
||||||
|
SlashCommandOptionType.CHANNEL, True),
|
||||||
|
manage_commands.create_option("role", "The role to give",
|
||||||
|
SlashCommandOptionType.ROLE, True)
|
||||||
|
])
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
@commands.guild_only()
|
@guild_only()
|
||||||
@commands.has_permissions(manage_guild=True)
|
@has_permissions(manage_guild=True)
|
||||||
async def presentation(self, ctx: commands.Context):
|
async def presentation_set(self, ctx: SlashContext, channel: GuildChannel, role: Role):
|
||||||
if ctx.invoked_subcommand is None:
|
if not isinstance(channel, TextChannel):
|
||||||
await ctx.invoke(self.presentation_help)
|
|
||||||
|
|
||||||
@presentation.group("help", pass_context=True)
|
|
||||||
async def presentation_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Presentation help", description="Give a role to a new member after a presentation")
|
|
||||||
embed.add_field(name="set <#channel> <@role>", value="Set the presentation channel and the role to give",
|
|
||||||
inline=False)
|
|
||||||
embed.add_field(name="disable", value="Disable the auto role give", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@presentation.group("set", pass_context=True)
|
|
||||||
async def presentation_set(self, ctx: commands.Context):
|
|
||||||
if len(ctx.message.channel_mentions) != 1 and not len(ctx.message.role_mentions) != 1:
|
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
p = s.query(db.Presentation).filter(db.Presentation.guild == ctx.guild.id).first()
|
p = s.query(db.Presentation).filter(db.Presentation.guild == ctx.guild.id).first()
|
||||||
if not p:
|
if not p:
|
||||||
p = db.Presentation(ctx.guild.id, ctx.message.channel_mentions[0].id, ctx.message.role_mentions[0].id)
|
p = db.Presentation(ctx.guild.id, channel.id, role.id)
|
||||||
s.add(p)
|
s.add(p)
|
||||||
else:
|
else:
|
||||||
p.channel = ctx.message.channel_mentions[0].id
|
p.channel = channel.id
|
||||||
p.role = ctx.message.role_mentions[0].id
|
p.role = role.id
|
||||||
s.commit()
|
s.commit()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@presentation.group("disable", pass_context=True)
|
@cog_ext.cog_subcommand(base="presentation", name="disable", description="Disable the auto role give")
|
||||||
async def presentation_disable(self, ctx: commands.Context):
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(manage_guild=True)
|
||||||
|
async def presentation_disable(self, ctx: SlashContext):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
p = s.query(db.Presentation).filter(db.Presentation.guild == ctx.guild.id).first()
|
p = s.query(db.Presentation).filter(db.Presentation.guild == ctx.guild.id).first()
|
||||||
if not p:
|
if not p:
|
||||||
await ctx.send(f"Nothing to disable !")
|
await ctx.send(content="Nothing to disable !")
|
||||||
else:
|
else:
|
||||||
s.delete(p)
|
s.delete(p)
|
||||||
s.commit()
|
s.commit()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
|
|
|
@ -2,8 +2,10 @@ from asyncio import sleep
|
||||||
|
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import Embed, RawReactionActionEvent
|
from discord import Embed, RawReactionActionEvent
|
||||||
|
from discord_slash import SlashContext, cog_ext
|
||||||
|
|
||||||
from administrator.check import is_enabled
|
from administrator import slash
|
||||||
|
from administrator.check import is_enabled, guild_only, has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator.utils import event_is_enabled
|
from administrator.utils import event_is_enabled
|
||||||
|
|
||||||
|
@ -15,34 +17,23 @@ class Purge(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.purges = {}
|
self.purges = {}
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Purge all messages between the command and the next add reaction"
|
return "Purge all messages between the command and the next add reaction"
|
||||||
|
|
||||||
@commands.group("purge", pass_context=True)
|
@cog_ext.cog_slash(name="purge", description="Purge all message delimited by the command to your next reaction")
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
@commands.guild_only()
|
@guild_only()
|
||||||
@commands.has_permissions(manage_messages=True)
|
@has_permissions(manage_messages=True)
|
||||||
async def purge(self, ctx: commands.Context):
|
async def purge(self, ctx: SlashContext):
|
||||||
if ctx.invoked_subcommand is None:
|
message = await ctx.channel.send(content="\U0001f44d")
|
||||||
self.purges[ctx.message.author.id] = ctx.message
|
self.purges[ctx.author.id] = message
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
|
||||||
|
|
||||||
await sleep(2*60)
|
await sleep(2*60)
|
||||||
try:
|
if ctx.author.id in self.purges and self.purges[ctx.author.id] == message:
|
||||||
if self.purges[ctx.message.author.id] == ctx.message:
|
await message.delete()
|
||||||
await ctx.message.clear_reactions()
|
del self.purges[ctx.author.id]
|
||||||
del self.purges[ctx.message.author.id]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@purge.group("help", pass_context=True)
|
|
||||||
@commands.guild_only()
|
|
||||||
async def purge_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Purge help")
|
|
||||||
embed.add_field(name="purge", value="Purge all message delimited by the command to your next reaction",
|
|
||||||
inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_raw_reaction_add(self, payload: RawReactionActionEvent):
|
async def on_raw_reaction_add(self, payload: RawReactionActionEvent):
|
||||||
|
@ -55,8 +46,7 @@ class Purge(commands.Cog):
|
||||||
if user.id in self.purges:
|
if user.id in self.purges:
|
||||||
if message.channel == self.purges[user.id].channel:
|
if message.channel == self.purges[user.id].channel:
|
||||||
async with message.channel.typing():
|
async with message.channel.typing():
|
||||||
await message.channel.purge(before=self.purges[user.id], after=message,
|
await message.channel.purge(before=self.purges[user.id], after=message, limit=None)
|
||||||
limit=None)
|
|
||||||
await self.purges[user.id].delete()
|
await self.purges[user.id].delete()
|
||||||
await message.delete()
|
await message.delete()
|
||||||
del self.purges[user.id]
|
del self.purges[user.id]
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import re
|
from datetime import datetime
|
||||||
from datetime import datetime, timedelta
|
|
||||||
|
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import Embed
|
from discord import Embed
|
||||||
from discord.ext.commands import BadArgument
|
from discord.ext.commands import BadArgument
|
||||||
from discord.ext import tasks
|
from discord.ext import tasks
|
||||||
|
from discord_slash import SlashContext, cog_ext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
from administrator.check import is_enabled
|
from administrator.check import is_enabled
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator import db
|
from administrator import db, slash
|
||||||
from administrator.utils import time_pars, seconds_to_time_string
|
from administrator.utils import time_pars, seconds_to_time_string
|
||||||
|
|
||||||
extension_name = "reminders"
|
extension_name = "reminders"
|
||||||
|
@ -18,58 +19,49 @@ logger = logger.getChild(extension_name)
|
||||||
class Reminders(commands.Cog, name="Reminder"):
|
class Reminders(commands.Cog, name="Reminder"):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Create and manage reminders"
|
return "Create and manage reminders"
|
||||||
|
|
||||||
@commands.group("reminder", pass_context=True)
|
@cog_ext.cog_subcommand(base="reminder", name="add", description="Add a reminder to your reminders list", options=[
|
||||||
|
manage_commands.create_option("message", "The message", SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("time", "When, ?D?H?M?S", SlashCommandOptionType.STRING, True)
|
||||||
|
])
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
async def reminder(self, ctx: commands.Context):
|
async def reminder_add(self, ctx: SlashContext, message: str, time: str):
|
||||||
if ctx.invoked_subcommand is None:
|
|
||||||
await ctx.invoke(self.reminder_help)
|
|
||||||
|
|
||||||
@reminder.group("help", pass_context=True)
|
|
||||||
async def reminder_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Reminder help")
|
|
||||||
embed.add_field(name="reminder add <message> <time>", value="Add a reminder to your reminders list\n"
|
|
||||||
"Time: ?D?H?M?S", inline=False)
|
|
||||||
embed.add_field(name="reminder list", value="Show your tasks list", inline=False)
|
|
||||||
embed.add_field(name="reminder remove [N°]", value="Show your tasks list with if no id given\n"
|
|
||||||
"Remove the task withe the matching id", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@reminder.group("add", pass_context=True)
|
|
||||||
async def reminder_add(self, ctx: commands.Context, message: str, time: str):
|
|
||||||
time = time_pars(time)
|
time = time_pars(time)
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
s.add(db.Task(message, ctx.author.id, ctx.channel.id, now + time, ctx.message.created_at))
|
s.add(db.Task(message, ctx.author.id, ctx.channel.id, now + time, datetime.now()))
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
await ctx.send(f"""Remind you in {seconds_to_time_string(time.total_seconds())} !""")
|
await ctx.send(content=f"""Remind you in {seconds_to_time_string(time.total_seconds())} !""")
|
||||||
|
|
||||||
@reminder.group("list", pass_context=True)
|
@cog_ext.cog_subcommand(base="reminder", name="list", description="Show your tasks list")
|
||||||
async def reminder_list(self, ctx: commands.Context):
|
@is_enabled()
|
||||||
|
async def reminder_list(self, ctx: SlashContext):
|
||||||
embed = Embed(title="Tasks list")
|
embed = Embed(title="Tasks list")
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
for t in s.query(db.Task).filter(db.Task.user == ctx.author.id).all():
|
for t in s.query(db.Task).filter(db.Task.user == ctx.author.id).all():
|
||||||
embed.add_field(name=f"N°{t.id} | {t.date.strftime('%d/%m/%Y %H:%M')}", value=f"{t.message}", inline=False)
|
embed.add_field(name=f"N°{t.id} | {t.date.strftime('%d/%m/%Y %H:%M')}", value=f"{t.message}", inline=False)
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embeds=[embed])
|
||||||
|
|
||||||
@reminder.group("remove", pass_context=True)
|
@cog_ext.cog_subcommand(base="reminder", name="remove", description="Remove the task withe the matching id",
|
||||||
async def reminder_remove(self, ctx: commands.Context, n: int = None):
|
options=[
|
||||||
if n is None:
|
manage_commands.create_option("id", "The reminder id",
|
||||||
await ctx.invoke(self.reminder_list)
|
SlashCommandOptionType.INTEGER, True)])
|
||||||
else:
|
@is_enabled()
|
||||||
|
async def reminder_remove(self, ctx: SlashContext, n: int):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
t = s.query(db.Task).filter(db.Task.id == n).first()
|
t = s.query(db.Task).filter(db.Task.id == n).first()
|
||||||
if t and t.user == ctx.author.id:
|
if t and t.user == ctx.author.id:
|
||||||
s.delete(t)
|
s.delete(t)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
else:
|
else:
|
||||||
s.close()
|
s.close()
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
|
|
@ -1,84 +1,64 @@
|
||||||
import re
|
|
||||||
|
|
||||||
from discord.abc import GuildChannel
|
from discord.abc import GuildChannel
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import Embed, RawReactionActionEvent, RawBulkMessageDeleteEvent, RawMessageDeleteEvent, NotFound, \
|
from discord import Embed, RawReactionActionEvent, RawBulkMessageDeleteEvent, RawMessageDeleteEvent, NotFound, \
|
||||||
InvalidArgument, HTTPException, TextChannel, Forbidden
|
InvalidArgument, HTTPException, TextChannel, Forbidden, Role, Message
|
||||||
from discord.ext.commands import BadArgument
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import cog_ext, SlashContext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
from administrator import db
|
from administrator import db, slash
|
||||||
from administrator.check import is_enabled
|
from administrator.check import is_enabled, guild_only, has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator.utils import event_is_enabled
|
from administrator.utils import event_is_enabled, get_message_by_url
|
||||||
|
|
||||||
extension_name = "rorec"
|
extension_name = "rorec"
|
||||||
logger = logger.getChild(extension_name)
|
logger = logger.getChild(extension_name)
|
||||||
|
|
||||||
channel_id_re = re.compile(r"^<#([0-9]+)>$")
|
|
||||||
|
|
||||||
|
|
||||||
class RoRec(commands.Cog):
|
class RoRec(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Create role-reaction message to give role from a reaction add"
|
return "Create role-reaction message to give role from a reaction add"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_message(session: db.Session, message_id: int, guild_id: int) -> db.RoRec:
|
async def get_message(session: db.Session, ctx: SlashContext, url: str) -> db.RoRec:
|
||||||
m = session.query(db.RoRec).filter(db.RoRec.message == message_id and db.RoRec.guild == guild_id).first()
|
m = session.query(db.RoRec).filter(db.RoRec.message == (await get_message_by_url(ctx, url)).id and
|
||||||
|
db.RoRec.guild == ctx.guild.id).first()
|
||||||
if not m:
|
if not m:
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
else:
|
else:
|
||||||
return m
|
return m
|
||||||
|
|
||||||
async def try_emoji(self, ctx: commands.Context, emoji: str):
|
async def try_emoji(self, msg: Message, emoji: str):
|
||||||
try:
|
try:
|
||||||
await ctx.message.add_reaction(emoji)
|
await msg.add_reaction(emoji)
|
||||||
except (HTTPException, NotFound, InvalidArgument):
|
except (HTTPException, NotFound, InvalidArgument):
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
else:
|
else:
|
||||||
await (await ctx.channel.fetch_message(ctx.message.id)).remove_reaction(emoji, self.bot.user)
|
await (await msg.channel.fetch_message(msg.id)).remove_reaction(emoji, self.bot.user)
|
||||||
|
|
||||||
@commands.group("rorec", pass_context=True)
|
@cog_ext.cog_subcommand(base="rorec", name="new",
|
||||||
|
description="Create a new role-reaction message on the mentioned channel",
|
||||||
|
options=[
|
||||||
|
manage_commands.create_option("title", "The title",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("channel", "The target channel",
|
||||||
|
SlashCommandOptionType.CHANNEL, True),
|
||||||
|
manage_commands.create_option("description", "The description",
|
||||||
|
SlashCommandOptionType.STRING, False),
|
||||||
|
manage_commands.create_option("one", "If only one role is packable",
|
||||||
|
SlashCommandOptionType.BOOLEAN, False)
|
||||||
|
])
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
@commands.guild_only()
|
@guild_only()
|
||||||
@commands.has_permissions(manage_roles=True)
|
@has_permissions(manage_roles=True)
|
||||||
async def rorec(self, ctx: commands.Context):
|
async def rorec_new(self, ctx: SlashContext, title: str, channel: GuildChannel, description: str = "",
|
||||||
if ctx.invoked_subcommand is None:
|
|
||||||
await ctx.invoke(self.rorec_help)
|
|
||||||
|
|
||||||
@rorec.group("help", pass_context=True)
|
|
||||||
async def rorec_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Role-Reaction help")
|
|
||||||
embed.add_field(name="new <title> <#channel> [description] [Only one (True/False)]",
|
|
||||||
value="Create a new role-reaction message on the mentioned channel.\n"
|
|
||||||
"You can specify a description and if you can pick only one role",
|
|
||||||
inline=False)
|
|
||||||
embed.add_field(name="edit <message id> <title> [description}", value="Edit a role-reaction message title and "
|
|
||||||
"description",
|
|
||||||
inline=False)
|
|
||||||
embed.add_field(name="set <message_id> <emoji> <@role1> [@role2] ...",
|
|
||||||
value="Add/edit a emoji with linked roles", inline=False)
|
|
||||||
embed.add_field(name="remove <message_id> <emoji>", value="Remove a emoji of a role-reaction message",
|
|
||||||
inline=False)
|
|
||||||
embed.add_field(name="reload <message_id>", value="Reload the message and the reactions", inline=False)
|
|
||||||
embed.add_field(name="delete <message_id>", value="Remove a role-reaction message", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@rorec.group("new", pass_context=True)
|
|
||||||
async def rorec_new(self, ctx: commands.Context, title: str, channel: str, description: str = "",
|
|
||||||
one: bool = False):
|
one: bool = False):
|
||||||
channel = channel_id_re.findall(channel)
|
if not isinstance(channel, TextChannel):
|
||||||
if len(channel) != 1:
|
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
channel = ctx.guild.get_channel(int(channel[0]))
|
|
||||||
if not channel:
|
|
||||||
raise BadArgument()
|
|
||||||
|
|
||||||
if description in ["True", "False"]:
|
|
||||||
one = True if description == "True" else False
|
|
||||||
description = ""
|
|
||||||
|
|
||||||
embed = Embed(title=title, description=description)
|
embed = Embed(title=title, description=description)
|
||||||
embed.add_field(name="Roles", value="No role yet...")
|
embed.add_field(name="Roles", value="No role yet...")
|
||||||
|
@ -88,12 +68,24 @@ class RoRec(commands.Cog):
|
||||||
s.add(r)
|
s.add(r)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@rorec.group("edit", pass_context=True)
|
@cog_ext.cog_subcommand(base="rorec", name="edit",
|
||||||
async def rorec_edit(self, ctx: commands.Context, message_id: int, title: str, description: str = None):
|
description="Edit a role-reaction message title and description",
|
||||||
|
options=[
|
||||||
|
manage_commands.create_option("url", "The message url",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("title", "The new title",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("description", "The new description",
|
||||||
|
SlashCommandOptionType.STRING, False)
|
||||||
|
])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(manage_roles=True)
|
||||||
|
async def rorec_edit(self, ctx: SlashContext, url: str, title: str, description: str = ""):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
m = self.get_message(s, message_id, ctx.guild.id)
|
m = await self.get_message(s, ctx, url)
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
message = await ctx.guild.get_channel(m.channel).fetch_message(m.message)
|
message = await ctx.guild.get_channel(m.channel).fetch_message(m.message)
|
||||||
|
@ -101,31 +93,57 @@ class RoRec(commands.Cog):
|
||||||
embed.title = title
|
embed.title = title
|
||||||
embed.description = description
|
embed.description = description
|
||||||
await message.edit(embed=embed)
|
await message.edit(embed=embed)
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@rorec.group("set", pass_context=True)
|
@cog_ext.cog_subcommand(base="rorec", name="set",
|
||||||
async def rorec_set(self, ctx: commands.Context, message_id: int, emoji: str):
|
description="Add/edit a emoji with linked roles",
|
||||||
|
options=[
|
||||||
|
manage_commands.create_option("url", "The message url",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("emoji", "The emoji",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("role", "The role",
|
||||||
|
SlashCommandOptionType.ROLE, True)
|
||||||
|
])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(manage_roles=True)
|
||||||
|
async def rorec_set(self, ctx: SlashContext, url: str, emoji: str, role: Role):
|
||||||
|
await ctx.send(content="\U000023f3")
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
m = self.get_message(s, message_id, ctx.guild.id)
|
m = await self.get_message(s, ctx, url)
|
||||||
|
|
||||||
if len(ctx.message.role_mentions) == 0:
|
await ctx.delete()
|
||||||
raise BadArgument()
|
msg = await ctx.channel.send("\U000023f3")
|
||||||
|
await self.try_emoji(msg, emoji)
|
||||||
await self.try_emoji(ctx, emoji)
|
|
||||||
|
|
||||||
data = m.get_data()
|
data = m.get_data()
|
||||||
data[emoji] = list(map(lambda x: x.id, ctx.message.role_mentions))
|
data[emoji] = list(map(lambda x: x.id, [role]))
|
||||||
m.set_data(data)
|
m.set_data(data)
|
||||||
await self.rorec_update(m)
|
await self.rorec_update(m)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await msg.edit(content="\U0001f44d")
|
||||||
|
|
||||||
@rorec.group("remove", pass_context=True)
|
@cog_ext.cog_subcommand(base="rorec", name="remove",
|
||||||
async def rorec_remove(self, ctx: commands.Context, message_id: int, emoji: str):
|
description="Remove a emoji of a role-reaction message",
|
||||||
|
options=[
|
||||||
|
manage_commands.create_option("url", "The message url",
|
||||||
|
SlashCommandOptionType.STRING, True),
|
||||||
|
manage_commands.create_option("emoji", "The emoji",
|
||||||
|
SlashCommandOptionType.STRING, True)
|
||||||
|
])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(manage_roles=True)
|
||||||
|
async def rorec_remove(self, ctx: SlashContext, url: str, emoji: str):
|
||||||
|
await ctx.send(content="\U000023f3")
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
m = self.get_message(s, message_id, ctx.guild.id)
|
m = await self.get_message(s, ctx, url)
|
||||||
await self.try_emoji(ctx, emoji)
|
|
||||||
|
await ctx.delete()
|
||||||
|
msg = await ctx.channel.send("\U000023f3")
|
||||||
|
await self.try_emoji(msg, emoji)
|
||||||
|
|
||||||
data = m.get_data()
|
data = m.get_data()
|
||||||
if emoji not in data:
|
if emoji not in data:
|
||||||
|
@ -136,24 +154,37 @@ class RoRec(commands.Cog):
|
||||||
await self.rorec_update(m)
|
await self.rorec_update(m)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await msg.edit("\U0001f44d")
|
||||||
|
|
||||||
@rorec.group("reload", pass_context=True)
|
@cog_ext.cog_subcommand(base="rorec", name="reload",
|
||||||
async def rorec_reload(self, ctx: commands.Context, message_id: int):
|
description="Reload the message and the reactions",
|
||||||
|
options=[manage_commands.create_option("url", "The message url",
|
||||||
|
SlashCommandOptionType.STRING, True)])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(manage_roles=True)
|
||||||
|
async def rorec_reload(self, ctx: SlashContext, url: str):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
m = self.get_message(s, message_id, ctx.guild.id)
|
m = await self.get_message(s, ctx, url)
|
||||||
|
|
||||||
await self.rorec_update(m)
|
await self.rorec_update(m)
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@rorec.group("delete", pass_context=True)
|
@cog_ext.cog_subcommand(base="rorec", name="delete",
|
||||||
async def rorec_delete(self, ctx: commands.Context, message_id: int):
|
description="Remove a role-reaction message",
|
||||||
|
options=[manage_commands.create_option("url", "The message link",
|
||||||
|
SlashCommandOptionType.STRING, True)])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(manage_roles=True)
|
||||||
|
async def rorec_delete(self, ctx: SlashContext, url: str):
|
||||||
|
msg = await get_message_by_url(ctx, url)
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
m = self.get_message(s, message_id, ctx.guild.id)
|
await self.get_message(s, ctx, url)
|
||||||
s.close()
|
s.close()
|
||||||
await (await self.bot.get_channel(m.channel).fetch_message(m.message)).delete()
|
await msg.delete()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
async def rorec_update(self, m: db.RoRec):
|
async def rorec_update(self, m: db.RoRec):
|
||||||
channel = self.bot.get_channel(m.channel)
|
channel = self.bot.get_channel(m.channel)
|
||||||
|
@ -173,6 +204,8 @@ class RoRec(commands.Cog):
|
||||||
value += ", ".join(map(lambda x: self.bot.get_guild(m.guild).get_role(x).mention, data[d]))
|
value += ", ".join(map(lambda x: self.bot.get_guild(m.guild).get_role(x).mention, data[d]))
|
||||||
value += "\n"
|
value += "\n"
|
||||||
await message.add_reaction(d)
|
await message.add_reaction(d)
|
||||||
|
if not value:
|
||||||
|
value = "No role yet..."
|
||||||
embed.add_field(name=name, value=value)
|
embed.add_field(name=name, value=value)
|
||||||
await message.edit(embed=embed)
|
await message.edit(embed=embed)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import Member, VoiceState, Embed, Reaction, Guild
|
from discord import Member, VoiceState, Embed, Reaction, Guild
|
||||||
from discord.ext.commands import CommandNotFound
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import SlashContext, cog_ext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
from administrator.check import is_enabled
|
from administrator import slash
|
||||||
|
from administrator.check import is_enabled, guild_only, has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator.utils import event_is_enabled
|
from administrator.utils import event_is_enabled
|
||||||
|
|
||||||
|
@ -21,29 +24,24 @@ class Speak(commands.Cog):
|
||||||
self.last_reaction = None
|
self.last_reaction = None
|
||||||
self.voice_message = None
|
self.voice_message = None
|
||||||
self.last_message = None
|
self.last_message = None
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Speech manager"
|
return "Speech manager"
|
||||||
|
|
||||||
@commands.group("speak", pass_context=True)
|
@cog_ext.cog_subcommand(base="speak", name="setup",
|
||||||
|
description="Set your current voice channel as the speak channel",
|
||||||
|
options=[
|
||||||
|
manage_commands.create_option("strict", "Mute everyone on setup",
|
||||||
|
SlashCommandOptionType.BOOLEAN, False)
|
||||||
|
])
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
@commands.guild_only()
|
@guild_only()
|
||||||
@commands.has_guild_permissions(mute_members=True)
|
@has_permissions(mute_members=True)
|
||||||
async def speak(self, ctx: commands.Context):
|
async def speak_setup(self, ctx: SlashContext, strict: bool = False):
|
||||||
if ctx.invoked_subcommand is None:
|
self.strict = strict
|
||||||
raise CommandNotFound
|
if not ctx.author.voice:
|
||||||
|
raise BadArgument()
|
||||||
@speak.group("help", pass_context=True)
|
|
||||||
async def speak_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Speak help")
|
|
||||||
embed.add_field(name="speak setup [strict]",
|
|
||||||
value="Set your current voice channel as the speak channel", inline=False)
|
|
||||||
embed.add_field(name="speak mute", value="Mute everyone on the speak channel except you", inline=False)
|
|
||||||
embed.add_field(name="speak unmute", value="Unmute everyone on the speak channel except you", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@speak.group("setup", pass_context=True)
|
|
||||||
async def speak_setup(self, ctx: commands.Context, *args):
|
|
||||||
self.voice_chan = ctx.author.voice.channel.id
|
self.voice_chan = ctx.author.voice.channel.id
|
||||||
embed = Embed(title="Speak \U0001f508")
|
embed = Embed(title="Speak \U0001f508")
|
||||||
embed.add_field(name="Waiting list \u23f3", value="Nobody", inline=False)
|
embed.add_field(name="Waiting list \u23f3", value="Nobody", inline=False)
|
||||||
|
@ -57,24 +55,30 @@ class Speak(commands.Cog):
|
||||||
"\u274C Clear the speak\n"
|
"\u274C Clear the speak\n"
|
||||||
"Remove your reaction to remove from list",
|
"Remove your reaction to remove from list",
|
||||||
inline=False)
|
inline=False)
|
||||||
self.voice_message = await ctx.send(embed=embed)
|
self.voice_message = await ctx.channel.send(embed=embed)
|
||||||
for reaction in ["\U0001f5e3", "\u2757", "\u27A1", "\U0001F512", "\U0001F507", "\U0001F50A", "\u274C"]:
|
for reaction in ["\U0001f5e3", "\u2757", "\u27A1", "\U0001F512", "\U0001F507", "\U0001F50A", "\u274C"]:
|
||||||
await self.voice_message.add_reaction(reaction)
|
await self.voice_message.add_reaction(reaction)
|
||||||
self.voice_message = await self.voice_message.channel.fetch_message(self.voice_message.id)
|
self.voice_message = await self.voice_message.channel.fetch_message(self.voice_message.id)
|
||||||
|
|
||||||
@speak.group("mute", pass_context=True)
|
@cog_ext.cog_subcommand(base="speak", name="mute", description="Mute everyone on the speak channel except you")
|
||||||
async def speak_mute(self, ctx: commands.Context):
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(mute_members=True)
|
||||||
|
async def speak_mute(self, ctx: SlashContext):
|
||||||
if not await self.mute(True, ctx.author):
|
if not await self.mute(True, ctx.author):
|
||||||
await ctx.message.add_reaction("\u274C")
|
await ctx.send(content="\u274C")
|
||||||
else:
|
else:
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@speak.group("unmute", pass_context=True)
|
@cog_ext.cog_subcommand(base="speak", name="unmute", description="Unmute everyone on the speak channel except you")
|
||||||
async def speak_unmute(self, ctx: commands.Context):
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(mute_members=True)
|
||||||
|
async def speak_unmute(self, ctx: SlashContext):
|
||||||
if not await self.mute(False, ctx.author):
|
if not await self.mute(False, ctx.author):
|
||||||
await ctx.message.add_reaction("\u274C")
|
await ctx.send(content="\u274C")
|
||||||
else:
|
else:
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_voice_state_update(self, member: Member, before: VoiceState, after: VoiceState):
|
async def on_voice_state_update(self, member: Member, before: VoiceState, after: VoiceState):
|
||||||
|
@ -91,7 +95,7 @@ class Speak(commands.Cog):
|
||||||
(after is not None and after.channel is not None and after.channel.id != self.voice_chan):
|
(after is not None and after.channel is not None and after.channel.id != self.voice_chan):
|
||||||
await member.edit(mute=False)
|
await member.edit(mute=False)
|
||||||
|
|
||||||
async def cog_after_invoke(self, ctx: commands.Context):
|
async def cog_after_invoke(self, ctx: SlashContext):
|
||||||
await ctx.message.delete(delay=30)
|
await ctx.message.delete(delay=30)
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from discord import Embed
|
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
from discord_slash import cog_ext, SlashContext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
|
from administrator import slash
|
||||||
from administrator.check import is_enabled
|
from administrator.check import is_enabled
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
|
|
||||||
|
@ -14,26 +16,16 @@ class TeX(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.polls = {}
|
self.polls = {}
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Render TeX formula"
|
return "Render TeX formula"
|
||||||
|
|
||||||
@commands.group("tex", pass_context=True)
|
@cog_ext.cog_slash(name="tex", description="Render a TeX formula", options=[
|
||||||
|
manage_commands.create_option("formula", "The TeX formula", SlashCommandOptionType.STRING, True)])
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
async def tex(self, ctx: commands.Context):
|
async def tex(self, ctx: SlashContext, formula: str):
|
||||||
if ctx.message.content.count("`") == 2:
|
await ctx.send(content=f"https://chart.apis.google.com/chart?cht=tx&chs=40&{urlencode({'chl': formula})}")
|
||||||
start = ctx.message.content.find("`")
|
|
||||||
end = ctx.message.content.find("`", start+1)
|
|
||||||
command = ctx.message.content[start+1:end]
|
|
||||||
await ctx.send(f"https://chart.apis.google.com/chart?cht=tx&chs=40&{urlencode({'chl': command})}")
|
|
||||||
elif ctx.invoked_subcommand is None:
|
|
||||||
await ctx.invoke(self.tex_help)
|
|
||||||
|
|
||||||
@tex.group("help", pass_context=True)
|
|
||||||
async def tex_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="TeX help")
|
|
||||||
embed.add_field(name="tex \`formula\`", value="Render a TeX formula", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
|
|
@ -5,9 +5,12 @@ from time import mktime
|
||||||
from discord import Embed, Forbidden, HTTPException
|
from discord import Embed, Forbidden, HTTPException
|
||||||
from discord.ext import commands, tasks
|
from discord.ext import commands, tasks
|
||||||
from discord.ext.commands import BadArgument
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import SlashContext, cog_ext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
from feedparser import parse
|
from feedparser import parse
|
||||||
|
|
||||||
import db
|
import db
|
||||||
|
from administrator import slash
|
||||||
from administrator.check import is_enabled
|
from administrator.check import is_enabled
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
|
|
||||||
|
@ -21,25 +24,14 @@ class Tomuss(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.tomuss_loop.start()
|
self.tomuss_loop.start()
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "PCP Univ Lyon 1"
|
return "PCP Univ Lyon 1"
|
||||||
|
|
||||||
@commands.group("tomuss", pass_context=True)
|
@cog_ext.cog_subcommand(base="tomuss", name="set", description="Set your tomuss RSS feed", options=[
|
||||||
@is_enabled()
|
manage_commands.create_option("url", "The RSS URL", SlashCommandOptionType.STRING, True)])
|
||||||
async def tomuss(self, ctx: commands.Context):
|
async def tomuss_set(self, ctx: SlashContext, url: str):
|
||||||
if ctx.invoked_subcommand is None:
|
|
||||||
await ctx.invoke(self.tomuss_help)
|
|
||||||
|
|
||||||
@tomuss.group("help", pass_context=True)
|
|
||||||
async def tomuss_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Tomuss help")
|
|
||||||
embed.add_field(name="tomuss set <url>", value="Set your tomuss RSS feed", inline=False)
|
|
||||||
embed.add_field(name="tomuss unset", value="Unset your tomuss RSS feed", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@tomuss.group("set", pass_context=True)
|
|
||||||
async def tomuss_set(self, ctx: commands.Context, url: str):
|
|
||||||
if not url_re.fullmatch(url):
|
if not url_re.fullmatch(url):
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
entries = parse(url).entries
|
entries = parse(url).entries
|
||||||
|
@ -59,10 +51,10 @@ class Tomuss(commands.Cog):
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.channel.send(f"Tomuss RSS set for {ctx.author.mention} \U0001f44d")
|
||||||
|
|
||||||
@tomuss.group("unset", pass_context=True)
|
@cog_ext.cog_subcommand(base="tomuss", name="unset", description="Unset your tomuss RSS feed")
|
||||||
async def tomuss_unset(self, ctx: commands.Context):
|
async def tomuss_unset(self, ctx: SlashContext):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
t = s.query(db.Tomuss).get(ctx.author.id)
|
t = s.query(db.Tomuss).get(ctx.author.id)
|
||||||
if not t:
|
if not t:
|
||||||
|
@ -70,7 +62,7 @@ class Tomuss(commands.Cog):
|
||||||
s.delete(t)
|
s.delete(t)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@tasks.loop(minutes=5)
|
@tasks.loop(minutes=5)
|
||||||
async def tomuss_loop(self):
|
async def tomuss_loop(self):
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from discord import Embed, Member, Guild
|
from discord import Embed, Guild
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord.ext.commands import BadArgument, CommandError
|
from discord_slash import cog_ext, SlashContext, SlashCommandOptionType
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
|
from administrator import slash
|
||||||
from administrator.check import is_enabled
|
from administrator.check import is_enabled
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
|
|
||||||
|
@ -15,34 +17,17 @@ logger = logger.getChild(extension_name)
|
||||||
class Utils(commands.Cog):
|
class Utils(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Some tools"
|
return "Some tools"
|
||||||
|
|
||||||
@commands.group("utils", pass_context=True)
|
|
||||||
@is_enabled()
|
|
||||||
async def utils(self, ctx: commands.Context):
|
|
||||||
if ctx.invoked_subcommand is None:
|
|
||||||
await ctx.invoke(self.utils_help)
|
|
||||||
|
|
||||||
@utils.group("help", pass_context=True)
|
|
||||||
async def utils_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Utils help")
|
|
||||||
try:
|
|
||||||
if await self.eval.can_run(ctx):
|
|
||||||
embed.add_field(name="eval \`\`\`code\`\`\`", value="Execute some code", inline=False)
|
|
||||||
except CommandError:
|
|
||||||
pass
|
|
||||||
embed.add_field(name="ping", value="Return the ping with the discord API", inline=False)
|
|
||||||
embed.add_field(name="info [@user]", value="Show information on guild or user specified", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@commands.group("eval", pass_context=True)
|
@commands.group("eval", pass_context=True)
|
||||||
@commands.is_owner()
|
@commands.is_owner()
|
||||||
async def eval(self, ctx: commands.Context):
|
async def eval(self, ctx: commands.Context):
|
||||||
start = ctx.message.content.find("```")
|
start = ctx.message.content.find("```python")
|
||||||
end = ctx.message.content.find("```", start+3)
|
end = ctx.message.content.find("```", start+9)
|
||||||
command = ctx.message.content[start+3:end]
|
command = ctx.message.content[start+9:end]
|
||||||
try:
|
try:
|
||||||
exec("async def __ex(self, ctx):\n" + command.replace("\n", "\n "))
|
exec("async def __ex(self, ctx):\n" + command.replace("\n", "\n "))
|
||||||
out = str(await locals()["__ex"](self, ctx))
|
out = str(await locals()["__ex"](self, ctx))
|
||||||
|
@ -55,20 +40,20 @@ class Utils(commands.Cog):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await ctx.send(f"```{e.__class__.__name__}: {e}```")
|
await ctx.send(f"```{e.__class__.__name__}: {e}```")
|
||||||
|
|
||||||
@commands.group("ping", pass_context=True)
|
@cog_ext.cog_slash(name="ping", description="Return the ping with the discord API")
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
async def ping(self, ctx: commands.Context):
|
async def ping(self, ctx: SlashContext):
|
||||||
start = datetime.now()
|
start = datetime.now()
|
||||||
msg = await ctx.send(f"Discord WebSocket latency: `{round(self.bot.latency*1000)}ms`")
|
content = f"Discord WebSocket latency: `{round(self.bot.latency*1000)}ms`"
|
||||||
await msg.edit(content=msg.content+"\n"+f"Bot latency: `{round((msg.created_at - start).microseconds/1000)}ms`")
|
await ctx.send(content=content)
|
||||||
|
await ctx.edit(content=content+"\n"+f"Bot latency: `{round((datetime.now() - start).microseconds/1000)}ms`")
|
||||||
|
|
||||||
@commands.group("info", pass_context=True)
|
@cog_ext.cog_slash(name="info",
|
||||||
|
description="Show information on guild or user specified",
|
||||||
|
options=[manage_commands.create_option("user", "A user", SlashCommandOptionType.USER, False)])
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
async def info(self, ctx: commands.Context):
|
async def info(self, ctx: SlashContext, user: SlashCommandOptionType.USER = None):
|
||||||
if len(ctx.message.mentions) > 1:
|
if user:
|
||||||
raise BadArgument()
|
|
||||||
elif ctx.message.mentions:
|
|
||||||
user: Member = ctx.message.mentions[0]
|
|
||||||
embed = Embed(title=str(user))
|
embed = Embed(title=str(user))
|
||||||
embed.set_author(name="User infos", icon_url=user.avatar_url)
|
embed.set_author(name="User infos", icon_url=user.avatar_url)
|
||||||
embed.add_field(name="Display name", value=user.display_name)
|
embed.add_field(name="Display name", value=user.display_name)
|
||||||
|
@ -129,11 +114,11 @@ class Utils(commands.Cog):
|
||||||
embed.add_field(name="Shard ID", value=guild.shard_id)
|
embed.add_field(name="Shard ID", value=guild.shard_id)
|
||||||
embed.add_field(name="Created at", value=guild.created_at)
|
embed.add_field(name="Created at", value=guild.created_at)
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embeds=[embed])
|
||||||
|
|
||||||
@commands.group("about", pass_context=True)
|
@cog_ext.cog_slash(name="about", description="Show information about the bot")
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
async def about(self, ctx: commands.Context):
|
async def about(self, ctx: SlashContext):
|
||||||
embed = Embed(title=self.bot.user.display_name, description=self.bot.description)
|
embed = Embed(title=self.bot.user.display_name, description=self.bot.description)
|
||||||
embed.set_author(name="Administrator", icon_url=self.bot.user.avatar_url, url="https://github.com/flifloo")
|
embed.set_author(name="Administrator", icon_url=self.bot.user.avatar_url, url="https://github.com/flifloo")
|
||||||
flifloo = self.bot.get_user(177393521051959306)
|
flifloo = self.bot.get_user(177393521051959306)
|
||||||
|
@ -142,9 +127,12 @@ class Utils(commands.Cog):
|
||||||
value=(await self.bot.application_info()).owner.display_name)
|
value=(await self.bot.application_info()).owner.display_name)
|
||||||
embed.add_field(name="Guilds", value=str(len(self.bot.guilds)))
|
embed.add_field(name="Guilds", value=str(len(self.bot.guilds)))
|
||||||
embed.add_field(name="Extensions", value=str(len(self.bot.extensions)))
|
embed.add_field(name="Extensions", value=str(len(self.bot.extensions)))
|
||||||
embed.add_field(name="Commands", value=str(len(self.bot.all_commands)))
|
embed.add_field(name="Commands", value=str(len(self.bot.all_commands)+len(slash.commands)))
|
||||||
embed.add_field(name="Latency", value=f"{round(self.bot.latency*1000)} ms")
|
embed.add_field(name="Latency", value=f"{round(self.bot.latency*1000)} ms")
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embeds=[embed])
|
||||||
|
|
||||||
|
def cog_unload(self):
|
||||||
|
slash.remove_cog_commands(self)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
@ -165,3 +153,6 @@ def teardown(bot):
|
||||||
logger.error(f"Error unloading: {e}")
|
logger.error(f"Error unloading: {e}")
|
||||||
else:
|
else:
|
||||||
logger.info(f"Unload successful")
|
logger.info(f"Unload successful")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
from discord import Embed, Forbidden, Member, Guild
|
from discord import Embed, Forbidden, Member, Guild
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord.ext.commands import BadArgument
|
from discord.ext.commands import BadArgument
|
||||||
|
from discord_slash import cog_ext, SlashCommandOptionType, SlashContext
|
||||||
|
from discord_slash.utils import manage_commands
|
||||||
|
|
||||||
from administrator import db
|
from administrator import db, slash
|
||||||
from administrator.check import is_enabled
|
from administrator.check import is_enabled, guild_only, has_permissions
|
||||||
from administrator.logger import logger
|
from administrator.logger import logger
|
||||||
from administrator.utils import time_pars, seconds_to_time_string
|
from administrator.utils import time_pars, seconds_to_time_string
|
||||||
|
|
||||||
|
@ -14,12 +16,13 @@ logger = logger.getChild(extension_name)
|
||||||
class Warn(commands.Cog):
|
class Warn(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
slash.get_cog_commands(self)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return "Send warning to user and make custom action after a number of warn"
|
return "Send warning to user and make custom action after a number of warn"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def check_warn(ctx: commands.Context, target: Member):
|
async def check_warn(ctx: SlashContext, target: Member):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
c = s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id, db.Warn.user == target.id).count()
|
c = s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id, db.Warn.user == target.id).count()
|
||||||
a = s.query(db.WarnAction).filter(db.WarnAction.guild == ctx.guild.id, db.WarnAction.count == c).first()
|
a = s.query(db.WarnAction).filter(db.WarnAction.guild == ctx.guild.id, db.WarnAction.count == c).first()
|
||||||
|
@ -32,96 +35,72 @@ class Warn(commands.Cog):
|
||||||
elif a.action == "mute":
|
elif a.action == "mute":
|
||||||
pass # Integration with upcoming ban & mute extension
|
pass # Integration with upcoming ban & mute extension
|
||||||
|
|
||||||
@staticmethod
|
@cog_ext.cog_subcommand(base="warn", name="add", description="Send a warn to a user", options=[
|
||||||
def get_target(ctx: commands.Context, user: str) -> Member:
|
manage_commands.create_option("user", "The user", SlashCommandOptionType.USER, True),
|
||||||
users = {str(m): m for m in ctx.guild.members}
|
manage_commands.create_option("description", "The description", SlashCommandOptionType.STRING, True)
|
||||||
if user not in users:
|
])
|
||||||
raise BadArgument()
|
|
||||||
return users[user]
|
|
||||||
|
|
||||||
@commands.group("warn", pass_context=True)
|
|
||||||
@is_enabled()
|
@is_enabled()
|
||||||
@commands.guild_only()
|
@guild_only()
|
||||||
#@commands.has_permissions(manage_roles=True, kick_members=True, ban_members=True, mute_members=True)
|
@has_permissions(kick_members=True, ban_members=True, mute_members=True)
|
||||||
async def warn(self, ctx: commands.Context):
|
async def warn_add(self, ctx: SlashContext, user: Member, description: str):
|
||||||
if ctx.invoked_subcommand is None:
|
|
||||||
await ctx.invoke(self.warn_help)
|
|
||||||
|
|
||||||
@warn.group("help", pass_context=True)
|
|
||||||
async def warn_help(self, ctx: commands.Context):
|
|
||||||
embed = Embed(title="Warn help")
|
|
||||||
embed.add_field(name="add <user> <description>", value="Send a warn to a user", inline=False)
|
|
||||||
embed.add_field(name="remove <user> <number>", value="Remove a number of warn to a user", inline=False)
|
|
||||||
embed.add_field(name="purge <user>", value="Remove all warn of a user", inline=False)
|
|
||||||
embed.add_field(name="list [user#discriminator|actions]", value="List warn of the guild or a specified user\n"
|
|
||||||
"If you specify `actions` instead of a user, "
|
|
||||||
"all the actions of the guild will be listed",
|
|
||||||
inline=False)
|
|
||||||
embed.add_field(name="action <count> <action>", value="Set an action for a count of warn\n"
|
|
||||||
"Actions: `mute<time>`, `kick`, `ban[time]`, `nothing`\n"
|
|
||||||
"Time: `?D?H?M?S`\n"
|
|
||||||
"Example: `action 1 mute1H` to mute someone for one hour "
|
|
||||||
"after only one war\n"
|
|
||||||
"or `action 3 ban1D` to ban someone for one day after 3 "
|
|
||||||
"warns", inline=False)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
@warn.group("add", pass_context=True)
|
|
||||||
async def warn_add(self, ctx: commands.Context, user: str, description: str):
|
|
||||||
target = self.get_target(ctx, user)
|
|
||||||
|
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
s.add(db.Warn(target.id, ctx.author.id, ctx.guild.id, description))
|
s.add(db.Warn(user.id, ctx.author.id, ctx.guild.id, description))
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
embed = Embed(title="You get warned !", description="A moderator send you a warn", color=0xff0000)
|
embed = Embed(title="You get warned !", description="A moderator send you a warn", color=0xff0000)
|
||||||
embed.add_field(name="Description:", value=description)
|
embed.add_field(name="Description:", value=description)
|
||||||
await target.send(embed=embed)
|
await user.send(embed=embed)
|
||||||
except Forbidden:
|
except Forbidden:
|
||||||
await ctx.send("Fail to send warn notification to the user, DM close :warning:")
|
await ctx.send(content="Fail to send warn notification to the user, DM close :warning:")
|
||||||
else:
|
else:
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
await self.check_warn(ctx, target)
|
await self.check_warn(ctx, user)
|
||||||
|
|
||||||
@warn.group("remove", pass_context=True)
|
@cog_ext.cog_subcommand(base="warn", name="remove", description="Remove a number of warn to a user", options=[
|
||||||
async def warn_remove(self, ctx: commands.Context, user: str, number: int):
|
manage_commands.create_option("user", "The user", SlashCommandOptionType.USER, True),
|
||||||
target = self.get_target(ctx, user)
|
manage_commands.create_option("number", "The warn to remove", SlashCommandOptionType.INTEGER, True)
|
||||||
|
])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(kick_members=True, ban_members=True, mute_members=True)
|
||||||
|
async def warn_remove(self, ctx: SlashContext, user: Member, number: int):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
ws = s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id, db.Warn.user == target.id).all()
|
ws = s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id, db.Warn.user == user.id).all()
|
||||||
if number <= 0 or number > len(ws):
|
if number <= 0 or number > len(ws):
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
s.delete(ws[number-1])
|
s.delete(ws[number-1])
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@warn.group("purge", pass_context=True)
|
@cog_ext.cog_subcommand(base="warn", name="purge", description="Remove all warn of a user", options=[
|
||||||
async def warn_purge(self, ctx: commands.Context, user: str):
|
manage_commands.create_option("user", "The user", SlashCommandOptionType.USER, True)])
|
||||||
target = self.get_target(ctx, user)
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(kick_members=True, ban_members=True, mute_members=True)
|
||||||
|
async def warn_purge(self, ctx: SlashContext, user: Member):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
for w in s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id, db.Warn.user == target.id).all():
|
for w in s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id, db.Warn.user == user.id).all():
|
||||||
s.delete(w)
|
s.delete(w)
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@warn.group("list", pass_context=True)
|
@cog_ext.cog_subcommand(base="warn", name="list", description="List warn of the guild or a specified user",
|
||||||
async def warn_list(self, ctx: commands.Context, user: str = None):
|
options=[
|
||||||
|
manage_commands.create_option("user", "The user", SlashCommandOptionType.USER, False)
|
||||||
|
])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(kick_members=True, ban_members=True, mute_members=True)
|
||||||
|
async def warn_list(self, ctx: SlashContext, user: Member = None):
|
||||||
s = db.Session()
|
s = db.Session()
|
||||||
embed = Embed(title="Warn list")
|
embed = Embed(title="Warn list")
|
||||||
ws = {}
|
ws = {}
|
||||||
|
if user:
|
||||||
if user == "actions":
|
ws[user.id] = s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id, db.Warn.user == user.id).all()
|
||||||
embed.title = "Actions list"
|
|
||||||
for a in s.query(db.WarnAction).filter(db.WarnAction.guild == ctx.guild.id).order_by(db.WarnAction.count)\
|
|
||||||
.all():
|
|
||||||
action = f"{a.action} for {seconds_to_time_string(a.duration)}" if a.duration else a.action
|
|
||||||
embed.add_field(name=f"{a.count} warn(s)", value=action, inline=False)
|
|
||||||
elif user:
|
|
||||||
target = self.get_target(ctx, user)
|
|
||||||
ws[target.id] = s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id, db.Warn.user == target.id).all()
|
|
||||||
else:
|
else:
|
||||||
for w in s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id).all():
|
for w in s.query(db.Warn).filter(db.Warn.guild == ctx.guild.id).all():
|
||||||
if w.user not in ws:
|
if w.user not in ws:
|
||||||
|
@ -134,10 +113,45 @@ class Warn(commands.Cog):
|
||||||
for w in ws[u]]
|
for w in ws[u]]
|
||||||
embed.add_field(name=self.bot.get_user(u), value="\n".join(warns), inline=False)
|
embed.add_field(name=self.bot.get_user(u), value="\n".join(warns), inline=False)
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embeds=[embed])
|
||||||
|
|
||||||
@warn.group("action", pass_context=True)
|
@cog_ext.cog_subcommand(base="warn", name="actions", description="List all the actions of the guild")
|
||||||
async def warn_action(self, ctx: commands.Context, count: int, action: str):
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(kick_members=True, ban_members=True, mute_members=True)
|
||||||
|
async def warn_actions(self, ctx: SlashContext):
|
||||||
|
s = db.Session()
|
||||||
|
embed = Embed(title="Warn list")
|
||||||
|
ws = {}
|
||||||
|
embed.title = "Actions list"
|
||||||
|
for a in s.query(db.WarnAction).filter(db.WarnAction.guild == ctx.guild.id).order_by(db.WarnAction.count) \
|
||||||
|
.all():
|
||||||
|
action = f"{a.action} for {seconds_to_time_string(a.duration)}" if a.duration else a.action
|
||||||
|
embed.add_field(name=f"{a.count} warn(s)", value=action, inline=False)
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
for u in ws:
|
||||||
|
warns = [f"{self.bot.get_user(w.author).mention} - {w.date.strftime('%d/%m/%Y %H:%M')}```{w.description}```"
|
||||||
|
for w in ws[u]]
|
||||||
|
embed.add_field(name=self.bot.get_user(u), value="\n".join(warns), inline=False)
|
||||||
|
|
||||||
|
await ctx.send(embeds=[embed])
|
||||||
|
|
||||||
|
@cog_ext.cog_subcommand(base="warn", name="action", description="Set an action for a count of warn", options=[
|
||||||
|
manage_commands.create_option("count", "The number of warns", SlashCommandOptionType.INTEGER, True),
|
||||||
|
manage_commands.create_option("action", "The action", SlashCommandOptionType.STRING, True, [
|
||||||
|
manage_commands.create_choice("mute", "mute"),
|
||||||
|
manage_commands.create_choice("kick", "kick"),
|
||||||
|
manage_commands.create_choice("ban", "ban"),
|
||||||
|
manage_commands.create_choice("nothing", "nothing")
|
||||||
|
]),
|
||||||
|
manage_commands.create_option("time", "The duration of the action, ?D?H?M?S",
|
||||||
|
SlashCommandOptionType.STRING, False)
|
||||||
|
])
|
||||||
|
@is_enabled()
|
||||||
|
@guild_only()
|
||||||
|
@has_permissions(administrator=True)
|
||||||
|
async def warn_action(self, ctx: SlashContext, count: int, action: str, time: str = None):
|
||||||
if count <= 0 or\
|
if count <= 0 or\
|
||||||
(action not in ["kick", "nothing"] and not action.startswith("mute") and not action.startswith("ban")):
|
(action not in ["kick", "nothing"] and not action.startswith("mute") and not action.startswith("ban")):
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
|
@ -151,14 +165,8 @@ class Warn(commands.Cog):
|
||||||
else:
|
else:
|
||||||
raise BadArgument()
|
raise BadArgument()
|
||||||
else:
|
else:
|
||||||
time = None
|
if time:
|
||||||
if action.startswith("mute"):
|
time = time_pars(time).total_seconds()
|
||||||
time = time_pars(action.replace("mute", "")).total_seconds()
|
|
||||||
action = "mute"
|
|
||||||
elif action.startswith("ban"):
|
|
||||||
if action[3:]:
|
|
||||||
time = time_pars(action.replace("ban", "")).total_seconds()
|
|
||||||
action = "ban"
|
|
||||||
if a:
|
if a:
|
||||||
a.action = action
|
a.action = action
|
||||||
a.duration = time
|
a.duration = time
|
||||||
|
@ -167,7 +175,7 @@ class Warn(commands.Cog):
|
||||||
|
|
||||||
s.commit()
|
s.commit()
|
||||||
s.close()
|
s.close()
|
||||||
await ctx.message.add_reaction("\U0001f44d")
|
await ctx.send(content="\U0001f44d")
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_guild_remove(self, guild: Guild):
|
async def on_guild_remove(self, guild: Guild):
|
||||||
|
|
|
@ -3,6 +3,7 @@ async-timeout==3.0.1
|
||||||
attrs==20.2.0
|
attrs==20.2.0
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
discord==1.0.1
|
discord==1.0.1
|
||||||
|
discord-py-slash-command==1.0.8.5
|
||||||
discord.py==1.5.1
|
discord.py==1.5.1
|
||||||
feedparser==6.0.2
|
feedparser==6.0.2
|
||||||
idna==2.10
|
idna==2.10
|
||||||
|
|
Reference in a new issue