From 2d175b4453152192a0815642b07e10ad5464ac60 Mon Sep 17 00:00:00 2001 From: Romain J Date: Sun, 22 Sep 2019 04:18:28 +0200 Subject: [PATCH] update(cog|admin): add commands for warns --- cogs/admin.py | 208 +++++++++++++++++++++---- cogs/utility.py | 35 ++--- extras/locales/en/LC_MESSAGES/admin.mo | Bin 363 -> 449 bytes extras/locales/en/LC_MESSAGES/admin.po | 27 ++++ extras/locales/fr/LC_MESSAGES/admin.mo | Bin 634 -> 1144 bytes extras/locales/fr/LC_MESSAGES/admin.po | 29 +++- 6 files changed, 247 insertions(+), 52 deletions(-) diff --git a/cogs/admin.py b/cogs/admin.py index 2c57b91..4bbb35b 100644 --- a/cogs/admin.py +++ b/cogs/admin.py @@ -1,6 +1,8 @@ import datetime +import logging from typing import Union +import asyncio import discord import humanize from discord.ext import commands @@ -8,12 +10,13 @@ from discord.ext import commands from bot import TuxBot from .utils.lang import Texts +log = logging.getLogger(__name__) + class Admin(commands.Cog): def __init__(self, bot: TuxBot): self.bot = bot - self.db = bot.db async def cog_check(self, ctx: commands.Context) -> bool: permissions: discord.Permissions = ctx.channel.permissions_for( @@ -97,7 +100,7 @@ class Admin(commands.Cog): """---------------------------------------------------------------------""" @commands.command(name='ban') - async def _ban(self, ctx: commands.Context, user: discord.User, *, + async def _ban(self, ctx: commands.Context, user: discord.Member, *, reason=""): try: member: discord.Member = await ctx.guild.fetch_member(user.id) @@ -122,7 +125,7 @@ class Admin(commands.Cog): """---------------------------------------------------------------------""" @commands.command(name='kick') - async def _kick(self, ctx: commands.Context, user: discord.User, *, + async def _kick(self, ctx: commands.Context, user: discord.Member, *, reason=""): try: member: discord.Member = await ctx.guild.fetch_member(user.id) @@ -221,48 +224,189 @@ class Admin(commands.Cog): """---------------------------------------------------------------------""" + async def get_warn(self, ctx: commands.Context, + member: discord.Member = False): + query = """ + SELECT * FROM warns + WHERE created_at >= $1 AND server_id = $2 + """ + query += """AND user_id = $3""" if member else "" + query += """ORDER BY created_at DESC""" + week_ago = datetime.datetime.now() - datetime.timedelta(weeks=6) + + async with self.bot.db.acquire() as con: + await ctx.trigger_typing() + args = [week_ago, ctx.guild.id] + if member: + args.append(member.id) + + warns = await con.fetch(query, *args) + warns_list = '' + + for warn in warns: + row_id = warn.get('id') + user_id = warn.get('user_id') + user = await self.bot.fetch_user(user_id) + reason = warn.get('reason') + ago = humanize.naturaldelta( + datetime.datetime.now() - warn.get('created_at') + ) + + warns_list += f"[{row_id}] **{user}**: `{reason}` " \ + f"*({ago} ago)*\n" + + return warns_list, warns + @commands.group(name='warn', aliases=['warns']) async def _warn(self, ctx: commands.Context): if ctx.invoked_subcommand is None: - query = """ - SELECT user_id, reason, created_at FROM warns - WHERE created_at >= $1 AND server_id = $2 - ORDER BY created_at - DESC LIMIT 10 - """ - week_ago = datetime.datetime.now() - datetime.timedelta(weeks=6) + warns_list, warns = await self.get_warn(ctx) + e = discord.Embed( + title=f"{len(warns)} {Texts('admin').get('last warns')}: ", + description=warns_list + ) - async with self.bot.db.acquire() as con: - await ctx.trigger_typing() - warns = await con.fetch(query, week_ago, ctx.guild.id) - warns_list = '' + await ctx.send(embed=e) - for warn in warns: - user_id = warn.get('user_id') - user = await self.bot.fetch_user(user_id) - reason = warn.get('reason') - ago = humanize.naturaldelta( - datetime.datetime.now() - warn.get('created_at') - ) + async def add_warn(self, ctx: commands.Context, member: discord.Member, + reason): - warns_list += f"**{user}**: `{reason}` *({ago} ago)*\n" + query = """ + INSERT INTO warns (server_id, user_id, reason, created_at) + VALUES ($1, $2, $3, $4) + """ - e = discord.Embed( - title=f"{len(warns)} {Texts('admin').get('last warns')}: ", - description=warns_list - ) - - await ctx.send(embed=e) + now = datetime.datetime.now() + await self.bot.db.execute(query, ctx.guild.id, member.id, reason, now) @_warn.command(name='add', aliases=['new']) async def _warn_new(self, ctx: commands.Context, member: discord.Member, - *, reason): + *, reason="N/A"): + + member = await ctx.guild.fetch_member(member.id) + if not member: + return await ctx.send( + Texts('utils').get("Unable to find the user...") + ) + + query = """ + SELECT user_id, reason, created_at FROM warns + WHERE created_at >= $1 AND server_id = $2 and user_id = $3 """ - todo: push in database - if warn > 2 for member: - todo: ask for confirmation to kick or ban + week_ago = datetime.datetime.now() - datetime.timedelta(weeks=6) + + def check(payload: discord.RawReactionActionEvent): + if payload.message_id != choice.id \ + or payload.user_id != ctx.author.id: + return False + return payload.emoji.name in ('1⃣', '2⃣', '3⃣') + + async with self.bot.db.acquire() as con: + await ctx.trigger_typing() + warns = await con.fetch(query, week_ago, ctx.guild.id, member.id) + + if len(warns) >= 2: + e = discord.Embed( + title=Texts('admin').get('More than 2 warns'), + description=f"{member.mention} " + + Texts('admin').get('has more than 2 warns') + ) + e.add_field( + name='__Actions__', + value=':one: kick\n' + ':two: ban\n' + ':three: ' + Texts('admin').get('ignore') + ) + + choice = await ctx.send(embed=e) + + for reaction in ('1⃣', '2⃣', '3⃣'): + await choice.add_reaction(reaction) + + try: + payload = await self.bot.wait_for( + 'raw_reaction_add', + check=check, + timeout=50.0 + ) + except asyncio.TimeoutError: + return await ctx.send( + Texts('admin').get('Took too long. Aborting.') + ) + finally: + await choice.delete() + + if payload.emoji.name == '1⃣': + from jishaku.models import copy_context_with + + alt_ctx = await copy_context_with( + ctx, + content=f"{ctx.prefix}" + f"kick " + f"{member} " + f"{Texts('admin').get('More than 2 warns')}" + ) + return await alt_ctx.command.invoke(alt_ctx) + + elif payload.emoji.name == '2⃣': + from jishaku.models import copy_context_with + + alt_ctx = await copy_context_with( + ctx, + content=f"{ctx.prefix}" + f"ban " + f"{member} " + f"{Texts('admin').get('More than 2 warns')}" + ) + return await alt_ctx.command.invoke(alt_ctx) + + await self.add_warn(ctx, member, reason) + await ctx.send( + content=f"{member.mention} **{Texts('admin').get('got a warn')}**" + f"\n**{Texts('admin').get('Reason')}:** `{reason}`" + if reason != 'N/A' else '' + ) + + @_warn.command(name='remove', aliases=['revoke']) + async def _warn_remove(self, ctx: commands.Context, warn_id: int): + query = """ + DELETE FROM warns + WHERE id = $1 """ + async with self.bot.db.acquire() as con: + await ctx.trigger_typing() + await con.fetch(query, warn_id) + + await ctx.send(f"{Texts('admin').get('Warn with id')} `{warn_id}`" + f" {Texts('admin').get('successfully removed')}") + + @_warn.command(name='show', aliases=['list']) + async def _warn_show(self, ctx: commands.Context, member: discord.Member): + warns_list, warns = await self.get_warn(ctx, member) + e = discord.Embed( + title=f"{len(warns)} {Texts('admin').get('last warns')}: ", + description=warns_list + ) + + await ctx.send(embed=e) + + @_warn.command(name='edit', aliases=['change']) + async def _warn_edit(self, ctx: commands.Context, warn_id: int, *, + reason): + query = """ + UPDATE warns + SET reason = $2 + WHERE id = $1 + """ + + async with self.bot.db.acquire() as con: + await ctx.trigger_typing() + await con.fetch(query, warn_id, reason) + + await ctx.send(f"{Texts('admin').get('Warn with id')} `{warn_id}`" + f" {Texts('admin').get('successfully edited')}") + def setup(bot: TuxBot): bot.add_cog(Admin(bot)) diff --git a/cogs/utility.py b/cogs/utility.py index 13a0ecd..ecf6cb0 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -15,7 +15,22 @@ class Utility(commands.Cog): """---------------------------------------------------------------------""" - async def fetch_api(self, ctx: commands.Context, ip, addr): + @commands.command(name='iplocalise') + async def _iplocalise(self, ctx: commands.Context, addr, ip_type=''): + addr = re.sub(r'http(s?)://', '', addr) + addr = addr[:-1] if addr.endswith('/') else addr + + await ctx.trigger_typing() + + if ip_type in ('v6', 'ipv6'): + try: + ip = socket.getaddrinfo(addr, None, socket.AF_INET6)[1][4][0] + except socket.gaierror: + return await ctx.send( + Texts('utility').get('ipv6 not available')) + else: + ip = socket.gethostbyname(addr) + async with self.bot.session.get(f"http://ip-api.com/json/{ip}") as s: response: dict = await s.json() @@ -55,24 +70,6 @@ class Utility(commands.Cog): content=f"{Texts('utility').get('info not available')}" f"``{response.get('query')}``") - @commands.command(name='iplocalise') - async def _iplocalise(self, ctx: commands.Context, addr, ip_type=''): - addr = re.sub(r'http(s?)://', '', addr) - addr = addr[:-1] if addr.endswith('/') else addr - - await ctx.trigger_typing() - - if ip_type in ('v6', 'ipv6'): - try: - ip = socket.getaddrinfo(addr, None, socket.AF_INET6)[1][4][0] - except socket.gaierror: - return await ctx.send( - Texts('utility').get('ipv6 not available')) - else: - ip = socket.gethostbyname(addr) - - await self.fetch_api(ctx, ip, addr) - def setup(bot: TuxBot): bot.add_cog(Utility(bot)) diff --git a/extras/locales/en/LC_MESSAGES/admin.mo b/extras/locales/en/LC_MESSAGES/admin.mo index e56e9c9c4f698196d1c9f23390bf6da85a3ddd45..cd65b5e0abbb1e0d9c33537cd85a4730136c80d2 100644 GIT binary patch delta 140 zcmaFObdWjdo)F7a1|VPpVi_RT0dbIk4UjDg#I_*J$iNT`r1gP#B9P6Hkyxydn_rZw wP?C|Dr(mQ|o>-Juyiv!V(EzKAjzW1xVu?aZzCvYwDNu1%8-wf_0lXdsf&c&j diff --git a/extras/locales/en/LC_MESSAGES/admin.po b/extras/locales/en/LC_MESSAGES/admin.po index 46df0e2..3bec23b 100644 --- a/extras/locales/en/LC_MESSAGES/admin.po +++ b/extras/locales/en/LC_MESSAGES/admin.po @@ -25,4 +25,31 @@ msgid "Unable to kick this user" msgstr "" msgid "last warns" +msgstr "" + +msgid "More than 2 warns" +msgstr "" + +msgid "has more than 2 warns" +msgstr "has more than 2 warns, what do you want to do ?" + +msgid "ignore" +msgstr "" + +msgid "Took too long. Aborting." +msgstr "" + +msgid "got a warn" +msgstr "" + +msgid "Reason" +msgstr "" + +msgid "Warn with id" +msgstr "" + +msgid "successfully removed" +msgstr "" + +msgid "successfully edited" msgstr "" \ No newline at end of file diff --git a/extras/locales/fr/LC_MESSAGES/admin.mo b/extras/locales/fr/LC_MESSAGES/admin.mo index cdfee52546358357d655671a8242b05104a7cfd9..f08390cf07ba5261daf655473466283fca31f7e5 100644 GIT binary patch delta 677 zcmZ{fJxe4(5QckoQISLO`|FOYK+!-AHV_lh3(iPk5y8X*+nsWEu(x}i?wM7S1us2> zWAPtcvRq_hBA9GuZmPe){16ZB?VAl;#fEpDuIj0(x1O?pdTRHB*$aWw2YrNo_~6BP z#(e<#3ynbi86mpB8E_n&2gks#t@s=G0dWHMg5N=3cMkfxU#Q_8mn@S}MO86BadcLP_gdgKbE0*}U5=PC2H!F2uv|X%^c5EDO%(fN!HU(0%uw6uO%aWQ6*KFX6&A|Wj()G|eePgXS HdG+=Wc?qyE delta 192 zcmeyt@rxzro)F7a1|VPsVi_QI0dbH(4v;Mh#JNB$4#dqsECIx`ftU-3w*av%BLl;J zAT0^Re}QZjAT7?sz@Q4GZGbdLUlNd>%*QA`*_F|dD<`qIM4>#fD6e?)Jw|&*N#E3> z