import os import io import sys import asyncio import discord import aiohttp import pandas as pd import gradio as gr from datetime import datetime, timedelta from discord.ext import commands from apscheduler.schedulers.asyncio import AsyncIOScheduler # Environment variable for Discord token DISCORD_TOKEN = os.environ.get("DISCORD_TOKEN", None) # Create Discord bot with all intents intents = discord.Intents.all() bot = commands.Bot(command_prefix='!', intents=intents) # Setup an async scheduler for periodic tasks like a bot restart scheduler = AsyncIOScheduler() def restart_bot(): print("Restarting bot...") os.execv(sys.executable, ['python'] + sys.argv) @scheduler.scheduled_job('interval', minutes=60) def periodic_restart(): print("Scheduled restart triggered...") restart_bot() async def process_row(row, guild, role): """ Process a single CSV row to verify a member and add the role if needed. """ hf_user_name = row['hf_user_name'] if pd.notna(hf_user_name) and hf_user_name.lower() != 'n/a': discord_id = row['discord_user_id'].strip('L') try: member = guild.get_member(int(discord_id)) except Exception as e: print(f"Error converting Discord ID {discord_id}: {e}") return if not member: return if role not in member.roles: try: await member.add_roles(role) print(f"Role added to member: {member}") lunar = bot.get_user(811235357663297546) if lunar: await lunar.send(f"Verified role given to {member}!") await member.send( f"Verification successful! [{member} <---> {row['discord_user_name']}]" ) except Exception as e: print(f"Error processing member {member}: {e}") async def give_verified_roles(): """ Periodically fetch CSV data from Google Sheets and verify roles for members. """ while True: try: # Fetch the CSV from Google Sheets async with aiohttp.ClientSession() as session: try: async with session.get( "https://docs.google.com/spreadsheets/d/1C8aLqgCqLYcMiIFf-P_Aosaa03C_WLIB_UyqvjSdWg8/export?format=csv&gid=0", timeout=10 ) as response: if response.status != 200: print(f"Failed to fetch CSV: HTTP {response.status}") await asyncio.sleep(30) continue csv_data = await response.text() global_df = pd.read_csv(io.StringIO(csv_data)) except asyncio.TimeoutError: print("CSV fetch timed out.") await asyncio.sleep(30) continue except Exception as e: print(f"Error fetching CSV: {e}") await asyncio.sleep(30) continue # Get the guild and role objects guild = bot.get_guild(879548962464493619) if not guild: print("Guild not found.") await asyncio.sleep(30) continue role = guild.get_role(900063512829755413) if not role: print("Role not found.") await asyncio.sleep(30) continue await guild.chunk() # Ensure all guild members are cached # Process all rows concurrently tasks = [process_row(row, guild, role) for _, row in global_df.iterrows()] await asyncio.gather(*tasks) except Exception as e: print(f"Error in give_verified_roles loop: {e}") # Adjust the sleep interval based on how often you expect updates await asyncio.sleep(30) @bot.event async def on_ready(): print(f"We have logged in as {bot.user}") scheduler.start() # Start the background role verification loop bot.loop.create_task(give_verified_roles()) # A simple Gradio interface function def greet(name): return "Hello " + name + "!" # Create the Gradio interface demo = gr.Interface(fn=greet, inputs="text", outputs="text") async def main(): # Launch Gradio in non-blocking mode so it doesn't interfere with the bot's event loop demo.launch(share=False, block=False) # Start the Discord bot (this will run until the bot is stopped) await bot.start(DISCORD_TOKEN) if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: print("Shutting down...")