Files
ephemere/python/cohort/assign_cohort_role.py
T
naomi 6184801fed
CI / dependency-pin-check-typescript (pull_request) Failing after 4s
CI / typescript (pull_request) Has been skipped
CI / dependency-pin-check-python (pull_request) Failing after 4s
CI / python (pull_request) Has been skipped
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m23s
feat: cohort scripts
2026-01-23 18:26:39 -08:00

87 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""
Assign the Cohort role to all 155 participants.
Respects Discord rate limits with proper backoff and retry logic.
"""
import json
import os
import time
import requests
BOT_TOKEN = os.environ["DISCORD_BOT_TOKEN"]
GUILD_ID = "692816967895220344"
COHORT_ROLE_ID = "1464314780935258112"
BASE_URL = "https://discord.com/api/v10"
HEADERS = {
"Authorization": f"Bot {BOT_TOKEN}",
"Content-Length": "0"
}
def assign_role_with_retry(user_id: str, role_id: str, max_retries: int = 5) -> bool:
url = f"{BASE_URL}/guilds/{GUILD_ID}/members/{user_id}/roles/{role_id}"
for attempt in range(max_retries):
response = requests.put(url, headers=HEADERS)
if response.status_code == 204:
return True
elif response.status_code == 429:
# Check headers first, fall back to JSON body
retry_after = response.headers.get("Retry-After")
if retry_after is None:
retry_after = response.headers.get("X-RateLimit-Reset-After")
if retry_after is None:
try:
retry_after = response.json().get("retry_after", 1)
except:
retry_after = 1
retry_after = float(retry_after)
print(f" Rate limited! Waiting {retry_after:.2f}s before retry...")
time.sleep(retry_after)
else:
print(f" Error {response.status_code}: {response.text}")
backoff_time = (2 ** attempt) * 0.5
print(f" Retrying in {backoff_time:.2f}s...")
time.sleep(backoff_time)
return False
def main():
with open("team_assignments.json", "r") as f:
teams = json.load(f)
all_users = []
for team in teams:
all_users.extend(team["leaders"])
all_users.extend(team["participants"])
unique_users = list(dict.fromkeys(all_users))
print(f"Assigning Cohort role to {len(unique_users)} users...")
print(f"Role ID: {COHORT_ROLE_ID}")
print("-" * 50)
success_count = 0
fail_count = 0
for i, user_id in enumerate(unique_users, 1):
print(f"[{i}/{len(unique_users)}] Assigning to {user_id}...", end=" ")
if assign_role_with_retry(user_id, COHORT_ROLE_ID):
print("")
success_count += 1
else:
print("✗ FAILED")
fail_count += 1
# Small delay between requests to be nice to the API
time.sleep(0.1)
print("-" * 50)
print(f"Complete! Success: {success_count}, Failed: {fail_count}")
if __name__ == "__main__":
main()