twitterbridge: jitter polls and slow down at night

The feed is fetched with a real X account's cookie, so avoid a fixed
24/7 cadence: random 4-8 min by day, 20-35 min 01:00-06:00 Istanbul.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
esefandClaude Opus 5.5 committed 2026-10-06 20:34:26 +03:00
1 parent 2358679904
commit 234fbe88aa
1 file changed
+16 -3
+16 -3
View File
@@ -1,16 +1,24 @@
# Twitter/X RSS-to-Discord forwarding via Nitter RSS feeds. # Twitter/X RSS-to-Discord forwarding (feed: self-hosted RSSHub, see esefrss).
# Polls RSS endpoints on a timer, auto-rotates through fallback URLs # Polls RSS endpoints on a timer, auto-rotates through fallback URLs
# when an instance returns empty or fails, and posts new entries # when an instance returns empty or fails, and posts new entries
# to a Discord webhook. # to a Discord webhook.
import os import os
import random
import asyncio import asyncio
import logging import logging
from datetime import datetime
from zoneinfo import ZoneInfo
import aiohttp import aiohttp
import feedparser import feedparser
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
POLL_INTERVAL = 300 # 5 minutes # The feed comes from RSSHub on yuuka using a real X account's cookie, so
# polls are jittered and slower at night to avoid a robotic 24/7 pattern.
POLL_INTERVAL = (240, 480) # daytime: random 4-8 minutes
NIGHT_POLL_INTERVAL = (1200, 2100) # night: random 20-35 minutes
NIGHT_HOURS = range(1, 6) # 01:00-05:59 Istanbul; the account posts ~06:00-08:00
LOCAL_TZ = ZoneInfo('Europe/Istanbul')
REQUEST_TIMEOUT = 30 # seconds per HTTP call REQUEST_TIMEOUT = 30 # seconds per HTTP call
MAX_EMPTY_STRIKES = 3 # consecutive empty polls before rotating URL MAX_EMPTY_STRIKES = 3 # consecutive empty polls before rotating URL
@@ -72,11 +80,16 @@ class TwitterRSSForwarder:
logger.exception('unhandled error in twitter rss poll loop — will retry next cycle') logger.exception('unhandled error in twitter rss poll loop — will retry next cycle')
try: try:
await asyncio.sleep(POLL_INTERVAL) await asyncio.sleep(self._next_delay())
except asyncio.CancelledError: except asyncio.CancelledError:
self._running = False self._running = False
raise raise
@staticmethod
def _next_delay() -> float:
night = datetime.now(LOCAL_TZ).hour in NIGHT_HOURS
return random.uniform(*(NIGHT_POLL_INTERVAL if night else POLL_INTERVAL))
def stop(self): def stop(self):
self._running = False self._running = False
logger.info('twitter rss forwarder stop requested') logger.info('twitter rss forwarder stop requested')