···33CHANNEL_ID=@your_channel_name_or_id
4455# Discord Configuration
66+# For multiple webhooks, use a comma-separated list:
77+# DISCORD_WEBHOOK_URLS=https://discord.com/api/webhooks/xxx/yyy,https://discord.com/api/webhooks/aaa/bbb
88+# For a single webhook (legacy):
69DISCORD_WEBHOOK_URL=your_discord_webhook_url_here
710DISCORD_ENABLED=true
811
+78-59
bot/discordWebhook.js
···991010class DiscordWebhook {
1111 constructor() {
1212- this.webhookUrl = config.discord?.webhookUrl;
1212+ // Support multiple webhook URLs (array or single string)
1313+ let urls = config.discord?.webhookUrls || config.discord?.webhookUrl;
1414+ if (typeof urls === 'string') {
1515+ urls = [urls];
1616+ }
1717+ this.webhookUrls = Array.isArray(urls) ? urls.filter(Boolean) : [];
1318 this.enabled = config.discord?.enabled;
1414-1515- if (!this.webhookUrl) {
1616- console.warn('Discord webhook URL not configured. Discord integration disabled.');
1919+2020+ if (!this.webhookUrls.length) {
2121+ console.warn('Discord webhook URL(s) not configured. Discord integration disabled.');
1722 } else if (this.enabled === false) {
1818- console.log('Discord webhook URL is configured but integration is disabled in settings.');
2323+ console.log('Discord webhook URL(s) configured but integration is disabled in settings.');
1924 } else {
2020- console.log('Discord webhook integration initialized.');
2525+ console.log(`Discord webhook integration initialized for ${this.webhookUrls.length} webhook(s).`);
2126 }
2227 }
2328···2631 * @returns {boolean} - Whether Discord integration is enabled
2732 */
2833 isEnabled() {
2929- // Only return true if both the webhook URL is set AND explicitly enabled in config
3030- return !!this.webhookUrl && this.enabled !== false;
3434+ // Only return true if at least one webhook URL is set AND explicitly enabled in config
3535+ return this.webhookUrls.length > 0 && this.enabled !== false;
3136 }
32373338 /**
···148153 }
149154150155 // Send the embed
151151- try {
152152- await axios.post(this.webhookUrl, {
153153- embeds: [embed]
154154- }, {
155155- headers: {
156156- 'Content-Type': 'application/json'
156156+ for (const url of this.webhookUrls) {
157157+ try {
158158+ await axios.post(url, {
159159+ embeds: [embed]
160160+ }, {
161161+ headers: {
162162+ 'Content-Type': 'application/json'
163163+ }
164164+ });
165165+ console.log(`Successfully sent embed to Discord webhook: ${url}`);
166166+ } catch (error) {
167167+ console.error(`Error sending embed to ${url}:`, error.message);
168168+ if (error.response) {
169169+ console.error('Discord API response:', error.response.data);
157170 }
158158- });
159159- console.log('Successfully sent embed to Discord');
160160- } catch (error) {
161161- console.error('Error sending embed:', error.message);
162162- if (error.response) {
163163- console.error('Discord API response:', error.response.data);
164171 }
165165- throw error;
166172 }
167173 }
168174···218224 }
219225220226 // Send the embeds
221221- try {
222222- await axios.post(this.webhookUrl, {
223223- embeds: embeds
224224- }, {
225225- headers: {
226226- 'Content-Type': 'application/json'
227227+ for (const url of this.webhookUrls) {
228228+ try {
229229+ await axios.post(url, {
230230+ embeds: embeds
231231+ }, {
232232+ headers: {
233233+ 'Content-Type': 'application/json'
234234+ }
235235+ });
236236+ console.log(`Successfully sent ${embeds.length} embeds to Discord webhook: ${url}`);
237237+ } catch (error) {
238238+ console.error(`Error sending multiple embeds to ${url}:`, error.message);
239239+ if (error.response) {
240240+ console.error('Discord API response:', error.response.data);
227241 }
228228- });
229229- console.log(`Successfully sent ${embeds.length} embeds to Discord`);
230230- } catch (error) {
231231- console.error('Error sending multiple embeds:', error.message);
232232- if (error.response) {
233233- console.error('Discord API response:', error.response.data);
234242 }
235235- throw error;
236243 }
237244 } else {
238245 // If we only have one image or no array, fall back to single image embed
···280287 embed.description = "This post contains a video. Click the title to watch.";
281288282289 // Send the embed
283283- try {
284284- await axios.post(this.webhookUrl, {
285285- embeds: [embed]
286286- }, {
287287- headers: {
288288- 'Content-Type': 'application/json'
290290+ for (const url of this.webhookUrls) {
291291+ try {
292292+ await axios.post(url, {
293293+ embeds: [embed]
294294+ }, {
295295+ headers: {
296296+ 'Content-Type': 'application/json'
297297+ }
298298+ });
299299+ console.log(`Successfully sent video embed to Discord webhook: ${url}`);
300300+ } catch (error) {
301301+ console.error(`Error sending video embed to ${url}:`, error.message);
302302+ if (error.response) {
303303+ console.error('Discord API response:', error.response.data);
289304 }
290290- });
291291- console.log('Successfully sent video embed to Discord');
292292- } catch (error) {
293293- console.error('Error sending video embed:', error.message);
294294- if (error.response) {
295295- console.error('Discord API response:', error.response.data);
296305 }
297297- throw error;
298306 }
299307 }
300308···349357 });
350358351359 // Send the form
352352- await axios.post(this.webhookUrl, form, {
353353- headers: form.getHeaders()
354354- });
355355-356356- console.log(`Successfully sent local file embed with ${filePath}`);
360360+ for (const url of this.webhookUrls) {
361361+ try {
362362+ await axios.post(url, form, {
363363+ headers: form.getHeaders()
364364+ });
365365+ console.log(`Successfully sent local file embed with ${filePath} to Discord webhook: ${url}`);
366366+ } catch (error) {
367367+ console.error(`Error sending local file embed to ${url}:`, error.message);
368368+ }
369369+ }
357370 } catch (error) {
358371 console.error(`Error sending local file embed: ${error.message}`);
359372 // Fall back to text message
···367380 * @returns {Promise<void>}
368381 */
369382 async sendTextMessage(mediaData) {
370370- await axios.post(this.webhookUrl, {
371371- content: `${mediaData.title || 'New post'} from ${mediaData.siteName}: ${mediaData.sourceUrl}`
372372- }, {
373373- headers: {
374374- 'Content-Type': 'application/json'
383383+ for (const url of this.webhookUrls) {
384384+ try {
385385+ await axios.post(url, {
386386+ content: `${mediaData.title || 'New post'} from ${mediaData.siteName}: ${mediaData.sourceUrl}`
387387+ }, {
388388+ headers: {
389389+ 'Content-Type': 'application/json'
390390+ }
391391+ });
392392+ console.log(`Sent text-only message to Discord webhook: ${url}`);
393393+ } catch (error) {
394394+ console.error(`Error sending text message to ${url}:`, error.message);
375395 }
376376- });
377377- console.log('Sent text-only message to Discord webhook');
396396+ }
378397 }
379398380399 /**