diff --git a/assets/it-just-works.compressed.opus b/assets/it-just-works.compressed.opus deleted file mode 100644 index 1fcd74b..0000000 Binary files a/assets/it-just-works.compressed.opus and /dev/null differ diff --git a/assets/mine-diamonds.opus b/assets/mine-diamonds.opus new file mode 100644 index 0000000..25e327d Binary files /dev/null and b/assets/mine-diamonds.opus differ diff --git a/cogs/.verify.py.old b/cogs/.verify.py.old new file mode 100644 index 0000000..389e3af --- /dev/null +++ b/cogs/.verify.py.old @@ -0,0 +1,111 @@ +import discord +import orm +from discord.ext import commands +from utils import VerifyCode, Student, VerifyView, get_or_none, console, owner_or_admin + + +class VerifyCog(commands.Cog): + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.slash_command() + @discord.guild_only() + async def verify(self, ctx: discord.ApplicationContext): + """Verifies or generates a verification code""" + + try: + student: Student = await Student.objects.get(user_id=ctx.user.id) + return await ctx.respond(f"\N{cross mark} You're already verified as {student.id}!", ephemeral=True) + except orm.NoMatch: + pass + + role = discord.utils.find(lambda r: r.name.lower() == "verified", ctx.guild.roles) + channel = discord.utils.get(ctx.guild.text_channels, name="verify") + if role in ctx.user.roles: + if role and role < ctx.me.top_role: + await ctx.user.remove_roles(role, reason=f"Auto de-verified") + if channel: + try: + await ctx.user.send( + f"You have been automatically de-verified. Please re-verify by going to {channel.mention} " + f"and typing ." + ) + except discord.Forbidden: + pass + return + view = VerifyView(ctx) + return await ctx.respond(view=view, ephemeral=True) + + @commands.command(name="de-verify") + @commands.guild_only() + @owner_or_admin() + async def verification_del(self, ctx: commands.Context, *, user: discord.Member): + """Removes a user's verification status""" + # if not await self.bot.is_owner(ctx.author): + # if not ctx.author.guild_permissions.administrator: + # return await ctx.reply(":x: Permission denied.") + await ctx.trigger_typing() + for code in await VerifyCode.objects.all(bind=user.id): + await code.delete() + usr = await Student.objects.first(user_id=user.id) + if usr: + await usr.delete() + + role = discord.utils.find(lambda r: r.name.lower() == "verified", ctx.guild.roles) + if role and role < ctx.me.top_role: + await user.remove_roles(role, reason=f"De-verified by {ctx.author}") + + await ctx.message.delete(delay=10) + return await ctx.reply(f"\N{white heavy check mark} De-verified {user}.") + + @commands.command(name="verify") + @commands.guild_only() + @owner_or_admin() + async def verification_force(self, ctx: commands.Context, user: discord.Member, _id: str, name: str): + """Manually verifies someone""" + existing = await Student.objects.create(id=_id, user_id=user.id, name=name) + role = discord.utils.find(lambda r: r.name.lower() == "verified", ctx.guild.roles) + if role and role < ctx.guild.me.top_role: + await user.add_roles(role, reason="Verified") + try: + await user.edit(nick=f"{existing.name}", reason="Verified") + except discord.HTTPException: + pass + console.log(f"[green]{ctx.author} verified {user} ({user.id})") + await ctx.message.delete(delay=10) + return await ctx.reply( + "\N{white heavy check mark} Verification complete!", + ) + + @commands.user_command(name="B Number") + @discord.guild_only() + async def get_b_number(self, ctx: discord.ApplicationContext, member: discord.Member): + try: + student: Student = await Student.objects.get(user_id=member.id) + return await ctx.respond( + f"{member.mention}'s B number is saved as {student.id!r}.", + ephemeral=True, + allowed_mentions=discord.AllowedMentions.none(), + ) + except orm.NoMatch: + return await ctx.respond( + f"{member.mention} has no saved B number.", + ephemeral=True, + allowed_mentions=discord.AllowedMentions.none(), + ) + + @commands.command(name="rebind") + @owner_or_admin() + async def rebind_code(self, ctx: commands.Context, b_number: str, *, user: discord.Member): + # noinspection GrazieInspection + """Changes which account a B number is bound to""" + student = await get_or_none(Student, id=b_number.upper()) + if student: + await student.update(user_id=user.id) + return await ctx.message.add_reaction("\N{white heavy check mark}") + await ctx.message.add_reaction("\N{cross mark}") + await ctx.message.delete(delay=10) + + +def setup(bot): + bot.add_cog(VerifyCog(bot)) diff --git a/cogs/events.py b/cogs/events.py index c09e023..1154f7d 100644 --- a/cogs/events.py +++ b/cogs/events.py @@ -219,64 +219,65 @@ class Events(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message): - async def it_just_works(): - _file = Path.cwd() / "assets" / "it-just-works.ogg" - if message.author.voice is not None and message.author.voice.channel is not None: - voice: discord.VoiceClient | None = None - if message.guild.voice_client is not None: - # noinspection PyUnresolvedReferences - if message.guild.voice_client.is_playing(): - return + def play_voice(_file): + async def internal(): + if message.author.voice is not None and message.author.voice.channel is not None: + voice: discord.VoiceClient | None = None + if message.guild.voice_client is not None: + # noinspection PyUnresolvedReferences + if message.guild.voice_client.is_playing(): + return + try: + await _dc(message.guild.voice_client) + except discord.HTTPException: + pass try: - await _dc(message.guild.voice_client) - except discord.HTTPException: - pass - try: - voice = await message.author.voice.channel.connect(timeout=10, reconnect=False) - except asyncio.TimeoutError: - await message.channel.trigger_typing() - await message.reply( - "I'd play the song but discord's voice servers are shit.", - file=discord.File(_file) - ) - region = message.author.voice.channel.rtc_region - # noinspection PyUnresolvedReferences - console.log( - "Timed out connecting to voice channel: {0.name} in {0.guild.name} " - "(region {1})".format( - message.author.voice.channel, - region.name if region else "auto (unknown)" + voice = await message.author.voice.channel.connect(timeout=10, reconnect=False) + except asyncio.TimeoutError: + await message.channel.trigger_typing() + await message.reply( + "I'd play the song but discord's voice servers are shit.", + file=discord.File(_file) ) - ) - return - - if voice.channel != message.author.voice.channel: - await voice.move_to(message.author.voice.channel) - - if message.guild.me.voice.self_mute or message.guild.me.voice.mute: - await _dc(voice) - await message.channel.trigger_typing() - await message.reply("Unmute me >:(", file=discord.File(_file)) - else: + region = message.author.voice.channel.rtc_region + # noinspection PyUnresolvedReferences + console.log( + "Timed out connecting to voice channel: {0.name} in {0.guild.name} " + "(region {1})".format( + message.author.voice.channel, + region.name if region else "auto (unknown)" + ) + ) + return - def after(err): - asyncio.run_coroutine_threadsafe( - _dc(voice), - self.bot.loop - ) - if err is not None: - console.log(f"Error playing audio: {err}") + if voice.channel != message.author.voice.channel: + await voice.move_to(message.author.voice.channel) + + if message.guild.me.voice.self_mute or message.guild.me.voice.mute: + await _dc(voice) + await message.channel.trigger_typing() + await message.reply("Unmute me >:(", file=discord.File(_file)) + else: + + def after(err): + asyncio.run_coroutine_threadsafe( + _dc(voice), + self.bot.loop + ) + if err is not None: + console.log(f"Error playing audio: {err}") - # noinspection PyTypeChecker - src = discord.FFmpegPCMAudio(str(_file.resolve()), stderr=subprocess.DEVNULL) - src = discord.PCMVolumeTransformer(src, volume=0.5) - voice.play( - src, - after=after - ) - else: - await message.channel.trigger_typing() - await message.reply(file=discord.File(_file)) + # noinspection PyTypeChecker + src = discord.FFmpegPCMAudio(str(_file.resolve()), stderr=subprocess.DEVNULL) + src = discord.PCMVolumeTransformer(src, volume=0.5) + voice.play( + src, + after=after + ) + else: + await message.channel.trigger_typing() + await message.reply(file=discord.File(_file)) + return internal async def send_smeg(): directory = Path.cwd() / "assets" / "smeg" @@ -384,7 +385,10 @@ class Events(commands.Cog): "content": "https://ferdi-is.gay/bee", }, r"it just works": { - "func": it_just_works + "func": play_voice(assets / "it-just-works.mp3"), + "meta": { + "check": (assets / "it-just-works.mp3").exists + } }, r"^linux$": { "content": lambda: (assets / "copypasta.txt").read_text(), @@ -431,6 +435,12 @@ class Events(commands.Cog): "meta": { "check": lambda: message.content.startswith(self.bot.user.mention) } + }, + r"mine diamonds": { + "func": play_voice(assets / "mine-diamonds.opus"), + "meta": { + "check": (assets / "mine-diamonds.opus").exists + } } } # Stop responding to any bots