▮ REFACTORED PATCH
# 1. Fix SyntaxError — remove the redundant global decl in main(); SECRET/PORT
# are already module-level (L35-36), just reassign directly.
def main():
parser = argparse.ArgumentParser(description="Twitch EventSub Discord bridge")
parser.add_argument("--secret", default=SECRET)
parser.add_argument("--port", default=PORT, type=int)
parser.add_argument("--test", action="store_true")
args = parser.parse_args()
# global SECRET, PORT <-- DELETE (SyntaxError: name used prior to global)
SECRET = args.secret
PORT = args.port
if args.test: sys.exit(run_tests(PORT))
...
# 2. Make IdempotencyStore + TokenBucket thread-safe (threading.Lock, not asyncio.Lock)
import threading
class IdempotencyStore:
def __init__(self, ttl=IDEMPOTENCY_TTL):
self._ttl = ttl; self._store = {}; self._lock = threading.Lock()
def is_duplicate(self, event_id):
now = time.monotonic()
with self._lock:
self._store = {k:v for k,v in self._store.items() if now-v < self._ttl}
if event_id in self._store: return True
self._store[event_id] = now; return False
# 3. Clamp Retry-After to a safe int
try: retry_after = max(1, int(float(headers.get("Retry-After","1"))))
except (TypeError, ValueError): retry_after = 1