1
0
Fork 0
mirror of https://github.com/myned/modufur.git synced 2024-12-24 14:27:27 +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 = "*"
pyrasite = "*"
requests = "*"
websockets = "*"
[dev-packages]

35
Pipfile.lock generated
View file

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "c6b6bded7d81749dd74473eeb5b42bca29e9c2bff806aa90164523f8678ed5bf"
"sha256": "28a6c84504aba172b55cf50f8aba8eb059351bd393414e3f39e1696a2a86f526"
},
"pipfile-spec": 6,
"requires": {},
@ -67,10 +67,10 @@
},
"cachetools": {
"hashes": [
"sha256:90f1d559512fc073483fe573ef5ceb39bf6ad3d39edc98dc55178a2b2b176fa3",
"sha256:d1c398969c478d336f767ba02040fa22617333293fb0b8968e79b16028dfee35"
"sha256:0a258d82933a1dd18cb540aca4ac5d5690731e24d1239a08577b814998f49785",
"sha256:4621965b0d9d4c82a79a29edbad19946f5e7702df4afae7d1ed2df951559a8cc"
],
"version": "==2.1.0"
"version": "==3.0.0"
},
"certifi": {
"hashes": [
@ -312,6 +312,33 @@
],
"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": {
"hashes": [
"sha256:2556b779125621b311844a072e0ed367e8409a18fa12cbd68eb1258d187820f9",

View file

@ -181,7 +181,7 @@ class MsG:
u.tasks['auto_hrt'].remove(channel.id)
u.dump(u.tasks, 'cogs/tasks.pkl')
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.has_permissions(administrator=True)
@ -192,7 +192,7 @@ class MsG:
u.dump(u.tasks, 'cogs/tasks.pkl')
self.bot.loop.create_task(self.queue_for_hearts(channel=ctx.channel))
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:
raise exc.Exists
@ -212,12 +212,12 @@ class MsG:
# self.posting = True
#
# 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:
# raise 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}')
@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:
await dest.send('`{}` **related tags:**\n```\n{}```'.format(tag, formatter.tostring(related)))
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()
c += 1
@ -268,7 +268,7 @@ class MsG:
if aliases:
await dest.send('`{}` **aliases:**\n```\n{}```'.format(tag, formatter.tostring(aliases)))
else:
await ctx.send(f'**No aliases found for:** `{tag}`', delete_after=7)
await ctx.send(f'**No aliases found for:** `{tag}`')
aliases.clear()
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\}')
async def get(self, ctx):
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}')
@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']))
except exc.MissingArgument:
await ctx.send('**Invalid url**', delete_after=7)
await ctx.send('**Invalid url**')
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')
@ -328,13 +328,13 @@ class MsG:
c += 1
# 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:
await ctx.message.add_reaction('\N{CROSS MARK}')
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}')
@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"]}')
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
@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
except exc.MatchError as e:
await ctx.send('**No probable match for:** `{}`'.format(e), delete_after=7)
if remove:
with suppress(err.NotFound):
await ctx.message.delete()
await ctx.send('**No probable match for:** `{}`'.format(e))
if not c:
await ctx.message.add_reaction('\N{CROSS MARK}')
else:
with suppress(err.NotFound):
await ctx.message.delete()
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}')
except exc.SizeError as e:
await ctx.send(f'`{e}` **too large.** Maximum is 8 MB', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}')
except Exception:
await ctx.send('**The image database is offline.** Please try again later')
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}')
@cmds.command(name='reversify', aliases=['revify', 'risify', 'rify'])
async def reversify(self, ctx, *args):
@ -489,11 +488,11 @@ class MsG:
await message.delete()
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}')
c -= 1
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}')
c -= 1
@ -504,10 +503,10 @@ class MsG:
await ctx.message.add_reaction('\N{CROSS MARK}')
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}')
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}')
except Exception:
await ctx.send('**The image database is offline.** Please try again later')
@ -548,13 +547,13 @@ class MsG:
await message.delete()
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}')
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}')
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}')
print('STOPPED : reversifying')
@ -579,7 +578,7 @@ class MsG:
if not u.tasks['auto_rev']:
self.reversifying = False
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.has_permissions(manage_channels=True)
@ -594,9 +593,9 @@ class MsG:
self.reversifying = True
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:
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}')
async def _get_pool(self, ctx, *, destination, booru='e621', query=[]):
@ -664,7 +663,7 @@ class MsG:
# 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]))
blacklist.add(tag)
# Checks for, assigns, and removes first order in tags if possible
order = [tag for tag in tags if 'order:' in tag]
if order:
@ -843,7 +842,7 @@ class MsG:
except UnboundLocalError:
await dest.send('\N{HOURGLASS}')
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}')
except exc.Timeout:
await ctx.send('**Request timed out**')
@ -995,16 +994,16 @@ class MsG:
except UnboundLocalError:
await dest.send('\N{HOURGLASS}')
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}')
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}')
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}')
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}')
except exc.Timeout:
await ctx.send('**Request timed out**')
@ -1022,7 +1021,7 @@ class MsG:
# @e621_paginator.error
# async def e621_paginator_error(self, ctx, error):
# 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}')
@cmds.command(name='e926page', aliases=['e926p', 'e9p', '9p'])
@ -1157,16 +1156,16 @@ class MsG:
except UnboundLocalError:
await dest.send('\N{HOURGLASS}')
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}')
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}')
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}')
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}')
except exc.Timeout:
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))
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}')
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}')
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}')
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}')
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}')
except exc.Timeout:
await ctx.send('**Request timed out**')
@ -1230,7 +1229,7 @@ class MsG:
# @e621.error
# async def e621_error(self, ctx, error):
# 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}')
# 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))
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}')
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}')
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}')
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}')
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}')
except exc.Timeout:
await ctx.send('**Request timed out**')
@ -1281,7 +1280,7 @@ class MsG:
@cmds.group(aliases=['fave', 'fav', 'f'])
async def favorite(self, ctx):
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}')
@favorite.error
@ -1296,7 +1295,7 @@ class MsG:
async def __get_favorite_tags(self, ctx, *args):
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'])
async def __get_favorite_posts(self, ctx):
@ -1323,13 +1322,13 @@ class MsG:
'tags', set()).update(tags)
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:
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}')
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}')
@_add_favorite.command(name='posts', aliases=['p'])
@ -1356,13 +1355,13 @@ class MsG:
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:
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}')
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}')
@_remove_favorite.command(name='posts', aliases=['p'])
@ -1381,7 +1380,7 @@ class MsG:
del self.favorites[ctx.author.id]
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'])
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')
async def blacklist(self, ctx):
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}')
# @blacklist.error
# async def blacklist_error(self, ctx, error):
# 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\}')
async def _get_blacklist(self, ctx):
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}')
@_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')
async def __get_global_blacklist(self, ctx, *args):
dest = u.get_kwargs(ctx, args)['destination']
@ -1424,7 +1436,7 @@ class MsG:
async def __get_user_blacklist(self, ctx, *args):
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')
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...\}')
async def _add_tags(self, ctx):
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}')
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'])
@cmds.is_owner()
async def __add_global_tags(self, ctx, *args):
kwargs = u.get_kwargs(ctx, args)
dest, tags = kwargs['destination'], kwargs['remaining']
await dest.trigger_typing()
try:
await dest.trigger_typing()
self.blacklists['global_blacklist'].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')
tags = await self._aliases(dest, tags, self.blacklists['global_blacklist'])
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 ')
@cmds.has_permissions(manage_channels=True)
@ -1494,47 +1568,39 @@ class MsG:
guild = ctx.guild if isinstance(
ctx.guild, d.Guild) else ctx.channel
await dest.trigger_typing()
try:
await dest.trigger_typing()
self.blacklists['guild_blacklist'].setdefault(
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')
tags = await self._aliases(dest, tags, self.blacklists['guild_blacklist'].setdefault(guild.id, {}).setdefault(ctx.channel.id, set()))
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'])
async def __add_user_tags(self, ctx, *args):
kwargs = u.get_kwargs(ctx, args)
dest, tags = kwargs['destination'], kwargs['remaining']
await dest.trigger_typing()
try:
await dest.trigger_typing()
self.blacklists['user_blacklist'].setdefault(
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')
tags = await self._aliases(dest, tags, self.blacklists['user_blacklist'].setdefault(ctx.author.id, set()))
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'])
async def _remove_tags(self, ctx):
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}')
@_remove_tags.command(name='global', aliases=['gl', 'g'])
@ -1553,10 +1619,10 @@ class MsG:
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:
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}')
@_remove_tags.command(name='channel', aliases=['ch', 'c'])
@ -1579,10 +1645,10 @@ class MsG:
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:
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}')
@_remove_tags.command(name='me', aliases=['m'])
@ -1601,16 +1667,16 @@ class MsG:
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:
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}')
@blacklist.group(name='clear', aliases=['cl', 'c'])
async def _clear_blacklist(self, ctx):
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}')
@_clear_blacklist.command(name='global', aliases=['gl', 'g'])
@ -1621,7 +1687,7 @@ class MsG:
self.blacklists['global_blacklist'].clear()
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'])
@cmds.has_permissions(manage_channels=True)
@ -1635,7 +1701,7 @@ class MsG:
del self.blacklists['guild_blacklist'][guild.id][ctx.channel.id]
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'])
async def __clear_user_blacklist(self, ctx, *args):
@ -1645,4 +1711,4 @@ class MsG:
del self.blacklists['user_blacklist'][ctx.author.id]
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**')
except exc.Abort:
await ctx.send('**Deletion aborted**', delete_after=7)
await ctx.send('**Deletion aborted**')
await ctx.message.add_reaction('\N{CROSS MARK}')
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}')
@_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**')
except exc.Abort:
await ctx.send('**Deletion aborted**', delete_after=7)
await ctx.send('**Deletion aborted**')
await ctx.message.add_reaction('\N{CROSS MARK}')
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}')
@cmds.group(aliases=['task', 'tsk'])
@ -175,7 +175,7 @@ class Administration:
if not u.tasks['auto_del']:
self.deleting = False
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.has_permissions(administrator=True)
@ -189,12 +189,12 @@ class Administration:
self.bot.loop.create_task(self.delete())
self.deleting = True
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:
raise 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}')
@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 checks
from utils import utils as u
from utils import formatter
class Bot:
@ -65,7 +66,7 @@ class Bot:
async def invite(self, ctx):
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.is_owner()
@ -73,11 +74,36 @@ class Bot:
paginator = cmds.Paginator()
for guild in self.bot.guilds:
paginator.add_line(guild.name)
paginator.add_line(f'{guild.name} - @{guild.owner}')
for page in paginator.pages:
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.is_owner()
async def change_status(self, ctx, *, game=None):
@ -99,7 +125,7 @@ class Bot:
await self.bot.user.edit(username=username)
await ctx.send(f'**Username changed to** `{username}`')
else:
await ctx.send('**Invalid string**', delete_after=7)
await ctx.send('**Invalid string**')
await ctx.message.add_reaction('\N{CROSS MARK}')

