import gradio as gr
import json
from datetime import datetime
from datasets import Dataset
from huggingface_hub import login, HfApi
import pandas as pd
import os
import time
import tempfile
import logging
# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Replace with your actual dataset name
DATASET_NAME = "ysharma/gradio-hackathon-registrations-2025"
COUNTER = """
Hackathon Countdown
Registrations and Submissions are available until June 10 UTC EOD
"""
def safe_add_to_dataset(registration_data, max_retries=5, retry_delay=3):
"""
Safely add new registration data with bulletproof error handling
NEVER creates new datasets - only adds to existing ones
"""
try:
logger.info("Starting new registration process")
# Create new row
new_row = {
"timestamp": registration_data["timestamp"],
"full_name": registration_data["personal_info"]["full_name"],
"email": registration_data["personal_info"]["email"],
"github_username": registration_data["personal_info"]["github_username"] or "",
"hf_username": registration_data["personal_info"]["hf_username"],
"track_interest": str(registration_data["participation"]["track_interest"]),
"participation_type": registration_data["participation"]["participation_type"],
"teammates": registration_data["teammates"] or "",
"project_description": registration_data["additional"]["project_description"] or ""
}
logger.info("Created new row data")
# Multi-attempt loading with different strategies
existing_df = None
load_successful = False
for attempt in range(max_retries):
logger.info(f"Loading attempt {attempt + 1}/{max_retries}")
try:
# Strategy 1: Direct parquet file access (most reliable)
api = HfApi()
files = api.list_repo_files(DATASET_NAME, repo_type="dataset")
parquet_files = [f for f in files if f.endswith('.parquet') and 'train' in f]
if parquet_files:
logger.info(f"Found parquet file: {parquet_files[0]}")
# Download to temporary location
with tempfile.TemporaryDirectory() as temp_dir:
parquet_file = api.hf_hub_download(
repo_id=DATASET_NAME,
filename=parquet_files[0],
repo_type="dataset",
cache_dir=temp_dir,
force_download=True
)
existing_df = pd.read_parquet(parquet_file)
logger.info(f"Successfully loaded {len(existing_df)} existing rows")
load_successful = True
break
else:
logger.warning("No parquet files found")
except Exception as load_error:
logger.warning(f"Attempt {attempt + 1} failed: {str(load_error)[:100]}")
if attempt < max_retries - 1:
logger.info(f"Waiting {retry_delay} seconds before retry...")
time.sleep(retry_delay)
continue
# CRITICAL SAFETY CHECK: Never proceed without existing data
if not load_successful or existing_df is None:
error_msg = "🚨 CRITICAL SAFETY ERROR: Could not load existing dataset after multiple attempts."
logger.error(error_msg)
logger.error("🚨 REFUSING to proceed to prevent data loss!")
logger.error("🚨 Please check dataset manually or contact administrators.")
return False, (
"❌ Registration temporarily unavailable due to technical issues. "
"Please try again in a few minutes. If the problem persists, contact support."
)
# Check for duplicates
duplicate_check = existing_df[
(existing_df['email'].str.lower() == new_row['email'].lower()) |
(existing_df['hf_username'].str.lower() == new_row['hf_username'].lower())
]
if len(duplicate_check) > 0:
logger.warning("Duplicate registration attempt detected")
return False, "❌ Error: This email or Hugging Face username is already registered."
# Add new row safely
combined_df = pd.concat([existing_df, pd.DataFrame([new_row])], ignore_index=True)
logger.info(f"Combined data now has {len(combined_df)} rows (was {len(existing_df)})")
# Create timestamped backup before upload
backup_timestamp = int(time.time())
try:
# Convert to Dataset and upload
logger.info("Converting to HuggingFace Dataset format...")
updated_dataset = Dataset.from_pandas(combined_df)
# Create backup first
backup_name = f"{DATASET_NAME}-auto-backup-{backup_timestamp}"
logger.info(f"Creating backup: {backup_name}")
updated_dataset.push_to_hub(backup_name, private=True)
logger.info("Pushing to main dataset...")
updated_dataset.push_to_hub(DATASET_NAME, private=True)
logger.info("✅ Successfully saved new registration")
logger.info(f"Total rows in dataset: {len(combined_df)}")
# Quick verification
time.sleep(2)
try:
verify_files = api.list_repo_files(DATASET_NAME, repo_type="dataset")
logger.info("✅ Upload verification: Files updated successfully")
except:
logger.warning("⚠️ Could not verify upload (this may be normal)")
return True, "Registration successful!"
except Exception as upload_error:
error_msg = str(upload_error).lower()
if any(indicator in error_msg for indicator in ['rate limit', '429', 'too many requests']):
logger.warning("🚨 Rate limit hit - registration system temporarily busy")
return False, "⏳ Registration temporarily unavailable due to high server load. Please try again in 10-15 minutes."
else:
logger.error(f"Upload failed: {upload_error}")
return False, f"❌ Registration failed during upload: {str(upload_error)}"
except Exception as e:
logger.error(f"❌ Unexpected error in registration: {e}")
import traceback
traceback.print_exc()
return False, f"❌ Registration failed: {str(e)}"
def submit_registration(full_name, email, github_username, hf_username,
track_interest, participation_type, teammates,
commitment, api_credits_ack, project_description):
"""Process the registration form submission with enhanced validation"""
# Enhanced validation
if not full_name or not full_name.strip():
return "❌ Error: Please enter your full name"
if not email or not email.strip():
return "❌ Error: Please enter your email address"
if not hf_username or not hf_username.strip():
return "❌ Error: Please enter your Hugging Face username"
if not track_interest:
return "❌ Error: Please select at least one track of interest"
if not participation_type:
return "❌ Error: Please select your participation type"
if not commitment:
return "❌ Error: Please confirm your commitment to participate"
if not api_credits_ack:
return "❌ Error: Please acknowledge the API credits terms"
# Email format validation
import re
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, email.strip()):
return "❌ Error: Please enter a valid email address"
# Process the registration data
registration_data = {
"timestamp": datetime.now().isoformat(),
"personal_info": {
"full_name": full_name.strip(),
"email": email.strip().lower(), # Normalize email
"github_username": github_username.strip() if github_username else "",
"hf_username": hf_username.strip()
},
"participation": {
"track_interest": track_interest,
"participation_type": participation_type,
},
"teammates": teammates.strip() if teammates else None,
"additional": {
"project_description": project_description.strip() if project_description else None,
}
}
# Save to Hugging Face dataset with bulletproof error handling
success, message = safe_add_to_dataset(registration_data)
if not success:
return f"❌ Registration failed: {message}"
return f"""✅ Registration Successful!
Thank you, {full_name}! Your registration has been received and saved.
📧 You will receive an email prior to the Hackathon start dates containing information about the API credits, provided you meet the required criteria.
🔑 API and Compute credits will be distributed well before the Hackathon starting date and time.
💬 Be sure to join the Huggingface organization for regular updates on the hackathon and to submit your entries. Join our Discord community channel `agents-mcp-hackathon` for updates and support during the event: https://discord.gg/Qe3jMKVczR
See you at the hackathon! 🚀"""
# Health check function
def check_dataset_health():
"""Check if the dataset is accessible and healthy"""
try:
api = HfApi()
files = api.list_repo_files(DATASET_NAME, repo_type="dataset")
parquet_files = [f for f in files if f.endswith('.parquet')]
if parquet_files:
logger.info(f"✅ Dataset health check passed - found {len(parquet_files)} parquet files")
return True
else:
logger.warning("⚠️ Dataset health check: No parquet files found")
return False
except Exception as e:
logger.error(f"❌ Dataset health check failed: {e}")
return False
# Initialize with health check
logger.info("🚀 Starting Gradio Hackathon Registration System")
logger.info(f"📊 Dataset: {DATASET_NAME}")
if check_dataset_health():
logger.info("✅ System ready - dataset is healthy")
else:
logger.warning("⚠️ System starting with dataset health warnings")
# Create the Gradio interface (same as before, but using safe functions)
with gr.Blocks(title="Gradio Agents & MCP Hackathon 2025",) as demo:
# Header
gr.Markdown("""
# 🤖 Gradio Agents & MCP Hackathon 2025 Registration 🚀
**Updates: TOTAL SIGNUPS: 4K+. Signups are available all week till June 8. Emails containing credits are being sent regularly. You won't receive any email on successful registrations.**
**Join our [Discord Community](https://discord.gg/Qe3jMKVczR) channel `agents-mcp-hackathon` for active support during the hackathon.**
**📅 Event Dates:** June 2-10, 2025 | **🏆 Prizes: $16,500 in cash prizes** **💻 Location:** Online & Global |
**🎁 Bonus: FREE Credits** for participants* from our sponsors worth **$1 MILLION++**
- $250 of GPU/CPU Compute credits **TO EVERY PARTICIPANT** in the Hackathon from [Modal Labs](https://modal.com/)
- $25 of API credits **TO EVERY PARTICIPANT** in the Hackathon from [Huggingface](https://huggingface.co/)
- $25 of API credits to each of the first 3300 participants from [Nebius](https://nebius.com/)
- $25 of API credits to each of the first 1000 participants from [Anthropic](https://www.anthropic.com/)
- $25 of API credits to each of the first 1000 participants from [OpenAI](https://openai.com/)
- $15 of API credits to each of the first 1000 participants from [Hyperbolic Labs](https://hyperbolic.xyz/)
- $25 of API credits to each of the first 500 participants from [MistralAI](https://mistral.ai/)
- $25 of API credits to each of the first 250 participants from [Sambanova.AI](https://sambanova.ai/)
*API and GPU/CPU Compute credits are provided to support hackathon participation and will be distributed based on registration verification.
""")
gr.HTML(COUNTER)
gr.Markdown("---")
with gr.Column():
# Personal Information Section
gr.Markdown("## 1. Personal Information")
full_name = gr.Textbox(
label="Full Name *",
placeholder="Your full name as you'd like it on certificates",
max_lines=1
)
email = gr.Textbox(
label="Email Address *",
placeholder="Primary contact email (we'll send important updates here)",
max_lines=1
)
github_username = gr.Textbox(
label="GitHub Username",
placeholder="Your GitHub username (helps us verify your developer status)",
max_lines=1
)
hf_username = gr.Textbox(
label="Hugging Face Username *",
placeholder="Required for organization access and submissions",
max_lines=1
)
# Hackathon Participation Section
gr.Markdown("## 2. Hackathon Participation")
track_interest = gr.CheckboxGroup(
label="Which track interests you most? *",
choices=[
"Track 1: MCP Server Implementation",
"Track 2: Custom Agent Components",
"Track 3: Agentic Demo Showcase",
]
)
participation_type = gr.Radio(
label="Participation Type *",
choices=[
"Individual participant",
"Joining as a team",
]
)
teammates = gr.Textbox(
label="If you have a team, list your teammates' emails separated by commas",
placeholder="List names and emails of your team members (optional)",
lines=3
)
# Commitment & Verification Section
gr.Markdown("## 3. Commitment & Verification")
commitment = gr.Checkbox(
label="Hackathon Commitment *",
info="I commit to actively participate and submit a project by June 8, 2025",
)
api_credits_ack = gr.Checkbox(
label="API Credits Acknowledgment *",
info="I understand that API credits are provided to support hackathon participation and should be used for building my hackathon project. I commit to using these credits responsibly during the event period."
)
# Additional Information Section
gr.Markdown("## 4. Additional Information")
project_description = gr.Textbox(
label="What type of project are you most excited to build?",
placeholder="Brief description of your project idea or what interests you most",
lines=3
)
# Submit button
submit_btn = gr.Button("🚀 Register for Hackathon", variant="primary", size="lg")
# Output
output = gr.Markdown()
# Enhanced submit function
def handle_registration_with_state(*args):
try:
result = submit_registration(*args)
return result, gr.Button("🚀 Register for Hackathon", interactive=True, variant="primary")
except Exception as e:
logger.error(f"Registration handling error: {e}")
return f"❌ An unexpected error occurred: {str(e)}", gr.Button("🚀 Register for Hackathon", interactive=True, variant="primary")
# Click event
submit_btn.click(
fn=lambda *args: (gr.Button("⏳ Processing Registration...", interactive=False, variant="secondary"), ""),
inputs=[
full_name, email, github_username, hf_username,
track_interest, participation_type, teammates,
commitment, api_credits_ack, project_description,
],
outputs=[submit_btn, output],
queue=False
).then(
fn=handle_registration_with_state,
inputs=[
full_name, email, github_username, hf_username,
track_interest, participation_type, teammates,
commitment, api_credits_ack, project_description,
],
outputs=[output, submit_btn],
queue=True
)
if __name__ == "__main__":
demo.launch(allowed_paths=["."])