async def select_bestiary(self, ctx, name): user_bestiaries = await self.bot.mdb.bestiaries.find({ "owner": ctx.message.author.id }).to_list(None) if not user_bestiaries: raise NoBestiary() choices = [] for bestiary in user_bestiaries: url = bestiary['critterdb_id'] if bestiary['name'].lower() == name.lower(): choices.append((bestiary, url)) elif name.lower() in bestiary['name'].lower(): choices.append((bestiary, url)) if len(choices) > 1: choiceList = [(f"{c[0]['name']} (`{c[1]})`", c) for c in choices] result = await get_selection(ctx, choiceList, delete=True) if result is None: raise SelectionCancelled() bestiary = result[0] bestiary_url = result[1] elif len(choices) == 0: raise NoSelectionElements() else: bestiary = choices[0][0] bestiary_url = choices[0][1] return Bestiary.from_raw(bestiary_url, bestiary)
async def select_bestiary(self, ctx, name): user_bestiaries = self.bot.db.jget( ctx.message.author.id + '.bestiaries', None) if user_bestiaries is None: raise NoBestiary() choices = [] for url, bestiary in user_bestiaries.items(): if bestiary['name'].lower() == name.lower(): choices.append((bestiary, url)) elif name.lower() in bestiary['name'].lower(): choices.append((bestiary, url)) if len(choices) > 1: choiceList = [(f"{c[0]['name']} (`{c[1]})`", c) for c in choices] result = await get_selection(ctx, choiceList, delete=True) if result is None: raise SelectionCancelled() bestiary = result[0] bestiary_url = result[1] elif len(choices) == 0: raise NoSelectionElements() else: bestiary = choices[0][0] bestiary_url = choices[0][1] return Bestiary.from_raw(bestiary_url, bestiary)
async def get_selection(ctx, choices, delete=True, pm=False, message=None, force_select=False): """Returns the selected choice, or None. Choices should be a list of two-tuples of (name, choice). If delete is True, will delete the selection message and the response. If length of choices is 1, will return the only choice unless force_select is True. :raises NoSelectionElements if len(choices) is 0. :raises SelectionCancelled if selection is cancelled.""" if len(choices) == 0: raise NoSelectionElements() elif len(choices) == 1 and not force_select: return choices[0][1] page = 0 pages = paginate(choices, 10) m = None selectMsg = None def chk(msg): valid = [str(v) for v in range(1, len(choices) + 1)] + ["c", "n", "p"] return msg.author == ctx.author and msg.channel == ctx.channel and msg.content.lower( ) in valid for n in range(200): _choices = pages[page] names = [o[0] for o in _choices if o] embed = discord.Embed() embed.title = "Multiple Matches Found" selectStr = "Which one were you looking for? (Type the number or \"c\" to cancel)\n" if len(pages) > 1: selectStr += "`n` to go to the next page, or `p` for previous\n" embed.set_footer(text=f"Page {page + 1}/{len(pages)}") for i, r in enumerate(names): selectStr += f"**[{i + 1 + page * 10}]** - {r}\n" embed.description = selectStr embed.colour = random.randint(0, 0xffffff) if message: embed.add_field(name="Note", value=message, inline=False) if selectMsg: try: await selectMsg.delete() except: pass if not pm: selectMsg = await ctx.channel.send(embed=embed) else: embed.add_field( name="Instructions", value= "Type your response in the channel you called the command. This message was PMed to " "you to hide the monster name.", inline=False) selectMsg = await ctx.author.send(embed=embed) try: m = await ctx.bot.wait_for('message', timeout=30, check=chk) except asyncio.TimeoutError: m = None if m is None: break if m.content.lower() == 'n': if page + 1 < len(pages): page += 1 else: await ctx.channel.send("You are already on the last page.") elif m.content.lower() == 'p': if page - 1 >= 0: page -= 1 else: await ctx.channel.send("You are already on the first page.") else: break if delete and not pm: try: await selectMsg.delete() await m.delete() except: pass if m is None or m.content.lower() == "c": raise SelectionCancelled() return choices[int(m.content) - 1][1]