From a4dca2de2143b945df7ffe0f9fbf0bbde91f9a6b Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Mon, 21 May 2018 21:12:57 -0800 Subject: [PATCH 01/25] Update .gitignore --- .gitignore | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 98e2ace..c48ffda 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,93 @@ bot_secrets.json google_client_secret.json -__pycache__/ logs/* *.sh.swp -.idea/ + + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# mypy +.mypy_cache/ + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ +cmake-build-release/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests \ No newline at end of file From efc73a01191776f19dc567ce8ffc952a3b138216 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Mon, 21 May 2018 21:25:41 -0800 Subject: [PATCH 02/25] Moved misc to scratchpad --- misc.py | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 misc.py diff --git a/misc.py b/misc.py deleted file mode 100644 index 6960d6c..0000000 --- a/misc.py +++ /dev/null @@ -1,44 +0,0 @@ - @checks.no_bots() - @commands.cooldown(1,5,commands.BucketType.user) - @commands.command() - async def captcha(self, ctx, type, *, text): - type = type.lower() - if type not in "checked unchecked loading".split(): - raise commands.BadArgument(f"Invalid type {type!r}. Available " - "types: `unchecked`, `loading`, `checked`") - font = ImageFont.truetype("Roboto-Regular.ttf", 14) - async with ctx.typing(): - img = Image.open(f"blank-captcha-{type}.png") - img.load() - d = ImageDraw.Draw(img) - fnc = functools.partial(d.text, (53,30), text, fill=(0,0,0,255), - font=font) - await self.bot.loop.run_in_executor(None, fnc) - img.save("captcha.png") - await ctx.send(file=discord.File("captcha.png")) - os.system("rm captcha.png") - img.close() - - -import functools, youtube_dl -#bot.voice_chan = await ctx.author.voice.channel.connect() -bot.voice_chan.stop() -opts = {"format": 'webm[abr>0]/bestaudio/best',"ignoreerrors": True,"default_search": "auto","source_address": "0.0.0.0",'quiet': True} -ydl = youtube_dl.YoutubeDL(opts) -url = 'https://www.youtube.com/watch?v=hjbPszSt5Pc' -func = functools.partial(ydl.extract_info, url, download=False) -info = func() -#bot.voice_chan.play(discord.FFmpegPCMAudio('dead_puppies.mp3')) -bot.voice_chan.play(discord.FFmpegPCMAudio(info['url'])) -#async while bot.voice_chan.is_playing(): -# pass -#await bot.voice_chan.disconnect() - -# Run event in loop after number of seconds -from functools import partial -return bot.loop.call_later(120, partial(bot.loop.create_task, ctx.send(f"{ctx.author.mention} Timer's Up"))) - -# Get the number of tasks currently in the loop -import asyncio -return len(asyncio.Task.all_tasks()) - From 9dbcff12b40bf05d299bbb906a3ccb07e6ba090a Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Mon, 21 May 2018 21:50:55 -0800 Subject: [PATCH 03/25] Fixing errors --- exts/admin.py | 14 +++++++------- exts/imports/utils.py | 2 +- exts/patreon.py | 8 ++++---- exts/rcon.py | 20 ++++++++++---------- exts/utils.py | 14 +++++++------- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/exts/admin.py b/exts/admin.py index ecafd1a..b14b855 100644 --- a/exts/admin.py +++ b/exts/admin.py @@ -84,7 +84,7 @@ class Admin: @commands.command(hidden=True) @commands.check(checks.is_guild_owner) async def get_guild_config(self, ctx): - config = await self.bot.db_con.fetchval('select * from guild_config where guild_id = $1', ctx.guild.id) + config = await self.bot.db_con.fetchrow('select * from guild_config where guild_id = $1', ctx.guild.id) configs = [str(config)[i:i+1990] for i in range(0, len(config), 1990)] await ctx.message.author.send(f'The current config for the {ctx.guild.name} guild is:\n') admin_log.info(configs) @@ -110,7 +110,7 @@ class Admin: @set.command(name='admin_chan', aliases=['ac', 'admin_chat', 'admin chat']) async def _admin_channel(self, ctx, channel: discord.TextChannel=None): if ctx.guild: - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): if channel is not None: await self.bot.db_con.execute('update guild_config set admin_chat = $2 where guild_id = $1', ctx.guild.id, channel.id) @@ -119,10 +119,10 @@ class Admin: @set.command(name='channel_lockdown', aliases=['lockdown', 'restrict_access', 'cl']) async def _channel_lockdown(self, ctx, config='true'): if ctx.guild: - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): if str(config).lower() == 'true': if await self.bot.db_con.fetchval('select allowed_channels from guild_config ' - 'where guild_id = $1', ctx.guild.id) is []: + 'where guild_id = $1', ctx.guild.id) is []: await ctx.send('Please set at least one allowed channel before running this command.') else: await self.bot.db_con.execute('update guild_config set channel_lockdown = True ' @@ -144,7 +144,7 @@ class Admin: @add.command(name='allowed_channels', aliases=['channel', 'ac']) async def _allowed_channels(self, ctx, *, channels): if ctx.guild: - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): channels = channels.lower().replace(' ', '').split(',') added = '' for channel in channels: @@ -196,7 +196,7 @@ class Admin: @commands.cooldown(1, 5, type=commands.BucketType.guild) async def add_prefix(self, ctx, *, prefix=None): if ctx.guild: - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): prefixes = await self.bot.db_con.fetchval('select prefix from guild_config where guild_id = $1', ctx.guild.id) if prefix is None: @@ -225,7 +225,7 @@ class Admin: @commands.cooldown(1, 5, type=commands.BucketType.guild) async def remove_prefix(self, ctx, *, prefix=None): if ctx.guild: - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): prefixes = await self.bot.db_con.fetchval('select prefix from guild_config where guild_id = $1', ctx.guild.id) found = 0 diff --git a/exts/imports/utils.py b/exts/imports/utils.py index 582d568..c697e90 100644 --- a/exts/imports/utils.py +++ b/exts/imports/utils.py @@ -21,7 +21,7 @@ class Capturing(list): async def mute(bot, ctx, admin=0, member_id=None): mute_role = bot.db_con.fetchval(f'select muted_role from guild_config where guild_id = $1', ctx.guild.id) if mute_role: - if admin or checks.is_admin(bot, ctx): + if admin or await checks.is_admin(bot, ctx): if ctx.guild.me.guild_permissions.manage_roles: if member_id: ctx.guild.get_member(member_id).edit(roles=[discord.utils.get(ctx.guild.roles, id=mute_role)]) diff --git a/exts/patreon.py b/exts/patreon.py index 2ff603e..da82edb 100644 --- a/exts/patreon.py +++ b/exts/patreon.py @@ -33,7 +33,7 @@ class Patreon: @commands.command(aliases=['patreon_message']) async def set_patreon_message(self, ctx, message): - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): patreon_message = await self.bot.db_con.fetchval('select patreon_message from guild_config ' 'where guild_id = $1', ctx.guild.id) if message == patreon_message: @@ -47,7 +47,7 @@ class Patreon: @commands.command(aliases=['add_patreon', 'set_patreon']) async def add_patreon_info(self, ctx, name, url): - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): patreon_info = await self.bot.db_con.fetchval('select patreon_links from guild_config where guild_id = $1', ctx.guild.id) patreon_links = {} @@ -66,7 +66,7 @@ class Patreon: @commands.command(aliases=['remove_patreon']) async def remove_patreon_info(self, ctx, name): - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): patreon_info = await self.bot.db_con.fetchval('select patreon_links from guild_config where guild_id = $1', ctx.guild.id) if patreon_info: @@ -86,7 +86,7 @@ class Patreon: @commands.command() async def enable_patreon(self, ctx, state: bool=True): - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): patreon_status = await self.bot.db_con.fetchval('select patreon_enabled from guild_config ' 'where guild_id = $1', ctx.guild.id) if patreon_status and state: diff --git a/exts/rcon.py b/exts/rcon.py index b59f877..ccbe593 100644 --- a/exts/rcon.py +++ b/exts/rcon.py @@ -138,7 +138,7 @@ class Rcon: first_last "first last" To view all the valid ARK servers for this guild see list_ark_servers.""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): if server is not None: rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections ' 'from guild_config where guild_id = $1', @@ -200,7 +200,7 @@ class Rcon: async def end_monitor_chat(self, ctx, *, server=None): """Ends chat monitoring on the specified server. Context is the same as monitor_chat""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): if server is not None: rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections ' 'from guild_config where guild_id = $1', @@ -229,7 +229,7 @@ class Rcon: first_last "first last" To view all the valid ARK servers for this guild see list_ark_servers.""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections from guild_config ' 'where guild_id = $1', ctx.guild.id)) if server is not None: @@ -267,7 +267,7 @@ class Rcon: async def add_rcon_server(self, ctx, server, ip, port, password): """Adds the specified server to the current guild\'s rcon config. All strings (, , ) must be contained inside double quotes.""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): server = server.title() rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections from guild_config ' 'where guild_id = $1', ctx.guild.id)) @@ -296,7 +296,7 @@ class Rcon: async def remove_rcon_server(self, ctx, server): """removes the specified server from the current guild\'s rcon config. All strings must be contained inside double quotes.""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): server = server.title() rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections from guild_config ' 'where guild_id = $1', ctx.guild.id)) @@ -316,7 +316,7 @@ class Rcon: """Adds the included Steam 64 IDs to the running whitelist on all the ARK servers in the current guild\'s rcon config. Steam 64 IDs should be a comma seperated list of IDs. Example: 76561198024193239,76561198024193239,76561198024193239""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): if steam_ids is not None: rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections ' 'from guild_config where guild_id = $1', @@ -364,7 +364,7 @@ class Rcon: """Runs SaveWorld on the specified ARK server. If a server is not specified it will default to running saveworld on all servers in the guild\'s config. Will print out "World Saved" for each server when the command completes successfully.""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections from guild_config ' 'where guild_id = $1', ctx.guild.id)) success_msg = 'Running saveworld' @@ -406,7 +406,7 @@ class Rcon: """Sends a broadcast message to all servers in the guild config. The message will be prefixed with the Discord name of the person running the command. Will print "Success" for each server once the broadcast is sent.""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections from guild_config ' 'where guild_id = $1', ctx.guild.id)) if message is not None: @@ -443,7 +443,7 @@ class Rcon: The message will be prefixed with the Discord name of the person running the command. If has more than one word in it's name it will either need to be surrounded by double quotes or the words separated by _""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections from guild_config ' 'where guild_id = $1', ctx.guild.id)) if server is not None: @@ -481,7 +481,7 @@ class Rcon: and these channel's permissions will be synced to the category. These channels will be added to the guild's rcon config and are where the server chat messages will be sent when monitor_chat is run.""" - if checks.is_rcon_admin(self.bot, ctx): + if await checks.is_rcon_admin(self.bot, ctx): rcon_connections = json.loads(await self.bot.db_con.fetchval('select rcon_connections from guild_config ' 'where guild_id = $1', ctx.guild.id)) edited = 0 diff --git a/exts/utils.py b/exts/utils.py index e89b98f..054539b 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -292,7 +292,7 @@ class Utils: title=f'Admin Help Requests', color=discord.Colour.green() ) - if checks.is_admin(self.bot, ctx) or checks.is_rcon_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx) or await checks.is_rcon_admin(self.bot, ctx): if assigned_to is None: requests = await self.bot.db_con.fetch(f'select * from admin_requests where guild_orig = $1 ' f'and completed_time is null', ctx.guild.id) @@ -312,8 +312,8 @@ class Utils: else: em.add_field(name='There are no pending requests for this guild.', value='￰', inline=False) else: - if checks.check_admin_role(self.bot, ctx, assigned_to)\ - or checks.check_rcon_role(self.bot, ctx, assigned_to): + if await checks.check_admin_role(self.bot, ctx, assigned_to)\ + or await checks.check_rcon_role(self.bot, ctx, assigned_to): requests = await self.bot.db_con.fetch('select * from admin_requests where assigned_to = $1 ' 'and guild_orig = $2 and completed_time is null', assigned_to.id, ctx.guild.id) @@ -359,7 +359,7 @@ class Utils: """Allows Admin to close admin help tickets. [request_id] must be a valid integer pointing to an open Request ID """ - if checks.is_admin(self.bot, ctx) or checks.is_rcon_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx) or await checks.is_rcon_admin(self.bot, ctx): if request_ids: request_ids = request_ids.replace(' ', '').split(',') for request_id in request_ids: @@ -471,7 +471,7 @@ class Utils: def is_author(message): return message.author == ctx.author - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): if member: deleted = await ctx.channel.purge(limit=number, check=is_member) if member != ctx.author: @@ -487,7 +487,7 @@ class Utils: @commands.command(name='purge_all', aliases=['cls', 'clear']) @commands.cooldown(1, 3, type=commands.BucketType.user) async def purge_all(self, ctx, number: int=20, contents: str='all'): - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): if contents != 'all': deleted = await ctx.channel.purge(limit=number, check=lambda message: message.content == contents) else: @@ -513,7 +513,7 @@ class Utils: @commands.command(hidden=True, name='sheets') async def google_sheets(self, ctx, member: discord.Member): - if checks.is_admin(self.bot, ctx): + if await checks.is_admin(self.bot, ctx): scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive'] credentials = ServiceAccountCredentials.from_json_keyfile_name('config/google_client_secret.json', scope) From c0cb5568d75d154336e61a03db924f1a59e881a1 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Mon, 21 May 2018 21:56:10 -0800 Subject: [PATCH 04/25] Fixing errors --- exts/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/events.py b/exts/events.py index 89d7a9c..395b4ba 100644 --- a/exts/events.py +++ b/exts/events.py @@ -84,7 +84,7 @@ class BotEvents: ctx.webhook_id, [json.dumps({'id': a.id, 'size': a.size, 'height': a.height, 'width': a.width, 'filename': a.filename, 'url': a.url}) for a in ctx.attachments], ctx.pinned, [json.dumps({'emoji': r.emoji, 'count': r.count}) for r in ctx.reactions], - ctx.guild.id, ctx.created_at, ctx.system_content, ctx.author.id] + ctx.guild.id if ctx.guild else ctx.author.id, ctx.created_at, ctx.system_content, ctx.author.id] await self.bot.db_con.execute(sql, *msg_data) if ctx.guild: if ctx.author != ctx.guild.me: From c924412e6701ea693f8c93324a6886ece5415c9e Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Mon, 21 May 2018 22:14:37 -0800 Subject: [PATCH 05/25] Adjust speed on Explode --- exts/fun.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/fun.py b/exts/fun.py index acf8162..4c2f390 100644 --- a/exts/fun.py +++ b/exts/fun.py @@ -155,7 +155,7 @@ class Fun: trans = await self.bot.db_con.fetchval('select code from geeksbot_emojis where id = 405943174809255956') msg = await ctx.send(f'{member.mention}{trans*20}{self.bot.unicode_emojis["left_fist"]}') for i in range(4): - await asyncio.sleep(0.1) + await asyncio.sleep(0.5) await msg.edit(content=f'{member.mention}{trans*(20-(i*5))}{self.bot.unicode_emojis["left_fist"]}') await asyncio.sleep(0.1) await msg.edit(content=f'{self.bot.unicode_emojis["boom"]}') From bb7240689bc618f62cb17cfaac7aa7517c2f4046 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Wed, 23 May 2018 21:48:54 -0800 Subject: [PATCH 06/25] Fixed trout --- exts/admin.py | 16 ++++++++++++++++ exts/fun.py | 5 +++-- exts/utils.py | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/exts/admin.py b/exts/admin.py index b14b855..5ad30b8 100644 --- a/exts/admin.py +++ b/exts/admin.py @@ -109,6 +109,7 @@ class Admin: @set.command(name='admin_chan', aliases=['ac', 'admin_chat', 'admin chat']) async def _admin_channel(self, ctx, channel: discord.TextChannel=None): + """Sets the channel for admin specific notifications""" if ctx.guild: if await checks.is_admin(self.bot, ctx): if channel is not None: @@ -118,6 +119,8 @@ class Admin: @set.command(name='channel_lockdown', aliases=['lockdown', 'restrict_access', 'cl']) async def _channel_lockdown(self, ctx, config='true'): + """Toggles the channel lockdown restricting Geeksbot to only access channels defined in allowed_channels + If you run this before configuring allowed_channels it will tell you to run that command first.""" if ctx.guild: if await checks.is_admin(self.bot, ctx): if str(config).lower() == 'true': @@ -143,6 +146,8 @@ class Admin: @add.command(name='allowed_channels', aliases=['channel', 'ac']) async def _allowed_channels(self, ctx, *, channels): + """Allows Admin to restrict what channels Geeksbot is allowed to access + This only takes effect if channel_lockdown is enabled.""" if ctx.guild: if await checks.is_admin(self.bot, ctx): channels = channels.lower().replace(' ', '').split(',') @@ -195,6 +200,10 @@ class Admin: @add.command(aliases=['prefix', 'p']) @commands.cooldown(1, 5, type=commands.BucketType.guild) async def add_prefix(self, ctx, *, prefix=None): + """Adds a guild specific prefix to the guild config + Note: This overwrites the default of g$. If you would + like to keep using g$ you will need to add it to the + Guild config as well.""" if ctx.guild: if await checks.is_admin(self.bot, ctx): prefixes = await self.bot.db_con.fetchval('select prefix from guild_config where guild_id = $1', @@ -224,6 +233,9 @@ class Admin: @remove.command(aliases=['prefix', 'p']) @commands.cooldown(1, 5, type=commands.BucketType.guild) async def remove_prefix(self, ctx, *, prefix=None): + """Removes a guild specific prefix from the guild config + If the last prefix is removed then Geeksbot will default + Back to g$""" if ctx.guild: if await checks.is_admin(self.bot, ctx): prefixes = await self.bot.db_con.fetchval('select prefix from guild_config where guild_id = $1', @@ -260,6 +272,9 @@ class Admin: @commands.cooldown(1, 5, type=commands.BucketType.guild) @commands.check(checks.is_guild_owner) async def _add_admin_role(self, ctx, role=None): + """The Guild owner can add a role to the admin list + Allowing members of that role to run admin commands + on the current guild.""" role = discord.utils.get(ctx.guild.roles, name=role) if role is not None: roles = json.loads(await self.bot.db_con.fetchval('select admin_roles from guild_config ' @@ -278,6 +293,7 @@ class Admin: @commands.cooldown(1, 5, type=commands.BucketType.guild) @commands.check(checks.is_guild_owner) async def _remove_admin_role(self, ctx, role=None): + """The Guild owner can remove a role from the admin list""" role = discord.utils.get(ctx.guild.roles, name=role) if role is not None: roles = json.loads(await self.bot.db_con.fetchval('select admin_roles from guild_config ' diff --git a/exts/fun.py b/exts/fun.py index 4c2f390..c48e64a 100644 --- a/exts/fun.py +++ b/exts/fun.py @@ -65,13 +65,14 @@ class Fun: @commands.command() @commands.cooldown(1, 5, type=commands.BucketType.user) async def slap(self, ctx, member: discord.Member): + trout = await self.bot.db_con.fetchval("select code from geeksbot_emojis where name = 'trout'") if member.id == self.bot.user.id and ctx.author.id != owner_id: await ctx.send(f'You rolled a Critical Fail...\nThe trout bounces off and rebounds on the attacker.') await ctx.send(f'{ctx.author.mention} ' - f'You slap yourself in the face with a large trout <:trout:408543365085397013>') + f'You slap yourself in the face with a large trout {trout}') else: await ctx.send(f'{ctx.author.display_name} slaps ' - f'{member.mention} around a bit with a large trout <:trout:408543365085397013>') + f'{member.mention} around a bit with a large trout {trout}') @staticmethod def get_factorial(number): diff --git a/exts/utils.py b/exts/utils.py index 054539b..5d81f60 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -59,6 +59,7 @@ class Utils: @commands.command() @commands.is_owner() async def sysinfo(self, ctx): + """WIP Gets current system status for the server that Geeksbot is running on.""" await ctx.send(f'```ml\n' f'CPU Percentages: {psutil.cpu_percent(percpu=True)}\n' f'Memory Usage: {psutil.virtual_memory().percent}%\n' @@ -429,6 +430,8 @@ class Utils: @commands.command(name='localtime', aliases=['time', 'lt']) @commands.cooldown(1, 3, type=commands.BucketType.user) async def get_localtime(self, ctx, timezone: str='Anchorage'): + """Shows the current time localized to the timezone given + This defaults to the Bot's local timezone of Anchorage Alaska USA if none are given.""" em = discord.Embed() try: tz = pytz.timezone(timezone) @@ -453,6 +456,13 @@ class Utils: @commands.command(name='purge', aliases=['clean', 'erase']) @commands.cooldown(1, 3, type=commands.BucketType.user) async def purge_messages(self, ctx, number: int=20, member: discord.Member=None): + """Gives Admin the ability to quickly clear messages from a channel + By default this will only purge messages sent by Geeksbot and any messages that appear to + have called Geeksbot (aka start with one of the Geeksbot's prefixes for this Guild) + If you want to purge messages from a different user you must provide a number and member + + Note: Geeksbot will not find of messages by the given member, it will instead + search the last messages in the channel and delete any by the given member""" def is_me(message): if message.author == self.bot.user: return True @@ -487,6 +497,9 @@ class Utils: @commands.command(name='purge_all', aliases=['cls', 'clear']) @commands.cooldown(1, 3, type=commands.BucketType.user) async def purge_all(self, ctx, number: int=20, contents: str='all'): + """Will delete all of the last of messages from the channel + If is not 'all' then only messages containing + will be deleted.""" if await checks.is_admin(self.bot, ctx): if contents != 'all': deleted = await ctx.channel.purge(limit=number, check=lambda message: message.content == contents) @@ -500,6 +513,7 @@ class Utils: @commands.command(name='google', aliases=['g', 'search']) async def google_search(self, ctx, *, search): + """WIP Search Google for the given string""" res = self.bot.gcs_service.cse().list(q=search, cx=self.bot.bot_secrets['cx']).execute() results = res['items'][:4] em = discord.Embed() @@ -538,6 +552,7 @@ class Utils: @commands.command(name='iss') async def iss_loc(self, ctx): + """WIP Locates the International Space Station and display on a map""" def gen_image(iss_loc): lat = iss_loc['latitude'] lon = iss_loc['longitude'] @@ -561,6 +576,8 @@ class Utils: @commands.command(name='location', aliases=['loc', 'map']) async def map_location(self, ctx, *, location): + """WIP Displays the given location on a map + Note: This is SLOW!!! Be prepared to wait up to a minute for the result""" def draw_map(m, scale=1): # draw a shaded-relief image From fecff7925c7a4c796c79cfc617adf0888f233431 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Wed, 23 May 2018 22:06:10 -0800 Subject: [PATCH 07/25] Get trout by id instead of name --- exts/fun.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/fun.py b/exts/fun.py index c48e64a..7833e1f 100644 --- a/exts/fun.py +++ b/exts/fun.py @@ -65,7 +65,7 @@ class Fun: @commands.command() @commands.cooldown(1, 5, type=commands.BucketType.user) async def slap(self, ctx, member: discord.Member): - trout = await self.bot.db_con.fetchval("select code from geeksbot_emojis where name = 'trout'") + trout = await self.bot.db_con.fetchval("select code from geeksbot_emojis where id = 449083238766477312") if member.id == self.bot.user.id and ctx.author.id != owner_id: await ctx.send(f'You rolled a Critical Fail...\nThe trout bounces off and rebounds on the attacker.') await ctx.send(f'{ctx.author.mention} ' From 6e5ad99253d70e4a7e3a21284e3fead58dce19f3 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 21:56:58 -0800 Subject: [PATCH 08/25] Added command to get time in a different timezone --- exts/utils.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ geeksbot.py | 2 ++ 2 files changed, 57 insertions(+) diff --git a/exts/utils.py b/exts/utils.py index 5d81f60..0933cd8 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -18,6 +18,8 @@ from mpl_toolkits.basemap import Basemap from io import BytesIO from itertools import chain import numpy as np +from dateutil.parser import parse +from copy import copy config_dir = 'config/' admin_id_file = 'admin_ids' @@ -432,7 +434,9 @@ class Utils: async def get_localtime(self, ctx, timezone: str='Anchorage'): """Shows the current time localized to the timezone given This defaults to the Bot's local timezone of Anchorage Alaska USA if none are given.""" + em = discord.Embed() + try: tz = pytz.timezone(timezone) localtime = datetime.now(tz=tz) @@ -453,6 +457,57 @@ class Utils: em.colour = discord.Colour.red() await ctx.send(embed=em) + # noinspection PyUnboundLocalVariable + @commands.command(name='gettimein', aliases=['timein', 'gti']) + @commands.cooldown(1, 3, type=commands.BucketType.user) + async def get_time_in_timezone(self, ctx, timezone: str='US/Eastern', *, time: str=None): + em = discord.Embed() + description = '' + + if time is None: + description += 'Time not given... using current UTC time.' + in_time = datetime.utcnow() + else: + try: + orig_time = copy(time) + for tz in pytz.all_timezones: + if tz.lower() in time.lower(): + time = time.replace(tz, '') + parsed_tz = pytz.timezone(tz) + break + else: + description += 'Valid timezone not found in time string. Using UTC...' + parsed_tz = pytz.timezone('UTC') + in_time = parse(time.upper()) + in_time = parsed_tz.localize(in_time) + except ValueError: + em.title = 'Can\' parse time.' + em.description = f'For some reason I can\'t parse this time string: {orig_time}\n' \ + f'Examples of valid time strings are in my help documentation.\n' \ + f'Please try again.' + em.colour = discord.Colour.red() + + try: + out_tz = pytz.timezone(timezone) + except pytz.exceptions.UnknownTimeZoneError: + for tz in pytz.all_timezones: + if timezone.lower() in tz.lower(): + out_tz = pytz.timezone(tz) + break + else: + out_tz = None + em.title = 'Unknown Timezone.' + em.colour = discord.Colour.red() + finally: + if out_tz: + out_time = in_time.astimezone(out_tz) + em.add_field(name=f'{clock_emojis[(in_time.hour % 12)]} {in_time.strftime("%c")}', + value='input', inline=False) + em.add_field(name=f'{clock_emojis[(out_time.hour % 12)]} {out_time.strftime("%c")}', + value='output', inline=False) + em.colour = self.bot.embed_color + await ctx.send(embed=em) + @commands.command(name='purge', aliases=['clean', 'erase']) @commands.cooldown(1, 3, type=commands.BucketType.user) async def purge_messages(self, ctx, number: int=20, member: discord.Member=None): diff --git a/geeksbot.py b/geeksbot.py index 57b2d4c..b0fa799 100644 --- a/geeksbot.py +++ b/geeksbot.py @@ -1,5 +1,6 @@ from typing import Dict +import discord from discord.ext import commands import logging from datetime import datetime @@ -56,6 +57,7 @@ class Geeksbot(commands.Bot): self.guild_config = {} self.infected = {} self.TOKEN = self.bot_secrets['token'] + self.embed_color = discord.Colour.from_rgb(49, 107, 111) # async def connect_db(): # return await asyncpg.create_pool(host=self.bot_secrets['db_con']['host'], From 62a58bc1ece4bcb9408d7ad9d330d7813e4a9419 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 22:01:27 -0800 Subject: [PATCH 09/25] Adjust gti --- exts/utils.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index 0933cd8..014e2dd 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -486,27 +486,27 @@ class Utils: f'Examples of valid time strings are in my help documentation.\n' \ f'Please try again.' em.colour = discord.Colour.red() - - try: - out_tz = pytz.timezone(timezone) - except pytz.exceptions.UnknownTimeZoneError: - for tz in pytz.all_timezones: - if timezone.lower() in tz.lower(): - out_tz = pytz.timezone(tz) - break else: - out_tz = None - em.title = 'Unknown Timezone.' - em.colour = discord.Colour.red() - finally: - if out_tz: - out_time = in_time.astimezone(out_tz) - em.add_field(name=f'{clock_emojis[(in_time.hour % 12)]} {in_time.strftime("%c")}', - value='input', inline=False) - em.add_field(name=f'{clock_emojis[(out_time.hour % 12)]} {out_time.strftime("%c")}', - value='output', inline=False) - em.colour = self.bot.embed_color - await ctx.send(embed=em) + try: + out_tz = pytz.timezone(timezone) + except pytz.exceptions.UnknownTimeZoneError: + for tz in pytz.all_timezones: + if timezone.lower() in tz.lower(): + out_tz = pytz.timezone(tz) + break + else: + out_tz = None + em.title = 'Unknown Timezone.' + em.colour = discord.Colour.red() + finally: + if out_tz: + out_time = in_time.astimezone(out_tz) + em.add_field(name=f'{clock_emojis[(in_time.hour % 12)]} {in_time.strftime("%c")}', + value='input', inline=False) + em.add_field(name=f'{clock_emojis[(out_time.hour % 12)]} {out_time.strftime("%c")}', + value='output', inline=False) + em.colour = self.bot.embed_color + await ctx.send(embed=em) @commands.command(name='purge', aliases=['clean', 'erase']) @commands.cooldown(1, 3, type=commands.BucketType.user) From ec5d1bd1da57190b655a6c0c5cced02bf28a751d Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 22:09:49 -0800 Subject: [PATCH 10/25] Adjust gti --- exts/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exts/utils.py b/exts/utils.py index 014e2dd..7ce394c 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -482,7 +482,8 @@ class Utils: in_time = parsed_tz.localize(in_time) except ValueError: em.title = 'Can\' parse time.' - em.description = f'For some reason I can\'t parse this time string: {orig_time}\n' \ + em.description = f'For some reason I can\'t parse this time string: \n' \ + f'{orig_time} {time} {in_time}' \ f'Examples of valid time strings are in my help documentation.\n' \ f'Please try again.' em.colour = discord.Colour.red() From 70535d039948cbd347b09068a40232cb147fdaa8 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 22:11:10 -0800 Subject: [PATCH 11/25] Adjust gti --- exts/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/utils.py b/exts/utils.py index 7ce394c..db30c78 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -483,7 +483,7 @@ class Utils: except ValueError: em.title = 'Can\' parse time.' em.description = f'For some reason I can\'t parse this time string: \n' \ - f'{orig_time} {time} {in_time}' \ + f'{orig_time} {time} {parsed_tz}' \ f'Examples of valid time strings are in my help documentation.\n' \ f'Please try again.' em.colour = discord.Colour.red() From cc9a934fe6566264179ee6660427f34c3183586c Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 23:11:21 -0800 Subject: [PATCH 12/25] Adjust gti --- exts/imports/utils.py | 6 ++++++ exts/utils.py | 48 +++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/exts/imports/utils.py b/exts/imports/utils.py index c697e90..3057813 100644 --- a/exts/imports/utils.py +++ b/exts/imports/utils.py @@ -4,6 +4,7 @@ import asyncio import discord from discord.ext.commands.formatter import Paginator from . import checks +import re class Capturing(list): @@ -64,6 +65,11 @@ def to_list_of_str(items, out: list=list(), level=1, recurse=0): return out +def replace_text_ignorecase(in_str: str, old: str, new: str='') -> str: + re_replace = re.compile(re.escape(old), re.IGNORECASE) + return re_replace.sub(f'{new}', in_str) + + def paginate(text, maxlen=1990): paginator = Paginator(prefix='```py', max_size=maxlen+10) if type(text) == list: diff --git a/exts/utils.py b/exts/utils.py index db30c78..75b97a1 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -7,7 +7,7 @@ import psutil from datetime import datetime, timedelta import asyncio import async_timeout -from .imports import checks +from .imports import checks, utils import pytz import gspread from oauth2client.service_account import ServiceAccountCredentials @@ -31,6 +31,7 @@ invite_match = '(https?://)?(www.)?discord(app.com/(invite|oauth2)|.gg|.io)/[\w\ utils_log = logging.getLogger('utils') clock_emojis = ['🕛', '🕐', '🕑', '🕒', '🕓', '🕔', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚'] +replace_tzs = {'MST': 'US/Mountain', 'HST': 'US/Hawaii', 'EST': 'US/Eastern'} class Utils: @@ -471,8 +472,12 @@ class Utils: try: orig_time = copy(time) for tz in pytz.all_timezones: - if tz.lower() in time.lower(): - time = time.replace(tz, '') + if any([t.replace(' ', '_') in tz.lower() + or t.replace(' ', '-') in tz.lower() + for t in time.lower().split()]): + time = utils.replace_text_ignorecase(time, old=tz, new='') + if tz in replace_tzs: + tz = replace_tzs['tz'] parsed_tz = pytz.timezone(tz) break else: @@ -487,26 +492,25 @@ class Utils: f'Examples of valid time strings are in my help documentation.\n' \ f'Please try again.' em.colour = discord.Colour.red() + try: + out_tz = pytz.timezone(timezone) + except pytz.exceptions.UnknownTimeZoneError: + for tz in pytz.all_timezones: + if timezone.lower() in tz.lower(): + out_tz = pytz.timezone(tz) + break else: - try: - out_tz = pytz.timezone(timezone) - except pytz.exceptions.UnknownTimeZoneError: - for tz in pytz.all_timezones: - if timezone.lower() in tz.lower(): - out_tz = pytz.timezone(tz) - break - else: - out_tz = None - em.title = 'Unknown Timezone.' - em.colour = discord.Colour.red() - finally: - if out_tz: - out_time = in_time.astimezone(out_tz) - em.add_field(name=f'{clock_emojis[(in_time.hour % 12)]} {in_time.strftime("%c")}', - value='input', inline=False) - em.add_field(name=f'{clock_emojis[(out_time.hour % 12)]} {out_time.strftime("%c")}', - value='output', inline=False) - em.colour = self.bot.embed_color + out_tz = None + em.title = 'Unknown Timezone.' + em.colour = discord.Colour.red() + finally: + if out_tz: + out_time = in_time.astimezone(out_tz) + em.add_field(name=f'{clock_emojis[(in_time.hour % 12)]} {in_time.strftime("%c")}', + value='input', inline=False) + em.add_field(name=f'{clock_emojis[(out_time.hour % 12)]} {out_time.strftime("%c")}', + value='output', inline=False) + em.colour = self.bot.embed_color await ctx.send(embed=em) @commands.command(name='purge', aliases=['clean', 'erase']) From 352470e3646b13bcc09e27b4a22d454ef95e8487 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 23:25:03 -0800 Subject: [PATCH 13/25] Adjust gti --- exts/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index 75b97a1..97861d0 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -466,7 +466,7 @@ class Utils: description = '' if time is None: - description += 'Time not given... using current UTC time.' + em.set_footer(text='Time not given... using current UTC time.') in_time = datetime.utcnow() else: try: @@ -481,7 +481,7 @@ class Utils: parsed_tz = pytz.timezone(tz) break else: - description += 'Valid timezone not found in time string. Using UTC...' + em.set_footer(text='Valid timezone not found in time string. Using UTC...') parsed_tz = pytz.timezone('UTC') in_time = parse(time.upper()) in_time = parsed_tz.localize(in_time) From 02f189781fa2c6b3aa22c40b79795f651a249561 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 23:30:52 -0800 Subject: [PATCH 14/25] Adjust gti --- exts/utils.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index 97861d0..e825bbe 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -463,7 +463,6 @@ class Utils: @commands.cooldown(1, 3, type=commands.BucketType.user) async def get_time_in_timezone(self, ctx, timezone: str='US/Eastern', *, time: str=None): em = discord.Embed() - description = '' if time is None: em.set_footer(text='Time not given... using current UTC time.') @@ -472,9 +471,7 @@ class Utils: try: orig_time = copy(time) for tz in pytz.all_timezones: - if any([t.replace(' ', '_') in tz.lower() - or t.replace(' ', '-') in tz.lower() - for t in time.lower().split()]): + if time.lower().split()[-1] in tz.lower(): time = utils.replace_text_ignorecase(time, old=tz, new='') if tz in replace_tzs: tz = replace_tzs['tz'] @@ -488,7 +485,7 @@ class Utils: except ValueError: em.title = 'Can\' parse time.' em.description = f'For some reason I can\'t parse this time string: \n' \ - f'{orig_time} {time} {parsed_tz}' \ + f'{orig_time} {time} {parsed_tz}\n' \ f'Examples of valid time strings are in my help documentation.\n' \ f'Please try again.' em.colour = discord.Colour.red() From 73503c9199ab17ce64371d21c8623f6e9492aee9 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 23:39:43 -0800 Subject: [PATCH 15/25] Adjust gti --- exts/utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index e825bbe..407d23a 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -470,9 +470,10 @@ class Utils: else: try: orig_time = copy(time) + split_time = time.split() for tz in pytz.all_timezones: - if time.lower().split()[-1] in tz.lower(): - time = utils.replace_text_ignorecase(time, old=tz, new='') + if split_time[-1].lower() in tz.lower(): + time = utils.replace_text_ignorecase(time, old=split_time[-1], new='') if tz in replace_tzs: tz = replace_tzs['tz'] parsed_tz = pytz.timezone(tz) From ea177a3d7119381a8353bc65f9251d353edb3806 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 23:45:49 -0800 Subject: [PATCH 16/25] Adjust gti --- exts/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index 407d23a..5ed6edd 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -505,9 +505,9 @@ class Utils: if out_tz: out_time = in_time.astimezone(out_tz) em.add_field(name=f'{clock_emojis[(in_time.hour % 12)]} {in_time.strftime("%c")}', - value='input', inline=False) + value=f'{parsed_tz}', inline=False) em.add_field(name=f'{clock_emojis[(out_time.hour % 12)]} {out_time.strftime("%c")}', - value='output', inline=False) + value=f'{out_tz}', inline=False) em.colour = self.bot.embed_color await ctx.send(embed=em) From e2252f714089a07aabb69c402fc51da1720e48a2 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 23:48:52 -0800 Subject: [PATCH 17/25] Adjust gti --- exts/utils.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index 5ed6edd..01ce911 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -471,16 +471,20 @@ class Utils: try: orig_time = copy(time) split_time = time.split() - for tz in pytz.all_timezones: - if split_time[-1].lower() in tz.lower(): - time = utils.replace_text_ignorecase(time, old=split_time[-1], new='') - if tz in replace_tzs: - tz = replace_tzs['tz'] - parsed_tz = pytz.timezone(tz) - break - else: - em.set_footer(text='Valid timezone not found in time string. Using UTC...') - parsed_tz = pytz.timezone('UTC') + try: + parsed_tz = pytz.timezone(split_time[-1]) + time = utils.replace_text_ignorecase(time, old=split_time[-1], new='') + except pytz.exceptions.UnknownTimeZoneError: + for tz in pytz.all_timezones: + if split_time[-1].lower() in tz.lower(): + time = utils.replace_text_ignorecase(time, old=split_time[-1], new='') + if tz in replace_tzs: + tz = replace_tzs['tz'] + parsed_tz = pytz.timezone(tz) + break + else: + em.set_footer(text='Valid timezone not found in time string. Using UTC...') + parsed_tz = pytz.timezone('UTC') in_time = parse(time.upper()) in_time = parsed_tz.localize(in_time) except ValueError: From ca5b862852766fa0f2e734777eb11b0d2df60db9 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sat, 2 Jun 2018 23:52:27 -0800 Subject: [PATCH 18/25] Adjust gti --- exts/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/utils.py b/exts/utils.py index 01ce911..644522e 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -472,7 +472,7 @@ class Utils: orig_time = copy(time) split_time = time.split() try: - parsed_tz = pytz.timezone(split_time[-1]) + parsed_tz = pytz.timezone(replace_tzs[split_time[-1].upper()] or split_time[-1]) time = utils.replace_text_ignorecase(time, old=split_time[-1], new='') except pytz.exceptions.UnknownTimeZoneError: for tz in pytz.all_timezones: From f188a145eb642b36b0b12bfe46074a546f0dda67 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sun, 3 Jun 2018 00:03:30 -0800 Subject: [PATCH 19/25] Adjust gti --- exts/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/exts/utils.py b/exts/utils.py index 644522e..caf1cea 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -467,6 +467,7 @@ class Utils: if time is None: em.set_footer(text='Time not given... using current UTC time.') in_time = datetime.utcnow() + parsed_tz = pytz.timezone('UTC') else: try: orig_time = copy(time) From 43477595b2fd81431d6c25e3732b41e358e3ec5d Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sun, 3 Jun 2018 00:07:33 -0800 Subject: [PATCH 20/25] Adjust gti --- exts/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/utils.py b/exts/utils.py index caf1cea..5cd4b94 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -473,7 +473,7 @@ class Utils: orig_time = copy(time) split_time = time.split() try: - parsed_tz = pytz.timezone(replace_tzs[split_time[-1].upper()] or split_time[-1]) + parsed_tz = pytz.timezone(replace_tzs.get(split_time[-1].upper()) or split_time[-1]) time = utils.replace_text_ignorecase(time, old=split_time[-1], new='') except pytz.exceptions.UnknownTimeZoneError: for tz in pytz.all_timezones: From cf729b094be25a628d4a2bb99c60e74cbb3f20af Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sun, 3 Jun 2018 22:52:37 -0800 Subject: [PATCH 21/25] Adjust gti --- exts/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index 5cd4b94..f1d2653 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -509,10 +509,10 @@ class Utils: finally: if out_tz: out_time = in_time.astimezone(out_tz) - em.add_field(name=f'{clock_emojis[(in_time.hour % 12)]} {in_time.strftime("%c")}', - value=f'{parsed_tz}', inline=False) - em.add_field(name=f'{clock_emojis[(out_time.hour % 12)]} {out_time.strftime("%c")}', - value=f'{out_tz}', inline=False) + em.add_field(name=f'{parsed_tz}', + value=f'{clock_emojis[(in_time.hour % 12)]} {in_time.strftime("%c")}', inline=False) + em.add_field(name=f'{out_tz}', + value=f'{clock_emojis[(out_time.hour % 12)]} {out_time.strftime("%c")}', inline=False) em.colour = self.bot.embed_color await ctx.send(embed=em) From 70dbc350c23f8e3b57d6108cc70db5902a4fe34f Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sun, 3 Jun 2018 23:33:39 -0800 Subject: [PATCH 22/25] Adjust gti --- exts/utils.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index f1d2653..ebe4a23 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -489,12 +489,10 @@ class Utils: in_time = parse(time.upper()) in_time = parsed_tz.localize(in_time) except ValueError: - em.title = 'Can\' parse time.' - em.description = f'For some reason I can\'t parse this time string: \n' \ - f'{orig_time} {time} {parsed_tz}\n' \ - f'Examples of valid time strings are in my help documentation.\n' \ - f'Please try again.' - em.colour = discord.Colour.red() + raise commands.CommandError(f'For some reason I can\'t parse this time string: \n' + f'{orig_time} {time} {parsed_tz}\n' + f'Examples of valid time strings are in my help documentation.\n' + f'Please try again.') try: out_tz = pytz.timezone(timezone) except pytz.exceptions.UnknownTimeZoneError: From 55fb9ae3e74272dd25fdc89eb0f61c894e0e3293 Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sun, 3 Jun 2018 23:50:16 -0800 Subject: [PATCH 23/25] Adjust gti --- exts/utils.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/exts/utils.py b/exts/utils.py index ebe4a23..2369d67 100644 --- a/exts/utils.py +++ b/exts/utils.py @@ -486,8 +486,12 @@ class Utils: else: em.set_footer(text='Valid timezone not found in time string. Using UTC...') parsed_tz = pytz.timezone('UTC') - in_time = parse(time.upper()) - in_time = parsed_tz.localize(in_time) + if not time.isspace() and not time == '': + in_time = parse(time.upper()) + in_time = parsed_tz.localize(in_time) + else: + em.set_footer(text='Time not given. Using current time.') + in_time = parsed_tz.localize(datetime.utcnow()) except ValueError: raise commands.CommandError(f'For some reason I can\'t parse this time string: \n' f'{orig_time} {time} {parsed_tz}\n' From d5e4a5dbd7cf80af54ac73ed8428204093823eae Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Sun, 3 Jun 2018 23:56:26 -0800 Subject: [PATCH 24/25] Modified exec output --- exts/repl.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/exts/repl.py b/exts/repl.py index 7ca306c..464aab1 100644 --- a/exts/repl.py +++ b/exts/repl.py @@ -69,17 +69,9 @@ class Repl: await ctx.message.add_reaction('✅') except Exception: pass - if ret is None: - if value: - for page in paginate(value): - await ctx.send(page) - else: - self._last_result = ret - if value: - for page in paginate(value): - await ctx.send(page) - for page in paginate(ret): - await ctx.send(page) + output = f'{value}\nReturned: {ret}' + for page in paginate(output): + await ctx.send(page) @commands.command(hidden=True) async def repl(self, ctx): From 0fc8d6644d1374eeb1b598607337d04af938ffed Mon Sep 17 00:00:00 2001 From: "Dusty.P" Date: Mon, 4 Jun 2018 00:58:56 -0800 Subject: [PATCH 25/25] Start working on Paginator --- exts/imports/utils.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/exts/imports/utils.py b/exts/imports/utils.py index 3057813..b15a7fc 100644 --- a/exts/imports/utils.py +++ b/exts/imports/utils.py @@ -5,6 +5,7 @@ import discord from discord.ext.commands.formatter import Paginator from . import checks import re +import typing class Capturing(list): @@ -99,4 +100,22 @@ async def run_command(args): # Return stdout return stdout.decode().strip() + # TODO Add Paginator +class Paginator: + def __init__(self, + max_chars: int=1990, + max_lines: int=20, + prefix: str='```md', + suffix: str='```', + page_break: str=''): + assert 0 < max_lines <= max_chars + + self._parts = list() + self._prefix = prefix + self._suffix = suffix + self._max_chars = max_chars if max_chars + len(prefix) + len(suffix) + 2 <= 2000 \ + else 2000 - len(prefix) - len(suffix) - 2 + self._max_lines = max_lines - (prefix + suffix).count('\n') + 1 + self._page_break = page_break +