Add toggle for plain text message to telegram notification adapter (#299)

This commit is contained in:
Adrian Bartnik
2026-04-16 12:05:57 +02:00
committed by GitHub
parent e2d10d179e
commit c384781137
2 changed files with 52 additions and 13 deletions

View File

@@ -105,6 +105,32 @@ function buildText(jobName, serviceName, o) {
); );
} }
/**
* Build a plain text Telegram photo caption (max 4096 characters).
* @param {string} jobName
* @param {string} serviceName
* @param {Object} o - Listing object
* @returns {string}
*/
function buildCaptionPlain(jobName, serviceName, o) {
const title = shorten((o.title || '').replace(/\*/g, ''), 90);
const meta = [o.address, o.price, o.size].filter(Boolean).join(' | ');
return `${jobName} (${serviceName})\n${title}\n${meta}\n\n${o.link || ''}`.slice(0, 4096);
}
/**
* Build a plain text Telegram message.
* @param {string} jobName
* @param {string} serviceName
* @param {Object} o - Listing object
* @returns {string}
*/
function buildTextPlain(jobName, serviceName, o) {
const title = shorten((o.title || '').replace(/\*/g, ''), 90);
const meta = [o.address, o.price, o.size].filter(Boolean).join(' | ');
return `${jobName} (${serviceName})\n${title}\n${o.link || ''}\n${meta}`;
}
/** /**
* Send new listings to Telegram. * Send new listings to Telegram.
* - Respects per-chat Telegram rate limits using a lightweight throttle cache. * - Respects per-chat Telegram rate limits using a lightweight throttle cache.
@@ -122,7 +148,7 @@ export const send = ({ serviceName, newListings = [], notificationConfig, jobKey
if (!adapterCfg || !adapterCfg.fields) { if (!adapterCfg || !adapterCfg.fields) {
throw new Error(`Telegram adapter configuration missing for job '${jobKey || ''}'`); throw new Error(`Telegram adapter configuration missing for job '${jobKey || ''}'`);
} }
const { token, chatId, messageThreadId } = adapterCfg.fields; const { token, chatId, messageThreadId, plainText } = adapterCfg.fields;
if (!token || !chatId) { if (!token || !chatId) {
throw new Error("Telegram 'token' and 'chatId' must be provided in notification config"); throw new Error("Telegram 'token' and 'chatId' must be provided in notification config");
} }
@@ -163,8 +189,8 @@ export const send = ({ serviceName, newListings = [], notificationConfig, jobKey
const img = normalizeImageUrl(o.image); const img = normalizeImageUrl(o.image);
const textPayload = { const textPayload = {
chat_id: chatId, chat_id: chatId,
text: buildText(jobName, serviceName, o), text: plainText ? buildTextPlain(jobName, serviceName, o) : buildText(jobName, serviceName, o),
parse_mode: 'HTML', ...(plainText ? {} : { parse_mode: 'HTML' }),
disable_web_page_preview: true, disable_web_page_preview: true,
...(message_thread_id ? { message_thread_id } : {}), ...(message_thread_id ? { message_thread_id } : {}),
}; };
@@ -178,8 +204,8 @@ export const send = ({ serviceName, newListings = [], notificationConfig, jobKey
return await throttledCall('sendPhoto', { return await throttledCall('sendPhoto', {
chat_id: chatId, chat_id: chatId,
photo: img, photo: img,
caption: buildCaption(jobName, serviceName, o), caption: plainText ? buildCaptionPlain(jobName, serviceName, o) : buildCaption(jobName, serviceName, o),
parse_mode: 'HTML', ...(plainText ? {} : { parse_mode: 'HTML' }),
...(message_thread_id ? { message_thread_id } : {}), ...(message_thread_id ? { message_thread_id } : {}),
}).catch(async (e) => { }).catch(async (e) => {
logger.error(`Error sending photo to Telegram and use a fallback: ${e.message}`); logger.error(`Error sending photo to Telegram and use a fallback: ${e.message}`);
@@ -220,5 +246,11 @@ export const config = {
description: description:
'Optional: The topic/thread id within a supergroup to post into (Telegram message_thread_id). Provide a positive integer.', 'Optional: The topic/thread id within a supergroup to post into (Telegram message_thread_id). Provide a positive integer.',
}, },
plainText: {
type: 'boolean',
optional: true,
label: 'Send as plain text',
description: 'Send messages as plain text instead of HTML formatted.',
},
}, },
}; };

View File

@@ -156,14 +156,21 @@ export default function NotificationAdapterMutator({
return ( return (
<Form key={key}> <Form key={key}>
{uiElement.type === 'boolean' ? ( {uiElement.type === 'boolean' ? (
<div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}> <div>
<Switch <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
checked={uiElement.value || false} <Switch
onChange={(checked) => { checked={uiElement.value || false}
setValue(selectedAdapter, uiElement, key, checked); onChange={(checked) => {
}} setValue(selectedAdapter, uiElement, key, checked);
/> }}
{uiElement.label} />
{uiElement.label}
</div>
{uiElement.description && (
<div className="semi-form-field-extra" style={{ marginTop: '4px' }}>
{uiElement.description}
</div>
)}
</div> </div>
) : ( ) : (
<Form.Input <Form.Input