File size: 8,800 Bytes
705031b 1b86d8a d919708 5243061 1b86d8a f841fdd 1b86d8a 379310a 1b86d8a d8b507b 7250ede 705031b 7250ede 705031b 7250ede 705031b 8f6aeec 705031b 1b86d8a f5c6ef3 1b86d8a 7fa30a6 1b86d8a 2ee9112 1b86d8a bb3c951 1b86d8a 7250ede 8f6aeec 1b86d8a 486f759 1b86d8a 8f6aeec 1b86d8a 8f6aeec 7250ede 5243061 f841fdd 5243061 f841fdd 2404de6 5243061 bb3c951 d919708 1b86d8a 6346369 bb3c951 5243061 bb3c951 f841fdd 1b86d8a bb3c951 1b86d8a 5243061 1b86d8a 5243061 bb3c951 705031b a374e98 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
import os
import logging
from fastapi import FastAPI, Request, Depends, HTTPException, status, Query
from fastapi.responses import HTMLResponse, RedirectResponse, PlainTextResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.sessions import SessionMiddleware
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.middleware.cors import CORSMiddleware
from api.endpoints import router as api_router
from api.auth import fastapi_users, auth_backend, current_active_user, google_oauth_client, github_oauth_client
from api.database import get_db, engine, Base
from api.models import User
from motor.motor_asyncio import AsyncIOMotorClient
from pydantic import BaseModel
from typing import List
import uvicorn
import markdown2
# إعداد التسجيل
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# تحقق من الملفات في /app/
logger.info("Files in /app/: %s", os.listdir("/app"))
# إعداد العميل لـ Hugging Face Inference API
HF_TOKEN = os.getenv("HF_TOKEN")
if not HF_TOKEN:
logger.error("HF_TOKEN is not set in environment variables.")
raise ValueError("HF_TOKEN is required for Inference API.")
# إعداد MongoDB
MONGO_URI = os.getenv("MONGODB_URI")
if not MONGO_URI:
logger.error("MONGODB_URI is not set in environment variables.")
raise ValueError("MONGODB_URI is required for MongoDB.")
client = AsyncIOMotorClient(MONGO_URI)
db = client["hager"]
# إعداد Jinja2 مع دعم Markdown
templates = Jinja2Templates(directory="templates")
templates.env.filters['markdown'] = lambda text: markdown2.markdown(text)
# موديل للمقالات
class BlogPost(BaseModel):
id: str
title: str
content: str
author: str
date: str
created_at: str
# إعدادات الـ queue
QUEUE_SIZE = int(os.getenv("QUEUE_SIZE", 80))
CONCURRENCY_LIMIT = int(os.getenv("CONCURRENCY_LIMIT", 20))
# إعداد FastAPI
app = FastAPI(title="MGZon Chatbot API")
# إضافة SessionMiddleware
app.add_middleware(SessionMiddleware, secret_key=os.getenv("JWT_SECRET"))
# إنشاء الجداول تلقائيًا
Base.metadata.create_all(bind=engine)
# ربط الملفات الثابتة
app.mount("/static", StaticFiles(directory="static"), name="static")
# إضافة CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://mgzon-mgzon-app.hf.space"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# إضافة auth routers
app.include_router(
fastapi_users.get_auth_router(auth_backend),
prefix="/auth/jwt",
tags=["auth"],
)
app.include_router(
fastapi_users.get_register_router(),
prefix="/auth",
tags=["auth"],
)
app.include_router(
fastapi_users.get_users_router(),
prefix="/users",
tags=["users"],
)
app.include_router(
fastapi_users.get_oauth_router(google_oauth_client, auth_backend, os.getenv("JWT_SECRET"), redirect_url="https://mgzon-mgzon-app.hf.space/auth/google/callback"),
prefix="/auth/google",
tags=["auth"],
)
app.include_router(
fastapi_users.get_oauth_router(github_oauth_client, auth_backend, os.getenv("JWT_SECRET"), redirect_url="https://mgzon-mgzon-app.hf.space/auth/github/callback"),
prefix="/auth/github",
tags=["auth"],
)
# Middleware لمعالجة 404
class NotFoundMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
try:
response = await call_next(request)
if response.status_code == 404:
logger.warning(f"404 Not Found: {request.url}")
return templates.TemplateResponse("404.html", {"request": request}, status_code=404)
return response
except Exception as e:
logger.exception(f"Error processing request {request.url}: {e}")
return templates.TemplateResponse("500.html", {"request": request, "error": str(e)}, status_code=500)
app.add_middleware(NotFoundMiddleware)
# Root endpoint
@app.get("/", response_class=HTMLResponse)
async def root(request: Request, user: User = Depends(fastapi_users.current_user(optional=True))):
return templates.TemplateResponse("index.html", {"request": request, "user": user})
# Chat endpoint
@app.get("/chat", response_class=HTMLResponse)
async def chat(request: Request, user: User = Depends(fastapi_users.current_user(optional=True))):
return templates.TemplateResponse("chat.html", {"request": request, "user": user})
# About endpoint
@app.get("/about", response_class=HTMLResponse)
async def about(request: Request, user: User = Depends(fastapi_users.current_user(optional=True))):
return templates.TemplateResponse("about.html", {"request": request, "user": user})
# Blog endpoint (قائمة المقالات)
@app.get("/blog", response_class=HTMLResponse)
async def blog(request: Request, skip: int = Query(0, ge=0), limit: int = Query(10, ge=1, le=100)):
posts = await db.blog_posts.find().skip(skip).limit(limit).to_list(limit)
return templates.TemplateResponse("blog.html", {"request": request, "posts": posts})
# Blog post endpoint (عرض مقالة كاملة)
@app.get("/blog/{post_id}", response_class=HTMLResponse)
async def blog_post(request: Request, post_id: str):
post = await db.blog_posts.find_one({"id": post_id})
if not post:
raise HTTPException(status_code=404, detail="Post not found")
return templates.TemplateResponse("blog_post.html", {"request": request, "post": post})
# Docs endpoint
@app.get("/docs", response_class=HTMLResponse)
async def docs(request: Request):
return templates.TemplateResponse("docs.html", {"request": request})
# Swagger UI endpoint
@app.get("/swagger", response_class=HTMLResponse)
async def swagger_ui():
return get_swagger_ui_html(openapi_url="/openapi.json", title="MGZon API Documentation")
# Sitemap endpoint (ديناميكي)
@app.get("/sitemap.xml", response_class=PlainTextResponse)
async def sitemap():
posts = await db.blog_posts.find().to_list(100)
xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'
xml += ' <url>\n'
xml += ' <loc>https://mgzon-mgzon-app.hf.space/</loc>\n'
xml += ' <lastmod>2025-09-01</lastmod>\n'
xml += ' <changefreq>daily</changefreq>\n'
xml += ' <priority>1.0</priority>\n'
xml += ' </url>\n'
xml += ' <url>\n'
xml += ' <loc>https://mgzon-mgzon-app.hf.space/chat</loc>\n'
xml += ' <lastmod>2025-09-01</lastmod>\n'
xml += ' <changefreq>daily</changefreq>\n'
xml += ' <priority>0.8</priority>\n'
xml += ' </url>\n'
xml += ' <url>\n'
xml += ' <loc>https://mgzon-mgzon-app.hf.space/about</loc>\n'
xml += ' <lastmod>2025-09-01</lastmod>\n'
xml += ' <changefreq>weekly</changefreq>\n'
xml += ' <priority>0.7</priority>\n'
xml += ' </url>\n'
xml += ' <url>\n'
xml += ' <loc>https://mgzon-mgzon-app.hf.space/login</loc>\n'
xml += ' <lastmod>2025-09-01</lastmod>\n'
xml += ' <changefreq>weekly</changefreq>\n'
xml += ' <priority>0.8</priority>\n'
xml += ' </url>\n'
xml += ' <url>\n'
xml += ' <loc>https://mgzon-mgzon-app.hf.space/register</loc>\n'
xml += ' <lastmod>2025-09-01</lastmod>\n'
xml += ' <changefreq>weekly</changefreq>\n'
xml += ' <priority>0.8</priority>\n'
xml += ' </url>\n'
xml += ' <url>\n'
xml += ' <loc>https://mgzon-mgzon-app.hf.space/docs</loc>\n'
xml += ' <lastmod>2025-09-01</lastmod>\n'
xml += ' <changefreq>weekly</changefreq>\n'
xml += ' <priority>0.9</priority>\n'
xml += ' </url>\n'
xml += ' <url>\n'
xml += ' <loc>https://mgzon-mgzon-app.hf.space/blog</loc>\n'
xml += ' <lastmod>2025-09-01</lastmod>\n'
xml += ' <changefreq>daily</changefreq>\n'
xml += ' <priority>0.9</priority>\n'
xml += ' </url>\n'
for post in posts:
xml += ' <url>\n'
xml += f' <loc>https://mgzon-mgzon-app.hf.space/blog/{post["id"]}</loc>\n'
xml += f' <lastmod>{post["date"]}</lastmod>\n'
xml += ' <changefreq>weekly</changefreq>\n'
xml += ' <priority>0.9</priority>\n'
xml += ' </url>\n'
xml += '</urlset>'
return xml
# Redirect لـ /gradio
@app.get("/gradio", response_class=RedirectResponse)
async def launch_chatbot():
return RedirectResponse(url="/chat", status_code=302)
# ربط API endpoints
app.include_router(api_router)
# تشغيل الخادم
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=int(os.getenv("PORT", 7860)))
|