Skip to content

Commit 3fd1146

Browse files
committed
feat: adding attachments to snippets.
This adds the ability to add attachments to snippets
1 parent 3c3608f commit 3fd1146

File tree

6 files changed

+474
-33
lines changed

6 files changed

+474
-33
lines changed

bot.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,9 +1309,18 @@ async def get_contexts(self, message, *, cls=commands.Context):
13091309
# Check if a snippet is being called.
13101310
# This needs to be done before checking for aliases since
13111311
# snippets can have multiple words.
1312+
snippet_invoked = False
13121313
try:
13131314
# Use removeprefix once PY3.9+
1314-
snippet_text = self.snippets[message.content[len(invoked_prefix) :]]
1315+
snippet_data = self.snippets[message.content[len(invoked_prefix) :]]
1316+
# Extract text from snippet (handle both old string format and new dict format)
1317+
if isinstance(snippet_data, str):
1318+
snippet_text = snippet_data
1319+
elif isinstance(snippet_data, dict):
1320+
snippet_text = snippet_data.get("text", "")
1321+
else:
1322+
snippet_text = None
1323+
snippet_invoked = True
13151324
except KeyError:
13161325
snippet_text = None
13171326

@@ -1327,9 +1336,43 @@ async def get_contexts(self, message, *, cls=commands.Context):
13271336
for alias in aliases:
13281337
command = None
13291338
try:
1330-
snippet_text = self.snippets[alias]
1339+
snippet_data = self.snippets[alias]
1340+
# Extract text from snippet (handle both old string format and new dict format)
1341+
if isinstance(snippet_data, str):
1342+
snippet_text = snippet_data
1343+
elif isinstance(snippet_data, dict):
1344+
snippet_text = snippet_data.get("text", "")
1345+
# Download attachment if present
1346+
if snippet_data.get("file_id"):
1347+
try:
1348+
import io
1349+
1350+
file_data, metadata = await self.api.download_snippet_attachment(
1351+
snippet_data["file_id"]
1352+
)
1353+
1354+
class AttachmentWrapper:
1355+
def __init__(self, file_data, metadata):
1356+
self.file_data = file_data
1357+
self.id = 0
1358+
self.url = f"attachment://{metadata['filename']}"
1359+
self.filename = metadata["filename"]
1360+
self.size = metadata["length"]
1361+
self.width = None
1362+
1363+
async def to_file(self):
1364+
return discord.File(
1365+
io.BytesIO(self.file_data), filename=self.filename
1366+
)
1367+
1368+
message.attachments = [AttachmentWrapper(file_data, metadata)]
1369+
except Exception as e:
1370+
logger.warning("Failed to download snippet attachment: %s", e)
1371+
else:
1372+
snippet_text = None
13311373
except KeyError:
13321374
command_invocation_text = alias
1375+
snippet_text = None
13331376
else:
13341377
command = self._get_snippet_command()
13351378
command_invocation_text = f"{invoked_prefix}{command} {snippet_text}"
@@ -1346,11 +1389,38 @@ async def get_contexts(self, message, *, cls=commands.Context):
13461389

13471390
if snippet_text is not None:
13481391
# Process snippets
1392+
snippet_name = message.content[len(invoked_prefix) :]
1393+
snippet_data = self.snippets.get(snippet_name)
1394+
# Download attachment if present
1395+
if isinstance(snippet_data, dict) and snippet_data.get("file_id"):
1396+
try:
1397+
import io
1398+
1399+
file_data, metadata = await self.api.download_snippet_attachment(snippet_data["file_id"])
1400+
1401+
# Create a list-like object that mimics message.attachments
1402+
class AttachmentWrapper:
1403+
def __init__(self, file_data, metadata):
1404+
self.file_data = file_data
1405+
self.id = 0
1406+
self.url = f"attachment://{metadata['filename']}"
1407+
self.filename = metadata["filename"]
1408+
self.size = metadata["length"]
1409+
self.width = None
1410+
1411+
async def to_file(self):
1412+
return discord.File(io.BytesIO(self.file_data), filename=self.filename)
1413+
1414+
message.attachments = [AttachmentWrapper(file_data, metadata)]
1415+
except Exception as e:
1416+
logger.warning("Failed to download snippet attachment: %s", e)
13491417
ctx.command = self._get_snippet_command()
13501418
reply_view = StringView(f"{invoked_prefix}{ctx.command} {snippet_text}")
13511419
discord.utils.find(reply_view.skip_string, prefixes)
13521420
ctx.invoked_with = reply_view.get_word().lower()
13531421
ctx.view = reply_view
1422+
# Mark that a snippet was invoked so we can delete the command message
1423+
ctx.snippet_invoked = snippet_invoked
13541424
else:
13551425
ctx.command = self.all_commands.get(invoker)
13561426
ctx.invoked_with = invoker

0 commit comments

Comments
 (0)