import gradio as gr import json from datetime import datetime from datasets import Dataset, load_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__) # Authenticate with Hugging Face HF_TOKEN = os.environ.get("HF_TOKEN") if HF_TOKEN: login(token=HF_TOKEN) logger.info("βœ… Authenticated with Hugging Face") else: logger.warning("⚠️ HF_TOKEN not found - running without authentication") # Replace with your actual dataset name for Winter 2025 DATASET_NAME = "ysharma/gradio-hackathon-registrations-winter-2025" COUNTER = """ Hackathon Countdown

MCP's 1st Birthday Party Has Begun. Registrations are open throughout the Hackathon!

00
Days
00
Hours
00
Minutes
00
Seconds
""" 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 with updated fields new_row = { "timestamp": registration_data["timestamp"], "full_name": registration_data["personal_info"]["full_name"], "email": registration_data["personal_info"]["email"], "hf_username": registration_data["personal_info"]["hf_username"], "gradio_usage": registration_data["personal_info"]["gradio_usage"], "track_interest": str(registration_data["participation"]["track_interest"]), "previous_participation": registration_data["participation"]["previous_participation"], "experience_level": registration_data["participation"]["experience_level"], "how_heard": registration_data["participation"]["how_heard"], "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 verify_registration(email, hf_username): """ Verify if a user is registered by checking both email and HF username Returns registration details if both match """ try: # Validate inputs if not email or not email.strip(): return "❌ Please enter your email address" if not hf_username or not hf_username.strip(): return "❌ Please enter your Hugging Face username" logger.info(f"Verification attempt for email: {email}") # Load dataset try: dataset = load_dataset(DATASET_NAME, split="train") df = dataset.to_pandas() logger.info(f"Loaded dataset with {len(df)} registrations") except Exception as load_error: logger.error(f"Failed to load dataset: {load_error}") return "❌ Unable to verify registration at this time. Please try again later." # Search for exact match (both email AND username must match) email_lower = email.strip().lower() username_lower = hf_username.strip().lower() match = df[ (df['email'].str.lower() == email_lower) & (df['hf_username'].str.lower() == username_lower) ] if len(match) == 0: # Check if email exists with different username email_exists = df[df['email'].str.lower() == email_lower] username_exists = df[df['hf_username'].str.lower() == username_lower] if len(email_exists) > 0 and len(username_exists) == 0: return "❌ Email found but Hugging Face username doesn't match. Please check your username." elif len(username_exists) > 0 and len(email_exists) == 0: return "❌ Hugging Face username found but email doesn't match. Please check your email." else: return "❌ No registration found with this email and Hugging Face username combination." # Registration found - format the details registration = match.iloc[0] # Parse timestamp try: timestamp = pd.to_datetime(registration['timestamp']) reg_date = timestamp.strftime("%B %d, %Y at %I:%M %p UTC") except: reg_date = registration['timestamp'] # Format track interests track_interest = registration['track_interest'] if isinstance(track_interest, str): # Clean up the string representation of list track_interest = track_interest.strip("[]'\"").replace("'", "") result = f""" ## βœ… Registration Confirmed! **Participant Details:** - **Full Name:** {registration['full_name']} - **Email:** {registration['email']} - **Hugging Face Username:** {registration['hf_username']} - **Registered On:** {reg_date} **Hackathon Participation:** - **Track Interest:** {track_interest} - **Gradio Usage:** {registration['gradio_usage']} - **Previous Participation:** {registration['previous_participation']} - **Experience Level:** {registration['experience_level']} - **How You Heard:** {registration['how_heard']} **Project Idea:** {registration['project_description'] if registration['project_description'] else '_No project description provided_'} --- **Next Steps:** - πŸ”‘ API and Compute credits will be distributed before or during the hackathon - πŸ’¬ Join our Discord community channel `mcp-1st-birthday-officialπŸ†`: https://discord.gg/92sEPT2Zhv - πŸ“§ Watch your email for important updates - πŸš€ Start planning your project! """ logger.info(f"βœ… Verification successful for {email}") return result except Exception as e: logger.error(f"Error during verification: {e}") import traceback traceback.print_exc() return f"❌ An error occurred during verification: {str(e)}" def submit_registration(full_name, email, hf_username, gradio_usage, track_interest, previous_participation, experience_level, how_heard, acknowledgment, 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 gradio_usage: return "❌ Error: Please select how you're currently using Gradio" if not track_interest: return "❌ Error: Please select at least one track of interest" if not previous_participation: return "❌ Error: Please select your hackathon experience" if not experience_level: return "❌ Error: Please select your experience level" if not how_heard: return "❌ Error: Please select how you heard about this hackathon" if not acknowledgment: return "❌ Error: Please confirm your acknowledgment to participate" # 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(), "hf_username": hf_username.strip(), "gradio_usage": gradio_usage, }, "participation": { "track_interest": track_interest, "previous_participation": previous_participation, "experience_level": experience_level, "how_heard": how_heard, }, "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 information about API credits as we finalize sponsor partnerships.
πŸ”‘ API and Compute credits will be distributed before or during the Hackathon starting date.
πŸ’¬ Be sure to **join the Huggingface organization** for regular updates on the hackathon and **to submit your entries**. Join our Discord community channel `mcp-1st-birthday-officialπŸ†` for updates and support during the event: https://discord.gg/92sEPT2Zhv **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 - Winter 2025") 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") # Custom CSS for MCP theme custom_css = """ .gradio-container { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; } .header-gradient { color: #000000; } /* MCP-themed Submit Button Styling */ #gradient-submit-btn { background: #C8DDD7 !important; border: 2px solid #000000 !important; color: #000000 !important; font-weight: 600 !important; font-size: 18px !important; padding: 16px 32px !important; border-radius: 12px !important; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important; transition: all 0.3s ease !important; text-transform: none !important; } #gradient-submit-btn:hover { transform: translateY(-2px) !important; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25) !important; background: #B8CEC7 !important; } #gradient-submit-btn:active { transform: translateY(0px) !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important; } /* Disabled state for the button */ #gradient-submit-btn:disabled { opacity: 0.6 !important; cursor: not-allowed !important; transform: none !important; } /* Verify button styling - Inverted MCP theme */ #verify-btn { background: #000000 !important; border: 2px solid #C8DDD7 !important; color: #C8DDD7 !important; font-weight: 600 !important; font-size: 16px !important; padding: 12px 24px !important; border-radius: 8px !important; box-shadow: 0 3px 10px rgba(200, 221, 215, 0.3) !important; transition: all 0.3s ease !important; } #verify-btn:hover { transform: translateY(-2px) !important; box-shadow: 0 5px 15px rgba(200, 221, 215, 0.5) !important; background: #1a1a1a !important; border-color: #D8EDE7 !important; } """ # Create the Gradio interface with gr.Blocks(title="Gradio Agents & MCP Hackathon - Winter 2025", css=custom_css, theme="ocean") as demo: # Header gr.Markdown(""" # MCP's 1st Birthday - Hosted by Anthropic and Gradio **Join our [Discord Community](https://discord.gg/92sEPT2Zhv) channel `mcp-1st-birthday-officialπŸ†` for active support during the hackathon.** **NOTE: If the registration app says you are registered, then that information is correct and you don't need to send us anything else. NO CONFIRMATION EMAILS ARE SENT FROM OUR SIDE.** **πŸ“… Event Dates:** November 14-30, 2025 (17 days, 3 weekends) | **πŸ† Prizes: $21,000 in cash prizes** | **πŸ’» Location:** Online & Global **🎁 FREE API & Compute Credits** (Details available on our landing page - [MCP 1st Birthday](https://huggingface.co/MCP-1st-Birthday)):
API credits from major AI providers | Access to latest and greatest LLMs | Compute resources for building your projects **The premier Agents & MCP event is back!** Join the community that launched the MCP developer movement in June with 600+ world-class apps. Participate and stand a chance to learn the latest AI technologies and also WIN BIG! """) gr.HTML(COUNTER) gr.Markdown("---") # Create tabs with gr.Tabs(): # Registration Tab with gr.Tab("πŸ“ Register"): with gr.Row(): 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 ) hf_username = gr.Textbox( label="Hugging Face Username *", placeholder="Required for organization access and submissions", max_lines=1 ) gradio_usage = gr.Radio( label="How are you currently using Gradio? *", choices=[ "Professional work - My company uses Gradio", "Personal projects - Building side projects", "Academic/Research - University or research work", "Learning - New to Gradio, want to learn", "Not using yet - Interested to start" ], info="Helps us understand our community better" ) with gr.Column(): # Hackathon Participation Section gr.Markdown("## 2. Hackathon Participation") track_interest = gr.CheckboxGroup( label="Which track interests you most? *", choices=[ "Track 1: Building MCP", "Track 2: MCP in Action (Agents)", ] ) previous_participation = gr.Radio( label="Hackathon experience *", choices=[ "I participated in June 2025 Agents & MCP Hackathon", "I've done other AI hackathons before", "This is my first AI hackathon" ] ) experience_level = gr.Radio( label="Your experience with AI/Agents development *", choices=[ "Beginner - New to AI development", "Intermediate - Some AI projects", "Advanced - Regular AI developer", "Expert - Professional AI engineer" ] ) how_heard = gr.Dropdown( label="How did you hear about this hackathon? *", choices=[ "Hugging Face email/newsletter", "Twitter/X", "LinkedIn", "Discord", "From a colleague/friend", "YouTube", "Reddit", "Sponsor announcement", "I participated in June 2025", "Other" ] ) with gr.Row(): with gr.Column(): # Additional Information Section gr.Markdown("## 3. 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 ) with gr.Column(): # Acknowledgment Section gr.Markdown("## 4. Acknowledgment") acknowledgment = gr.Checkbox( label="Acknowledgment *", info="""I commit to actively participate and submit a project by November 30, 2025. I understand that API/compute 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.""", ) # Submit button submit_btn = gr.Button("πŸš€ Register for Hackathon", variant="primary", size="lg", elem_id="gradient-submit-btn") # 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 with updated inputs submit_btn.click( fn=lambda *args: (gr.Button("⏳ Processing Registration...", interactive=False, variant="secondary"), ""), inputs=[ full_name, email, hf_username, gradio_usage, track_interest, previous_participation, experience_level, how_heard, acknowledgment, project_description, ], outputs=[submit_btn, output], queue=False ).then( fn=handle_registration_with_state, inputs=[ full_name, email, hf_username, gradio_usage, track_interest, previous_participation, experience_level, how_heard, acknowledgment, project_description, ], outputs=[output, submit_btn], queue=True ) # Verification Tab with gr.Tab("πŸ” Verify Registration"): gr.Markdown(""" ## Check Your Registration Status Enter your email address and Hugging Face username to verify your registration and view your details. **Note:** Both email and username must match exactly for security purposes. """) with gr.Row(): with gr.Column(): verify_email = gr.Textbox( label="Email Address", placeholder="Enter your registered email", max_lines=1 ) verify_hf_username = gr.Textbox( label="Hugging Face Username", placeholder="Enter your registered HF username", max_lines=1 ) verify_btn = gr.Button("πŸ” Check Registration Status", variant="primary", size="lg", elem_id="verify-btn") with gr.Column(): gr.Markdown(""" ### Need Help? - Make sure you enter the **exact** email and username you used during registration - Both fields are **case-insensitive** but must match your registration - If you can't find your registration, try registering again or contact support **Support:** - Discord: https://discord.gg/92sEPT2Zhv - Email: gradio-team@huggingface.co """) verify_output = gr.Markdown() # Verification click event verify_btn.click( fn=verify_registration, inputs=[verify_email, verify_hf_username], outputs=verify_output ) # Footer gr.Markdown(""" **Questions?** Join Huggingface [Discord](https://discord.gg/92sEPT2Zhv) or email: gradio-team@huggingface.co """) if __name__ == "__main__": demo.launch(allowed_paths=["."])