async def view_speaking(self, ctx: commands.Context) -> None: """ View the channels Parrot can imitate people in. """ embed = ParrotEmbed(title="Parrot is learning from these channels:") channel_mentions = [] for channel in ctx.guild.channels: if channel.id in self.bot.speaking_channels: channel_mentions.append(channel.mention) paginator = Paginator.FromList( ctx, entries=channel_mentions, template_embed=embed, ) await paginator.run()
async def voices(self, ctx: commands.Context) -> None: """ List the speakers that Parrot can imitate through vo.codes. """ embed = ParrotEmbed(title="Speakers", ) embed.set_footer(text="Powered by vo.codes: https://vo.codes/") paginator = Paginator.FromList( ctx, entries=speaker_names, template_embed=embed, ) paginator.add_reaction("⏪", "back") paginator.add_reaction("⏹", "delete") paginator.add_reaction("⏩", "next") await paginator.run()
async def quickstart(self, ctx: commands.Context, user: Userlike = None) -> None: """ Scan your past messages to get started using Parrot right away. """ if user is None or ctx.author == user: user = ctx.author else: if not is_admin(ctx): raise UserPermissionError( "You can only run Quickstart on yourself.") if not user.bot: raise UserPermissionError( "Quickstart can only be run on behalf of bots.") if ctx.channel.id not in self.ongoing_scans: self.ongoing_scans[ctx.channel.id] = [] # You can't run Quickstart in a channel that Quickstart is already # currently scanning for you. if user.id in self.ongoing_scans[ctx.channel.id]: if ctx.author == user: raise AlreadyScanning( "❌ You are already currently running Quickstart in this channel!" ) raise AlreadyScanning( f"❌ Quickstart is already running for {user} in this channel!") # Record that Quickstart is scanning this channel for this user. self.ongoing_scans[ctx.channel.id].append(user.id) # Tell the user off if they try to run this command in a DM channel. if ctx.channel.type != ChannelType.text: await ctx.send( f"Quickstart is only available in servers. Try running Quickstart again in a server that Parrot is in." ) return # Show the user where they can use Quickstart within this server if they # use the command in a channel where Parrot can't learn. if ctx.channel.id not in self.bot.learning_channels: embed = ParrotEmbed( title="Quickstart Channels", description= "Quickstart is available in channels where Parrot can learn from your messages. Try running Quickstart again in one of these channels:", ) channel_mentions = [] for channel in ctx.guild.channels: if channel.id in self.bot.learning_channels: channel_mentions.append(channel.mention) paginator = Paginator.FromList( ctx, entries=channel_mentions, template_embed=embed, ) await paginator.run() return # Create and embed that will show the status of the Quickstart # operation and DM it to the user who invoked the command. if ctx.author == user: name = "your" else: name = f"{user.mention}'s" embed = ParrotEmbed( description= f"**Scanning {ctx.channel.mention}...**\nCollected 0 new messages...", ) embed.set_author( name="Quickstart", icon_url="https://i.gifer.com/ZZ5H.gif", # Loading spinner ) embed.set_footer( text=f"Scanning for {user.mention}", icon_url=user.avatar_url, ) status_message = await ctx.author.send(embed=embed) await ctx.send(embed=ParrotEmbed( title="Quickstart is scanning", description= f"Parrot is now scanning this channel and learning from {name} past messages.\nThis could take a few minutes.\nCheck your DMs to see its progress." ), reference=ctx.message) # Create an iterator representing this channel's past messages. def message_filter(message: Message) -> bool: return message.author == user history = ctx.channel.history( limit=100_000, after=user.joined_at, ).filter(message_filter) # Create an object that will scan through the channel's message history # and learn from the messages this user has posted. crawler = ChannelCrawler( history=history, action=self.bot.learn_from, ) # Start the crawler and periodically update the status_message with its # progress. # Fun fact: these HAVE to be asyncio.gathered together. If they aren't, # either the updater function won't be able to run until after the # crawler has stopped, or the command will hang forever as the updater # loops into eternity as it waits for the crawler (which isn't # running) to tell it to stop. await asyncio.gather( crawler.crawl(), self.live_update_status( source_channel=ctx.channel, status_message=status_message, user=user, crawler=crawler, ), loop=self.bot.loop, ) # Update the status embed one last time, but DELETE it this time and # post a brand new one so that the user gets a new notification. if ctx.author == user: name = "you" else: name = f"{user}" embed = ParrotEmbed( description= f"**Scan in {ctx.channel.mention} complete.**\nCollected {crawler.num_collected} new messages.", ) embed.set_author(name="✅ Quickstart") embed.set_footer( text=f"Scanning for {user}", icon_url=user.avatar_url, ) if crawler.num_collected == 0: embed.description += f"\n😕 Couldn't find any messages from {name} in this channel." embed.color = ParrotEmbed.colors["red"] await asyncio.gather(status_message.delete(), ctx.author.send(embed=embed)) self.ongoing_scans[ctx.channel.id].remove(user.id) if len(self.ongoing_scans[ctx.channel.id]) == 0: del self.ongoing_scans[ctx.channel.id]