|
1 | 1 | import asyncio
|
2 | 2 | import time
|
3 | 3 | from contextlib import asynccontextmanager
|
4 |
| -from fastapi import FastAPI, HTTPException |
5 | 4 | import httpx
|
6 | 5 | from typing import Dict
|
7 | 6 | import uvicorn
|
| 7 | +from fastapi import FastAPI, HTTPException |
| 8 | +from fastapi.responses import HTMLResponse |
8 | 9 |
|
9 | 10 | app = FastAPI()
|
10 | 11 | leetcode_url = "https://leetcode.com/graphql"
|
@@ -327,6 +328,132 @@ async def get_daily_challenge():
|
327 | 328 | except Exception as e:
|
328 | 329 | raise HTTPException(status_code=500, detail=str(e))
|
329 | 330 |
|
| 331 | +@app.get("/", response_class=HTMLResponse, include_in_schema=False) |
| 332 | +async def home(): |
| 333 | + return """ |
| 334 | + <!DOCTYPE html> |
| 335 | + <html lang="en"> |
| 336 | + <head> |
| 337 | + <meta charset="UTF-8"> |
| 338 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 339 | + <title>LeetCode API</title> |
| 340 | + <script src="https://cdn.tailwindcss.com"></script> |
| 341 | + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> |
| 342 | + <style> |
| 343 | + /* Dark mode styles */ |
| 344 | + body.dark-mode { |
| 345 | + background-color: #1a202c !important; |
| 346 | + color: #e2e8f0; |
| 347 | + } |
| 348 | + |
| 349 | + body.dark-mode .bg-white { |
| 350 | + background-color: #2d3748 !important; |
| 351 | + } |
| 352 | +
|
| 353 | + body.dark-mode .text-gray-800 { |
| 354 | + color: #e2e8f0 !important; |
| 355 | + } |
| 356 | +
|
| 357 | + body.dark-mode .text-gray-600 { |
| 358 | + color: #cbd5e0 !important; |
| 359 | + } |
| 360 | +
|
| 361 | + body.dark-mode .text-gray-500 { |
| 362 | + color: #a0aec0 !important; |
| 363 | + } |
| 364 | +
|
| 365 | + body.dark-mode .bg-blue-500 { |
| 366 | + background-color: #2563eb !important; |
| 367 | + } |
| 368 | +
|
| 369 | + body.dark-mode .bg-green-500 { |
| 370 | + background-color: #059669 !important; |
| 371 | + } |
| 372 | +
|
| 373 | + body.dark-mode .hover\:bg-blue-600:hover { |
| 374 | + background-color: #1d4ed8 !important; |
| 375 | + } |
| 376 | +
|
| 377 | + body.dark-mode .hover\:bg-green-600:hover { |
| 378 | + background-color: #047857 !important; |
| 379 | + } |
| 380 | + </style> |
| 381 | + </head> |
| 382 | + <body class="bg-gray-100 min-h-screen flex items-center justify-center"> |
| 383 | + <div class="max-w-2xl mx-4 text-center"> |
| 384 | + <div class="bg-white rounded-lg shadow-lg p-8 space-y-6"> |
| 385 | + <div class="flex justify-end"> |
| 386 | + <button id="theme-toggle" class="text-gray-500 hover:text-gray-700 dark:text-gray-300 dark:hover:text-gray-100 focus:outline-none"> |
| 387 | + <i id="theme-icon" class="fas fa-moon"></i> |
| 388 | + </button> |
| 389 | + </div> |
| 390 | + <h1 class="text-4xl font-bold text-gray-800 mb-4"> |
| 391 | + LeetCode API Gateway |
| 392 | + <i class="fas fa-rocket text-blue-500 ml-2"></i> |
| 393 | + </h1> |
| 394 | + |
| 395 | + <p class="text-gray-600 text-lg"> |
| 396 | + Explore LeetCode data through our API endpoints. Get problem details, |
| 397 | + user statistics, submissions history, and more! |
| 398 | + </p> |
| 399 | +
|
| 400 | + <div class="flex flex-col sm:flex-row justify-center gap-4"> |
| 401 | + <a href="https://leetcode-api-pied.vercel.app/docs" |
| 402 | + target="_blank" |
| 403 | + class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-3 rounded-lg |
| 404 | + transition-all duration-300 transform hover:scale-105 |
| 405 | + flex items-center justify-center gap-2"> |
| 406 | + <i class="fas fa-book-open"></i> |
| 407 | + API Documentation |
| 408 | + </a> |
| 409 | + |
| 410 | + <a href="https://docs.google.com/spreadsheets/d/1sRWp95wqo3a7lLBbtNd_3KkTyGjx_9sctTOL5JOb6pA/edit?usp=sharing" |
| 411 | + target="_blank" |
| 412 | + class="bg-green-500 hover:bg-green-600 text-white px-6 py-3 rounded-lg |
| 413 | + transition-all duration-300 transform hover:scale-105 |
| 414 | + flex items-center justify-center gap-2"> |
| 415 | + <i class="fas fa-table"></i> |
| 416 | + Google Sheet (Updated Daily) |
| 417 | + </a> |
| 418 | + </div> |
| 419 | +
|
| 420 | + <p class="text-gray-500 text-sm mt-8 flex items-center justify-center gap-1"> |
| 421 | + Made with ❤️ by |
| 422 | + <a href="https://noworneverev.github.io/" target="_blank" |
| 423 | + class="text-blue-500 font-semibold hover:text-blue-600 transition duration-300"> |
| 424 | + Yan-Ying Liao |
| 425 | + </a> |
| 426 | + </p> |
| 427 | + </div> |
| 428 | + </div> |
| 429 | +
|
| 430 | + <script> |
| 431 | + const themeToggleBtn = document.getElementById('theme-toggle'); |
| 432 | + const themeIcon = document.getElementById('theme-icon'); |
| 433 | + const body = document.body; |
| 434 | +
|
| 435 | + // Check local storage for theme preference |
| 436 | + const currentTheme = localStorage.getItem('theme'); |
| 437 | + if (currentTheme === 'dark') { |
| 438 | + body.classList.add('dark-mode'); |
| 439 | + themeIcon.classList.replace('fa-moon', 'fa-sun'); |
| 440 | + } |
| 441 | +
|
| 442 | + themeToggleBtn.addEventListener('click', () => { |
| 443 | + body.classList.toggle('dark-mode'); |
| 444 | + if (body.classList.contains('dark-mode')) { |
| 445 | + themeIcon.classList.replace('fa-moon', 'fa-sun'); |
| 446 | + localStorage.setItem('theme', 'dark'); |
| 447 | + } else { |
| 448 | + themeIcon.classList.replace('fa-sun', 'fa-moon'); |
| 449 | + localStorage.setItem('theme', 'light'); |
| 450 | + } |
| 451 | + }); |
| 452 | + </script> |
| 453 | + </body> |
| 454 | + </html> |
| 455 | + """ |
| 456 | + |
330 | 457 |
|
331 | 458 | if __name__ == "__main__":
|
332 | 459 | uvicorn.run(app, host="0.0.0.0", port=8000)
|
0 commit comments