1
0
Fork 0
mirror of https://github.com/myned/modufur.git synced 2024-11-01 21:02:38 +00:00

Merge branch 'dev'

This commit is contained in:
Dylan Dizon 2018-11-06 15:32:25 -05:00
commit 04244ea55e
10 changed files with 279 additions and 148 deletions

View file

@ -16,5 +16,6 @@ hurry = "*"
lxml = "*" lxml = "*"
pyrasite = "*" pyrasite = "*"
requests = "*" requests = "*"
websockets = "*"
[dev-packages] [dev-packages]

35
Pipfile.lock generated
View file

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "c6b6bded7d81749dd74473eeb5b42bca29e9c2bff806aa90164523f8678ed5bf" "sha256": "28a6c84504aba172b55cf50f8aba8eb059351bd393414e3f39e1696a2a86f526"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": {}, "requires": {},
@ -67,10 +67,10 @@
}, },
"cachetools": { "cachetools": {
"hashes": [ "hashes": [
"sha256:90f1d559512fc073483fe573ef5ceb39bf6ad3d39edc98dc55178a2b2b176fa3", "sha256:0a258d82933a1dd18cb540aca4ac5d5690731e24d1239a08577b814998f49785",
"sha256:d1c398969c478d336f767ba02040fa22617333293fb0b8968e79b16028dfee35" "sha256:4621965b0d9d4c82a79a29edbad19946f5e7702df4afae7d1ed2df951559a8cc"
], ],
"version": "==2.1.0" "version": "==3.0.0"
}, },
"certifi": { "certifi": {
"hashes": [ "hashes": [
@ -312,6 +312,33 @@
], ],
"version": "==1.24.1" "version": "==1.24.1"
}, },
"websockets": {
"hashes": [
"sha256:04b42a1b57096ffa5627d6a78ea1ff7fad3bc2c0331ffc17bc32a4024da7fea0",
"sha256:08e3c3e0535befa4f0c4443824496c03ecc25062debbcf895874f8a0b4c97c9f",
"sha256:10d89d4326045bf5e15e83e9867c85d686b612822e4d8f149cf4840aab5f46e0",
"sha256:232fac8a1978fc1dead4b1c2fa27c7756750fb393eb4ac52f6bc87ba7242b2fa",
"sha256:4bf4c8097440eff22bc78ec76fe2a865a6e658b6977a504679aaf08f02c121da",
"sha256:51642ea3a00772d1e48fb0c492f0d3ae3b6474f34d20eca005a83f8c9c06c561",
"sha256:55d86102282a636e195dad68aaaf85b81d0bef449d7e2ef2ff79ac450bb25d53",
"sha256:564d2675682bd497b59907d2205031acbf7d3fadf8c763b689b9ede20300b215",
"sha256:5d13bf5197a92149dc0badcc2b699267ff65a867029f465accfca8abab95f412",
"sha256:5eda665f6789edb9b57b57a159b9c55482cbe5b046d7db458948370554b16439",
"sha256:5edb2524d4032be4564c65dc4f9d01e79fe8fad5f966e5b552f4e5164fef0885",
"sha256:79691794288bc51e2a3b8de2bc0272ca8355d0b8503077ea57c0716e840ebaef",
"sha256:7fcc8681e9981b9b511cdee7c580d5b005f3bb86b65bde2188e04a29f1d63317",
"sha256:8e447e05ec88b1b408a4c9cde85aa6f4b04f06aa874b9f0b8e8319faf51b1fee",
"sha256:90ea6b3e7787620bb295a4ae050d2811c807d65b1486749414f78cfd6fb61489",
"sha256:9e13239952694b8b831088431d15f771beace10edfcf9ef230cefea14f18508f",
"sha256:d40f081187f7b54d7a99d8a5c782eaa4edc335a057aa54c85059272ed826dc09",
"sha256:e1df1a58ed2468c7b7ce9a2f9752a32ad08eac2bcd56318625c3647c2cd2da6f",
"sha256:e98d0cec437097f09c7834a11c69d79fe6241729b23f656cfc227e93294fc242",
"sha256:f8d59627702d2ff27cb495ca1abdea8bd8d581de425c56e93bff6517134e0a9b",
"sha256:fc30cdf2e949a2225b012a7911d1d031df3d23e99b7eda7dfc982dc4a860dae9"
],
"index": "pypi",
"version": "==7.0"
},
"yarl": { "yarl": {
"hashes": [ "hashes": [
"sha256:2556b779125621b311844a072e0ed367e8409a18fa12cbd68eb1258d187820f9", "sha256:2556b779125621b311844a072e0ed367e8409a18fa12cbd68eb1258d187820f9",

View file

@ -181,7 +181,7 @@ class MsG:
u.tasks['auto_hrt'].remove(channel.id) u.tasks['auto_hrt'].remove(channel.id)
u.dump(u.tasks, 'cogs/tasks.pkl') u.dump(u.tasks, 'cogs/tasks.pkl')
print('STOPPED : auto-hearting in #{}'.format(channel.name)) print('STOPPED : auto-hearting in #{}'.format(channel.name))
await channel.send('**Stopped queueing messages for hearting in** {}'.format(channel.mention), delete_after=5) await channel.send('**Stopped queueing messages for hearting in** {}'.format(channel.mention))
@cmds.command(name='autoheart', aliases=['autohrt']) @cmds.command(name='autoheart', aliases=['autohrt'])
@cmds.has_permissions(administrator=True) @cmds.has_permissions(administrator=True)
@ -192,7 +192,7 @@ class MsG:
u.dump(u.tasks, 'cogs/tasks.pkl') u.dump(u.tasks, 'cogs/tasks.pkl')
self.bot.loop.create_task(self.queue_for_hearts(channel=ctx.channel)) self.bot.loop.create_task(self.queue_for_hearts(channel=ctx.channel))
print('STARTED : auto-hearting in #{}'.format(ctx.channel.name)) print('STARTED : auto-hearting in #{}'.format(ctx.channel.name))
await ctx.send('**Auto-hearting all messages in {}**'.format(ctx.channel.mention), delete_after=5) await ctx.send('**Auto-hearting all messages in {}**'.format(ctx.channel.mention))
else: else:
raise exc.Exists raise exc.Exists
@ -212,12 +212,12 @@ class MsG:
# self.posting = True # self.posting = True
# #
# print('STARTED : auto-posting in #{}'.format(ctx.channel.name)) # print('STARTED : auto-posting in #{}'.format(ctx.channel.name))
# await ctx.send('**Auto-posting all images in {}**'.format(ctx.channel.mention), delete_after=5) # await ctx.send('**Auto-posting all images in {}**'.format(ctx.channel.mention))
# else: # else:
# raise exc.Exists # raise exc.Exists
# #
# except exc.Exists: # except exc.Exists:
# await ctx.send('**Already auto-posting in {}.** Type `stop` to stop.'.format(ctx.channel.mention), delete_after=7) # await ctx.send('**Already auto-posting in {}.** Type `stop` to stop.'.format(ctx.channel.mention))
# await ctx.message.add_reaction('\N{CROSS MARK}') # await ctx.message.add_reaction('\N{CROSS MARK}')
@cmds.group(aliases=['tag', 't'], brief='(G) Get info on tags', description='Group command for obtaining info on tags\n\nUsage:\n\{p\}tag \{flag\} \{tag(s)\}') @cmds.group(aliases=['tag', 't'], brief='(G) Get info on tags', description='Group command for obtaining info on tags\n\nUsage:\n\{p\}tag \{flag\} \{tag(s)\}')
@ -242,7 +242,7 @@ class MsG:
if related: if related:
await dest.send('`{}` **related tags:**\n```\n{}```'.format(tag, formatter.tostring(related))) await dest.send('`{}` **related tags:**\n```\n{}```'.format(tag, formatter.tostring(related)))
else: else:
await ctx.send(f'**No related tags found for:** `{tag}`', delete_after=7) await ctx.send(f'**No related tags found for:** `{tag}`')
related.clear() related.clear()
c += 1 c += 1
@ -268,7 +268,7 @@ class MsG:
if aliases: if aliases:
await dest.send('`{}` **aliases:**\n```\n{}```'.format(tag, formatter.tostring(aliases))) await dest.send('`{}` **aliases:**\n```\n{}```'.format(tag, formatter.tostring(aliases)))
else: else:
await ctx.send(f'**No aliases found for:** `{tag}`', delete_after=7) await ctx.send(f'**No aliases found for:** `{tag}`')
aliases.clear() aliases.clear()
c += 1 c += 1
@ -279,7 +279,7 @@ class MsG:
@cmds.group(aliases=['g'], brief='(G) Get e621 elements', description='Group command for obtaining various elements like post info\n\nUsage:\n\{p\}get \{flag\} \{args\}') @cmds.group(aliases=['g'], brief='(G) Get e621 elements', description='Group command for obtaining various elements like post info\n\nUsage:\n\{p\}get \{flag\} \{args\}')
async def get(self, ctx): async def get(self, ctx):
if not ctx.invoked_subcommand: if not ctx.invoked_subcommand:
await ctx.send('**Use a flag to get items.**\n*Type* `{}help get` *for more info.*'.format(ctx.prefix), delete_after=7) await ctx.send('**Use a flag to get items.**\n*Type* `{}help get` *for more info.*'.format(ctx.prefix))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@get.command(name='info', aliases=['i'], brief='(get) Get info from post', description='Return info for given post URL or ID\n\nExample:\n\{p\}get info 1145042') @get.command(name='info', aliases=['i'], brief='(get) Get info from post', description='Return info for given post URL or ID\n\nExample:\n\{p\}get info 1145042')
@ -307,7 +307,7 @@ class MsG:
icon_url=self._get_score(post['score'])) icon_url=self._get_score(post['score']))
except exc.MissingArgument: except exc.MissingArgument:
await ctx.send('**Invalid url**', delete_after=7) await ctx.send('**Invalid url**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@get.command(name='image', aliases=['img'], brief='(get) Get direct image from post', description='Return direct image URL for given post\n\nExample:\n\{p\}get image 1145042') @get.command(name='image', aliases=['img'], brief='(get) Get direct image from post', description='Return direct image URL for given post\n\nExample:\n\{p\}get image 1145042')
@ -328,13 +328,13 @@ class MsG:
c += 1 c += 1
# except # except
# await ctx.send(f'**No aliases found for:** `{tag}`', delete_after=7) # await ctx.send(f'**No aliases found for:** `{tag}`')
if not c: if not c:
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.MissingArgument: except exc.MissingArgument:
await ctx.send('**Invalid url or file**', delete_after=7) await ctx.send('**Invalid url or file**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@get.command(name='pool', aliases=['p'], brief='(get) Get pool from query', description='Return pool info for given query\n\nExample:\n\{p\}get pool 1145042') @get.command(name='pool', aliases=['p'], brief='(get) Get pool from query', description='Return pool info for given query\n\nExample:\n\{p\}get pool 1145042')
@ -381,7 +381,7 @@ class MsG:
await ctx.send(f'**{tempool["name"]}**\nhttps://e621.net/pool/show/{tempool["id"]}') await ctx.send(f'**{tempool["name"]}**\nhttps://e621.net/pool/show/{tempool["id"]}')
except exc.Abort as e: except exc.Abort as e:
await e.message.edit(content='\N{NO ENTRY SIGN}', delete_after=7) await e.message.edit(content='\N{NO ENTRY SIGN}')
# Reverse image searches a linked image using the public iqdb # Reverse image searches a linked image using the public iqdb
@cmds.command(name='reverse', aliases=['rev', 'ris'], brief='Reverse image search from e621', description='NSFW\nReverse-search an image with given URL') @cmds.command(name='reverse', aliases=['rev', 'ris'], brief='Reverse image search from e621', description='NSFW\nReverse-search an image with given URL')
@ -416,24 +416,23 @@ class MsG:
c += 1 c += 1
except exc.MatchError as e: except exc.MatchError as e:
await ctx.send('**No probable match for:** `{}`'.format(e), delete_after=7) await ctx.send('**No probable match for:** `{}`'.format(e))
if remove:
with suppress(err.NotFound):
await ctx.message.delete()
if not c: if not c:
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
else:
with suppress(err.NotFound):
await ctx.message.delete()
except exc.MissingArgument: except exc.MissingArgument:
await ctx.send('**Invalid url or file.** Be sure the link directs to an image file', delete_after=7) await ctx.send('**Invalid url or file.** Be sure the link directs to an image file')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.SizeError as e: except exc.SizeError as e:
await ctx.send(f'`{e}` **too large.** Maximum is 8 MB', delete_after=7) await ctx.send(f'`{e}` **too large.** Maximum is 8 MB')
await ctx.message.add_reaction('\N{CROSS MARK}')
except Exception:
await ctx.send('**The image database is offline.** Please try again later')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
# except Exception:
# await ctx.send('**The image database is offline.** Please try again later')
# await ctx.message.add_reaction('\N{CROSS MARK}')
@cmds.command(name='reversify', aliases=['revify', 'risify', 'rify']) @cmds.command(name='reversify', aliases=['revify', 'risify', 'rify'])
async def reversify(self, ctx, *args): async def reversify(self, ctx, *args):
@ -489,11 +488,11 @@ class MsG:
await message.delete() await message.delete()
except exc.MatchError as e: except exc.MatchError as e:
await ctx.send('`{} / {}` **No probable match for:** `{}`'.format(n, len(links), e), delete_after=7) await ctx.send('`{} / {}` **No probable match for:** `{}`'.format(n, len(links), e))
await message.add_reaction('\N{CROSS MARK}') await message.add_reaction('\N{CROSS MARK}')
c -= 1 c -= 1
except exc.SizeError as e: except exc.SizeError as e:
await ctx.send(f'`{e}` **too large.** Maximum is 8 MB', delete_after=7) await ctx.send(f'`{e}` **too large.** Maximum is 8 MB')
await message.add_reaction('\N{CROSS MARK}') await message.add_reaction('\N{CROSS MARK}')
c -= 1 c -= 1
@ -504,10 +503,10 @@ class MsG:
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.NotFound: except exc.NotFound:
await ctx.send('**No matches found**', delete_after=7) await ctx.send('**No matches found**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.BoundsError as e: except exc.BoundsError as e:
await ctx.send('`{}` **invalid limit.** Query limited to 30'.format(e), delete_after=7) await ctx.send('`{}` **invalid limit.** Query limited to 30'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except Exception: except Exception:
await ctx.send('**The image database is offline.** Please try again later') await ctx.send('**The image database is offline.** Please try again later')
@ -548,13 +547,13 @@ class MsG:
await message.delete() await message.delete()
except exc.MatchError as e: except exc.MatchError as e:
await message.channel.send('**No probable match for:** `{}`'.format(e), delete_after=7) await message.channel.send('**No probable match for:** `{}`'.format(e))
await message.add_reaction('\N{CROSS MARK}') await message.add_reaction('\N{CROSS MARK}')
except exc.SizeError as e: except exc.SizeError as e:
await message.channel.send(f'`{e}` **too large.** Maximum is 8 MB', delete_after=7) await message.channel.send(f'`{e}` **too large.** Maximum is 8 MB')
await message.add_reaction('\N{CROSS MARK}') await message.add_reaction('\N{CROSS MARK}')
except Exception: except Exception:
await message.channel.send(f'**An unknown error occurred.**', delete_after=7) await message.channel.send(f'**An unknown error occurred.**')
await message.add_reaction('\N{WARNING SIGN}') await message.add_reaction('\N{WARNING SIGN}')
print('STOPPED : reversifying') print('STOPPED : reversifying')
@ -579,7 +578,7 @@ class MsG:
if not u.tasks['auto_rev']: if not u.tasks['auto_rev']:
self.reversifying = False self.reversifying = False
print('STOPPED : reversifying #{}'.format(channel.name)) print('STOPPED : reversifying #{}'.format(channel.name))
await channel.send('**Stopped queueing messages for reversification in** {}'.format(channel.mention), delete_after=5) await channel.send('**Stopped queueing messages for reversification in** {}'.format(channel.mention))
@cmds.command(name='autoreversify', aliases=['autorev']) @cmds.command(name='autoreversify', aliases=['autorev'])
@cmds.has_permissions(manage_channels=True) @cmds.has_permissions(manage_channels=True)
@ -594,9 +593,9 @@ class MsG:
self.reversifying = True self.reversifying = True
print('STARTED : auto-reversifying in #{}'.format(ctx.channel.name)) print('STARTED : auto-reversifying in #{}'.format(ctx.channel.name))
await ctx.send('**Auto-reversifying all images in** {}'.format(ctx.channel.mention), delete_after=5) await ctx.send('**Auto-reversifying all images in** {}'.format(ctx.channel.mention))
else: else:
await ctx.send('**Already auto-reversifying in {}.** Type `stop r(eversifying)` to stop.'.format(ctx.channel.mention), delete_after=7) await ctx.send('**Already auto-reversifying in {}.** Type `stop r(eversifying)` to stop.'.format(ctx.channel.mention))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
async def _get_pool(self, ctx, *, destination, booru='e621', query=[]): async def _get_pool(self, ctx, *, destination, booru='e621', query=[]):
@ -664,7 +663,7 @@ class MsG:
# Creates temp blacklist based on context # Creates temp blacklist based on context
for bl in (self.blacklists['global_blacklist'], self.blacklists['guild_blacklist'].get(guild.id, {}).get(ctx.channel.id, set()), self.blacklists['user_blacklist'].get(ctx.author.id, set())): for bl in (self.blacklists['global_blacklist'], self.blacklists['guild_blacklist'].get(guild.id, {}).get(ctx.channel.id, set()), self.blacklists['user_blacklist'].get(ctx.author.id, set())):
for tag in bl: for tag in bl:
blacklist.update([tag] + list(self.aliases[tag])) blacklist.add(tag)
# Checks for, assigns, and removes first order in tags if possible # Checks for, assigns, and removes first order in tags if possible
order = [tag for tag in tags if 'order:' in tag] order = [tag for tag in tags if 'order:' in tag]
if order: if order:
@ -843,7 +842,7 @@ class MsG:
except UnboundLocalError: except UnboundLocalError:
await dest.send('\N{HOURGLASS}') await dest.send('\N{HOURGLASS}')
except exc.NotFound: except exc.NotFound:
await ctx.send('**Pool not found**', delete_after=7) await ctx.send('**Pool not found**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.Timeout: except exc.Timeout:
await ctx.send('**Request timed out**') await ctx.send('**Request timed out**')
@ -995,16 +994,16 @@ class MsG:
except UnboundLocalError: except UnboundLocalError:
await dest.send('\N{HOURGLASS}') await dest.send('\N{HOURGLASS}')
except exc.NotFound as e: except exc.NotFound as e:
await ctx.send('`{}` **not found**'.format(e), delete_after=7) await ctx.send('`{}` **not found**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.TagBlacklisted as e: except exc.TagBlacklisted as e:
await ctx.send('\N{NO ENTRY SIGN} `{}` **blacklisted**'.format(e), delete_after=7) await ctx.send('\N{NO ENTRY SIGN} `{}` **blacklisted**'.format(e))
await ctx.message.add_reaction('\N{NO ENTRY SIGN}') await ctx.message.add_reaction('\N{NO ENTRY SIGN}')
except exc.TagBoundsError as e: except exc.TagBoundsError as e:
await ctx.send('`{}` **out of bounds.** Tags limited to 5.'.format(e), delete_after=7) await ctx.send('`{}` **out of bounds.** Tags limited to 5.'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.FavoritesNotFound: except exc.FavoritesNotFound:
await ctx.send('**You have no favorite tags**', delete_after=7) await ctx.send('**You have no favorite tags**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.Timeout: except exc.Timeout:
await ctx.send('**Request timed out**') await ctx.send('**Request timed out**')
@ -1022,7 +1021,7 @@ class MsG:
# @e621_paginator.error # @e621_paginator.error
# async def e621_paginator_error(self, ctx, error): # async def e621_paginator_error(self, ctx, error):
# if isinstance(error, exc.NSFW): # if isinstance(error, exc.NSFW):
# await ctx.send('\N{NO ENTRY} {} **is not an NSFW channel**'.format(ctx.channel.mention), delete_after=7) # await ctx.send('\N{NO ENTRY} {} **is not an NSFW channel**'.format(ctx.channel.mention))
# await ctx.message.add_reaction('\N{NO ENTRY}') # await ctx.message.add_reaction('\N{NO ENTRY}')
@cmds.command(name='e926page', aliases=['e926p', 'e9p', '9p']) @cmds.command(name='e926page', aliases=['e926p', 'e9p', '9p'])
@ -1157,16 +1156,16 @@ class MsG:
except UnboundLocalError: except UnboundLocalError:
await dest.send('\N{HOURGLASS}') await dest.send('\N{HOURGLASS}')
except exc.NotFound as e: except exc.NotFound as e:
await ctx.send('`{}` **not found**'.format(e), delete_after=7) await ctx.send('`{}` **not found**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.TagBlacklisted as e: except exc.TagBlacklisted as e:
await ctx.send('\N{NO ENTRY SIGN} `{}` **blacklisted**'.format(e), delete_after=7) await ctx.send('\N{NO ENTRY SIGN} `{}` **blacklisted**'.format(e))
await ctx.message.add_reaction('\N{NO ENTRY SIGN}') await ctx.message.add_reaction('\N{NO ENTRY SIGN}')
except exc.TagBoundsError as e: except exc.TagBoundsError as e:
await ctx.send('`{}` **out of bounds.** Tags limited to 5.'.format(e), delete_after=7) await ctx.send('`{}` **out of bounds.** Tags limited to 5.'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.FavoritesNotFound: except exc.FavoritesNotFound:
await ctx.send('**You have no favorite tags**', delete_after=7) await ctx.send('**You have no favorite tags**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.Timeout: except exc.Timeout:
await ctx.send('**Request timed out**') await ctx.send('**Request timed out**')
@ -1209,19 +1208,19 @@ class MsG:
self.bot.loop.create_task(self.queue_for_hearts(message=message, send=embed)) self.bot.loop.create_task(self.queue_for_hearts(message=message, send=embed))
except exc.TagBlacklisted as e: except exc.TagBlacklisted as e:
await ctx.send('`{}` **blacklisted**'.format(e), delete_after=7) await ctx.send('`{}` **blacklisted**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.BoundsError as e: except exc.BoundsError as e:
await ctx.send('`{}` **out of bounds.** Images limited to 3.'.format(e), delete_after=7) await ctx.send('`{}` **out of bounds.** Images limited to 3.'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.TagBoundsError as e: except exc.TagBoundsError as e:
await ctx.send('`{}` **out of bounds.** Tags limited to 5.'.format(e), delete_after=7) await ctx.send('`{}` **out of bounds.** Tags limited to 5.'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.NotFound as e: except exc.NotFound as e:
await ctx.send('`{}` **not found**'.format(e), delete_after=7) await ctx.send('`{}` **not found**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.FavoritesNotFound: except exc.FavoritesNotFound:
await ctx.send('**You have no favorite tags**', delete_after=7) await ctx.send('**You have no favorite tags**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.Timeout: except exc.Timeout:
await ctx.send('**Request timed out**') await ctx.send('**Request timed out**')
@ -1230,7 +1229,7 @@ class MsG:
# @e621.error # @e621.error
# async def e621_error(self, ctx, error): # async def e621_error(self, ctx, error):
# if isinstance(error, exc.NSFW): # if isinstance(error, exc.NSFW):
# await ctx.send('\N{NO ENTRY} {} **is not an NSFW channel**'.format(ctx.channel.mention), delete_after=7) # await ctx.send('\N{NO ENTRY} {} **is not an NSFW channel**'.format(ctx.channel.mention))
# await ctx.message.add_reaction('\N{NO ENTRY}') # await ctx.message.add_reaction('\N{NO ENTRY}')
# Searches for and returns images from e926.net given tags when not blacklisted # Searches for and returns images from e926.net given tags when not blacklisted
@ -1260,19 +1259,19 @@ class MsG:
self.bot.loop.create_task(self.queue_for_hearts(message=message, send=embed)) self.bot.loop.create_task(self.queue_for_hearts(message=message, send=embed))
except exc.TagBlacklisted as e: except exc.TagBlacklisted as e:
await ctx.send('`{}` **blacklisted**'.format(e), delete_after=7) await ctx.send('`{}` **blacklisted**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.BoundsError as e: except exc.BoundsError as e:
await ctx.send('`{}` **out of bounds.** Images limited to 3.'.format(e), delete_after=7) await ctx.send('`{}` **out of bounds.** Images limited to 3.'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.TagBoundsError as e: except exc.TagBoundsError as e:
await ctx.send('`{}` **out of bounds.** Tags limited to 5.'.format(e), delete_after=7) await ctx.send('`{}` **out of bounds.** Tags limited to 5.'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.NotFound as e: except exc.NotFound as e:
await ctx.send('`{}` **not found**'.format(e), delete_after=7) await ctx.send('`{}` **not found**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.FavoritesNotFound: except exc.FavoritesNotFound:
await ctx.send('**You have no favorite tags**', delete_after=7) await ctx.send('**You have no favorite tags**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.Timeout: except exc.Timeout:
await ctx.send('**Request timed out**') await ctx.send('**Request timed out**')
@ -1281,7 +1280,7 @@ class MsG:
@cmds.group(aliases=['fave', 'fav', 'f']) @cmds.group(aliases=['fave', 'fav', 'f'])
async def favorite(self, ctx): async def favorite(self, ctx):
if not ctx.invoked_subcommand: if not ctx.invoked_subcommand:
await ctx.send('**Use a flag to manage favorites.**\n*Type* `{}help fav` *for more info.*'.format(ctx.prefix), delete_after=7) await ctx.send('**Use a flag to manage favorites.**\n*Type* `{}help fav` *for more info.*'.format(ctx.prefix))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@favorite.error @favorite.error
@ -1296,7 +1295,7 @@ class MsG:
async def __get_favorite_tags(self, ctx, *args): async def __get_favorite_tags(self, ctx, *args):
dest = u.get_kwargs(ctx, args)['destination'] dest = u.get_kwargs(ctx, args)['destination']
await dest.send('\N{WHITE MEDIUM STAR} {}**\'s favorite tags:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(self.favorites.get(ctx.author.id, {}).get('tags', set()))), delete_after=7) await dest.send('\N{WHITE MEDIUM STAR} {}**\'s favorite tags:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(self.favorites.get(ctx.author.id, {}).get('tags', set()))))
@_get_favorite.command(name='posts', aliases=['p']) @_get_favorite.command(name='posts', aliases=['p'])
async def __get_favorite_posts(self, ctx): async def __get_favorite_posts(self, ctx):
@ -1323,13 +1322,13 @@ class MsG:
'tags', set()).update(tags) 'tags', set()).update(tags)
u.dump(self.favorites, 'cogs/favorites.pkl') u.dump(self.favorites, 'cogs/favorites.pkl')
await dest.send('{} **added to their favorites:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(tags)), delete_after=5) await dest.send('{} **added to their favorites:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(tags)))
except exc.BoundsError: except exc.BoundsError:
await ctx.send('**Favorites list currently limited to:** `5`', delete_after=7) await ctx.send('**Favorites list currently limited to:** `5`')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.TagBlacklisted as e: except exc.TagBlacklisted as e:
await ctx.send('\N{NO ENTRY SIGN} `{}` **blacklisted**', delete_after=7) await ctx.send('\N{NO ENTRY SIGN} `{}` **blacklisted**')
await ctx.message.add_reaction('\N{NO ENTRY SIGN}') await ctx.message.add_reaction('\N{NO ENTRY SIGN}')
@_add_favorite.command(name='posts', aliases=['p']) @_add_favorite.command(name='posts', aliases=['p'])
@ -1356,13 +1355,13 @@ class MsG:
u.dump(self.favorites, 'cogs/favorites.pkl') u.dump(self.favorites, 'cogs/favorites.pkl')
await dest.send('{} **removed from their favorites:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(tags)), delete_after=5) await dest.send('{} **removed from their favorites:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(tags)))
except KeyError: except KeyError:
await ctx.send('**You do not have any favorites**', delete_after=7) await ctx.send('**You do not have any favorites**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except exc.TagError as e: except exc.TagError as e:
await ctx.send('`{}` **not in favorites**'.format(e), delete_after=7) await ctx.send('`{}` **not in favorites**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@_remove_favorite.command(name='posts', aliases=['p']) @_remove_favorite.command(name='posts', aliases=['p'])
@ -1381,7 +1380,7 @@ class MsG:
del self.favorites[ctx.author.id] del self.favorites[ctx.author.id]
u.dump(self.favorites, 'cogs/favorites.pkl') u.dump(self.favorites, 'cogs/favorites.pkl')
await dest.send('{}**\'s favorites cleared**'.format(ctx.author.mention), delete_after=5) await dest.send('{}**\'s favorites cleared**'.format(ctx.author.mention))
@_clear_favorite.command(name='posts', aliases=['p']) @_clear_favorite.command(name='posts', aliases=['p'])
async def __clear_favorite_posts(self, ctx): async def __clear_favorite_posts(self, ctx):
@ -1391,20 +1390,33 @@ class MsG:
@cmds.group(aliases=['bl', 'b'], brief='(G) Manage blacklists', description='Manage channel or personal blacklists\n\nUsage:\n{p}bl get {blacklist} to show a blacklist\n{p}bl clear {blacklist} to clear a blacklist\n{p}bl add {blacklist} {tags...} to add tag(s) to a blacklist\n{p}bl remove {blacklist} {tags...} to remove tags from a blacklist') @cmds.group(aliases=['bl', 'b'], brief='(G) Manage blacklists', description='Manage channel or personal blacklists\n\nUsage:\n{p}bl get {blacklist} to show a blacklist\n{p}bl clear {blacklist} to clear a blacklist\n{p}bl add {blacklist} {tags...} to add tag(s) to a blacklist\n{p}bl remove {blacklist} {tags...} to remove tags from a blacklist')
async def blacklist(self, ctx): async def blacklist(self, ctx):
if not ctx.invoked_subcommand: if not ctx.invoked_subcommand:
await ctx.send('**Use a flag to manage blacklists.**\n*Type* `{}help bl` *for more info.*'.format(ctx.prefix), delete_after=7) await ctx.send('**Use a flag to manage blacklists.**\n*Type* `{}help bl` *for more info.*'.format(ctx.prefix))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
# @blacklist.error # @blacklist.error
# async def blacklist_error(self, ctx, error): # async def blacklist_error(self, ctx, error):
# if isinstance(error, KeyError): # if isinstance(error, KeyError):
# return await ctx.send('**Blacklist does not exist**', delete_after=7) # return await ctx.send('**Blacklist does not exist**')
@blacklist.group(name='get', aliases=['g'], brief='(G) Get a blacklist\n\nUsage:\n\{p\}bl get \{blacklist\}') @blacklist.group(name='get', aliases=['g'], brief='(G) Get a blacklist\n\nUsage:\n\{p\}bl get \{blacklist\}')
async def _get_blacklist(self, ctx): async def _get_blacklist(self, ctx):
if not ctx.invoked_subcommand: if not ctx.invoked_subcommand:
await ctx.send('**Invalid blacklist**', delete_after=7) await ctx.send('**Invalid blacklist**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@_get_blacklist.command(name='alias', aliases=['aliases'])
async def __get_blacklist_aliases(self, ctx, *args):
guild = ctx.guild if isinstance(
ctx.guild, d.Guild) else ctx.channel
blacklist = set()
# Creates temp blacklist based on context
for bl in (self.blacklists['global_blacklist'], self.blacklists['guild_blacklist'].get(guild.id, {}).get(ctx.channel.id, set()), self.blacklists['user_blacklist'].get(ctx.author.id, set())):
for tag in bl:
blacklist.update([tag] + list(self.aliases[tag]))
await ctx.send(f'**Contextual blacklist aliases:**\n```\n{formatter.tostring(blacklist)}```')
@_get_blacklist.command(name='global', aliases=['gl', 'g'], brief='Get current global blacklist', description='Get current global blacklist\n\nThis applies to all booru commands, in accordance with Discord\'s ToS agreement\n\nExample:\n\{p\}bl get global') @_get_blacklist.command(name='global', aliases=['gl', 'g'], brief='Get current global blacklist', description='Get current global blacklist\n\nThis applies to all booru commands, in accordance with Discord\'s ToS agreement\n\nExample:\n\{p\}bl get global')
async def __get_global_blacklist(self, ctx, *args): async def __get_global_blacklist(self, ctx, *args):
dest = u.get_kwargs(ctx, args)['destination'] dest = u.get_kwargs(ctx, args)['destination']
@ -1424,7 +1436,7 @@ class MsG:
async def __get_user_blacklist(self, ctx, *args): async def __get_user_blacklist(self, ctx, *args):
dest = u.get_kwargs(ctx, args)['destination'] dest = u.get_kwargs(ctx, args)['destination']
await dest.send('\N{NO ENTRY SIGN} {}**\'s blacklist:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(self.blacklists['user_blacklist'].get(ctx.author.id, set()))), delete_after=7) await dest.send('\N{NO ENTRY SIGN} {}**\'s blacklist:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(self.blacklists['user_blacklist'].get(ctx.author.id, set()))))
@_get_blacklist.command(name='here', aliases=['h'], brief='Get current global and channel blacklists', description='Get current global and channel blacklists in a single message\n\nExample:\{p\}bl get here') @_get_blacklist.command(name='here', aliases=['h'], brief='Get current global and channel blacklists', description='Get current global and channel blacklists in a single message\n\nExample:\{p\}bl get here')
async def __get_here_blacklists(self, ctx, *args): async def __get_here_blacklists(self, ctx, *args):
@ -1461,29 +1473,91 @@ class MsG:
@blacklist.group(name='add', aliases=['a'], brief='(G) Add tag(s) to a blacklist\n\nUsage:\n\{p\}bl add \{blacklist\} \{tags...\}') @blacklist.group(name='add', aliases=['a'], brief='(G) Add tag(s) to a blacklist\n\nUsage:\n\{p\}bl add \{blacklist\} \{tags...\}')
async def _add_tags(self, ctx): async def _add_tags(self, ctx):
if not ctx.invoked_subcommand: if not ctx.invoked_subcommand:
await ctx.send('**Invalid blacklist**', delete_after=7) await ctx.send('**Invalid blacklist**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
async def _aliases(self, ctx, tags, blacklist):
def on_reaction(reaction, user):
if user is ctx.author and reaction.message.channel is ctx.message.channel:
if reaction.emoji == '\N{HEAVY MINUS SIGN}':
raise exc.Remove
if reaction.emoji == '\N{THUMBS DOWN SIGN}':
raise exc.Continue
elif reaction.emoji == '\N{THUMBS UP SIGN}':
return True
else:
return False
def on_message(msg):
if msg.author is ctx.message.author and msg.channel is ctx.message.channel:
if msg.content == '0':
raise exc.Abort
return True
return False
aliases = set()
try:
for tag in tags:
aliases.add(tag)
alias_request = await u.fetch('https://e621.net/tag_alias/index.json', params={'aliased_to': tag, 'approved': 'true'}, json=True)
if alias_request:
for dic in alias_request:
aliases.add(dic['name'])
message = await ctx.send(f'**Also add aliases?**```\n{formatter.tostring(aliases)}```')
await message.add_reaction('\N{THUMBS DOWN SIGN}')
await message.add_reaction('\N{HEAVY MINUS SIGN}')
await message.add_reaction('\N{THUMBS UP SIGN}')
try:
await self.bot.wait_for('reaction_add', check=on_reaction, timeout=7 * 60)
except exc.Remove:
await message.edit(content=f'**Also add aliases?**```\n{formatter.tostring(aliases)}```\nType the tag(s) to remove or `0` to abort:')
await message.remove_reaction('\N{HEAVY MINUS SIGN}', self.bot.user)
await message.remove_reaction('\N{HEAVY MINUS SIGN}', ctx.author)
response = await self.bot.wait_for('message', check=on_message, timeout=7 * 60)
for tag in response.content.split(' '):
if tag in aliases:
aliases.remove(tag)
await message.edit(content=f'**Also add aliases?**```\n{formatter.tostring(aliases)}```\nConfirm or deny changes')
await self.bot.wait_for('reaction_add', check=on_reaction, timeout=7 * 60)
blacklist.update(aliases)
await message.delete()
return aliases
except exc.Continue:
await message.delete()
return tags
except exc.Abort:
await message.delete()
raise exc.Abort
@_add_tags.command(name='global', aliases=['gl', 'g']) @_add_tags.command(name='global', aliases=['gl', 'g'])
@cmds.is_owner() @cmds.is_owner()
async def __add_global_tags(self, ctx, *args): async def __add_global_tags(self, ctx, *args):
kwargs = u.get_kwargs(ctx, args) kwargs = u.get_kwargs(ctx, args)
dest, tags = kwargs['destination'], kwargs['remaining'] dest, tags = kwargs['destination'], kwargs['remaining']
try:
await dest.trigger_typing() await dest.trigger_typing()
self.blacklists['global_blacklist'].update(tags) tags = await self._aliases(dest, tags, self.blacklists['global_blacklist'])
for tag in tags:
alias_request = await u.fetch('https://e621.net/tag_alias/index.json', params={'aliased_to': tag, 'approved': 'true'}, json=True)
if alias_request:
for dic in alias_request:
self.aliases.setdefault(tag, set()).add(dic['name'])
else:
self.aliases.setdefault(tag, set())
u.dump(self.blacklists, 'cogs/blacklists.pkl')
u.dump(self.aliases, 'cogs/aliases.pkl')
await dest.send('**Added to global blacklist:**\n```\n{}```'.format(formatter.tostring(tags)), delete_after=5) u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('**Added to global blacklist:**\n```\n{}```'.format(formatter.tostring(tags)))
except exc.Abort:
await dest.send('**Aborted**')
@_add_tags.command(name='channel', aliases=['ch', 'c'], brief='@manage_channel@ Add tag(s) to the current channel blacklist (requires manage_channel)', description='Add tag(s) to the current channel blacklist ') @_add_tags.command(name='channel', aliases=['ch', 'c'], brief='@manage_channel@ Add tag(s) to the current channel blacklist (requires manage_channel)', description='Add tag(s) to the current channel blacklist ')
@cmds.has_permissions(manage_channels=True) @cmds.has_permissions(manage_channels=True)
@ -1494,47 +1568,39 @@ class MsG:
guild = ctx.guild if isinstance( guild = ctx.guild if isinstance(
ctx.guild, d.Guild) else ctx.channel ctx.guild, d.Guild) else ctx.channel
try:
await dest.trigger_typing() await dest.trigger_typing()
self.blacklists['guild_blacklist'].setdefault( tags = await self._aliases(dest, tags, self.blacklists['guild_blacklist'].setdefault(guild.id, {}).setdefault(ctx.channel.id, set()))
guild.id, {}).setdefault(ctx.channel.id, set()).update(tags)
for tag in tags:
alias_request = await u.fetch('https://e621.net/tag_alias/index.json', params={'aliased_to': tag, 'approved': 'true'}, json=True)
if alias_request:
for dic in alias_request:
self.aliases.setdefault(tag, set()).add(dic['name'])
else:
self.aliases.setdefault(tag, set())
u.dump(self.blacklists, 'cogs/blacklists.pkl')
u.dump(self.aliases, 'cogs/aliases.pkl')
await dest.send('**Added to** {} **blacklist:**\n```\n{}```'.format(ctx.channel.mention, formatter.tostring(tags)), delete_after=5) u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('**Added to** {} **blacklist:**\n```\n{}```'.format(ctx.channel.mention, formatter.tostring(tags)))
except exc.Abort:
await dest.send('**Aborted**')
@_add_tags.command(name='me', aliases=['m']) @_add_tags.command(name='me', aliases=['m'])
async def __add_user_tags(self, ctx, *args): async def __add_user_tags(self, ctx, *args):
kwargs = u.get_kwargs(ctx, args) kwargs = u.get_kwargs(ctx, args)
dest, tags = kwargs['destination'], kwargs['remaining'] dest, tags = kwargs['destination'], kwargs['remaining']
try:
await dest.trigger_typing() await dest.trigger_typing()
self.blacklists['user_blacklist'].setdefault( tags = await self._aliases(dest, tags, self.blacklists['user_blacklist'].setdefault(ctx.author.id, set()))
ctx.author.id, set()).update(tags)
for tag in tags:
alias_request = await u.fetch('https://e621.net/tag_alias/index.json', params={'aliased_to': tag, 'approved': 'true'}, json=True)
if alias_request:
for dic in alias_request:
self.aliases.setdefault(tag, set()).add(dic['name'])
else:
self.aliases.setdefault(tag, set())
u.dump(self.blacklists, 'cogs/blacklists.pkl')
u.dump(self.aliases, 'cogs/aliases.pkl')
await dest.send('{} **added to their blacklist:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(tags)), delete_after=5) u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('{} **added to their blacklist:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(tags)))
except exc.Abort:
await dest.send('**Aborted**')
@blacklist.group(name='remove', aliases=['rm', 'r']) @blacklist.group(name='remove', aliases=['rm', 'r'])
async def _remove_tags(self, ctx): async def _remove_tags(self, ctx):
if not ctx.invoked_subcommand: if not ctx.invoked_subcommand:
await ctx.send('**Invalid blacklist**', delete_after=7) await ctx.send('**Invalid blacklist**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@_remove_tags.command(name='global', aliases=['gl', 'g']) @_remove_tags.command(name='global', aliases=['gl', 'g'])
@ -1553,10 +1619,10 @@ class MsG:
u.dump(self.blacklists, 'cogs/blacklists.pkl') u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('**Removed from global blacklist:**\n```\n{}```'.format(formatter.tostring(tags)), delete_after=5) await dest.send('**Removed from global blacklist:**\n```\n{}```'.format(formatter.tostring(tags)))
except exc.TagError as e: except exc.TagError as e:
await ctx.send('`{}` **not in blacklist**'.format(e), delete_after=7) await ctx.send('`{}` **not in blacklist**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@_remove_tags.command(name='channel', aliases=['ch', 'c']) @_remove_tags.command(name='channel', aliases=['ch', 'c'])
@ -1579,10 +1645,10 @@ class MsG:
u.dump(self.blacklists, 'cogs/blacklists.pkl') u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('**Removed from** {} **blacklist:**\n```\n{}```'.format(ctx.channel.mention, formatter.tostring(tags), delete_after=5)) await dest.send('**Removed from** {} **blacklist:**\n```\n{}```'.format(ctx.channel.mention, formatter.tostring(tags)))
except exc.TagError as e: except exc.TagError as e:
await ctx.send('`{}` **not in blacklist**'.format(e), delete_after=7) await ctx.send('`{}` **not in blacklist**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@_remove_tags.command(name='me', aliases=['m']) @_remove_tags.command(name='me', aliases=['m'])
@ -1601,16 +1667,16 @@ class MsG:
u.dump(self.blacklists, 'cogs/blacklists.pkl') u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('{} **removed from their blacklist:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(tags)), delete_after=5) await dest.send('{} **removed from their blacklist:**\n```\n{}```'.format(ctx.author.mention, formatter.tostring(tags)))
except exc.TagError as e: except exc.TagError as e:
await ctx.send('`{}` **not in blacklist**'.format(e), delete_after=7) await ctx.send('`{}` **not in blacklist**'.format(e))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@blacklist.group(name='clear', aliases=['cl', 'c']) @blacklist.group(name='clear', aliases=['cl', 'c'])
async def _clear_blacklist(self, ctx): async def _clear_blacklist(self, ctx):
if not ctx.invoked_subcommand: if not ctx.invoked_subcommand:
await ctx.send('**Invalid blacklist**', delete_after=7) await ctx.send('**Invalid blacklist**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@_clear_blacklist.command(name='global', aliases=['gl', 'g']) @_clear_blacklist.command(name='global', aliases=['gl', 'g'])
@ -1621,7 +1687,7 @@ class MsG:
self.blacklists['global_blacklist'].clear() self.blacklists['global_blacklist'].clear()
u.dump(self.blacklists, 'cogs/blacklists.pkl') u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('**Global blacklist cleared**', delete_after=5) await dest.send('**Global blacklist cleared**')
@_clear_blacklist.command(name='channel', aliases=['ch', 'c']) @_clear_blacklist.command(name='channel', aliases=['ch', 'c'])
@cmds.has_permissions(manage_channels=True) @cmds.has_permissions(manage_channels=True)
@ -1635,7 +1701,7 @@ class MsG:
del self.blacklists['guild_blacklist'][guild.id][ctx.channel.id] del self.blacklists['guild_blacklist'][guild.id][ctx.channel.id]
u.dump(self.blacklists, 'cogs/blacklists.pkl') u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('{} **blacklist cleared**'.format(ctx.channel.mention), delete_after=5) await dest.send('{} **blacklist cleared**'.format(ctx.channel.mention))
@_clear_blacklist.command(name='me', aliases=['m']) @_clear_blacklist.command(name='me', aliases=['m'])
async def __clear_user_blacklist(self, ctx, *args): async def __clear_user_blacklist(self, ctx, *args):
@ -1645,4 +1711,4 @@ class MsG:
del self.blacklists['user_blacklist'][ctx.author.id] del self.blacklists['user_blacklist'][ctx.author.id]
u.dump(self.blacklists, 'cogs/blacklists.pkl') u.dump(self.blacklists, 'cogs/blacklists.pkl')
await dest.send('{}**\'s blacklist cleared**'.format(ctx.author.mention), delete_after=5) await dest.send('{}**\'s blacklist cleared**'.format(ctx.author.mention))

View file

@ -82,10 +82,10 @@ class Administration:
await ctx.send(f'\N{WHITE HEAVY CHECK MARK} **Finished deleting** `{c}` **of** {user.mention}**\'s messages**') await ctx.send(f'\N{WHITE HEAVY CHECK MARK} **Finished deleting** `{c}` **of** {user.mention}**\'s messages**')
except exc.Abort: except exc.Abort:
await ctx.send('**Deletion aborted**', delete_after=7) await ctx.send('**Deletion aborted**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except TimeoutError: except TimeoutError:
await ctx.send('**Deletion timed out**', delete_after=7) await ctx.send('**Deletion timed out**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@_prune_user.command(name='all', aliases=['a'], brief='Prune a user\'s messages from the guild', description='about flag centers on message 50 of 101 messages\n\npfg \{user id\} [before|after|about] [\{message id\}]\n\nExample:\npfg \{user id\} before \{message id\}', hidden=True) @_prune_user.command(name='all', aliases=['a'], brief='Prune a user\'s messages from the guild', description='about flag centers on message 50 of 101 messages\n\npfg \{user id\} [before|after|about] [\{message id\}]\n\nExample:\npfg \{user id\} before \{message id\}', hidden=True)
@ -131,10 +131,10 @@ class Administration:
await ctx.send(f'\N{WHITE HEAVY CHECK MARK} **Finished deleting** `{c}` **of** {user.mention}**\'s messages**') await ctx.send(f'\N{WHITE HEAVY CHECK MARK} **Finished deleting** `{c}` **of** {user.mention}**\'s messages**')
except exc.Abort: except exc.Abort:
await ctx.send('**Deletion aborted**', delete_after=7) await ctx.send('**Deletion aborted**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except TimeoutError: except TimeoutError:
await ctx.send('**Deletion timed out**', delete_after=7) await ctx.send('**Deletion timed out**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@cmds.group(aliases=['task', 'tsk']) @cmds.group(aliases=['task', 'tsk'])
@ -175,7 +175,7 @@ class Administration:
if not u.tasks['auto_del']: if not u.tasks['auto_del']:
self.deleting = False self.deleting = False
print('STOPPED : deleting #{}'.format(channel.name)) print('STOPPED : deleting #{}'.format(channel.name))
await channel.send('**Stopped queueing messages for deletion in** {}'.format(channel.mention), delete_after=5) await channel.send('**Stopped queueing messages for deletion in** {}'.format(channel.mention))
@cmds.command(name='autodelete', aliases=['autodel']) @cmds.command(name='autodelete', aliases=['autodel'])
@cmds.has_permissions(administrator=True) @cmds.has_permissions(administrator=True)
@ -189,12 +189,12 @@ class Administration:
self.bot.loop.create_task(self.delete()) self.bot.loop.create_task(self.delete())
self.deleting = True self.deleting = True
print('STARTED : auto-deleting in #{}'.format(ctx.channel.name)) print('STARTED : auto-deleting in #{}'.format(ctx.channel.name))
await ctx.send('**Auto-deleting all messages in {}**'.format(ctx.channel.mention), delete_after=5) await ctx.send('**Auto-deleting all messages in {}**'.format(ctx.channel.mention))
else: else:
raise exc.Exists raise exc.Exists
except exc.Exists: except exc.Exists:
await ctx.send('**Already auto-deleting in {}.** Type `stop d(eleting)` to stop.'.format(ctx.channel.mention), delete_after=7) await ctx.send('**Already auto-deleting in {}.** Type `stop d(eleting)` to stop.'.format(ctx.channel.mention))
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@cmds.group(aliases=['setting', 'set', 's']) @cmds.group(aliases=['setting', 'set', 's'])

View file

@ -14,6 +14,7 @@ from discord.ext import commands as cmds
from misc import exceptions as exc from misc import exceptions as exc
from misc import checks from misc import checks
from utils import utils as u from utils import utils as u
from utils import formatter
class Bot: class Bot:
@ -65,7 +66,7 @@ class Bot:
async def invite(self, ctx): async def invite(self, ctx):
await ctx.message.add_reaction('\N{ENVELOPE}') await ctx.message.add_reaction('\N{ENVELOPE}')
await ctx.send('https://discordapp.com/oauth2/authorize?&client_id={}&scope=bot&permissions={}'.format(u.config['client_id'], u.config['permissions']), delete_after=5) await ctx.send('https://discordapp.com/oauth2/authorize?&client_id={}&scope=bot&permissions={}'.format(u.config['client_id'], u.config['permissions']))
@cmds.command(name=',guilds', aliases=[',glds', ',servers', ',svrs']) @cmds.command(name=',guilds', aliases=[',glds', ',servers', ',svrs'])
@cmds.is_owner() @cmds.is_owner()
@ -73,11 +74,36 @@ class Bot:
paginator = cmds.Paginator() paginator = cmds.Paginator()
for guild in self.bot.guilds: for guild in self.bot.guilds:
paginator.add_line(guild.name) paginator.add_line(f'{guild.name} - @{guild.owner}')
for page in paginator.pages: for page in paginator.pages:
await ctx.send(f'**Guilds:**\n{page}') await ctx.send(f'**Guilds:**\n{page}')
@cmds.command(name=',permissions', aliases=[',permission', ',perms', ',perm'])
@cmds.is_owner()
async def permissions(self, ctx, *args: d.Member):
members = list(args)
permissions = {}
if not members:
members.append(ctx.guild.me)
for member in members:
permissions[member.mention] = []
for k, v in dict(ctx.channel.permissions_for(member)).items():
if v:
permissions[member.mention].append(k)
await ctx.send(f'**Permissions:**\n\n{formatter.dict_tostring(permissions, f=False)}')
@cmds.command(name=',tasks', aliases=[',task'])
@cmds.is_owner()
async def tasks(self, ctx):
tasks = [task for task in asyncio.Task.all_tasks() if not task.done()]
await ctx.send(f'**Tasks active:** `{int((len(tasks) - 6) / 3)}`')
@cmds.command(name=',status', aliases=[',presence', ',game'], hidden=True) @cmds.command(name=',status', aliases=[',presence', ',game'], hidden=True)
@cmds.is_owner() @cmds.is_owner()
async def change_status(self, ctx, *, game=None): async def change_status(self, ctx, *, game=None):
@ -99,7 +125,7 @@ class Bot:
await self.bot.user.edit(username=username) await self.bot.user.edit(username=username)
await ctx.send(f'**Username changed to** `{username}`') await ctx.send(f'**Username changed to** `{username}`')
else: else:
await ctx.send('**Invalid string**', delete_after=7) await ctx.send('**Invalid string**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')

View file

@ -32,19 +32,19 @@ class Utils:
context = u.last_commands[ctx.author.id] context = u.last_commands[ctx.author.id]
if arg == 'show' or arg == 'sh' or arg == 's': if arg == 'show' or arg == 'sh' or arg == 's':
await ctx.send(f'`{context.prefix}{context.invoked_with} {" ".join(context.args[2:])}`', delete_after=7) await ctx.send(f'`{context.prefix}{context.invoked_with} {" ".join(context.args[2:])}`')
else: else:
await ctx.invoke(context.command, *context.args[2:], **context.kwargs) await ctx.invoke(context.command, *context.args[2:], **context.kwargs)
except KeyError: except KeyError:
await ctx.send('**No last command**', delete_after=7) await ctx.send('**No last command**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
# Displays latency # Displays latency
@cmds.command(aliases=['p'], brief='Pong!', description='Returns latency from bot to Discord servers, not to user') @cmds.command(aliases=['p'], brief='Pong!', description='Returns latency from bot to Discord servers, not to user')
async def ping(self, ctx): async def ping(self, ctx):
await ctx.message.add_reaction('\N{TABLE TENNIS PADDLE AND BALL}') await ctx.message.add_reaction('\N{TABLE TENNIS PADDLE AND BALL}')
await ctx.send(ctx.author.mention + ' \N{TABLE TENNIS PADDLE AND BALL} `' + str(round(self.bot.latency * 1000)) + 'ms`', delete_after=5) await ctx.send(ctx.author.mention + ' \N{TABLE TENNIS PADDLE AND BALL} `' + str(round(self.bot.latency * 1000)) + 'ms`')
@cmds.command(aliases=['pre', 'prefixes'], brief='List bot prefixes', description='Shows all used prefixes') @cmds.command(aliases=['pre', 'prefixes'], brief='List bot prefixes', description='Shows all used prefixes')
async def prefix(self, ctx): async def prefix(self, ctx):
@ -65,11 +65,11 @@ class Utils:
await tempchannel.send(message) await tempchannel.send(message)
except AttributeError: except AttributeError:
await ctx.send('**Invalid channel**', delete_after=7) await ctx.send('**Invalid channel**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except AttributeError: except AttributeError:
await ctx.send('**Invalid guild**', delete_after=7) await ctx.send('**Invalid guild**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@send.command(name='user', aliases=['u', 'member', 'm']) @send.command(name='user', aliases=['u', 'member', 'm'])

View file

@ -10,6 +10,9 @@ async def send_error(ctx, error):
# class NSFW(errext.CheckFailure): # class NSFW(errext.CheckFailure):
# pass # pass
class Remove(Exception):
pass
class SizeError(Exception): class SizeError(Exception):
pass pass

View file

@ -136,7 +136,7 @@ async def on_message(message):
@bot.event @bot.event
async def on_error(error, *args, **kwargs): async def on_error(error, *args, **kwargs):
print('\n! ! ! ! !\nE R R O R : {}\n! ! ! ! !\n'.format(error), file=sys.stderr) print('\n! ! ! ! !\nE R R O R : {}\n! ! ! ! !\n'.format(sys.exc_info()[1].text), file=sys.stderr)
tb.print_exc() tb.print_exc()
await bot.get_user(u.config['owner_id']).send('**ERROR** \N{WARNING SIGN}\n```\n{}```'.format(error)) await bot.get_user(u.config['owner_id']).send('**ERROR** \N{WARNING SIGN}\n```\n{}```'.format(error))
await bot.get_channel(u.config['info_channel']).send('**ERROR** \N{WARNING SIGN}\n```\n{}```'.format(error)) await bot.get_channel(u.config['info_channel']).send('**ERROR** \N{WARNING SIGN}\n```\n{}```'.format(error))
@ -162,13 +162,13 @@ async def on_command_error(ctx, error):
if isinstance(error, err.NotFound): if isinstance(error, err.NotFound):
print('NOT FOUND') print('NOT FOUND')
elif isinstance(error, errext.MissingRequiredArgument): elif isinstance(error, errext.MissingRequiredArgument):
await ctx.send('**Missing required argument**', delete_after=7) await ctx.send('**Missing required argument**')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
elif isinstance(error, errext.BadArgument): elif isinstance(error, errext.BadArgument):
await ctx.send(f'**Invalid argument.** {error}', delete_after=7) await ctx.send(f'**Invalid argument.** {error}')
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
elif isinstance(error, errext.CheckFailure): elif isinstance(error, errext.CheckFailure):
await ctx.send('**Insufficient permissions**', delete_after=7) await ctx.send('**Insufficient permissions**')
await ctx.message.add_reaction('\N{NO ENTRY}') await ctx.message.add_reaction('\N{NO ENTRY}')
elif isinstance(error, errext.CommandNotFound): elif isinstance(error, errext.CommandNotFound):
print('INVALID COMMAND : {}'.format(error), file=sys.stderr) print('INVALID COMMAND : {}'.format(error), file=sys.stderr)
@ -195,6 +195,7 @@ async def on_command_completion(ctx):
if ctx.guild.id in u.settings['del_ctx'] and ctx.me.permissions_in(ctx.channel).manage_messages and isinstance(ctx.message.channel, d.TextChannel): if ctx.guild.id in u.settings['del_ctx'] and ctx.me.permissions_in(ctx.channel).manage_messages and isinstance(ctx.message.channel, d.TextChannel):
await ctx.message.delete() await ctx.message.delete()
with suppress(err.Forbidden):
await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}')
for command in ('lastcommand', ',restart', ',die'): for command in ('lastcommand', ',restart', ',die'):
@ -235,8 +236,8 @@ async def test(ctx):
if post['tags']: if post['tags']:
temptags = post['tags'].split(' ') temptags = post['tags'].split(' ')
cis = [] cis = []
for tag in suggested: # for tag in suggested:
pass # pass
for tag in temptags: for tag in temptags:
tags.append(f'[{tag}](https://e621.net/post?tags={tag})') tags.append(f'[{tag}](https://e621.net/post?tags={tag})')
# tags = ' '.join(tags) # tags = ' '.join(tags)

View file

@ -1,8 +1,8 @@
def tostring(i, *, order=None): def tostring(i, *, order=None, newline=False):
o = '' o = ''
if i: if i:
for v in i: for v in i:
o += v + ' ' o += v + (' ' if newline is False else '\n')
o = o[:-1] o = o[:-1]
elif order: elif order:
o += order o += order
@ -20,11 +20,17 @@ def tostring_commas(i):
return '' return ''
def dict_tostring(i): def dict_tostring(i, f=True):
o = '' o = ''
if f:
if i: if i:
for k, v in i.items(): for k, v in i.items():
o += '**' + k + ':** `' + tostring(v) + '`\n' o += '**' + k + ':** `' + tostring(v) + '`\n'
else:
if i:
for k, v in i.items():
o += k + ': ```' + tostring(v, newline=True) + '```\n'
return o return o

View file

@ -6,6 +6,7 @@ import subprocess
from contextlib import suppress from contextlib import suppress
from fractions import gcd from fractions import gcd
import math import math
from pprint import pprint
import aiohttp import aiohttp
import discord as d import discord as d