mirror of
https://github.com/neoarz/Syntrel.git
synced 2025-12-25 11:40:12 +01:00
feat(slop): tag system needs to be fixed
This commit is contained in:
145
cogs/general/tags/__init__.py
Normal file
145
cogs/general/tags/__init__.py
Normal file
@@ -0,0 +1,145 @@
|
||||
from discord import Interaction, Embed, Color
|
||||
from discord.ui import View
|
||||
from discord.app_commands import Choice, Group, autocomplete, describe
|
||||
|
||||
from .views.base import BaseCog
|
||||
from .views.models import AsyncTagManager, Tag
|
||||
from .views.tags import (
|
||||
AddTagButtonModal,
|
||||
TagSelectButton,
|
||||
)
|
||||
from .tagsend import TagSend
|
||||
from .tagcreate import TagCreate
|
||||
from .tagedit import TagEdit
|
||||
from .tagdelete import TagDelete
|
||||
|
||||
|
||||
class Tags(BaseCog):
|
||||
def __init__(self, bot):
|
||||
super().__init__(bot)
|
||||
self.description = "A cog for retrieving and setting tags."
|
||||
|
||||
self._conn: AsyncTagManager | None = None
|
||||
|
||||
# Initialize command classes
|
||||
self.tag_send = TagSend(self)
|
||||
self.tag_create = TagCreate(self)
|
||||
self.tag_edit = TagEdit(self)
|
||||
self.tag_delete = TagDelete(self)
|
||||
|
||||
@property
|
||||
def conn(self) -> AsyncTagManager:
|
||||
if self._conn is None: raise ValueError("Initialized improperly!")
|
||||
return self._conn
|
||||
|
||||
@classmethod
|
||||
async def setup(cls, bot):
|
||||
import os
|
||||
c = await super().setup(bot)
|
||||
db_path = f"{os.path.realpath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))}/database/database.db"
|
||||
c._conn = await AsyncTagManager.from_file(db_path)
|
||||
return c
|
||||
|
||||
async def cog_unload(self):
|
||||
if self._conn:
|
||||
await self._conn.close()
|
||||
await super().cog_unload()
|
||||
|
||||
async def tag_completer(self, inter: Interaction, current: str):
|
||||
_ = inter
|
||||
if self._conn is None or inter.guild is None:
|
||||
return []
|
||||
return [
|
||||
Choice(name=f"[G] {t.name}" if t.guild is None else t.name, value=str(t.tid))
|
||||
for t in await self._conn.tags
|
||||
if current.lower() in t.name.lower() and (inter.guild.id == t.guild or t.guild is None)
|
||||
][:25]
|
||||
|
||||
async def tag_button_completer(self, inter: Interaction, current: str):
|
||||
_ = inter
|
||||
if self._conn is None or inter.guild is None:
|
||||
return []
|
||||
return [
|
||||
Choice(name=f"[G] {t.name}" if t.guild is None else t.name, value=str(t.tid))
|
||||
for t in await self._conn.tags
|
||||
if current.lower() in t.name.lower()
|
||||
and (inter.guild.id == t.guild or t.guild is None)
|
||||
and len(t.buttons) > 0
|
||||
][:25]
|
||||
|
||||
tags = Group(name="tags", description="The parent for tag operations.", guild_only=True)
|
||||
urls = Group(name="urls", description="Manage url buttons for tags.", parent=tags, guild_only=True)
|
||||
|
||||
async def check_conn_tag(self, name: str) -> str | Tag:
|
||||
if self._conn is None:
|
||||
return "Error: couldn't connect to the db file to get tags!"
|
||||
if not name.isnumeric():
|
||||
return f"Error: Tag {name!r} was not found!"
|
||||
if (tag := await self._conn.tag(tid=int(name))) is None:
|
||||
return f"Error: Tag with id {name!r} was not found!"
|
||||
return tag
|
||||
|
||||
@tags.command(description="Send contents of a tag.")
|
||||
@describe(name="The name of the tag you want to send.")
|
||||
@autocomplete(name=tag_completer)
|
||||
async def send(self, inter: Interaction, name: str):
|
||||
await self.tag_send.send(inter, name)
|
||||
|
||||
@tags.command(description="Create a new tag.")
|
||||
async def create(self, inter: Interaction):
|
||||
await self.tag_create.create(inter)
|
||||
|
||||
@tags.command(description="Edit a tag.")
|
||||
@describe(name="The name of the tag you want to edit.")
|
||||
@autocomplete(name=tag_completer)
|
||||
async def edit(self, inter: Interaction, name: str):
|
||||
await self.tag_edit.edit(inter, name)
|
||||
|
||||
@tags.command(description="Delete a tag.")
|
||||
@describe(name="The name of the tag you want to delete.")
|
||||
@autocomplete(name=tag_completer)
|
||||
async def delete(self, inter: Interaction, name: str):
|
||||
await self.tag_delete.delete(inter, name)
|
||||
|
||||
@urls.command(name="add", description="Add a url button to tag.")
|
||||
@describe(name="The name of the tag you want to add a url button to.")
|
||||
@autocomplete(name=tag_completer)
|
||||
async def button_add(self, inter: Interaction, name: str):
|
||||
tag = await self.check_conn_tag(name)
|
||||
if isinstance(tag, str) or self._conn is None:
|
||||
return await inter.response.send_message(tag, ephemeral=True)
|
||||
await inter.response.send_modal(AddTagButtonModal(self, tag))
|
||||
|
||||
@urls.command(name="edit", description="Edit a button for a tag.")
|
||||
@describe(name="The name of the tag you want to edit button from.")
|
||||
@autocomplete(name=tag_button_completer)
|
||||
async def button_edit(self, inter: Interaction, name: str):
|
||||
tag = await self.check_conn_tag(name)
|
||||
if isinstance(tag, str) or self._conn is None:
|
||||
return await inter.response.send_message(tag, ephemeral=True)
|
||||
try:
|
||||
button_sel = TagSelectButton(self, tag)
|
||||
button_view = View()
|
||||
button_view.add_item(button_sel)
|
||||
await inter.response.send_message(view=button_view, ephemeral=True)
|
||||
except:
|
||||
button_sel = TagSelectButton(self, tag, safe=True)
|
||||
button_view = View()
|
||||
button_view.add_item(button_sel)
|
||||
await inter.response.send_message(view=button_view, ephemeral=True)
|
||||
|
||||
@urls.command(name="delete", description="Delete button(s) for a tag.")
|
||||
@describe(name="The name of the tag you want to delete button(s) from.")
|
||||
@autocomplete(name=tag_button_completer)
|
||||
async def button_delete(self, inter: Interaction, name: str):
|
||||
tag = await self.check_conn_tag(name)
|
||||
if isinstance(tag, str) or self._conn is None:
|
||||
return await inter.response.send_message(tag, ephemeral=True)
|
||||
button_sel = TagSelectButton(self, tag, True)
|
||||
button_view = View()
|
||||
button_view.add_item(button_sel)
|
||||
await inter.response.send_message(view=button_view, ephemeral=True)
|
||||
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(await Tags.setup(bot))
|
||||
16
cogs/general/tags/tagcreate.py
Normal file
16
cogs/general/tags/tagcreate.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from discord import Interaction
|
||||
|
||||
from .views.base import BaseCog
|
||||
from .views.tags import CreateTagModal
|
||||
|
||||
|
||||
class TagCreate:
|
||||
def __init__(self, cog: BaseCog):
|
||||
self.cog = cog
|
||||
|
||||
async def create(self, inter: Interaction):
|
||||
"""Create a new tag."""
|
||||
if self.cog._conn is None:
|
||||
await inter.response.send_message(f"Error: DB connection was None!", ephemeral=True)
|
||||
return
|
||||
await inter.response.send_modal(CreateTagModal(self.cog))
|
||||
38
cogs/general/tags/tagdelete.py
Normal file
38
cogs/general/tags/tagdelete.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import discord
|
||||
from discord import Interaction
|
||||
|
||||
from .views.base import BaseCog
|
||||
from .views.models import AsyncTagManager, Tag
|
||||
from .views.tags import ConfirmDeleteTag
|
||||
|
||||
|
||||
class TagDelete:
|
||||
def __init__(self, cog: BaseCog):
|
||||
self.cog = cog
|
||||
|
||||
async def check_conn_tag(self, name: str) -> str | Tag:
|
||||
if self.cog._conn is None:
|
||||
return "Error: couldn't connect to the db file to get tags!"
|
||||
if not name.isnumeric():
|
||||
return f"Error: Tag {name!r} was not found!"
|
||||
if (tag := await self.cog._conn.tag(tid=int(name))) is None:
|
||||
return f"Error: Tag with id {name!r} was not found!"
|
||||
return tag
|
||||
|
||||
async def delete(self, inter: Interaction, name: str):
|
||||
"""Delete a tag."""
|
||||
tag = await self.check_conn_tag(name)
|
||||
if isinstance(tag, str) or self.cog._conn is None:
|
||||
return await inter.response.send_message(tag, ephemeral=True)
|
||||
delete_tag = ConfirmDeleteTag(self.cog, tag)
|
||||
embed = discord.Embed(
|
||||
title="Confirm Deletion",
|
||||
description=f"Are you sure you want to delete `{tag.name}`?",
|
||||
color=0xFF0000
|
||||
)
|
||||
embed.set_author(name="Tags", icon_url="https://yes.nighty.works/raw/y5SEZ9.webp")
|
||||
await inter.response.send_message(
|
||||
embed=embed,
|
||||
view=delete_tag,
|
||||
ephemeral=True,
|
||||
)
|
||||
36
cogs/general/tags/tagedit.py
Normal file
36
cogs/general/tags/tagedit.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from discord import Interaction, Embed
|
||||
|
||||
from .views.base import BaseCog
|
||||
from .views.models import AsyncTagManager, Tag
|
||||
from .views.tags import EditTagPreview
|
||||
|
||||
|
||||
class TagEdit:
|
||||
def __init__(self, cog: BaseCog):
|
||||
self.cog = cog
|
||||
|
||||
async def check_conn_tag(self, name: str) -> str | Tag:
|
||||
if self.cog._conn is None:
|
||||
return "Error: couldn't connect to the db file to get tags!"
|
||||
if not name.isnumeric():
|
||||
return f"Error: Tag {name!r} was not found!"
|
||||
if (tag := await self.cog._conn.tag(tid=int(name))) is None:
|
||||
return f"Error: Tag with id {name!r} was not found!"
|
||||
return tag
|
||||
|
||||
async def edit(self, inter: Interaction, name: str):
|
||||
"""Edit a tag."""
|
||||
tag = await self.check_conn_tag(name)
|
||||
if isinstance(tag, str) or self.cog._conn is None:
|
||||
return await inter.response.send_message(tag, ephemeral=True)
|
||||
|
||||
embed = Embed(
|
||||
title=f"Edit Tag: {tag.name}",
|
||||
description=f"```\n{tag.content}\n```",
|
||||
color=0x7289DA
|
||||
)
|
||||
embed.set_author(name="Tags", icon_url="https://yes.nighty.works/raw/y5SEZ9.webp")
|
||||
embed.set_footer(text="Click Edit to modify this tag or Close to cancel")
|
||||
|
||||
view = EditTagPreview(self.cog, tag)
|
||||
await inter.response.send_message(embed=embed, view=view, ephemeral=True)
|
||||
40
cogs/general/tags/tagsend.py
Normal file
40
cogs/general/tags/tagsend.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from discord import Interaction
|
||||
|
||||
from .views.base import BaseCog
|
||||
from .views.models import AsyncTagManager, Tag
|
||||
from .views.tags import TagEmbed, TagButtonView
|
||||
|
||||
|
||||
class TagSend:
|
||||
def __init__(self, cog: BaseCog):
|
||||
self.cog = cog
|
||||
|
||||
@property
|
||||
def conn(self) -> AsyncTagManager:
|
||||
return self.cog.conn
|
||||
|
||||
async def check_conn_tag(self, name: str) -> str | Tag:
|
||||
if self.cog._conn is None:
|
||||
return "Error: couldn't connect to the db file to get tags!"
|
||||
if not name.isnumeric():
|
||||
return f"Error: Tag {name!r} was not found!"
|
||||
if (tag := await self.cog._conn.tag(tid=int(name))) is None:
|
||||
return f"Error: Tag with id {name!r} was not found!"
|
||||
return tag
|
||||
|
||||
async def send(self, inter: Interaction, name: str):
|
||||
"""Send contents of a tag."""
|
||||
tag = await self.check_conn_tag(name)
|
||||
if isinstance(tag, str) or self.cog._conn is None:
|
||||
return await inter.response.send_message(tag, ephemeral=True)
|
||||
ephemeral = inter.guild is None
|
||||
author = self.cog.bot.get_user(tag.author)
|
||||
authname = author.name if author else str(tag.author)
|
||||
await inter.response.send_message(
|
||||
embeds=[TagEmbed(tag, authname)],
|
||||
view=TagButtonView(tag.buttons),
|
||||
ephemeral=ephemeral
|
||||
)
|
||||
tag.used += 1
|
||||
await self.cog._conn.update(tag)
|
||||
self.cog.logger.info(f"{inter.user.name!r} sent {tag.name!r}")
|
||||
0
cogs/general/tags/views/__init__.py
Normal file
0
cogs/general/tags/views/__init__.py
Normal file
15
cogs/general/tags/views/base.py
Normal file
15
cogs/general/tags/views/base.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import logging
|
||||
from discord.ext import commands
|
||||
|
||||
|
||||
class BaseCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.logger = logging.getLogger(f"discord_bot.{self.__class__.__name__}")
|
||||
|
||||
@classmethod
|
||||
async def setup(cls, bot):
|
||||
return cls(bot)
|
||||
|
||||
async def cog_unload(self):
|
||||
pass
|
||||
187
cogs/general/tags/views/models.py
Normal file
187
cogs/general/tags/views/models.py
Normal file
@@ -0,0 +1,187 @@
|
||||
import aiosqlite
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class TagButton:
|
||||
id: int
|
||||
tag_id: int
|
||||
label: str
|
||||
url: str
|
||||
emoji: Optional[str] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class Tag:
|
||||
tid: int
|
||||
name: str
|
||||
content: str
|
||||
author: int
|
||||
guild: Optional[int]
|
||||
used: int = 0
|
||||
buttons: List[TagButton] = None
|
||||
|
||||
def __post_init__(self):
|
||||
if self.buttons is None:
|
||||
self.buttons = []
|
||||
|
||||
|
||||
class AsyncTagManager:
|
||||
def __init__(self, db_path: str):
|
||||
self.db_path = db_path
|
||||
self._connection = None
|
||||
self._tags_cache = None
|
||||
|
||||
@classmethod
|
||||
async def from_file(cls, db_path: str):
|
||||
manager = cls(db_path)
|
||||
await manager._connect()
|
||||
return manager
|
||||
|
||||
async def _connect(self):
|
||||
self._connection = await aiosqlite.connect(self.db_path)
|
||||
await self._load_tags()
|
||||
|
||||
async def close(self):
|
||||
if self._connection:
|
||||
await self._connection.close()
|
||||
self._connection = None
|
||||
|
||||
async def _load_tags(self):
|
||||
if not self._connection:
|
||||
return
|
||||
|
||||
cursor = await self._connection.execute("""
|
||||
SELECT t.tid, t.name, t.content, t.author, t.guild, t.used,
|
||||
b.id, b.label, b.url, b.emoji
|
||||
FROM tags t
|
||||
LEFT JOIN tag_buttons b ON t.tid = b.tag_id
|
||||
ORDER BY t.tid
|
||||
""")
|
||||
|
||||
rows = await cursor.fetchall()
|
||||
await cursor.close()
|
||||
|
||||
tags_dict = {}
|
||||
for row in rows:
|
||||
tid = row[0]
|
||||
if tid not in tags_dict:
|
||||
tags_dict[tid] = Tag(
|
||||
tid=row[0],
|
||||
name=row[1],
|
||||
content=row[2],
|
||||
author=row[3],
|
||||
guild=row[4],
|
||||
used=row[5],
|
||||
buttons=[]
|
||||
)
|
||||
|
||||
if row[6] is not None:
|
||||
button = TagButton(
|
||||
id=row[6],
|
||||
tag_id=tid,
|
||||
label=row[7],
|
||||
url=row[8],
|
||||
emoji=row[9]
|
||||
)
|
||||
tags_dict[tid].buttons.append(button)
|
||||
|
||||
self._tags_cache = list(tags_dict.values())
|
||||
|
||||
@property
|
||||
async def tags(self) -> List[Tag]:
|
||||
if self._tags_cache is None:
|
||||
await self._load_tags()
|
||||
return self._tags_cache
|
||||
|
||||
async def tag(self, tid: int = None, name: str = None) -> Optional[Tag]:
|
||||
tags = await self.tags
|
||||
if tid is not None:
|
||||
return next((tag for tag in tags if tag.tid == tid), None)
|
||||
if name is not None:
|
||||
return next((tag for tag in tags if tag.name.lower() == name.lower()), None)
|
||||
return None
|
||||
|
||||
async def create_tag(self, name: str, content: str, author: int, guild: Optional[int] = None) -> Tag:
|
||||
if not self._connection:
|
||||
raise ValueError("Database not connected")
|
||||
|
||||
cursor = await self._connection.execute(
|
||||
"INSERT INTO tags (name, content, author, guild) VALUES (?, ?, ?, ?)",
|
||||
(name, content, author, guild)
|
||||
)
|
||||
await self._connection.commit()
|
||||
|
||||
tid = cursor.lastrowid
|
||||
await cursor.close()
|
||||
|
||||
tag = Tag(tid=tid, name=name, content=content, author=author, guild=guild, used=0, buttons=[])
|
||||
self._tags_cache.append(tag)
|
||||
return tag
|
||||
|
||||
async def update(self, tag: Tag):
|
||||
if not self._connection:
|
||||
raise ValueError("Database not connected")
|
||||
|
||||
await self._connection.execute(
|
||||
"UPDATE tags SET name=?, content=?, used=? WHERE tid=?",
|
||||
(tag.name, tag.content, tag.used, tag.tid)
|
||||
)
|
||||
await self._connection.commit()
|
||||
|
||||
if self._tags_cache:
|
||||
for i, cached_tag in enumerate(self._tags_cache):
|
||||
if cached_tag.tid == tag.tid:
|
||||
self._tags_cache[i] = tag
|
||||
break
|
||||
|
||||
async def delete_tag(self, tag: Tag):
|
||||
if not self._connection:
|
||||
raise ValueError("Database not connected")
|
||||
|
||||
await self._connection.execute("DELETE FROM tags WHERE tid=?", (tag.tid,))
|
||||
await self._connection.commit()
|
||||
|
||||
if self._tags_cache:
|
||||
self._tags_cache = [t for t in self._tags_cache if t.tid != tag.tid]
|
||||
|
||||
async def add_button(self, tag: Tag, label: str, url: str, emoji: Optional[str] = None) -> TagButton:
|
||||
if not self._connection:
|
||||
raise ValueError("Database not connected")
|
||||
|
||||
cursor = await self._connection.execute(
|
||||
"INSERT INTO tag_buttons (tag_id, label, url, emoji) VALUES (?, ?, ?, ?)",
|
||||
(tag.tid, label, url, emoji)
|
||||
)
|
||||
await self._connection.commit()
|
||||
|
||||
button_id = cursor.lastrowid
|
||||
await cursor.close()
|
||||
|
||||
button = TagButton(id=button_id, tag_id=tag.tid, label=label, url=url, emoji=emoji)
|
||||
tag.buttons.append(button)
|
||||
return button
|
||||
|
||||
async def update_button(self, button: TagButton):
|
||||
if not self._connection:
|
||||
raise ValueError("Database not connected")
|
||||
|
||||
await self._connection.execute(
|
||||
"UPDATE tag_buttons SET label=?, url=?, emoji=? WHERE id=?",
|
||||
(button.label, button.url, button.emoji, button.id)
|
||||
)
|
||||
await self._connection.commit()
|
||||
|
||||
async def delete_button(self, button: TagButton):
|
||||
if not self._connection:
|
||||
raise ValueError("Database not connected")
|
||||
|
||||
await self._connection.execute("DELETE FROM tag_buttons WHERE id=?", (button.id,))
|
||||
await self._connection.commit()
|
||||
|
||||
for tag in await self.tags:
|
||||
if tag.tid == button.tag_id:
|
||||
tag.buttons = [b for b in tag.buttons if b.id != button.id]
|
||||
break
|
||||
398
cogs/general/tags/views/tags.py
Normal file
398
cogs/general/tags/views/tags.py
Normal file
@@ -0,0 +1,398 @@
|
||||
import discord
|
||||
from discord import Interaction, ButtonStyle, SelectOption
|
||||
from discord.ui import Modal, TextInput, View, Button, Select
|
||||
from typing import TYPE_CHECKING, List
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .models import Tag, TagButton
|
||||
|
||||
class TagEmbed(discord.Embed):
|
||||
def __init__(self, tag: "Tag", author_name: str):
|
||||
super().__init__(
|
||||
description=tag.content,
|
||||
color=0x7289DA,
|
||||
timestamp=discord.utils.utcnow()
|
||||
)
|
||||
self.set_author(name="Tags", icon_url="https://yes.nighty.works/raw/y5SEZ9.webp")
|
||||
self.set_footer(text=f"Created by {author_name} | Used {tag.used} times")
|
||||
|
||||
|
||||
class TagButtonView(View):
|
||||
def __init__(self, buttons: List["TagButton"]):
|
||||
super().__init__(timeout=None)
|
||||
for button in buttons[:5]:
|
||||
self.add_item(TagUrlButton(button))
|
||||
|
||||
|
||||
class TagUrlButton(Button):
|
||||
def __init__(self, tag_button: "TagButton"):
|
||||
super().__init__(
|
||||
label=tag_button.label,
|
||||
url=tag_button.url,
|
||||
emoji=tag_button.emoji,
|
||||
style=ButtonStyle.link
|
||||
)
|
||||
|
||||
|
||||
class CreateTagModal(Modal):
|
||||
def __init__(self, cog):
|
||||
super().__init__(title="Create New Tag")
|
||||
self.cog = cog
|
||||
|
||||
self.name_input = TextInput(
|
||||
label="Tag Name",
|
||||
placeholder="Enter the name for your tag...",
|
||||
max_length=100,
|
||||
required=True
|
||||
)
|
||||
self.content_input = TextInput(
|
||||
label="Tag Content",
|
||||
placeholder="Enter the content for your tag...",
|
||||
style=discord.TextStyle.paragraph,
|
||||
max_length=2000,
|
||||
required=True
|
||||
)
|
||||
|
||||
self.add_item(self.name_input)
|
||||
self.add_item(self.content_input)
|
||||
|
||||
async def on_submit(self, interaction: Interaction):
|
||||
name = self.name_input.value
|
||||
content = self.content_input.value
|
||||
author = interaction.user.id
|
||||
guild = interaction.guild.id if interaction.guild else None
|
||||
|
||||
existing_tag = await self.cog.conn.tag(name=name)
|
||||
if existing_tag and (existing_tag.guild == guild or existing_tag.guild is None):
|
||||
await interaction.response.send_message(
|
||||
f"A tag with the name '{name}' already exists!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
tag = await self.cog.conn.create_tag(name, content, author, guild)
|
||||
embed = discord.Embed(
|
||||
title="Tag Created!",
|
||||
description=f"Successfully created tag `{name}`!",
|
||||
color=0x7289DA
|
||||
)
|
||||
embed.set_author(name="Tags", icon_url="https://yes.nighty.works/raw/y5SEZ9.webp")
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
self.cog.logger.info(f"Tag '{name}' created by {interaction.user.name}")
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(
|
||||
f"An error occurred while creating the tag: {str(e)}",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
|
||||
class EditTagPreview(View):
|
||||
def __init__(self, cog, tag: "Tag"):
|
||||
super().__init__(timeout=300)
|
||||
self.cog = cog
|
||||
self.tag = tag
|
||||
|
||||
@discord.ui.button(label="Edit", style=ButtonStyle.primary)
|
||||
async def edit_button(self, interaction: Interaction, button: Button):
|
||||
if interaction.user.id != self.tag.author and not interaction.user.guild_permissions.manage_messages:
|
||||
await interaction.response.send_message(
|
||||
"You don't have permission to edit this tag!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
await interaction.response.send_modal(EditTagModal(self.cog, self.tag))
|
||||
|
||||
@discord.ui.button(label="Close", style=ButtonStyle.danger)
|
||||
async def close_button(self, interaction: Interaction, button: Button):
|
||||
await interaction.response.edit_message(content="Tag edit cancelled.", embed=None, view=None)
|
||||
|
||||
|
||||
class EditTagModal(Modal):
|
||||
def __init__(self, cog, tag: "Tag"):
|
||||
super().__init__(title=f"Edit Tag: {tag.name}")
|
||||
self.cog = cog
|
||||
self.tag = tag
|
||||
|
||||
self.name_input = TextInput(
|
||||
label="Tag Name",
|
||||
default=tag.name,
|
||||
max_length=100,
|
||||
required=True
|
||||
)
|
||||
self.content_input = TextInput(
|
||||
label="Tag Content",
|
||||
default=tag.content,
|
||||
style=discord.TextStyle.paragraph,
|
||||
max_length=2000,
|
||||
required=True
|
||||
)
|
||||
|
||||
self.add_item(self.name_input)
|
||||
self.add_item(self.content_input)
|
||||
|
||||
async def on_submit(self, interaction: Interaction):
|
||||
if interaction.user.id != self.tag.author and not interaction.user.guild_permissions.manage_messages:
|
||||
await interaction.response.send_message(
|
||||
"You don't have permission to edit this tag!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
name = self.name_input.value
|
||||
content = self.content_input.value
|
||||
|
||||
guild = interaction.guild.id if interaction.guild else None
|
||||
existing_tag = await self.cog.conn.tag(name=name)
|
||||
if existing_tag and existing_tag.tid != self.tag.tid and (existing_tag.guild == guild or existing_tag.guild is None):
|
||||
await interaction.response.send_message(
|
||||
f"A tag with the name '{name}' already exists!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
self.tag.name = name
|
||||
self.tag.content = content
|
||||
await self.cog.conn.update(self.tag)
|
||||
embed = discord.Embed(
|
||||
title="Success!",
|
||||
description=f"Successfully updated tag `{name}`!",
|
||||
color=0x00FF00
|
||||
)
|
||||
embed.set_author(name="Tags", icon_url="https://yes.nighty.works/raw/y5SEZ9.webp")
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
self.cog.logger.info(f"Tag '{name}' updated by {interaction.user.name}")
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(
|
||||
f"An error occurred while updating the tag: {str(e)}",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
|
||||
class ConfirmDeleteTag(View):
|
||||
def __init__(self, cog, tag: "Tag"):
|
||||
super().__init__(timeout=60)
|
||||
self.cog = cog
|
||||
self.tag = tag
|
||||
|
||||
@discord.ui.button(label="Yes", style=ButtonStyle.danger)
|
||||
async def confirm_delete(self, interaction: Interaction, button: Button):
|
||||
if interaction.user.id != self.tag.author and not interaction.user.guild_permissions.manage_messages:
|
||||
await interaction.response.send_message(
|
||||
"You don't have permission to delete this tag!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
await self.cog.conn.delete_tag(self.tag)
|
||||
await interaction.response.edit_message(
|
||||
embed=discord.Embed(
|
||||
title="Success!",
|
||||
description=f"Tag `{self.tag.name}` has been deleted.",
|
||||
color=0x00FF00
|
||||
),
|
||||
view=None
|
||||
)
|
||||
self.cog.logger.info(f"Tag '{self.tag.name}' deleted by {interaction.user.name}")
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(
|
||||
f"An error occurred while deleting the tag: {str(e)}",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
@discord.ui.button(label="No", style=ButtonStyle.secondary)
|
||||
async def cancel_delete(self, interaction: Interaction, button: Button):
|
||||
await interaction.response.edit_message(
|
||||
content="Tag deletion cancelled.",
|
||||
view=None
|
||||
)
|
||||
|
||||
|
||||
class AddTagButtonModal(Modal):
|
||||
def __init__(self, cog, tag: "Tag"):
|
||||
super().__init__(title=f"Add Button to: {tag.name}")
|
||||
self.cog = cog
|
||||
self.tag = tag
|
||||
|
||||
self.label_input = TextInput(
|
||||
label="Button Label",
|
||||
placeholder="Enter the button label...",
|
||||
max_length=80,
|
||||
required=True
|
||||
)
|
||||
self.url_input = TextInput(
|
||||
label="Button URL",
|
||||
placeholder="https://example.com",
|
||||
max_length=512,
|
||||
required=True
|
||||
)
|
||||
self.emoji_input = TextInput(
|
||||
label="Button Emoji (Optional)",
|
||||
placeholder="Enter emoji...",
|
||||
max_length=100,
|
||||
required=False
|
||||
)
|
||||
|
||||
self.add_item(self.label_input)
|
||||
self.add_item(self.url_input)
|
||||
self.add_item(self.emoji_input)
|
||||
|
||||
async def on_submit(self, interaction: Interaction):
|
||||
if interaction.user.id != self.tag.author and not interaction.user.guild_permissions.manage_messages:
|
||||
await interaction.response.send_message(
|
||||
"You don't have permission to modify this tag!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
if len(self.tag.buttons) >= 5:
|
||||
await interaction.response.send_message(
|
||||
"Tags can only have up to 5 buttons!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
label = self.label_input.value
|
||||
url = self.url_input.value
|
||||
emoji = self.emoji_input.value if self.emoji_input.value else None
|
||||
|
||||
try:
|
||||
await self.cog.conn.add_button(self.tag, label, url, emoji)
|
||||
await interaction.response.send_message(
|
||||
f"Successfully added button '{label}' to tag '{self.tag.name}'!",
|
||||
ephemeral=True
|
||||
)
|
||||
self.cog.logger.info(f"Button '{label}' added to tag '{self.tag.name}' by {interaction.user.name}")
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(
|
||||
f"An error occurred while adding the button: {str(e)}",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
|
||||
class TagSelectButton(Select):
|
||||
def __init__(self, cog, tag: "Tag", delete_mode: bool = False, safe: bool = False):
|
||||
self.cog = cog
|
||||
self.tag = tag
|
||||
self.delete_mode = delete_mode
|
||||
|
||||
options = []
|
||||
for i, button in enumerate(tag.buttons[:25]):
|
||||
option_label = button.label
|
||||
if len(option_label) > 100:
|
||||
option_label = option_label[:97] + "..."
|
||||
|
||||
options.append(SelectOption(
|
||||
label=option_label,
|
||||
value=str(button.id),
|
||||
description=button.url[:100] if len(button.url) <= 100 else button.url[:97] + "...",
|
||||
emoji=button.emoji if not safe else None
|
||||
))
|
||||
|
||||
if not options:
|
||||
options.append(SelectOption(
|
||||
label="No buttons available",
|
||||
value="none",
|
||||
description="This tag has no buttons"
|
||||
))
|
||||
|
||||
super().__init__(
|
||||
placeholder="Select a button to edit..." if not delete_mode else "Select a button to delete...",
|
||||
options=options,
|
||||
disabled=len(tag.buttons) == 0
|
||||
)
|
||||
|
||||
async def callback(self, interaction: Interaction):
|
||||
if interaction.user.id != self.tag.author and not interaction.user.guild_permissions.manage_messages:
|
||||
await interaction.response.send_message(
|
||||
"You don't have permission to modify this tag!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
if self.values[0] == "none":
|
||||
await interaction.response.send_message(
|
||||
"No buttons available to modify.",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
button_id = int(self.values[0])
|
||||
button = next((b for b in self.tag.buttons if b.id == button_id), None)
|
||||
|
||||
if not button:
|
||||
await interaction.response.send_message(
|
||||
"Button not found!",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
if self.delete_mode:
|
||||
try:
|
||||
await self.cog.conn.delete_button(button)
|
||||
await interaction.response.send_message(
|
||||
f"Successfully deleted button '{button.label}' from tag '{self.tag.name}'!",
|
||||
ephemeral=True
|
||||
)
|
||||
self.cog.logger.info(f"Button '{button.label}' deleted from tag '{self.tag.name}' by {interaction.user.name}")
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(
|
||||
f"An error occurred while deleting the button: {str(e)}",
|
||||
ephemeral=True
|
||||
)
|
||||
else:
|
||||
await interaction.response.send_modal(EditTagButtonModal(self.cog, self.tag, button))
|
||||
|
||||
|
||||
class EditTagButtonModal(Modal):
|
||||
def __init__(self, cog, tag: "Tag", button: "TagButton"):
|
||||
super().__init__(title=f"Edit Button: {button.label}")
|
||||
self.cog = cog
|
||||
self.tag = tag
|
||||
self.button = button
|
||||
|
||||
self.label_input = TextInput(
|
||||
label="Button Label",
|
||||
default=button.label,
|
||||
max_length=80,
|
||||
required=True
|
||||
)
|
||||
self.url_input = TextInput(
|
||||
label="Button URL",
|
||||
default=button.url,
|
||||
max_length=512,
|
||||
required=True
|
||||
)
|
||||
self.emoji_input = TextInput(
|
||||
label="Button Emoji (Optional)",
|
||||
default=button.emoji or "",
|
||||
max_length=100,
|
||||
required=False
|
||||
)
|
||||
|
||||
self.add_item(self.label_input)
|
||||
self.add_item(self.url_input)
|
||||
self.add_item(self.emoji_input)
|
||||
|
||||
async def on_submit(self, interaction: Interaction):
|
||||
label = self.label_input.value
|
||||
url = self.url_input.value
|
||||
emoji = self.emoji_input.value if self.emoji_input.value else None
|
||||
|
||||
try:
|
||||
self.button.label = label
|
||||
self.button.url = url
|
||||
self.button.emoji = emoji
|
||||
await self.cog.conn.update_button(self.button)
|
||||
await interaction.response.send_message(
|
||||
f"Successfully updated button '{label}' on tag '{self.tag.name}'!",
|
||||
ephemeral=True
|
||||
)
|
||||
self.cog.logger.info(f"Button '{label}' updated on tag '{self.tag.name}' by {interaction.user.name}")
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(
|
||||
f"An error occurred while updating the button: {str(e)}",
|
||||
ephemeral=True
|
||||
)
|
||||
Reference in New Issue
Block a user