diff --git a/action.py b/action.py index 42f9bf2..88bf225 100644 --- a/action.py +++ b/action.py @@ -2,11 +2,13 @@ from typing import Any, TypeVar, NewType from enum import Enum import discord -AT = TypeVar("AT", bound="Action") +actions = { + "Add Role": "add_role" + } class ActionInteraction(Enum): - ACCEPT = "accept" - DECLINE = "decline" + ACCEPT = "Accept" + DECLINE = "Decline" class Action(): def __init__(self, action: ActionInteraction): @@ -20,4 +22,10 @@ class Action(): else: raise ValueError("Action object already set type") + def get_data(self): + if self.set_type is not None: + return { + "type": self.set_type + } + diff --git a/bot.py b/bot.py index 6692d06..df20847 100644 --- a/bot.py +++ b/bot.py @@ -4,6 +4,7 @@ import asyncio import discord import os import json +import pickle from dotenv import load_dotenv from discord.ui import Modal, InputText from discord.utils import get @@ -12,7 +13,9 @@ from dbutil import MessageDB from dbutil import StartButtonDB from dbutil import GuildAppDB -from action import Action, ActionInteraction +from action import Action, ActionInteraction, actions + +usable_actions = actions load_dotenv() @@ -105,6 +108,16 @@ async def editor(ctx): view.add_item(options) await ctx.response.send_message(view=view, ephemeral=True) +@commands.has_permissions(administrator=True) +@application.command(description="Opens Actions™ editor") +async def actions(ctx): + view = discord.ui.View() + options = SelectActionOptionsEditor(max_values=1, placeholder="Select application") + for i in GuildAppDB.get_applications(str(ctx.guild.id)): + options.add_option(label=i, value=i) + view.add_item(options) + await ctx.response.send_message(view=view, ephemeral=True) + @commands.has_permissions(administrator=True) @application.command(description="Select response channel for application") async def response_channel(ctx): @@ -323,6 +336,182 @@ class MoveQuestionSelectNum(discord.ui.Select): +def get_actions_embed(guild_id, application, action_type: ActionInteraction) -> discord.Embed: + embed = discord.Embed(title=f"Application: {application}", description=f"Actions happening on: {action_type.value}") + actions = GuildAppDB.get_actions(str(guild_id), application, action_type) + for i, que in enumerate(actions): + if que["action_type"] == "add_role": + role = bot.get_guild(int(guild_id)).get_role(que["data"]["role_id"]).name + embed.add_field(value=f"**{i+1}. {que['display_type']}: {role}**", name="", inline=False) + else: + embed.add_field(value=f"**{i+1}. {que['display_type']}**", name="", inline=False) + embed.set_footer(text="Made by @anorak01", icon_url="https://cdn.discordapp.com/avatars/269164865480949760/a1af9962da20d5ddaa136043cf45d015?size=1024") + return embed + +class ActionAcceptEditorView(discord.ui.View): + def __init__(self, guild_id, application_name): + super().__init__(timeout=180) + self.guild_id = guild_id + self.application_name = application_name + + @discord.ui.button( + label="New", + style=discord.ButtonStyle.green, + custom_id="action_accept_editor:add", + row=0 + ) + async def add_action(self, button: discord.ui.Button, interaction: discord.Interaction): + view = ActionAcceptEditorView(str(interaction.guild.id), self.application_name) + options = AddActionSelect(max_values=1, placeholder="Select action to add") + options.set_app_name(self.application_name) + options.set_action_type(ActionInteraction.ACCEPT) + for i, que in enumerate(usable_actions): + options.add_option(label=f"{str(i+1)}. {que}", value=str(usable_actions[que])) + view.add_item(options) + await interaction.response.edit_message(view=view) + + @discord.ui.button( + label="Remove", + style=discord.ButtonStyle.red, + custom_id="action_accept_editor:remove", + row=0 + ) + async def remove_action(self, button, interaction: discord.Interaction): + view = ActionAcceptEditorView(str(interaction.guild.id), self.application_name) + options = RemoveActionSelect(max_values=1, placeholder="Select action to remove") + options.set_app_name(self.application_name) + actions = GuildAppDB.get_actions(str(interaction.guild.id), self.application_name, action_type=ActionInteraction.ACCEPT) + options.set_action_type(ActionInteraction.ACCEPT) + for i, que in enumerate(actions): + options.add_option(label=f"{str(i+1)}. {que}", value=str(i)) + view.add_item(options) + await interaction.response.edit_message(view=view) + +class ActionDeclineEditorView(discord.ui.View): + def __init__(self, guild_id, application_name): + super().__init__(timeout=180) + self.guild_id = guild_id + self.application_name = application_name + + @discord.ui.button( + label="New", + style=discord.ButtonStyle.green, + custom_id="action_decline_editor:add", + row=0 + ) + async def add_action(self, button: discord.ui.Button, interaction: discord.Interaction): + view = ActionDeclineEditorView(str(interaction.guild.id), self.application_name) + options = AddActionSelect(max_values=1, placeholder="Select action to add") + options.set_app_name(self.application_name) + options.set_action_type(ActionInteraction.DECLINE) + for i, que in enumerate(usable_actions): + options.add_option(label=f"{str(i+1)}. {que}", value=str(usable_actions[que])) + view.add_item(options) + await interaction.response.edit_message(view=view) + + @discord.ui.button( + label="Remove", + style=discord.ButtonStyle.red, + custom_id="action_decline_editor:remove", + row=0 + ) + async def remove_action(self, button, interaction: discord.Interaction): + view = ActionDeclineEditorView(str(interaction.guild.id), self.application_name) + options = RemoveActionSelect(max_values=1, placeholder="Select action to remove") + options.set_app_name(self.application_name) + actions = GuildAppDB.get_actions(str(interaction.guild.id), self.application_name, action_type=ActionInteraction.DECLINE) + options.set_action_type(ActionInteraction.DECLINE) + for i, que in enumerate(actions): + options.add_option(label=f"{str(i+1)}. {que}", value=str(i)) + view.add_item(options) + await interaction.response.edit_message(view=view) + +class AddActionSelect(discord.ui.Select): + def set_app_name(self, app_name): + self.app_name = app_name + + def set_action_type(self, action_type): + self.action_type = action_type + + async def callback(self, interaction: discord.Interaction): + self.disabled = True + action = self.values[0] + if action == "add_role": + view = discord.ui.View() + options = SelectRoleToAdd(select_type=discord.ComponentType.role_select, max_values=1, placeholder="Select role to add") + options.set_app_name(self.app_name) + options.set_action_type(self.action_type) + view.add_item(options) + await interaction.response.edit_message(view=view) + +class SelectRoleToAdd(discord.ui.Select): + def set_app_name(self, app_name): + self.app_name = app_name + + def set_action_type(self, action_type): + self.action_type = action_type + + async def callback(self, interaction: discord.Interaction): + self.disabled = True + role = self.values[0] + action = {"result": self.action_type, "action_type": "add_role", "display_type": "Add Role", "data": {"role_id": role.id}} + GuildAppDB.add_action(str(interaction.guild.id), self.app_name, action) + if self.action_type == ActionInteraction.ACCEPT: + editor = ActionAcceptEditorView(str(interaction.guild.id), self.app_name) + embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.ACCEPT) + if self.action_type == ActionInteraction.DECLINE: + editor = ActionDeclineEditorView(str(interaction.guild.id), self.app_name) + embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.DECLINE) + await interaction.response.edit_message(embed = embed, view = editor) + + +class RemoveActionSelect(discord.ui.Select): + def set_app_name(self, app_name): + self.app_name = app_name + + def set_action_type(self, action_type: ActionInteraction): + self.action_type = action_type + + async def callback(self, interaction: discord.Interaction): + self.disabled = True + GuildAppDB.remove_action(str(interaction.guild.id), self.app_name, int(self.values[0])+1) + if self.action_type == ActionInteraction.ACCEPT: + editor = ActionAcceptEditorView(str(interaction.guild.id), self.app_name) + embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.ACCEPT) + if self.action_type == ActionInteraction.DECLINE: + editor = ActionDeclineEditorView(str(interaction.guild.id), self.app_name) + embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.DECLINE) + await interaction.response.edit_message(embed = embed, view = editor) + + +class SelectActionOptionsEditor(discord.ui.Select): + async def callback(self, interaction: discord.Interaction): + self.disabled = True + + view = discord.ui.View() + options = SelectActionType(max_values=1, placeholder="Select Action™ type") + options.add_option(label="Accept", value="accept") + options.add_option(label="Decline", value="decline") + options.set_app_name(self.values[0]) + view.add_item(options) + await interaction.response.edit_message(view=view) + +class SelectActionType(discord.ui.Select): + def set_app_name(self, app_name): + self.app_name = app_name + + async def callback(self, interaction: discord.Interaction): + self.disabled = True + if self.values[0] == "accept": + editor = ActionAcceptEditorView(str(interaction.guild.id), self.app_name) + embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.ACCEPT) + if self.values[0] == "decline": + editor = ActionDeclineEditorView(str(interaction.guild.id), self.app_name) + embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.DECLINE) + await interaction.response.edit_message(embed = embed, view=editor) + + + # View with button that starts the application process class ApplicationStartButtonView(discord.ui.View): def __init__(self): diff --git a/dbutil.py b/dbutil.py index b23143d..9c14703 100644 --- a/dbutil.py +++ b/dbutil.py @@ -3,7 +3,7 @@ import os import sqlite3 import pickle -from action import Action +from action import Action, ActionInteraction class MessageDB(): @@ -247,14 +247,13 @@ class GuildAppDB(): - def add_action(guild_id: str, application_name: str, action: Action) -> str: + def add_action(guild_id: str, application_name: str, action: dict) -> str: con = sqlite3.connect("applications.db") cur = con.cursor() cur.execute("SELECT applications_blob FROM app_guildapp_db WHERE guild_id=(?)", (guild_id, )) application_blob = cur.fetchone() applications = pickle.loads(application_blob[0]) if application_name in applications.keys(): - action_index = int(len(applications[application_name]["actions"])) applications[application_name]["actions"].append(action) application_blob2 = pickle.dumps(applications) cur.execute("UPDATE app_guildapp_db SET applications_blob = (?) WHERE guild_id= (?)", (application_blob2, guild_id)) @@ -263,7 +262,7 @@ class GuildAppDB(): else: return "error on add action: application not found" - def get_actions(guild_id: str, application_name: str): + def get_actions(guild_id: str, application_name: str, action_type: ActionInteraction): con = sqlite3.connect("applications.db") cur = con.cursor() cur.execute("SELECT applications_blob FROM app_guildapp_db WHERE guild_id=(?)", (guild_id, )) @@ -271,7 +270,11 @@ class GuildAppDB(): applications = pickle.loads(application_blob[0]) if application_name in applications.keys(): actions = applications[application_name]["actions"] - return actions + actret = [] + for i in actions: + if i["result"] == action_type: + actret.append(i) + return actret else: return "error on get actions: application not found" diff --git a/scheme.py b/scheme.py index fbe8330..5140949 100644 --- a/scheme.py +++ b/scheme.py @@ -16,12 +16,14 @@ application_name: { "app_id": "", # basically useless but hey its there "resp_channel": "", "questions": [], - "actions": { - "action_name": { + "actions": [ + { + "result": ActionInteraction.ACCEPT, "action_type": "action_type", + "data": "" }, - "action_name2": Action() + {} - } + ] }