View file

@ -32,19 +32,19 @@ class Utils:
context = u.last_commands[ctx.author.id]
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:
await ctx.invoke(context.command, *context.args[2:], **context.kwargs)
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}')
# Displays latency
@cmds.command(aliases=['p'], brief='Pong!', description='Returns latency from bot to Discord servers, not to user')
async def ping(self, ctx):
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')
async def prefix(self, ctx):
@ -65,11 +65,11 @@ class Utils:
await tempchannel.send(message)
except AttributeError:
await ctx.send('**Invalid channel**', delete_after=7)
await ctx.send('**Invalid channel**')
await ctx.message.add_reaction('\N{CROSS MARK}')
except AttributeError:
await ctx.send('**Invalid guild**', delete_after=7)
await ctx.send('**Invalid guild**')
await ctx.message.add_reaction('\N{CROSS MARK}')
@send.command(name='user', aliases=['u', 'member', 'm'])

View file

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

View file

@ -136,7 +136,7 @@ async def on_message(message):
@bot.event
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()
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))
@ -162,13 +162,13 @@ async def on_command_error(ctx, error):
if isinstance(error, err.NotFound):
print('NOT FOUND')
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}')
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}')
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}')
elif isinstance(error, errext.CommandNotFound):
print('INVALID COMMAND : {}'.format(error), file=sys.stderr)
@ -195,7 +195,8 @@ 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):
await ctx.message.delete()
await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}')
with suppress(err.Forbidden):
await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}')
for command in ('lastcommand', ',restart', ',die'):
if ctx.command.name == command:
@ -235,8 +236,8 @@ async def test(ctx):
if post['tags']:
temptags = post['tags'].split(' ')
cis = []
for tag in suggested:
pass
# for tag in suggested:
# pass
for tag in temptags:
tags.append(f'[{tag}](https://e621.net/post?tags={tag})')
# tags = ' '.join(tags)

View file

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

View file

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