From f1abf4e0b39805380dc66a89926b622946ee6b92 Mon Sep 17 00:00:00 2001 From: Myned Date: Fri, 27 Oct 2017 21:06:41 -0400 Subject: [PATCH 1/5] Testing n stuff --- src/main/run.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/run.py b/src/main/run.py index 54244fa..582fd9c 100644 --- a/src/main/run.py +++ b/src/main/run.py @@ -136,12 +136,14 @@ def after(voice, error): @bot.command(name=',test', hidden=True) @commands.is_owner() @checks.del_ctx() -async def test(ctx): - logs = [] - async for entry in ctx.guild.audit_logs(limit=None, action=d.AuditLogAction.message_delete): - logs.append( - f'@{entry.user.name} deleted {entry.extra.count} messages from @{entry.target.name} in #{entry.extra.channel.name}') - pprint(logs) +async def test(ctx, message): + if '<:N_:368917475531816962>' in message: + await ctx.send('<:N_:368917475531816962>') + # logs = [] + # async for entry in ctx.guild.audit_logs(limit=None, action=d.AuditLogAction.message_delete): + # logs.append( + # f'@{entry.user.name} deleted {entry.extra.count} messages from @{entry.target.name} in #{entry.extra.channel.name}') + # pprint(logs) # channel = bot.get_channel(int(cid)) # voice = await channel.connect() # voice.play(d.AudioSource, after=lambda: after(voice)) From fac0cc58f06624adba5b36357de8126497ea69fb Mon Sep 17 00:00:00 2001 From: Myned Date: Fri, 27 Oct 2017 21:07:06 -0400 Subject: [PATCH 2/5] Added getpool command --- src/main/cogs/booru.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/main/cogs/booru.py b/src/main/cogs/booru.py index 8303be9..73be5c7 100644 --- a/src/main/cogs/booru.py +++ b/src/main/cogs/booru.py @@ -111,6 +111,46 @@ class MsG: await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') + @commands.command(name='pool', aliases=['getpool', 'getp', 'gp'], brief='e621 Search for pools', description='e621 | NSFW\nReturn pool for query', usage='[related|rel]') + @checks.del_ctx() + async def get_pool(self, ctx, *args): + def on_message(msg): + if (msg.content.isdigit() and int(msg.content) == 0) or msg.content.lower() == 'cancel' and msg.author is ctx.author and msg.channel is ctx.channel: + raise exc.Abort + elif msg.content.isdigit(): + if int(msg.content) <= len(pools) and int(msg.content) > 0 and msg.author is ctx.author and msg.channel is ctx.channel: + return True + return False + + try: + kwargs = u.get_kwargs(ctx, args) + dest, query = kwargs['destination'], kwargs['remaining'] + ident = None + + await dest.trigger_typing() + + pools = [] + pool_request = await u.fetch('https://e621.net/pool/index.json', params={'query': ' '.join(query)}, json=True) + if len(pool_request) > 1: + for pool in pool_request: + pools.append(pool['name']) + match = await ctx.send('**Multiple pools found for `{}`.** Type the number of the correct match.\n```\n{}```\n`0` or `cancel`'.format(' '.join(query), '\n'.join(['{} {}'.format(c, elem) for c, elem in enumerate(pools, 1)]))) + selection = await self.bot.wait_for('message', check=on_message, timeout=60) + await match.delete() + tempool = [pool for pool in pool_request if pool['name'] == pools[int(selection.content) - 1]][0] + await selection.delete() + elif pool_request: + tempool = pool_request[0] + else: + raise exc.NotFound + + await ctx.send(f'**{tempool["name"]}**\nhttps://e621.net/pool/show?id={tempool["id"]}') + await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') + + except exc.Abort: + await ctx.send('**Search aborted**', delete_after=10) + await ctx.message.add_reaction('\N{CROSS MARK}') + @commands.command(name='getimage', aliases=['geti', 'gi']) @checks.del_ctx() async def get_image(self, ctx, *args): From 1c212ee20de54900d25b41bdc4ca0fcd69a5d7cc Mon Sep 17 00:00:00 2001 From: Myned Date: Fri, 27 Oct 2017 21:07:49 -0400 Subject: [PATCH 3/5] Added "0" in addition to "cancel" to abort wait_for --- src/main/cogs/booru.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cogs/booru.py b/src/main/cogs/booru.py index 73be5c7..21e2136 100644 --- a/src/main/cogs/booru.py +++ b/src/main/cogs/booru.py @@ -510,7 +510,7 @@ class MsG: async def _get_pool(self, ctx, *, booru='e621', query=[]): def on_message(msg): - if msg.content.lower() == 'cancel' and msg.author is ctx.author and msg.channel is ctx.channel: + if (msg.content.isdigit() and int(msg.content) == 0) or msg.content.lower() == 'cancel' and msg.author is ctx.author and msg.channel is ctx.channel: raise exc.Abort elif msg.content.isdigit(): if int(msg.content) <= len(pools) and int(msg.content) > 0 and msg.author is ctx.author and msg.channel is ctx.channel: From e51e2c124c5ad82dc1e0af774d2bc15ea05a0d6b Mon Sep 17 00:00:00 2001 From: Myned Date: Fri, 27 Oct 2017 21:08:23 -0400 Subject: [PATCH 4/5] Formatting tweak, removed try/except/finally block for logging purposes --- src/main/cogs/booru.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/cogs/booru.py b/src/main/cogs/booru.py index 21e2136..06b520e 100644 --- a/src/main/cogs/booru.py +++ b/src/main/cogs/booru.py @@ -525,12 +525,8 @@ class MsG: if len(pool_request) > 1: for pool in pool_request: pools.append(pool['name']) - match = await ctx.send('**Multiple pools found.** Type in the correct match.\n```\n{}```\nor `cancel` to cancel.'.format('\n'.join(['{} {}'.format(c, elem) for c, elem in enumerate(pools, 1)]))) - try: - selection = await self.bot.wait_for('message', check=on_message, timeout=5 * 60) - except exc.Abort: - raise exc.Abort - finally: + match = await ctx.send('**Multiple pools found for `{}`.** Type the number of the correct match.\n```\n{}```\n`0` or `cancel`'.format(' '.join(query), '\n'.join(['{} {}'.format(c, elem) for c, elem in enumerate(pools, 1)]))) + selection = await self.bot.wait_for('message', check=on_message, timeout=60) await match.delete() tempool = [pool for pool in pool_request if pool['name'] == pools[int(selection.content) - 1]][0] From 06d5d562de4e4b662c1eb8c176ab4d4a8db0be56 Mon Sep 17 00:00:00 2001 From: Myned Date: Fri, 27 Oct 2017 21:08:52 -0400 Subject: [PATCH 5/5] Temporarily combined e6/pool paginator into one method for clarity --- src/main/cogs/booru.py | 437 ++++++++++++++++++++--------------------- 1 file changed, 214 insertions(+), 223 deletions(-) diff --git a/src/main/cogs/booru.py b/src/main/cogs/booru.py index 06b520e..da1dff0 100644 --- a/src/main/cogs/booru.py +++ b/src/main/cogs/booru.py @@ -527,7 +527,7 @@ class MsG: pools.append(pool['name']) match = await ctx.send('**Multiple pools found for `{}`.** Type the number of the correct match.\n```\n{}```\n`0` or `cancel`'.format(' '.join(query), '\n'.join(['{} {}'.format(c, elem) for c, elem in enumerate(pools, 1)]))) selection = await self.bot.wait_for('message', check=on_message, timeout=60) - await match.delete() + await match.delete() tempool = [pool for pool in pool_request if pool['name'] == pools[int(selection.content) - 1]][0] await selection.delete() @@ -547,147 +547,6 @@ class MsG: return pool, posts - # Creates reaction-based paginator for linked pools - @commands.command(name='pool', aliases=['e6pp', '6pp'], brief='e621 pool paginator', description='e621 | NSFW\nShow pools in a page format', hidden=True) - @checks.del_ctx() - async def pool_paginator(self, ctx, *args): - def on_reaction(reaction, user): - if reaction.emoji == '\N{OCTAGONAL SIGN}' and reaction.message.id == ctx.message.id and user is ctx.author: - raise exc.Abort - elif reaction.emoji == '\N{GROWING HEART}' and reaction.message.id == paginator.id and user is ctx.author: - raise exc.Save - elif reaction.emoji == '\N{LEFTWARDS BLACK ARROW}' and reaction.message.id == paginator.id and user is ctx.author: - raise exc.Left - elif reaction.emoji == '\N{NUMBER SIGN}\N{COMBINING ENCLOSING KEYCAP}' and reaction.message.id == paginator.id and user is ctx.author: - raise exc.GoTo - elif reaction.emoji == '\N{BLACK RIGHTWARDS ARROW}' and reaction.message.id == paginator.id and user is ctx.author: - raise exc.Right - return False - - def on_message(msg): - if msg.content.isdigit(): - if 1 <= int(msg.content) <= len(posts) and msg.author is ctx.author and msg.channel is ctx.channel: - return True - return False - - try: - kwargs = u.get_kwargs(ctx, args) - dest, query = kwargs['destination'], kwargs['remaining'] - hearted = [] - c = 1 - - await dest.trigger_typing() - - pool, posts = await self._get_pool(ctx, booru='e621', query=query) - keys = list(posts.keys()) - values = list(posts.values()) - - embed = d.Embed( - title=values[c - 1]['author'], url='https://e621.net/post/show/{}'.format(keys[c - 1]), color=dest.me.color if isinstance(dest.channel, d.TextChannel) else self.color) - embed.set_image(url=values[c - 1]['url']) - embed.set_author(name=pool['name'], - url='https://e621.net/pool/show?id={}'.format(pool['id']), icon_url=ctx.author.avatar_url) - embed.set_footer(text='{} / {}'.format(c, len(posts)), - icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') - - paginator = await dest.send(embed=embed) - - for emoji in ('\N{GROWING HEART}', '\N{LEFTWARDS BLACK ARROW}', '\N{NUMBER SIGN}\N{COMBINING ENCLOSING KEYCAP}', '\N{BLACK RIGHTWARDS ARROW}'): - await paginator.add_reaction(emoji) - await ctx.message.add_reaction('\N{OCTAGONAL SIGN}') - await asyncio.sleep(1) - - while not self.bot.is_closed(): - try: - done, pending = await asyncio.wait([self.bot.wait_for('reaction_add', check=on_reaction, timeout=10 * 60), - self.bot.wait_for('reaction_remove', check=on_reaction, timeout=10 * 60)], return_when=asyncio.FIRST_COMPLETED) - for future in done: - future.result() - - except exc.Save: - if values[c - 1]['url'] not in hearted: - hearted.append(values[c - 1]['url']) - - await paginator.edit(content='\N{HEAVY BLACK HEART}') - else: - hearted.remove(values[c - 1]['url']) - - await paginator.edit(content='\N{BROKEN HEART}') - - except exc.Left: - if c > 1: - c -= 1 - embed.title = values[c - 1]['author'] - embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) - embed.set_footer(text='{} / {}'.format(c, len(posts)), - icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') - embed.set_image(url=values[c - 1]['url']) - - await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) - else: - await paginator.edit(content='**First image.**') - - except exc.GoTo: - await paginator.edit(content='**Enter image number...**') - number = await self.bot.wait_for('message', check=on_message, timeout=10 * 60) - - c = int(number.content) - await number.delete() - embed.title = values[c - 1]['author'] - embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) - embed.set_footer(text='{} / {}'.format(c, len(posts)), - icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') - embed.set_image(url=values[c - 1]['url']) - - await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) - - except exc.Right: - if c < len(keys): - c += 1 - embed.title = values[c - 1]['author'] - embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) - embed.set_footer(text='{} / {}'.format(c, len(posts)), - icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') - embed.set_image(url=values[c - 1]['url']) - - await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) - else: - await paginator.edit(content='**Last image.**') - - except exc.Abort: - try: - await paginator.edit(content='**Exited paginator.**') - - except UnboundLocalError: - await dest.send('**Exited paginator.**') - if not hearted: - await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') - except asyncio.TimeoutError: - try: - await paginator.edit(content='**Paginator timed out.**') - - except UnboundLocalError: - await dest.send('**Paginator timed out.**') - if not hearted: - await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') - except exc.NotFound: - await ctx.send('**Pool not found.**', delete_after=10) - await ctx.message.add_reaction('\N{CROSS MARK}') - except exc.Timeout: - await ctx.send('**Request timed out.**') - await ctx.message.add_reaction('\N{CROSS MARK}') - - finally: - if hearted: - await ctx.message.add_reaction('\N{HOURGLASS WITH FLOWING SAND}') - - for url in hearted: - await ctx.author.send('`{} / {}`\n{}'.format(hearted.index(url) + 1, len(hearted), url)) - - await asyncio.sleep(self.RATE_LIMIT) - - await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') - # Messy code that checks image limit and tags in blacklists async def _get_posts(self, ctx, *, booru='e621', tags=[], limit=1, previous={}): guild = ctx.guild if isinstance( @@ -751,10 +610,7 @@ class MsG: else: raise exc.NotFound - @commands.command(name='e621p', aliases=['e6p', '6p']) - @checks.del_ctx() - @checks.is_nsfw() - async def e621_paginator(self, ctx, *args): + async def paginate(self, ctx, *, args, pool=False): def on_reaction(reaction, user): if reaction.emoji == '\N{OCTAGONAL SIGN}' and reaction.message.id == ctx.message.id and user is ctx.author: raise exc.Abort @@ -775,89 +631,72 @@ class MsG: return False try: - kwargs = u.get_kwargs(ctx, args) - dest, tags = kwargs['destination'], kwargs['remaining'] - limit = self.LIMIT / 5 - hearted = [] - c = 1 + if not pool: + kwargs = u.get_kwargs(ctx, args) + dest, tags = kwargs['destination'], kwargs['remaining'] + limit = self.LIMIT / 5 + hearted = [] + c = 1 - tags = self._get_favorites(ctx, tags) + tags = self._get_favorites(ctx, tags) - await ctx.trigger_typing() + await ctx.trigger_typing() - posts = await self._get_posts(ctx, booru='e621', tags=tags, limit=limit) - keys = list(posts.keys()) - values = list(posts.values()) + posts = await self._get_posts(ctx, booru='e621', tags=tags, limit=limit) + keys = list(posts.keys()) + values = list(posts.values()) - embed = d.Embed( - title=values[c - 1]['author'], url='https://e621.net/post/show/{}'.format(keys[c - 1]), color=ctx.me.color if isinstance(ctx.channel, d.TextChannel) else self.color) - embed.set_image(url=values[c - 1]['url']) - embed.set_author(name=formatter.tostring(tags, random=True), - url='https://e621.net/post?tags={}'.format(','.join(tags)), icon_url=ctx.author.avatar_url) - embed.set_footer(text='{} / {}'.format(c, len(posts)), - icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') + embed = d.Embed( + title=values[c - 1]['author'], url='https://e621.net/post/show/{}'.format(keys[c - 1]), color=ctx.me.color if isinstance(ctx.channel, d.TextChannel) else self.color) + embed.set_image(url=values[c - 1]['url']) + embed.set_author(name=formatter.tostring(tags, random=True), + url='https://e621.net/post?tags={}'.format(','.join(tags)), icon_url=ctx.author.avatar_url) + embed.set_footer(text='{} / {}'.format(c, len(posts)), + icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') - paginator = await dest.send(embed=embed) + paginator = await dest.send(embed=embed) - for emoji in ('\N{GROWING HEART}', '\N{LEFTWARDS BLACK ARROW}', '\N{NUMBER SIGN}\N{COMBINING ENCLOSING KEYCAP}', '\N{BLACK RIGHTWARDS ARROW}'): - await paginator.add_reaction(emoji) - await ctx.message.add_reaction('\N{OCTAGONAL SIGN}') - await asyncio.sleep(1) + for emoji in ('\N{GROWING HEART}', '\N{LEFTWARDS BLACK ARROW}', '\N{NUMBER SIGN}\N{COMBINING ENCLOSING KEYCAP}', '\N{BLACK RIGHTWARDS ARROW}'): + await paginator.add_reaction(emoji) + await ctx.message.add_reaction('\N{OCTAGONAL SIGN}') + await asyncio.sleep(1) - while not self.bot.is_closed(): - try: - done, pending = await asyncio.wait([self.bot.wait_for('reaction_add', check=on_reaction, timeout=10 * 60), - self.bot.wait_for('reaction_remove', check=on_reaction, timeout=10 * 60)], return_when=asyncio.FIRST_COMPLETED) - for future in done: - future.result() - - except exc.Save: - if values[c - 1]['url'] not in hearted: - hearted.append(values[c - 1]['url']) - - await paginator.edit(content='\N{HEAVY BLACK HEART}') - else: - hearted.remove(values[c - 1]['url']) - - await paginator.edit(content='\N{BROKEN HEART}') - - except exc.Left: - if c > 1: - c -= 1 - embed.title = values[c - 1]['author'] - embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) - embed.set_footer(text='{} / {}'.format(c, len(posts)), - icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') - embed.set_image(url=values[c - 1]['url']) - - await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) - else: - await paginator.edit(content='**First image.**') - - except exc.GoTo: - await paginator.edit(content='**Enter image number...**') - number = await self.bot.wait_for('message', check=on_message, timeout=10 * 60) - - c = int(number.content) - await number.delete() - embed.title = values[c - 1]['author'] - embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) - embed.set_footer(text='{} / {}'.format(c, len(posts)), - icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') - embed.set_image(url=values[c - 1]['url']) - - await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) - - except exc.Right: + while not self.bot.is_closed(): try: - if c % limit == 0: - await dest.trigger_typing() - posts.update(await self._get_posts(ctx, booru='e621', tags=tags, limit=limit, previous=posts)) + done, pending = await asyncio.wait([self.bot.wait_for('reaction_add', check=on_reaction, timeout=10 * 60), + self.bot.wait_for('reaction_remove', check=on_reaction, timeout=10 * 60)], return_when=asyncio.FIRST_COMPLETED) + for future in done: + future.result() - keys = list(posts.keys()) - values = list(posts.values()) + except exc.Save: + if values[c - 1]['url'] not in hearted: + hearted.append(values[c - 1]['url']) - c += 1 + await paginator.edit(content='\N{HEAVY BLACK HEART}') + else: + hearted.remove(values[c - 1]['url']) + + await paginator.edit(content='\N{BROKEN HEART}') + + except exc.Left: + if c > 1: + c -= 1 + embed.title = values[c - 1]['author'] + embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) + embed.set_footer(text='{} / {}'.format(c, len(posts)), + icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') + embed.set_image(url=values[c - 1]['url']) + + await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) + else: + await paginator.edit(content='**First image.**') + + except exc.GoTo: + await paginator.edit(content='**Enter image number...**') + number = await self.bot.wait_for('message', check=on_message, timeout=10 * 60) + + c = int(number.content) + await number.delete() embed.title = values[c - 1]['author'] embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) embed.set_footer(text='{} / {}'.format(c, len(posts)), @@ -866,10 +705,162 @@ class MsG: await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) - except IndexError: - await paginator.edit(content='**No more images found.**') - except exc.NotFound: - await paginator.edit(content='**No more images found.**') + except exc.Right: + try: + if c % limit == 0: + await dest.trigger_typing() + posts.update(await self._get_posts(ctx, booru='e621', tags=tags, limit=limit, previous=posts)) + + keys = list(posts.keys()) + values = list(posts.values()) + + c += 1 + embed.title = values[c - 1]['author'] + embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) + embed.set_footer(text='{} / {}'.format(c, len(posts)), + icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') + embed.set_image(url=values[c - 1]['url']) + + await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) + + except IndexError: + await paginator.edit(content='**No more images found.**') + except exc.NotFound: + await paginator.edit(content='**No more images found.**') + else: + kwargs = u.get_kwargs(ctx, args) + dest, query = kwargs['destination'], kwargs['remaining'] + hearted = [] + c = 1 + + await dest.trigger_typing() + + pool, posts = await self._get_pool(ctx, booru='e621', query=query) + keys = list(posts.keys()) + values = list(posts.values()) + + embed = d.Embed( + title=values[c - 1]['author'], url='https://e621.net/post/show/{}'.format(keys[c - 1]), color=dest.me.color if isinstance(dest.channel, d.TextChannel) else self.color) + embed.set_image(url=values[c - 1]['url']) + embed.set_author(name=pool['name'], + url='https://e621.net/pool/show?id={}'.format(pool['id']), icon_url=ctx.author.avatar_url) + embed.set_footer(text='{} / {}'.format(c, len(posts)), + icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') + + paginator = await dest.send(embed=embed) + + for emoji in ('\N{GROWING HEART}', '\N{LEFTWARDS BLACK ARROW}', '\N{NUMBER SIGN}\N{COMBINING ENCLOSING KEYCAP}', '\N{BLACK RIGHTWARDS ARROW}'): + await paginator.add_reaction(emoji) + await ctx.message.add_reaction('\N{OCTAGONAL SIGN}') + await asyncio.sleep(1) + + while not self.bot.is_closed(): + try: + done, pending = await asyncio.wait([self.bot.wait_for('reaction_add', check=on_reaction, timeout=10 * 60), + self.bot.wait_for('reaction_remove', check=on_reaction, timeout=10 * 60)], return_when=asyncio.FIRST_COMPLETED) + for future in done: + future.result() + + except exc.Save: + if values[c - 1]['url'] not in hearted: + hearted.append(values[c - 1]['url']) + + await paginator.edit(content='\N{HEAVY BLACK HEART}') + else: + hearted.remove(values[c - 1]['url']) + + await paginator.edit(content='\N{BROKEN HEART}') + + except exc.Left: + if c > 1: + c -= 1 + embed.title = values[c - 1]['author'] + embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) + embed.set_footer(text='{} / {}'.format(c, len(posts)), + icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') + embed.set_image(url=values[c - 1]['url']) + + await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) + else: + await paginator.edit(content='**First image.**') + + except exc.GoTo: + await paginator.edit(content='**Enter image number...**') + number = await self.bot.wait_for('message', check=on_message, timeout=10 * 60) + + c = int(number.content) + await number.delete() + embed.title = values[c - 1]['author'] + embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) + embed.set_footer(text='{} / {}'.format(c, len(posts)), + icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') + embed.set_image(url=values[c - 1]['url']) + + await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) + + except exc.Right: + if c < len(keys): + c += 1 + embed.title = values[c - 1]['author'] + embed.url = 'https://e621.net/post/show/{}'.format(keys[c - 1]) + embed.set_footer(text='{} / {}'.format(c, len(posts)), + icon_url='http://lh6.ggpht.com/d3pNZNFCcJM8snBsRSdKUhR9AVBnJMcYYrR92RRDBOzCrxZMhuTeoGOQSmSEn7DAPQ=w300') + embed.set_image(url=values[c - 1]['url']) + + await paginator.edit(content='\N{HEAVY BLACK HEART}' if values[c - 1]['url'] in hearted else None, embed=embed) + else: + await paginator.edit(content='**Last image.**') + + finally: + return hearted + + # Creates reaction-based paginator for linked pools + @commands.command(name='poolp', aliases=['e621pp', 'e6pp', '6pp'], brief='e621 pool paginator', description='e621 | NSFW\nShow pools in a page format', hidden=True) + @checks.del_ctx() + async def pool_paginator(self, ctx, *args): + try: + hearted = await self.paginate(pool=True) + + except exc.Abort: + try: + await paginator.edit(content='**Exited paginator.**') + + except UnboundLocalError: + await dest.send('**Exited paginator.**') + if not hearted: + await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') + except asyncio.TimeoutError: + try: + await paginator.edit(content='**Paginator timed out.**') + + except UnboundLocalError: + await dest.send('**Paginator timed out.**') + if not hearted: + await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') + except exc.NotFound: + await ctx.send('**Pool not found.**', delete_after=10) + await ctx.message.add_reaction('\N{CROSS MARK}') + except exc.Timeout: + await ctx.send('**Request timed out.**') + await ctx.message.add_reaction('\N{CROSS MARK}') + + finally: + if hearted: + await ctx.message.add_reaction('\N{HOURGLASS WITH FLOWING SAND}') + + for url in hearted: + await ctx.author.send('`{} / {}`\n{}'.format(hearted.index(url) + 1, len(hearted), url)) + + await asyncio.sleep(self.RATE_LIMIT) + + await ctx.message.add_reaction('\N{WHITE HEAVY CHECK MARK}') + + @commands.command(name='e621p', aliases=['e6p', '6p']) + @checks.del_ctx() + @checks.is_nsfw() + async def e621_paginator(self, ctx, *args): + try: + hearted = await self.paginate(ctx, args=args) except exc.Abort: try: