feat: support agent-to-user image sending via Discord
Parse [SendImage: /absolute/path] tags from agent responses and send them as Discord file attachments alongside the text message.
This commit is contained in:
@@ -303,22 +303,48 @@ export class DiscordChannel implements Channel {
|
|||||||
|
|
||||||
const textChannel = channel as TextChannel;
|
const textChannel = channel as TextChannel;
|
||||||
|
|
||||||
|
// Extract image attachments from [SendImage: /path] tags
|
||||||
|
const SEND_IMAGE_RE = /\[SendImage:\s*(\/[^\]]+)\]/g;
|
||||||
|
const imageFiles: string[] = [];
|
||||||
|
let match;
|
||||||
|
while ((match = SEND_IMAGE_RE.exec(text)) !== null) {
|
||||||
|
const imgPath = match[1].trim();
|
||||||
|
if (fs.existsSync(imgPath)) {
|
||||||
|
imageFiles.push(imgPath);
|
||||||
|
} else {
|
||||||
|
logger.warn({ path: imgPath }, 'SendImage file not found, skipping');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let cleaned = text.replace(SEND_IMAGE_RE, '').trim();
|
||||||
|
|
||||||
// Convert @username mentions to Discord mention format
|
// Convert @username mentions to Discord mention format
|
||||||
const mentionMap: Record<string, string> = {
|
const mentionMap: Record<string, string> = {
|
||||||
눈쟁이: '216851709744513024',
|
눈쟁이: '216851709744513024',
|
||||||
};
|
};
|
||||||
let resolved = text;
|
|
||||||
for (const [name, id] of Object.entries(mentionMap)) {
|
for (const [name, id] of Object.entries(mentionMap)) {
|
||||||
resolved = resolved.replace(new RegExp(`@${name}`, 'g'), `<@${id}>`);
|
cleaned = cleaned.replace(new RegExp(`@${name}`, 'g'), `<@${id}>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discord has a 2000 character limit per message — split if needed
|
// Discord has a 2000 character limit per message — split if needed
|
||||||
const MAX_LENGTH = 2000;
|
const MAX_LENGTH = 2000;
|
||||||
if (resolved.length <= MAX_LENGTH) {
|
const files = imageFiles.map((f) => ({
|
||||||
await textChannel.send(resolved);
|
attachment: f,
|
||||||
|
name: path.basename(f),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (cleaned.length <= MAX_LENGTH) {
|
||||||
|
await textChannel.send({
|
||||||
|
content: cleaned || undefined,
|
||||||
|
files: files.length > 0 ? files : undefined,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < resolved.length; i += MAX_LENGTH) {
|
// Send text in chunks, attach images to the first chunk
|
||||||
await textChannel.send(resolved.slice(i, i + MAX_LENGTH));
|
for (let i = 0; i < cleaned.length; i += MAX_LENGTH) {
|
||||||
|
const chunk = cleaned.slice(i, i + MAX_LENGTH);
|
||||||
|
await textChannel.send({
|
||||||
|
content: chunk,
|
||||||
|
files: i === 0 && files.length > 0 ? files : undefined,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.info({ jid, length: text.length }, 'Discord message sent');
|
logger.info({ jid, length: text.length }, 'Discord message sent');
|
||||||
|
|||||||
Reference in New Issue
Block a user