this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Add owner ID configuration and update bot to allow manual updates from owner. Added new Bluesky Patterns

+76 -4
+3
.env.example
··· 9 9 # User Access Control (comma-separated list of Telegram user IDs) 10 10 AUTHORIZED_USERS=123456789,987654321 11 11 12 + # Bot Owner ID (for admin-only commands like manual updates) 13 + OWNER_ID=123456789 14 + 12 15 # Posting Schedule Configuration 13 16 DEFAULT_CRON_SCHEDULE=0 */1 * * * 14 17 IMAGES_PER_INTERVAL=1
+65 -2
bot/telegramBot.js
··· 1 1 const TelegramBot = require('node-telegram-bot-api'); 2 2 const axios = require('axios'); 3 3 const fs = require('fs'); 4 + const { exec } = require('child_process'); 5 + const { promisify } = require('util'); 6 + const execAsync = promisify(exec); 4 7 const config = require('../config'); 5 8 const queueManager = require('../queue/queueManager'); 6 9 const scraperManager = require('../utils/scraperManager'); ··· 38 41 /setcount [number] - Set number of images per scheduled post (default: 1) 39 42 /clear - Clear the queue 40 43 /cleancache - Clean expired items from media cache 44 + /update - Update bot from GitHub repository (owner only) 41 45 42 46 Send any link to a supported site to add it to the queue. 43 47 Supported sites: e621, FurAffinity, SoFurry, Weasyl, Bluesky ··· 234 238 this.bot.sendMessage(chatId, `Queue cleared (${queueLength} items removed).`); 235 239 }); 236 240 241 + // Command to manually trigger an update from GitHub 242 + this.bot.onText(/\/update/, async (msg) => { 243 + const chatId = msg.chat.id; 244 + 245 + // Only the bot owner can run updates 246 + if (!this.isOwner(msg.from.id)) { 247 + this.bot.sendMessage(chatId, 'Only the bot owner can trigger updates.'); 248 + return; 249 + } 250 + 251 + this.bot.sendMessage(chatId, 'Checking for updates...'); 252 + 253 + try { 254 + const updater = require('../utils/updater'); 255 + const isUpdateAvailable = await updater.isUpdateAvailable(); 256 + 257 + if (!isUpdateAvailable) { 258 + this.bot.sendMessage(chatId, 'No updates available. Bot is already running the latest version.'); 259 + return; 260 + } 261 + 262 + const statusMessage = await this.bot.sendMessage(chatId, 'Updates found! Downloading and applying updates...'); 263 + 264 + const updateResult = await updater.manualUpdate(); 265 + 266 + if (updateResult) { 267 + await this.bot.editMessageText('Update successful! Bot will restart to apply changes.', { 268 + chat_id: chatId, 269 + message_id: statusMessage.message_id 270 + }); 271 + 272 + // Give a moment for the message to be delivered before restarting 273 + setTimeout(async () => { 274 + try { 275 + // Restart the bot using PM2 276 + await execAsync('pm2 restart --update-env stagehand'); 277 + } catch (restartError) { 278 + console.error('Error restarting bot:', restartError); 279 + this.bot.sendMessage(chatId, `Error during restart: ${restartError.message}`); 280 + } 281 + }, 2000); 282 + } else { 283 + this.bot.sendMessage(chatId, 'Update process completed, but no changes were applied.'); 284 + } 285 + } catch (error) { 286 + console.error('Error during manual update:', error); 287 + this.bot.sendMessage(chatId, `Error during update: ${error.message}`); 288 + } 289 + }); 290 + 237 291 // Handle URL links 238 292 this.bot.on('message', async (msg) => { 239 293 if (msg.text && msg.text.startsWith('http')) { ··· 436 490 // Show posting status for each service 437 491 let statusIcons = ''; 438 492 if (item.postedTo) { 439 - if (item.postedTo.telegram) statusIcons += '✓TG '; 493 + if (item.postedTo.telegram) statusIcons += '✅TG '; 440 494 else statusIcons += '❌TG '; 441 495 442 496 if (queueManager.postServices.includes('discord')) { 443 - if (item.postedTo.discord) statusIcons += '✓DS'; 497 + if (item.postedTo.discord) statusIcons += '✅DS'; 444 498 else statusIcons += '❌DS'; 445 499 } 446 500 } ··· 528 582 } 529 583 530 584 return config.authorizedUsers.includes(userId.toString()); 585 + } 586 + 587 + /** 588 + * Check if the user is the owner of the bot 589 + * @param {number} userId - The Telegram user ID to check 590 + * @returns {boolean} - Whether the user is the owner 591 + */ 592 + isOwner(userId) { 593 + return config.ownerId && userId.toString() === config.ownerId.toString(); 531 594 } 532 595 533 596 /**
+6
config.js
··· 14 14 15 15 // Access control - can be expanded with more user IDs 16 16 authorizedUsers: process.env.AUTHORIZED_USERS ? process.env.AUTHORIZED_USERS.split(',') : [], 17 + ownerId: process.env.OWNER_ID, 17 18 18 19 // Queue configuration 19 20 defaultCronSchedule: process.env.DEFAULT_CRON_SCHEDULE || '0 */1 * * *', // Default: every hour ··· 40 41 name: 'Bluesky', 41 42 domain: 'deer.social', 42 43 pattern: /^https:\/\/(?:www\.)?deer\.social\// 44 + }, 45 + { 46 + name: 'Bluesky', 47 + domain: 'sky.thebull.app', 48 + pattern: /^https:\/\/(?:www\.)?sky\.thebull\.app\// 43 49 }, 44 50 { 45 51 name: 'e621',
+2 -2
scrapers/blueskyScraper.js
··· 11 11 super(); 12 12 // Initialize with service endpoint only - no authentication needed for public posts 13 13 this.serviceEndpoint = config.bluesky.service || 'https://bsky.social'; 14 - // Update regex to support both bsky.app and deer.social 15 - this.matcher = new RegExp('(?:https?://)?(?:bsky\\.app|deer\\.social)/profile/(?<repo>\\S+)/post/(?<rkey>\\S+)'); 14 + // Update regex to support bsky.app, deer.social, and sky.thebull.app 15 + this.matcher = new RegExp('(?:https?://)?(?:bsky\\.app|deer\\.social|sky\\.thebull\\.app)/profile/(?<repo>\\S+)/post/(?<rkey>\\S+)'); 16 16 17 17 // Initialize the agent 18 18 this.agent = new BskyAgent({ service: this.serviceEndpoint });