From 035f0e9f833197d782e36d6eaf25c899b8aa96f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brockm=C3=B6ller?= Date: Sun, 5 Oct 2025 17:06:57 +0200 Subject: [PATCH] Check Telegram response (#205) (#211) * Add error handling and logging to Telegram message sending * Add debug logging for new listings --- lib/FredyRuntime.js | 12 ++++++++-- lib/notification/adapter/telegram.js | 34 ++++++++++++++++------------ 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/lib/FredyRuntime.js b/lib/FredyRuntime.js index 0b358f2..29f54f2 100755 --- a/lib/FredyRuntime.js +++ b/lib/FredyRuntime.js @@ -77,6 +77,7 @@ class FredyRuntime { } _findNew(listings) { + logger.debug(`Checking ${listings.length} listings for new entries (Provider: '${this._providerId}')`); const hashes = getKnownListingHashesForJobAndProvider(this._jobKey, this._providerId) || []; const newListings = listings.filter((o) => !hashes.includes(o.id)); @@ -95,6 +96,7 @@ class FredyRuntime { } _save(newListings) { + logger.debug(`Storing ${newListings.length} new listings (Provider: '${this._providerId}')`); storeListings(this._jobKey, this._providerId, newListings); return newListings; } @@ -103,7 +105,9 @@ class FredyRuntime { const filteredList = listings.filter((listing) => { const similar = this._similarityCache.hasSimilarEntries(listing.title, listing.address); if (similar) { - logger.debug(`Filtering similar entry for title: ${listing.title} and address ${listing.address}`); + logger.debug( + `Filtering similar entry for title '${listing.title}' and address '${listing.address}' (Provider: '${this._providerId}')`, + ); } return !similar; }); @@ -112,7 +116,11 @@ class FredyRuntime { } _handleError(err) { - if (err.name !== 'NoNewListingsWarning') logger.error(err); + if (err.name === 'NoNewListingsWarning') { + logger.debug(`No new listings found (Provider: '${this._providerId}').`); + } else { + logger.error(err); + } } } diff --git a/lib/notification/adapter/telegram.js b/lib/notification/adapter/telegram.js index a33b1ce..b2e3133 100644 --- a/lib/notification/adapter/telegram.js +++ b/lib/notification/adapter/telegram.js @@ -3,6 +3,7 @@ import { getJob } from '../../services/storage/jobStorage.js'; import fetch from 'node-fetch'; import pThrottle from 'p-throttle'; import { normalizeImageUrl } from '../../utils.js'; +import logger from '../../services/logger.js'; const RATE_LIMIT_INTERVAL = 1000; const chatThrottleMap = new Map(); @@ -68,6 +69,11 @@ export const send = ({ serviceName, newListings, notificationConfig, jobKey }) = body: JSON.stringify(body), headers: { 'Content-Type': 'application/json' }, }); + + if (!res.ok) { + const errorBody = await res.text(); + throw new Error(`API error for '${jobName}'. '${endpoint}' returned ${errorBody}`); + } return res; }); @@ -81,23 +87,23 @@ export const send = ({ serviceName, newListings, notificationConfig, jobKey }) = }; if (!img) { - return throttledCall('sendMessage', textPayload); + return await throttledCall('sendMessage', textPayload).catch(async (e) => { + logger.error(`Error sending message to Telegram: ${e.message}`); + }); } - try { - return await throttledCall('sendPhoto', { - chat_id: chatId, - photo: img, - caption: buildCaption(jobName, serviceName, o), - parse_mode: 'HTML', + return await throttledCall('sendPhoto', { + chat_id: chatId, + photo: img, + caption: buildCaption(jobName, serviceName, o), + parse_mode: 'HTML', + }).catch(async (e) => { + logger.error(`Error sending photo to Telegram and use a fallback: ${e.message}`); + return await throttledCall('sendMessage', textPayload).catch((e) => { + logger.error(`Error sending message to Telegram: ${e.message}`); + throw e; }); - } catch (e) { - // If we see a timeout due to sending an image, try sending it without - if (e && (e.code === 'ETIMEDOUT' || e.errno === 'ETIMEDOUT')) { - return throttledCall('sendMessage', textPayload); - } - throw e; - } + }); }); return Promise.all(promises);