Skip to content

Instantly share code, notes, and snippets.

@Jan200101
Created April 1, 2017 22:40
Show Gist options
  • Save Jan200101/0e2a90fc8444a33a5fcd81066c4e4b91 to your computer and use it in GitHub Desktop.
Save Jan200101/0e2a90fc8444a33a5fcd81066c4e4b91 to your computer and use it in GitHub Desktop.
import logging
import pagify
class ReactionGui():
def __init__(self):
self.logger = logging.getLogger("red")
async def interactive_results(self, ctx, results, single_msg=True,):
author = ctx.message.author
channel = ctx.message.channel
if single_msg:
choices = OrderedDict((('◀', 'prev'),
('❌', 'close'),
('▶', 'next')))
else:
choices = OrderedDict((('❌', 'close'),
('🔽', 'next')))
nbs = '​'
discord_fmt = nbs + '```py\n{}\n```'
prompt = (" Output too long. Navigate pages with ({})"
.format('/'.join(choices.values())))
pages = [p for p in pagify(results, ['\n', ' '],
page_length=1500)]
# results is not a generator, so no reason to keep this as one
pages = [discord_fmt.format(p) + 'pg. {}/{}'
.format(c + 1, len(pages))
for c, p in enumerate(pages)]
pages[0] += prompt
choice = 'next'
page_num = 0
dirs = {'next': 1, 'prev': -1}
msgs = []
while choice:
msg = await self.display_page(pages[page_num], channel, choices,
msgs, single_msg)
choice = await self.wait_for_interaction(msg, author, choices)
if choice == 'close':
try:
await self.bot.delete_messages(msgs)
except: # selfbots
for m in msgs:
await self.bot.delete_message(m)
break
if choice in dirs:
page_num = (page_num + dirs[choice]) % len(pages)
if choice is None:
await self.remove_reactions(msgs.pop())
async def display_page(self, page, channel, emojis, msgs, overwrite_prev):
if msgs and overwrite_prev:
msg = msgs.pop()
embed = msg.embeds[0] if len(msg.embeds) else None
msg = await self.bot.edit_message(msg, new_content=page, embed=embed)
else:
send_msg = self.bot.send_message(channel, page)
if msgs:
# refresh msg
prv_msg = await self.bot.get_message(channel, msgs[len(msgs) - 1].id)
tasks = (send_msg, self.remove_reactions(prv_msg))
results = await asyncio.gather(*tasks, return_exceptions=True)
msg = results[0]
else:
msg = await send_msg
try:
async def add_emojis(m, es):
try:
for e in es: # we want these to be in order
await self.bot.add_reaction(m, e)
except discord.errors.NotFound:
# was deleted before we could react
pass
# but we don't want to wait
self.bot.loop.create_task(add_emojis(msg, emojis))
except:
pass
msgs.append(msg)
return msg
async def wait_for_interaction(self, msg, author, choices: OrderedDict,
timeout=120, delete_msg=True,
match_first_char=True):
"""waits for a message or reaction add/remove
If the response is a msg,
schedules msg deletion it if delete_msg
also match 1 character msgs to the choice if match_first_char
"""
emojis = tuple(choices.keys())
words = tuple(choices.values())
first_letters = {w[0]: w for w in words}
def mcheck(msg):
lm = msg.content.lower()
return (lm in words or
(match_first_char and lm in first_letters))
tasks = (self.bot.wait_for_message(author=author, timeout=timeout,
channel=msg.channel, check=mcheck),
self.bot.wait_for_reaction(user=author, timeout=timeout,
message=msg, emoji=emojis),
self.wait_for_reaction_remove(user=author, timeout=timeout,
message=msg, emoji=emojis))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment