async def displayResult(message: YagooMessage, unsubData: UnsubscriptionResponse): """ Displays the unsubscription result. message: The message used to display the result. unsubData: The unsubscription data. """ subTypeText = "" channels = "" for subType in unsubData.subTypes: subTypeText += f"{subType.capitalize()}, " if len(unsubData.channels) <= 5: for channel in unsubData.channels: channels += f"{channel.channelName}, " else: channels = f"{len(unsubData.channels)} channels" message.resetEmbed() message.embed.title = "Successfully Unsubscribed!" message.embed.description = f"This channel is now unsubscribed from {channels.strip(', ')}." message.embed.color = discord.Color.green() message.embed.add_field(name="Subscription Types", value=subTypeText.strip(", "), inline=False) message.msg = await message.msg.edit(content=None, embed=message.embed, view=None) return
async def sublistDisplay(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot): """ Show the user about the current subscriptions for the channel. Arguments --- cmd: Context or interaction from the invoked command. bot: The Discord bot. """ db = await botdb.getDB(bot.pool) server = await dbTools.serverGrab(bot, str(cmd.guild.id), str(cmd.channel.id), tuple(allSubTypes(False)), db) if isinstance(cmd, commands.Context): message = YagooMessage(bot, cmd.author) message.msg = await cmd.send("Loading channel subscriptions...") else: message = YagooMessage(bot, cmd.user) subList = await unsubUtils.parseToSubTypes(server, db) pages = await subPrompts.sublistDisplay.parseToPages(subList) if len(pages) == 0: raise NoSubscriptions(str(cmd.channel.id)) await subPrompts.sublistDisplay.prompt(cmd, message, pages, subList) await removeMessage(cmd=cmd)
async def confirm(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage, twtUser: tweepy.User): """ Asks for confirmation of following the Twitter account that was requested. Arguments --- cmd: Context or interaction from the invoked command. message: The message used to display the confirmation. twtUser: The Twitter account. """ message.embed.title = f"Following {twtUser.name} to this channel" message.embed.description = "Do you want to follow this Twitter account?" message.addButton(1, "cancel", "Cancel", style=discord.ButtonStyle.red) message.addButton(1, "confirm", "Confirm", style=discord.ButtonStyle.green) if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) return result
async def test(self, interaction: discord.Interaction): await interaction.response.defer() message = YagooMessage(self.bot, interaction.user, "Subscribing to a VTuber", "Pick the VTuber's affiliation:", color=discord.Color.from_rgb(32, 34, 37)) message.embed.add_field( name="Action", value= "Pick an entry in the list or use the buttons below for further actions." ) selectOptions = [] for i in range(1, 100): selectOptions.append(YagooSelectOption(str(i))) message.addSelect(selectOptions) message.addButton(3, "search", "Search for a VTuber") message.addButton(3, "all", "Subscribe to all VTubers") message.addButton(4, "cancel", "Cancel", style=discord.ButtonStyle.red) response = await message.post(interaction, True, True) print(vars(response)) if response.selectValues: await message.msg.edit( content=f"You picked the option: `{response.selectValues[0]}`", embed=None, view=None) elif response.buttonID: await message.msg.edit( content=f"You picked the button: `{response.buttonID}`", embed=None, view=None) else: await message.msg.edit(content="The message timed out!", embed=None, view=None)
async def subCustom(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot, search: str): """ Subscribes to a VTuber with the channel name provided to the user. Arguments --- ctx: Context from the executed command. bot: The Discord bot. search: The name of the channel to search for. """ db = await botdb.getDB(bot.pool) if isinstance(cmd, commands.Context): message = YagooMessage(bot, cmd.author) message.msg = await cmd.send("Loading channels list...") else: message = YagooMessage(bot, cmd.user) result = await subUtils.channelSearch(cmd, bot, message, search) if result.success: server = await dbTools.serverGrab( bot, str(cmd.guild.id), str(cmd.channel.id), tuple(["subDefault"] + allSubTypes(False)), db) subResult = await subUtils.subOne( cmd, message, server, str(cmd.channel.id), [YouTubeChannel(result.channelID, result.channelName)], db) if subResult.status: await subPrompts.displaySubbed(message, subResult) await removeMessage(cmd=cmd) return await removeMessage(message, cmd)
async def displaySubbed(message: YagooMessage, subResult: SubscriptionResponse): """ Gives a status to the user about subbed accounts. Arguments --- message: The message that will be used as the display. subResult: The `SubscriptionResponse` from the subscription prompts. """ channels = "" message.resetEmbed() for name in subResult.channelNames: channels += f"{name}, " if subResult.subTypes: message.embed.title = "Successfully Subscribed!" message.embed.description = f"This channel is now subscribed to {channels.strip(', ')}." message.embed.color = discord.Colour.green() subTypes = "" for subType in subResult.subTypes: subTypes += f"{subType.capitalize()}, " message.embed.add_field(name="Subscription Types", value=subTypes.strip(", ")) else: message.embed.title = "Already Subscribed!" message.embed.description = f"This channel is already subscribed to {channels.strip(', ')}!" message.embed.color = discord.Colour.red() message.msg = await message.msg.edit(content=None, embed=message.embed, view=None)
async def prompt(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage, buttonText: str = "Subscribe", buttonID: str = "subscribe", subTypes: dict = None, allowNone: bool = False): """ Prompts the user for subscription types. The title and description must be set beforehand. Arguments --- ctx: Context from the executed command. msg: The message that will be used as the prompt. buttonText: The text for the subscribe button. buttonID: The ID for the subscribe button. subTypes: Existing subscription type status as a `dict`. allowNone: To allow the user to select none of the subscription types. Returns --- `SubscriptionData` if the user confirmed the choice. `YagooViewResponse` if cancelled or timed out. """ buttonStates = subTypes if not buttonStates: buttonStates = {} subTypes = allSubTypes(False) for subType in subTypes: buttonStates[subType] = False while True: message.resetComponents() await subPrompts.subTypes.editMsg(subTypes, message, buttonStates, buttonText, buttonID, allowNone) if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) if result.responseType: if result.buttonID not in ["cancel", "all", buttonID]: buttonStates[result.buttonID] = not buttonStates[ result.buttonID] elif result.buttonID == "all": allBool = True for button in buttonStates: if allBool: allBool = buttonStates[button] for button in buttonStates: buttonStates[button] = not allBool else: if result.buttonID == buttonID: return SubscriptionData(buttonStates) return result else: return result
async def displayProgress(message: YagooMessage): message.resetEmbed() message.embed.title = "Currently Subscribing..." message.embed.description = "Currently subscribing to the channels specified.\n" \ "This might take longer if the amount of channels is larger." message.embed.color = discord.Color.from_rgb(0, 0, 0) message.msg = await message.msg.edit(content=None, embed=message.embed, view=None)
async def prompt(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage, followData: TwitterFollowData): """ Prompts the user for which Twitter accounts to be unfollowed. Arguments --- cmd: Context or interaction from the invoked command. msg: The message that will be used as the prompt. options: The Discord channel's Twitter follows. Returns --- `TwitterUnfollowResponse` """ response = TwitterUnfollowResponse(False) message.resetMessage() message.embed.title = "Unfollowing from Twitter Accounts" message.embed.description = "Choose the account(s) to be unfollowed." message.embed.add_field( name="Note seeing the Twitter account on this list?", value= "Twitter accounts followed through the `subscribe` command " "will need to be unfollowed through the `unsubscribe` command." ) options = [] for account in followData.accounts: options.append( YagooSelectOption(account.name, account.accountID, f"@{account.handle}")) message.addSelect(options, "Pick the Twitter account(s) here", max_values=25) message.addButton(3, "all", "Unfollow from all Twitter Channels") message.addButton(4, "cancel", "Cancel", style=discord.ButtonStyle.red) if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) if result.responseType: if result.selectValues: response.status = True for handle in result.selectValues: account = followData.findAccount(handle) response.addAccount(account.accountID, account.handle, account.name) elif result.buttonID == "all": response.status = True response.allAccounts = True return response
async def refreshCommand(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot): """ Refreshes the channel's webhook on request. Arguments --- cmd: Context or interaction from the invoked command. bot: The Discord bot. """ db = await botdb.getDB(bot.pool) if isinstance(cmd, commands.Context): message = YagooMessage(bot, cmd.author) else: message = YagooMessage(bot, cmd.user) result = await refreshPrompts.confirm(cmd, message) if result.responseType: if result.buttonID == "yes": await refreshWebhook(bot, cmd.guild, cmd.channel, db) message.resetEmbed() message.embed.title = "Successfully Refreshed!" message.embed.description = "The channel's webhook should now be refreshed. "\ "Channel notifications will be posted after a short while." message.msg = await message.msg.edit(content=None, embed=message.embed, view=None) return await removeMessage(message, cmd)
async def follow(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot, accLink: str): db = await botdb.getDB(bot.pool) if not accLink: raise ValueError("No Twitter ID") if isinstance(cmd, commands.Context): message = YagooMessage(bot, cmd.author) message.msg = await cmd.send("Searching for the Twitter user...") else: message = YagooMessage(bot, cmd.user) twtHandle = await TwitterUtils.getScreenName(accLink) twtUser = await TwitterScrape.getUserDetails(twtHandle) message.embed.title = f"Following {twtUser.name} to this channel" message.embed.description = "Do you want to follow this Twitter account?" message.addButton(1, "cancel", "Cancel", style=discord.ButtonStyle.red) message.addButton(1, "confirm", "Confirm", style=discord.ButtonStyle.green) if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) if result.buttonID == "confirm": await dbTools.serverGrab(bot, str(cmd.guild.id), str(cmd.channel.id), ("url", ), db) dbExist = await TwitterUtils.dbExists(twtUser.id_str, db) if not dbExist["status"]: await TwitterUtils.newAccount(twtUser, db) status = await TwitterUtils.followActions("add", str(cmd.channel.id), [twtUser.id_str], db=db) TwitterPrompts.follow.displayResult(message, twtUser.screen_name, status) message.msg = await message.msg.edit(content=None, embed=message.embed, view=None) await removeMessage(cmd=cmd) return await removeMessage(message, cmd)
async def confirm(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage): """ Prompts the user if they want to refresh the channel's webhook. Arguments --- cmd: Context or interaction from the invoked command. message: The message used for the prompt. """ message.embed.title = "Refreshing Channel Webhook" message.embed.description = "Are you sure you want to refresh this channel's webhook?" message.addButton(1, "no", "No", style=discord.ButtonStyle.red) message.addButton(1, "yes", "Yes", style=discord.ButtonStyle.green) if isinstance(cmd, commands.Context): return await message.legacyPost(cmd) return await message.post(cmd, True, True)
async def prompt(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage, pages: List[str], subData: ChannelSubscriptionData): """ Show the user about the current subscriptions for the channel. Arguments --- ctx: Context or interaction from the invoked command. message: The message that will be used as the prompt. pages: A `list` containing the pages of the Discord channel's subscriptions. subData: The channel's subscription data. """ message.embed.title = "Current Channel Subscriptions" pagePos = 0 subFilter = [ ] # TODO: (LATER) Subscription filter after this update if len(pages) > 1: message.pages = len(pages) message.addPaginator(1) while True: message.embed.description = pages[pagePos] if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) if result.responseType: if result.buttonID == "next": pagePos += 1 elif result.buttonID == "prev": pagePos -= 1 else: break if len(subData.allChannels) > 1: message.embed.description = f"This channel is currently subscribed to {len(subData.allChannels)} channels." else: message.embed.description = f"This channel is currently subscribed to 1 channel." await message.msg.edit(content=None, embed=message.embed, view=None)
async def defaultSubtype(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot): """ Prompts the user to either set or change the default subscription types for the channel. Arguments --- cmd: Context or interaction from the invoked command bot: The Discord bot. """ db = await botdb.getDB(bot.pool) server = await dbTools.serverGrab(bot, str(cmd.guild.id), str(cmd.channel.id), ("subDefault", ), db) if isinstance(cmd, commands.Context): message = YagooMessage(bot, cmd.author) message.msg = await cmd.send("Loading channel subscription defaults..." ) else: message = YagooMessage(bot, cmd.user) subTypes = {} for subType in allSubTypes(False): subTypes[subType] = False if not (server["subDefault"] is None or server["subDefault"] == ""): for subType in await botdb.listConvert(server["subDefault"]): subTypes[subType] = True message.embed.title = "Default Channel Subscription Types" message.embed.description = "Pick the subscription types for this channel to subscribe to by default." result = await subPrompts.subTypes.prompt(cmd, message, "Confirm", "confirm", subTypes, True) if isinstance(result, SubscriptionData): subDefault: List[str] = [] for subType in result.subList: if result.subList[subType]: subDefault.append(subType) await botdb.addData( (str(cmd.channel.id), await botdb.listConvert(subDefault)), ("channel", "subDefault"), "servers", db) message.resetEmbed() message.embed.title = "Successfully Set Channel Defaults!" if subDefault == []: message.embed.description = "Subscription commands will now ask for subscription types first." message.embed.color = discord.Color.from_rgb(0, 0, 0) else: defaultSubs = "" for sub in subDefault: defaultSubs += f"{sub.capitalize()}, " message.embed.description = "Subscription commands will now follow the channel's defaults." message.embed.color = discord.Color.green() message.embed.add_field(name="Default Subscriptions", value=defaultSubs.strip(", "), inline=False) await message.msg.edit(content=" ", embed=message.embed, view=None) return await removeMessage(cmd=cmd) await removeMessage(message, cmd)
def displayResult(message: YagooMessage, accName: str, status: bool): """ Display the result of the follow action. Arguments --- message: The message used to display the result. accName: The Twitter account name. status: The status from the follow command. """ message.resetEmbed() if status: message.embed.title = "Successfully Followed Account!" message.embed.description = f"This channel is now following @{accName}." message.embed.color = discord.Color.green() else: message.embed.title = "Already Followed Account!" message.embed.description = f"This channel is already following @{accName}." message.embed.color = discord.Color.red()
async def ctgPicker(cmd: Union[commands.Context, discord.Interaction], channels: dict, ctgMsg: YagooMessage): """ Prompts the user for a VTuber's affiliation. Arguments --- ctx: Context or interaction from the executed command. channels: Data from `channels` in `dict` form, with `id` as the main key. ctgMsg: Message to be used as the prompt message. Returns --- A `dict` with: - status: `True` if the user picked a category, `False` if otherwise. - all: `True` if the user picks to subscribe to all VTubers. - search: `True` if the user picks to search for a VTuber. - category: Contains the name of the category, `None` if there is no category picked. """ categories = await subPrompts.categoryPages(channels) ctgMsg.resetComponents() ctgMsg.embed.title = "Subscribing to a VTuber" ctgMsg.embed.description = "Pick the VTuber's affiliation:" ctgMsg.embed.add_field( name="Searching for a specific VTuber?", value="Add the VTuber's name after the `subscribe` command.", inline=False) ctgMsg.addSelect(categories, placeholder="Select the VTuber's Affiliation") ctgMsg.addButton(2, "search", "Search for a VTuber", disabled=True) ctgMsg.addButton(2, "all", "Subscribe to all VTubers") ctgMsg.addButton(3, "cancel", "Cancel", style=discord.ButtonStyle.red) if isinstance(cmd, commands.Context): response = await ctgMsg.legacyPost(cmd) else: response = await ctgMsg.post(cmd, True, True) return response
async def prompt(cmd: commands.Context, message: YagooMessage, category: dict, catName: str): """ Prompts the user for which VTuber to pick. Arguments --- cmd: Context or interaction from the invoked command. msg: The message that will be used as the prompt. category: The category as a `dict` containing `id` as the header, `name` as the sub-key. catName: The name of the category. Returns --- An instance of `CategorySubscriptionResponse` """ options = await subPrompts.channelPick.parseToPages(category) message.resetMessage() message.embed.title = f"Subscribing to {catName} VTubers" message.embed.description = "Pick a VTuber in the select below." message.embed.add_field( name="Not finding a VTuber in this category?", value= "Search for a VTuber by adding the VTuber's name after the `subscribe` command." ) message.addSelect(options, f"Pick the {catName} VTubers here", max_values=25) message.addButton(2, "all", f"Subscribe to all {catName} VTubers") message.addButton(3, "cancel", "Cancel", style=discord.ButtonStyle.red) if isinstance(cmd, commands.Context): response = await message.legacyPost(cmd) else: response = await message.post(cmd, True, True) if response.responseType: if response.responseType == "select": return CategorySubscriptionResponse( True, catName, channelIDs=response.selectValues, channelData=category) if response.buttonID == "all": return CategorySubscriptionResponse(True, catName, True) return CategorySubscriptionResponse(False)
async def unfollow(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot): db = await botdb.getDB(bot.pool) if isinstance(cmd, commands.Context): message = YagooMessage(bot, cmd.author) message.msg = await cmd.send("Loading custom Twitter accounts...") else: message = YagooMessage(bot, cmd.user) server = await dbTools.serverGrab(bot, str(cmd.guild.id), str(cmd.channel.id), ("custom", ), db) customTwt = await botdb.getAllData("twitter", ("twtID", "name", "screenName"), 1, "custom", "twtID", db) followedData = await botdb.listConvert(server["custom"]) if followedData == [''] or followedData == [] or not followedData: raise NoFollows(cmd.channel.id) followData = await TwitterPrompts.unfollow.parse( followedData, customTwt) userPick = await TwitterPrompts.unfollow.prompt( cmd, message, followData) if userPick.status: await TwitterUtils.followActions("remove", str(cmd.channel.id), userPick.accountIDs(), userPick.allAccounts, db) TwitterPrompts.unfollow.displayResult(message, userPick) message.msg = await message.msg.edit(content=None, embed=message.embed, view=None) await removeMessage(cmd=cmd) else: await removeMessage(message, cmd)
def displayResult(message: YagooMessage, unfollowData: TwitterUnfollowResponse): """ Display the result of the follow action. Arguments --- message: The message used to display the result. unfollowData: The channel's unfollow data. """ message.resetEmbed() message.embed.title = "Successfully Unfollowed Accounts!" message.embed.color = discord.Color.green() accounts = "" if len(unfollowData.accounts) <= 3: for account in unfollowData.accounts: accounts += f"@{account.handle}, " else: accounts = f"{len(unfollowData.accounts)} accounts'" if unfollowData.allAccounts: accounts = "all Twitter accounts'" message.embed.description = f"The channel has been unfollowed from {accounts.strip(', ')} tweets."
async def prompt(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage, title: str, action: str): """ Prompts to either confirm the choice of VTuber, cancel, or search for another VTuber. Arguments --- ctx: Context from the executed command. bot: The Discord bot. msg: The message that will be used for the prompt. title: The title of the prompt. Returns --- A `dict` with: - status: `True` if a user requested to search or confirms the choice. - action: The action that is requested by the user (`search`/`confirm`). """ message.resetMessage() message.embed.title = title if action.lower() == "unsubscribe": message.embed.description = "Are you sure you want to unsubscribe from this channel?" else: message.embed.description = f"Are you sure you want to {action} to this channel?" message.addButton(1, "cancel", "Cancel", style=discord.ButtonStyle.red) message.addButton(1, "results", "Search Results", style=discord.ButtonStyle.primary) message.addButton(1, "confirm", "Confirm", style=discord.ButtonStyle.green) if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) return result
async def modalslash(self, interaction: discord.Interaction): modal = YagooMessage(self.bot, interaction.user, "Test Modal", "This is a test modal.") modal.addTextInput(label="Input 1", placeholder="Enter Something Here", text_id="input1") modal.addTextInput(label="Input 2", placeholder="Enter Something Here Also", text_id="input2", row=1) response = await modal.postModal(interaction) print(vars(response)) await interaction.followup.send(content="Done!")
async def searchPick(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage, searchTerm: str, searchResult: ChannelSearchResponse): """ A prompt to pick possible search matches. Arguments --- cmd: Context or interaction from the invoked command. message: The message that will be used as the prompt. searchTerm: The search term by the user. searchResult: The `ChannelSearchResult` returned from searching for a channel. Returns --- `ChannelSearchResult` """ choices = [] message.resetMessage() message.embed.title = "Searching for a VTuber" message.embed.description = f"Displaying search results for: `{searchTerm}`\n" for item in searchResult.searchResults: choices.append(YagooSelectOption(item, item)) message.addSelect(choices, "Select the search result here") message.addButton(2, "cancel", "Cancel", style=discord.ButtonStyle.red) if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) if not result.responseType or result.buttonID == "cancel": searchResult.failed() return searchResult searchResult.matched() searchResult.channelName = result.selectValues[0] return searchResult
async def editMsg(message: YagooMessage, subTypes: dict): message.resetComponents() allSubs = True selected = False rowSort = { "livestream": 0, "milestone": 1, "premiere": 2, "twitter": 3 } for subType in subTypes: if subTypes[subType]: message.addButton(rowSort[subType], subType, f"{subType.capitalize()} Notifications", style=discord.ButtonStyle.green) allSubs = False else: message.addButton(rowSort[subType], subType, f"{subType.capitalize()} Notifications", style=discord.ButtonStyle.grey) selected = True if not allSubs: message.addButton(4, "cancel", "Cancel", style=discord.ButtonStyle.red) message.addButton(4, "select", "Select All") message.addButton(4, "submit", "Unsubscribe", style=discord.ButtonStyle.green, disabled=not selected) else: message.addButton(4, "cancel", "Cancel", style=discord.ButtonStyle.red) message.addButton(4, "select", "Select None", style=discord.ButtonStyle.grey) message.addButton(4, "submit", "Unsubscribe", style=discord.ButtonStyle.green, disabled=not selected)
async def editMsg(subTypes: List[str], message: YagooMessage, buttonStates: dict, subText: str, subID: str, allowNone: bool): """Supplementary command to `subTypes.prompt`""" selected = False allTypes = True rowNum = 0 for subType in subTypes: if buttonStates[subType]: message.addButton(rowNum, subType, f"{subType.capitalize()} Notifications", style=discord.ButtonStyle.green) selected = True else: message.addButton(rowNum, subType, f"{subType.capitalize()} Notifications", style=discord.ButtonStyle.red) allTypes = False rowNum += 1 if allowNone: selected = True message.addButton(rowNum, "cancel", "Cancel", style=discord.ButtonStyle.red) if not allTypes: message.addButton(rowNum, "all", "Select All", style=discord.ButtonStyle.primary) else: message.addButton(rowNum, "all", "Select None", style=discord.ButtonStyle.grey) message.addButton(rowNum, subID, subText, style=discord.ButtonStyle.green, disabled=not selected)
async def unsubChannel(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot, channel: str = None): """ Unsubscribes from a VTuber. (bypasses a prompt if a channel is given) Arguments --- ctx: Context or interaction from the invoked command. bot: The Discord bot. channel: The search term for the VTuber. """ db = await botdb.getDB(bot.pool) if isinstance(cmd, commands.Context): message = YagooMessage(bot, cmd.author) message.msg = await cmd.send("Loading channel subscriptions...") else: message = YagooMessage(bot, cmd.user) server = await dbTools.serverGrab(bot, str(cmd.guild.id), str(cmd.channel.id), tuple(allSubTypes(False)), db) subData = await unsubUtils.parseToSubTypes(server, db) if not subData.exists: raise NoSubscriptions(cmd.channel.id) if not channel: message.resetMessage() message.embed.title = "Unsubscribing from VTuber Channels" message.embed.description = "Choose the VTuber(s) to be unsubscribed from." message.embed.add_field( name="Searching for a VTuber?", value="Enter the VTuber's name after the `unsubscribe` command.") message.addSelect(await unsubUtils.parseToPages(subData), "Choose the VTuber(s) here", max_values=25) message.addButton(2, "search", label="Search for a VTuber", disabled=True) message.addButton(2, "all", "Unsubscribe from all VTubers") message.addButton(3, "cancel", "Cancel", style=discord.ButtonStyle.red) if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) else: wikiName = await subUtils.channelSearch(cmd, bot, message, channel, "unsubscribe") if wikiName.success: result = YagooViewResponse() result.responseType = "select" result.selectValues = [wikiName.channelID] else: result = YagooViewResponse() if result.responseType: if result.buttonID == "all": unsubResult = await unsubPrompts.removePrompt.prompt( cmd, message, None, subData, True) if not unsubResult.status: return await removeMessage(message, cmd) await unsubUtils.unsubAll(str(cmd.channel.id), unsubResult, db) elif result.buttonID == "cancel": return await removeMessage(message, cmd) else: unsubResult = await unsubPrompts.removePrompt.prompt( cmd, message, result.selectValues, subData) if not unsubResult.status: return await removeMessage(message, cmd) await unsubUtils.unsubOne(server, str(cmd.channel.id), unsubResult, db) await unsubPrompts.displayResult(message, unsubResult) return await removeMessage(cmd=cmd) await removeMessage(message, cmd)
async def subOne(cmd: commands.Context, message: YagooMessage, server: dict, channelId: str, channels: List[YouTubeChannel], db: mysql.connector.MySQLConnection): """ Subscribes to one/multiple channel(s) with the specified channel ID(s). Arguments --- cmd: Context or interaction from the executed command. msg: The message that will be used as a prompt. server: The server as a `dict` containing `subDefault` and other subscription types. channelId: The channel ID of the current Discord channel. channels: A `list` of `YouTubeChannel` of the currently being subscribed channels. db: An existing MySQL connection to reduce unnecessary connections. Returns --- An instance of `SubscriptionResponse` """ subDefault = await subUtils.checkDefault(server) subbed = [] if len(channels) > 1: ytChName = "Multiple Channels" else: ytChName = channels[0].channelName if subDefault == [''] or subDefault is None: message.resetEmbed() message.embed.title = f"Subscribing to {ytChName}" message.embed.description = "Pick the notifications to be posted to this channel.\n" \ "(This prompt can be bypassed by setting a default subscription type " \ "using the `subDefault` command)" result = await subPrompts.subTypes.prompt(cmd, message) if isinstance(result, YagooViewResponse): return SubscriptionResponse(False) subDefault = [] for subType in result.subList: if result.subList[subType]: subDefault.append(subType) for channel in channels: for subType in subDefault: stData = await botdb.listConvert(server[subType]) if not stData: stData = [] if subType == "twitter": twitter = (await botdb.getData(channel.channelID, "id", ("twitter", ), "channels", db))["twitter"] if twitter is not None: if twitter not in stData: stData.append(twitter) server[subType] = await botdb.listConvert(stData) await botdb.addData( (channelId, await botdb.listConvert(stData)), ("channel", subType), "servers", db) if subType not in subbed: subbed.append(subType) else: if channel.channelID not in stData: stData.append(channel.channelID) server[subType] = await botdb.listConvert(stData) await botdb.addData( (channelId, await botdb.listConvert(stData)), ("channel", subType), "servers", db) if subType not in subbed: subbed.append(subType) if len(channels) <= 5: channelNames = [] for channel in channels: channelNames.append(channel.channelName) else: channelNames = [f"{len(channels)} channels"] return SubscriptionResponse(True, subbed, channelNames=channelNames)
async def subAll(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage, server: dict, channelId: str, db: mysql.connector.MySQLConnection, category: str = None): """ Subscribes to all channels (in a category if specified, every channel if otherwise). Arguments --- cmd: Context or interaction from the invoked command. bot: The Discord bot. message: The message that will be used for prompts. server: The server as a `dict` containing `subDefault` and other subscription types. channelId: The channel ID of the current Discord channel. db: An existing MySQL connection to reduce unnecessary connections. category: The category filter for subscribing to channels within the category. Returns --- A `dict` with: - status: `True` if the subscription command was executed successfully. - subbed: A list containing the subscribed subscription types. """ channel = await botdb.getAllData("channels", ("id", "twitter"), category, "category", db=db) subDefault = await subUtils.checkDefault(server) twitter = [] channels = [] for ch in channel: if ch["id"]: channels.append(ch["id"]) if ch["twitter"]: twitter.append(ch["twitter"]) if category is None: category = "" else: category += " " if subDefault == [''] or subDefault is None: subDefault = [] message.resetEmbed() message.embed.title = f"Subscribing to all {category}VTubers" message.embed.description = "Pick the notifications to be posted to this channel.\n" \ "(This prompt can be bypassed by setting a default subscription type " \ "using the `subDefault` command)" result = await subPrompts.subTypes.prompt(cmd, message) if isinstance(result, SubscriptionData): for subType in result.subList: if result.subList[subType]: subDefault.append(subType) else: return SubscriptionResponse(False) for subType in subDefault: serverType = await botdb.listConvert(server[subType]) if serverType is None: serverType = [] if subType != "twitter": newData = list(set(serverType) | set(channels)) else: newData = list(set(serverType) | set(twitter)) await botdb.addData((channelId, await botdb.listConvert(newData)), ("channel", subType), "servers", db) return SubscriptionResponse(True, subDefault)
async def subCategory(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot): """ Subscription prompt that uses a category and channel based selection. Arguments --- cmd: Context or interaction from the executed command. bot: The Discord bot. """ db = await botdb.getDB(bot.pool) if isinstance(cmd, commands.Context): message = YagooMessage(bot, cmd.author) message.msg = await cmd.send("Loading channels list...") else: message = YagooMessage(bot, cmd.user) channels = await botdb.getAllData("channels", ("id", "category"), keyDict="id", db=db) ctgPick = await subPrompts.ctgPicker(cmd, channels, message) if checkCancel(ctgPick): await removeMessage(message, cmd) return server = await dbTools.serverGrab( bot, str(cmd.guild.id), str(cmd.channel.id), ("subDefault", "livestream", "milestone", "premiere", "twitter"), db) if ctgPick.buttonID == "all": subResult = await subUtils.subAll(cmd, message, server, str(cmd.channel.id), db) subResult.channelNames = ["all VTubers"] else: channels = await botdb.getAllData("channels", ("id", "name"), ctgPick.selectValues[0], "category", keyDict="id", db=db) result = await subPrompts.channelPick.prompt(cmd, message, channels, ctgPick.selectValues[0]) if result.status: await subPrompts.displayProgress(message) if result.allInCategory: subResult = await subUtils.subAll(cmd, message, server, str(cmd.channel.id), db, ctgPick.selectValues[0]) subResult.channelNames = [ f"all {ctgPick.selectValues[0]} VTubers" ] else: subResult = await subUtils.subOne(cmd, message, server, str(cmd.channel.id), result.channels, db) else: subResult = SubscriptionResponse(False) if subResult.status: await subPrompts.displaySubbed(message, subResult) await removeMessage(cmd=cmd) return await removeMessage(message, cmd)
async def channelSearch(cmd: Union[commands.Context, discord.Interaction], bot: commands.Bot, message: YagooMessage, channel: str, action: str = "subscribe"): """ Searches for a channel with input from the user. Arguments --- ctx: Context or interaction from the invoked command. bot: The Discord bot. message: The message that will be used for the prompt. channel: The name of the channel if already provided by the user. action: The action that is currently is being done with this search. Result --- A `dict` with: - status: `True` if the user successfully searches for a VTuber. - channelID: The channel ID of the VTuber channel. - channelName: The name of the channel. """ wikiName = await FandomScrape.searchChannel(channel) while True: if wikiName.status.cannotMatch: wikiName = await subPrompts.searchPick(cmd, message, channel, wikiName) if not wikiName.status.matched: return FandomChannel() uConfirm = await subPrompts.vtuberConfirm.prompt( cmd, message, wikiName.channelName, action) if uConfirm.responseType: if uConfirm.buttonID == "confirm": break elif uConfirm.buttonID == "results": wikiName.cannotMatch() else: return FandomChannel() else: return FandomChannel() channelData = await FandomScrape.getChannelURL(wikiName.channelName) if channelData.success: db = await botdb.getDB(bot.pool) if not await botdb.checkIfExists(channelData.channelID, "id", "channels", db): message.resetEmbed() message.embed.title = "Getting Channel Data..." message.embed.description = "This channel is new in the database.\nPlease wait while we're getting the channel's info." message.embed.color = discord.Color.from_rgb(0, 0, 0) message.msg = await message.msg.edit(content=None, embed=message.embed, view=None) chData = await subUtils.addChannel(channelData.channelID, channelData.channelName, ("id", "name"), db) else: chData = await botdb.getData(channelData.channelID, "id", ("id", "name"), "channels", db) return FandomChannel(True, chData["id"], chData["name"]) return FandomChannel()
async def prompt(cmd: Union[commands.Context, discord.Interaction], message: YagooMessage, channelIDs: Optional[List[str]] = None, subData: Optional[ChannelSubscriptionData] = None, allChannels: bool = False): """ Prompts the user for which subscription type to unsubscribe from. Arguments --- ctx: Context from the executed command. msg: The message that will be used as the prompt. channelIDs: IDs of the VTuber channels to be unsubscribed from. subData: The subscription data of the current channel. allChannels: If all channels are to be unsubscribed. Returns --- A `dict` with: - status: `True` if an option was chosen by the user. - unsubbed: A `list` with subscription types to unsubscribe from. """ if not allChannels: channels = await unsubPrompts.removePrompt.parseToChannels( channelIDs, subData) else: channels = subData.allChannels subTypes = {} if allChannels: name = "All Channels" elif len(channelIDs) > 1: name = "Multiple Channels" else: name = channels[0].channelName message.resetEmbed() message.embed.title = f"Unsubscribing from {name}" message.embed.description = "Choose the subscription types to unsubscribe from." if not allChannels: for channel in channels: for subType in subData.findTypes(channel.channelID): if subType not in subTypes: subTypes[subType] = True else: for subType in allSubTypes(False): subTypes[subType] = True while True: await unsubPrompts.removePrompt.editMsg(message, subTypes) if isinstance(cmd, commands.Context): result = await message.legacyPost(cmd) else: result = await message.post(cmd, True, True) if result.responseType: if result.buttonID == "cancel": return UnsubscriptionResponse(False) if result.buttonID == "submit": unsubbed = [] for subType in subTypes: if not subTypes[subType]: unsubbed.append(subType) return UnsubscriptionResponse(True, unsubbed, channels) if result.buttonID == "select": allSubs = True for subType in subTypes: if subTypes[subType]: allSubs = False for subType in subTypes: subTypes[subType] = allSubs else: subTypes[ result.buttonID] = not subTypes[result.buttonID] else: return UnsubscriptionResponse(False)