Commit
·
1b86d8a
1
Parent(s):
7fa30a6
Update endpoints and session support
Browse files- Dockerfile +5 -2
- api/auth.py +42 -0
- api/database.py +27 -0
- api/endpoints.py +137 -14
- api/models.py +30 -7
- data/mgzon_users.db +0 -0
- main.py +164 -344
- requirements.txt +11 -1
- space.yaml +6 -1
- static/css/styles.css +178 -0
- static/favicon.ico +0 -0
- static/google97468ef1f6b6e804.html +1 -0
- static/images/mg.svg +1 -0
- static/images/screenshot.png +0 -0
- static/js/chat.js +389 -0
- static/robots.txt +17 -0
- static/sitemap.xml +51 -0
- templates/500.html +32 -0
- templates/about.html +279 -0
- templates/blog.html +237 -0
- templates/blog_post.html +263 -0
- templates/chat.html +95 -0
- templates/docs.html +275 -310
- templates/index.html +132 -164
- templates/login.html +218 -0
- templates/register.html +214 -0
- utils/generation.py +21 -21
Dockerfile
CHANGED
|
@@ -19,14 +19,17 @@ RUN pip install --upgrade pip
|
|
| 19 |
COPY requirements.txt .
|
| 20 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 21 |
|
|
|
|
|
|
|
|
|
|
| 22 |
# Copy all project files
|
| 23 |
COPY . .
|
| 24 |
|
| 25 |
# Verify files in /app
|
| 26 |
RUN ls -R /app
|
| 27 |
|
| 28 |
-
# Expose port 7860 for
|
| 29 |
EXPOSE 7860
|
| 30 |
|
| 31 |
-
# Run the
|
| 32 |
CMD ["python", "main.py"]
|
|
|
|
| 19 |
COPY requirements.txt .
|
| 20 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 21 |
|
| 22 |
+
# Create /data directory with correct permissions
|
| 23 |
+
RUN mkdir -p /data && chmod -R 755 /data
|
| 24 |
+
|
| 25 |
# Copy all project files
|
| 26 |
COPY . .
|
| 27 |
|
| 28 |
# Verify files in /app
|
| 29 |
RUN ls -R /app
|
| 30 |
|
| 31 |
+
# Expose port 7860 for FastAPI
|
| 32 |
EXPOSE 7860
|
| 33 |
|
| 34 |
+
# Run the FastAPI app
|
| 35 |
CMD ["python", "main.py"]
|
api/auth.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# api/auth.py
|
| 2 |
+
from fastapi_users import FastAPIUsers
|
| 3 |
+
from fastapi_users.authentication import CookieTransport, JWTStrategy, AuthenticationBackend
|
| 4 |
+
from fastapi_users.db import SQLAlchemyUserDatabase
|
| 5 |
+
from httpx_oauth.clients.google import GoogleOAuth2
|
| 6 |
+
from httpx_oauth.clients.github import GitHubOAuth2
|
| 7 |
+
from api.database import SessionLocal
|
| 8 |
+
from api.models import User
|
| 9 |
+
import os
|
| 10 |
+
|
| 11 |
+
# إعداد Cookie Transport
|
| 12 |
+
cookie_transport = CookieTransport(cookie_max_age=3600)
|
| 13 |
+
|
| 14 |
+
# إعداد JWT Strategy
|
| 15 |
+
SECRET = os.getenv("JWT_SECRET", "your_jwt_secret_here") # ضعه في Space Secrets
|
| 16 |
+
|
| 17 |
+
def get_jwt_strategy() -> JWTStrategy:
|
| 18 |
+
return JWTStrategy(secret=SECRET, lifetime_seconds=3600)
|
| 19 |
+
|
| 20 |
+
auth_backend = AuthenticationBackend(
|
| 21 |
+
name="jwt",
|
| 22 |
+
transport=cookie_transport,
|
| 23 |
+
get_strategy=get_jwt_strategy,
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
# إعداد عملاء OAuth
|
| 27 |
+
GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
|
| 28 |
+
GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
|
| 29 |
+
GITHUB_CLIENT_ID = os.getenv("GITHUB_CLIENT_ID")
|
| 30 |
+
GITHUB_CLIENT_SECRET = os.getenv("GITHUB_CLIENT_SECRET")
|
| 31 |
+
|
| 32 |
+
google_oauth_client = GoogleOAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
|
| 33 |
+
github_oauth_client = GitHubOAuth2(GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET)
|
| 34 |
+
|
| 35 |
+
# إعداد FastAPIUsers
|
| 36 |
+
fastapi_users = FastAPIUsers[User, int](
|
| 37 |
+
lambda: SQLAlchemyUserDatabase(User, SessionLocal(), oauth_account_table=OAuthAccount),
|
| 38 |
+
[auth_backend],
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
# Dependency للحصول على المستخدم الحالي
|
| 42 |
+
current_active_user = fastapi_users.current_user(active=True)
|
api/database.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# api/database.py
|
| 2 |
+
import os
|
| 3 |
+
from sqlalchemy import create_engine
|
| 4 |
+
from sqlalchemy.ext.declarative import declarative_base
|
| 5 |
+
from sqlalchemy.orm import sessionmaker
|
| 6 |
+
|
| 7 |
+
# جلب URL قاعدة البيانات من المتغيرات البيئية
|
| 8 |
+
SQLALCHEMY_DATABASE_URL = os.getenv("SQLALCHEMY_DATABASE_URL")
|
| 9 |
+
if not SQLALCHEMY_DATABASE_URL:
|
| 10 |
+
raise ValueError("SQLALCHEMY_DATABASE_URL is not set in environment variables.")
|
| 11 |
+
|
| 12 |
+
# إنشاء المحرك
|
| 13 |
+
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
|
| 14 |
+
|
| 15 |
+
# إعداد الجلسة
|
| 16 |
+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
| 17 |
+
|
| 18 |
+
# قاعدة أساسية للنماذج
|
| 19 |
+
Base = declarative_base()
|
| 20 |
+
|
| 21 |
+
# دالة للحصول على الجلسة
|
| 22 |
+
def get_db():
|
| 23 |
+
db = SessionLocal()
|
| 24 |
+
try:
|
| 25 |
+
yield db
|
| 26 |
+
finally:
|
| 27 |
+
db.close()
|
api/endpoints.py
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
|
|
| 1 |
import os
|
| 2 |
-
|
|
|
|
| 3 |
from fastapi.responses import StreamingResponse
|
| 4 |
-
import io
|
| 5 |
-
from openai import OpenAI
|
| 6 |
from api.models import QueryRequest
|
|
|
|
|
|
|
|
|
|
| 7 |
from utils.generation import request_generation, select_model
|
| 8 |
from utils.web_search import web_search
|
|
|
|
|
|
|
| 9 |
|
| 10 |
router = APIRouter()
|
| 11 |
|
|
@@ -13,13 +18,16 @@ HF_TOKEN = os.getenv("HF_TOKEN")
|
|
| 13 |
BACKUP_HF_TOKEN = os.getenv("BACKUP_HF_TOKEN")
|
| 14 |
API_ENDPOINT = os.getenv("API_ENDPOINT", "https://router.huggingface.co/v1")
|
| 15 |
FALLBACK_API_ENDPOINT = os.getenv("FALLBACK_API_ENDPOINT", "https://api-inference.huggingface.co")
|
| 16 |
-
MODEL_NAME = os.getenv("MODEL_NAME", "openai/gpt-oss-120b:
|
| 17 |
-
SECONDARY_MODEL_NAME = os.getenv("SECONDARY_MODEL_NAME", "mistralai/Mistral-7B-Instruct-v0.2")
|
| 18 |
-
TERTIARY_MODEL_NAME = os.getenv("TERTIARY_MODEL_NAME", "openai/gpt-oss-20b:
|
| 19 |
CLIP_BASE_MODEL = os.getenv("CLIP_BASE_MODEL", "Salesforce/blip-image-captioning-large")
|
| 20 |
CLIP_LARGE_MODEL = os.getenv("CLIP_LARGE_MODEL", "openai/clip-vit-large-patch14")
|
| 21 |
ASR_MODEL = os.getenv("ASR_MODEL", "openai/whisper-large-v3")
|
| 22 |
-
TTS_MODEL = os.getenv("TTS_MODEL", "
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
@router.get("/api/model-info")
|
| 25 |
def model_info():
|
|
@@ -45,7 +53,26 @@ async def performance_stats():
|
|
| 45 |
}
|
| 46 |
|
| 47 |
@router.post("/api/chat")
|
| 48 |
-
async def chat_endpoint(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
model_name, api_endpoint = select_model(req.message, input_type="text")
|
| 50 |
stream = request_generation(
|
| 51 |
api_key=HF_TOKEN,
|
|
@@ -67,7 +94,26 @@ async def chat_endpoint(req: QueryRequest):
|
|
| 67 |
return {"response": response}
|
| 68 |
|
| 69 |
@router.post("/api/audio-transcription")
|
| 70 |
-
async def audio_transcription_endpoint(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
model_name, api_endpoint = select_model("transcribe audio", input_type="audio")
|
| 72 |
audio_data = await file.read()
|
| 73 |
stream = request_generation(
|
|
@@ -86,14 +132,33 @@ async def audio_transcription_endpoint(file: UploadFile = File(...)):
|
|
| 86 |
return {"transcription": response}
|
| 87 |
|
| 88 |
@router.post("/api/text-to-speech")
|
| 89 |
-
async def text_to_speech_endpoint(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
text = req.get("text", "")
|
| 91 |
model_name, api_endpoint = select_model("text to speech", input_type="tts")
|
| 92 |
stream = request_generation(
|
| 93 |
api_key=HF_TOKEN,
|
| 94 |
api_base=api_endpoint,
|
| 95 |
message=text,
|
| 96 |
-
system_prompt="Convert the provided text to speech using
|
| 97 |
model_name=model_name,
|
| 98 |
temperature=0.7,
|
| 99 |
max_new_tokens=128000,
|
|
@@ -104,7 +169,26 @@ async def text_to_speech_endpoint(req: dict):
|
|
| 104 |
return StreamingResponse(io.BytesIO(audio_data), media_type="audio/wav")
|
| 105 |
|
| 106 |
@router.post("/api/code")
|
| 107 |
-
async def code_endpoint(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
framework = req.get("framework")
|
| 109 |
task = req.get("task")
|
| 110 |
code = req.get("code", "")
|
|
@@ -129,7 +213,26 @@ async def code_endpoint(req: dict):
|
|
| 129 |
return {"generated_code": response}
|
| 130 |
|
| 131 |
@router.post("/api/analysis")
|
| 132 |
-
async def analysis_endpoint(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
message = req.get("text", "")
|
| 134 |
output_format = req.get("output_format", "text")
|
| 135 |
model_name, api_endpoint = select_model(message, input_type="text")
|
|
@@ -151,7 +254,27 @@ async def analysis_endpoint(req: dict):
|
|
| 151 |
return {"analysis": response}
|
| 152 |
|
| 153 |
@router.post("/api/image-analysis")
|
| 154 |
-
async def image_analysis_endpoint(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
model_name, api_endpoint = select_model("analyze image", input_type="image")
|
| 156 |
image_data = await file.read()
|
| 157 |
stream = request_generation(
|
|
|
|
| 1 |
+
# api/endpoints.py
|
| 2 |
import os
|
| 3 |
+
import uuid
|
| 4 |
+
from fastapi import APIRouter, Depends, HTTPException, Request, status, UploadFile, File
|
| 5 |
from fastapi.responses import StreamingResponse
|
|
|
|
|
|
|
| 6 |
from api.models import QueryRequest
|
| 7 |
+
from api.auth import current_active_user
|
| 8 |
+
from api.database import get_db
|
| 9 |
+
from sqlalchemy.orm import Session
|
| 10 |
from utils.generation import request_generation, select_model
|
| 11 |
from utils.web_search import web_search
|
| 12 |
+
import io
|
| 13 |
+
from openai import OpenAI
|
| 14 |
|
| 15 |
router = APIRouter()
|
| 16 |
|
|
|
|
| 18 |
BACKUP_HF_TOKEN = os.getenv("BACKUP_HF_TOKEN")
|
| 19 |
API_ENDPOINT = os.getenv("API_ENDPOINT", "https://router.huggingface.co/v1")
|
| 20 |
FALLBACK_API_ENDPOINT = os.getenv("FALLBACK_API_ENDPOINT", "https://api-inference.huggingface.co")
|
| 21 |
+
MODEL_NAME = os.getenv("MODEL_NAME", "openai/gpt-oss-120b:together")
|
| 22 |
+
SECONDARY_MODEL_NAME = os.getenv("SECONDARY_MODEL_NAME", "mistralai/Mistral-7B-Instruct-v0.2:featherless-ai")
|
| 23 |
+
TERTIARY_MODEL_NAME = os.getenv("TERTIARY_MODEL_NAME", "openai/gpt-oss-20b:together")
|
| 24 |
CLIP_BASE_MODEL = os.getenv("CLIP_BASE_MODEL", "Salesforce/blip-image-captioning-large")
|
| 25 |
CLIP_LARGE_MODEL = os.getenv("CLIP_LARGE_MODEL", "openai/clip-vit-large-patch14")
|
| 26 |
ASR_MODEL = os.getenv("ASR_MODEL", "openai/whisper-large-v3")
|
| 27 |
+
TTS_MODEL = os.getenv("TTS_MODEL", "facebook/mms-tts-ara")
|
| 28 |
+
|
| 29 |
+
# تخزين عدد الرسائل لكل جلسة (بديل مؤقت)
|
| 30 |
+
session_message_counts = {}
|
| 31 |
|
| 32 |
@router.get("/api/model-info")
|
| 33 |
def model_info():
|
|
|
|
| 53 |
}
|
| 54 |
|
| 55 |
@router.post("/api/chat")
|
| 56 |
+
async def chat_endpoint(
|
| 57 |
+
request: Request,
|
| 58 |
+
req: QueryRequest,
|
| 59 |
+
user: str = Depends(current_active_user, use_cache=False),
|
| 60 |
+
db: Session = Depends(get_db)
|
| 61 |
+
):
|
| 62 |
+
session_id = request.session.get("session_id")
|
| 63 |
+
if not user and not session_id:
|
| 64 |
+
session_id = str(uuid.uuid4())
|
| 65 |
+
request.session["session_id"] = session_id
|
| 66 |
+
session_message_counts[session_id] = 0
|
| 67 |
+
|
| 68 |
+
if not user:
|
| 69 |
+
session_message_counts[session_id] = session_message_counts.get(session_id, 0) + 1
|
| 70 |
+
if session_message_counts[session_id] > 4:
|
| 71 |
+
raise HTTPException(
|
| 72 |
+
status_code=status.HTTP_403_FORBIDDEN,
|
| 73 |
+
detail="Message limit reached. Please log in to continue."
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
model_name, api_endpoint = select_model(req.message, input_type="text")
|
| 77 |
stream = request_generation(
|
| 78 |
api_key=HF_TOKEN,
|
|
|
|
| 94 |
return {"response": response}
|
| 95 |
|
| 96 |
@router.post("/api/audio-transcription")
|
| 97 |
+
async def audio_transcription_endpoint(
|
| 98 |
+
request: Request,
|
| 99 |
+
file: UploadFile = File(...),
|
| 100 |
+
user: str = Depends(current_active_user, use_cache=False),
|
| 101 |
+
db: Session = Depends(get_db)
|
| 102 |
+
):
|
| 103 |
+
session_id = request.session.get("session_id")
|
| 104 |
+
if not user and not session_id:
|
| 105 |
+
session_id = str(uuid.uuid4())
|
| 106 |
+
request.session["session_id"] = session_id
|
| 107 |
+
session_message_counts[session_id] = 0
|
| 108 |
+
|
| 109 |
+
if not user:
|
| 110 |
+
session_message_counts[session_id] = session_message_counts.get(session_id, 0) + 1
|
| 111 |
+
if session_message_counts[session_id] > 4:
|
| 112 |
+
raise HTTPException(
|
| 113 |
+
status_code=status.HTTP_403_FORBIDDEN,
|
| 114 |
+
detail="Message limit reached. Please log in to continue."
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
model_name, api_endpoint = select_model("transcribe audio", input_type="audio")
|
| 118 |
audio_data = await file.read()
|
| 119 |
stream = request_generation(
|
|
|
|
| 132 |
return {"transcription": response}
|
| 133 |
|
| 134 |
@router.post("/api/text-to-speech")
|
| 135 |
+
async def text_to_speech_endpoint(
|
| 136 |
+
request: Request,
|
| 137 |
+
req: dict,
|
| 138 |
+
user: str = Depends(current_active_user, use_cache=False),
|
| 139 |
+
db: Session = Depends(get_db)
|
| 140 |
+
):
|
| 141 |
+
session_id = request.session.get("session_id")
|
| 142 |
+
if not user and not session_id:
|
| 143 |
+
session_id = str(uuid.uuid4())
|
| 144 |
+
request.session["session_id"] = session_id
|
| 145 |
+
session_message_counts[session_id] = 0
|
| 146 |
+
|
| 147 |
+
if not user:
|
| 148 |
+
session_message_counts[session_id] = session_message_counts.get(session_id, 0) + 1
|
| 149 |
+
if session_message_counts[session_id] > 4:
|
| 150 |
+
raise HTTPException(
|
| 151 |
+
status_code=status.HTTP_403_FORBIDDEN,
|
| 152 |
+
detail="Message limit reached. Please log in to continue."
|
| 153 |
+
)
|
| 154 |
+
|
| 155 |
text = req.get("text", "")
|
| 156 |
model_name, api_endpoint = select_model("text to speech", input_type="tts")
|
| 157 |
stream = request_generation(
|
| 158 |
api_key=HF_TOKEN,
|
| 159 |
api_base=api_endpoint,
|
| 160 |
message=text,
|
| 161 |
+
system_prompt="Convert the provided text to speech using a text-to-speech model.",
|
| 162 |
model_name=model_name,
|
| 163 |
temperature=0.7,
|
| 164 |
max_new_tokens=128000,
|
|
|
|
| 169 |
return StreamingResponse(io.BytesIO(audio_data), media_type="audio/wav")
|
| 170 |
|
| 171 |
@router.post("/api/code")
|
| 172 |
+
async def code_endpoint(
|
| 173 |
+
request: Request,
|
| 174 |
+
req: dict,
|
| 175 |
+
user: str = Depends(current_active_user, use_cache=False),
|
| 176 |
+
db: Session = Depends(get_db)
|
| 177 |
+
):
|
| 178 |
+
session_id = request.session.get("session_id")
|
| 179 |
+
if not user and not session_id:
|
| 180 |
+
session_id = str(uuid.uuid4())
|
| 181 |
+
request.session["session_id"] = session_id
|
| 182 |
+
session_message_counts[session_id] = 0
|
| 183 |
+
|
| 184 |
+
if not user:
|
| 185 |
+
session_message_counts[session_id] = session_message_counts.get(session_id, 0) + 1
|
| 186 |
+
if session_message_counts[session_id] > 4:
|
| 187 |
+
raise HTTPException(
|
| 188 |
+
status_code=status.HTTP_403_FORBIDDEN,
|
| 189 |
+
detail="Message limit reached. Please log in to continue."
|
| 190 |
+
)
|
| 191 |
+
|
| 192 |
framework = req.get("framework")
|
| 193 |
task = req.get("task")
|
| 194 |
code = req.get("code", "")
|
|
|
|
| 213 |
return {"generated_code": response}
|
| 214 |
|
| 215 |
@router.post("/api/analysis")
|
| 216 |
+
async def analysis_endpoint(
|
| 217 |
+
request: Request,
|
| 218 |
+
req: dict,
|
| 219 |
+
user: str = Depends(current_active_user, use_cache=False),
|
| 220 |
+
db: Session = Depends(get_db)
|
| 221 |
+
):
|
| 222 |
+
session_id = request.session.get("session_id")
|
| 223 |
+
if not user and not session_id:
|
| 224 |
+
session_id = str(uuid.uuid4())
|
| 225 |
+
request.session["session_id"] = session_id
|
| 226 |
+
session_message_counts[session_id] = 0
|
| 227 |
+
|
| 228 |
+
if not user:
|
| 229 |
+
session_message_counts[session_id] = session_message_counts.get(session_id, 0) + 1
|
| 230 |
+
if session_message_counts[session_id] > 4:
|
| 231 |
+
raise HTTPException(
|
| 232 |
+
status_code=status.HTTP_403_FORBIDDEN,
|
| 233 |
+
detail="Message limit reached. Please log in to continue."
|
| 234 |
+
)
|
| 235 |
+
|
| 236 |
message = req.get("text", "")
|
| 237 |
output_format = req.get("output_format", "text")
|
| 238 |
model_name, api_endpoint = select_model(message, input_type="text")
|
|
|
|
| 254 |
return {"analysis": response}
|
| 255 |
|
| 256 |
@router.post("/api/image-analysis")
|
| 257 |
+
async def image_analysis_endpoint(
|
| 258 |
+
request: Request,
|
| 259 |
+
file: UploadFile = File(...),
|
| 260 |
+
output_format: str = "text",
|
| 261 |
+
user: str = Depends(current_active_user, use_cache=False),
|
| 262 |
+
db: Session = Depends(get_db)
|
| 263 |
+
):
|
| 264 |
+
session_id = request.session.get("session_id")
|
| 265 |
+
if not user and not session_id:
|
| 266 |
+
session_id = str(uuid.uuid4())
|
| 267 |
+
request.session["session_id"] = session_id
|
| 268 |
+
session_message_counts[session_id] = 0
|
| 269 |
+
|
| 270 |
+
if not user:
|
| 271 |
+
session_message_counts[session_id] = session_message_counts.get(session_id, 0) + 1
|
| 272 |
+
if session_message_counts[session_id] > 4:
|
| 273 |
+
raise HTTPException(
|
| 274 |
+
status_code=status.HTTP_403_FORBIDDEN,
|
| 275 |
+
detail="Message limit reached. Please log in to continue."
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
model_name, api_endpoint = select_model("analyze image", input_type="image")
|
| 279 |
image_data = await file.read()
|
| 280 |
stream = request_generation(
|
api/models.py
CHANGED
|
@@ -1,11 +1,34 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
from typing import List, Optional
|
| 3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
class QueryRequest(BaseModel):
|
| 5 |
message: str
|
| 6 |
-
system_prompt: str = "You are an expert assistant providing detailed, comprehensive, and well-structured responses.
|
| 7 |
-
history: Optional[List[dict]] =
|
| 8 |
-
temperature: float = 0.7
|
| 9 |
-
max_new_tokens: int = 128000
|
| 10 |
-
enable_browsing: bool =
|
| 11 |
-
output_format: str = "text"
|
|
|
|
| 1 |
+
# api/models.py
|
| 2 |
+
from fastapi_users.db import SQLAlchemyBaseUserTable, SQLAlchemyBaseOAuthAccountTable
|
| 3 |
+
from sqlalchemy import Column, Integer, String, Boolean
|
| 4 |
+
from sqlalchemy.orm import relationship
|
| 5 |
+
from sqlalchemy.ext.declarative import declarative_base
|
| 6 |
+
from pydantic import BaseModel, Field
|
| 7 |
from typing import List, Optional
|
| 8 |
|
| 9 |
+
Base = declarative_base()
|
| 10 |
+
|
| 11 |
+
# جدول OAuth Accounts لتخزين بيانات تسجيل الدخول الخارجي
|
| 12 |
+
class OAuthAccount(SQLAlchemyBaseOAuthAccountTable, Base):
|
| 13 |
+
__tablename__ = "oauth_accounts"
|
| 14 |
+
pass
|
| 15 |
+
|
| 16 |
+
# نموذج المستخدم
|
| 17 |
+
class User(SQLAlchemyBaseUserTable, Base):
|
| 18 |
+
__tablename__ = "users"
|
| 19 |
+
id = Column(Integer, primary_key=True, index=True)
|
| 20 |
+
email = Column(String, unique=True, index=True, nullable=False)
|
| 21 |
+
hashed_password = Column(String, nullable=True) # nullable لأن OAuth ممكن ما يحتاج باسورد
|
| 22 |
+
is_active = Column(Boolean, default=True)
|
| 23 |
+
is_superuser = Column(Boolean, default=False)
|
| 24 |
+
oauth_accounts = relationship("OAuthAccount", back_populates="user")
|
| 25 |
+
|
| 26 |
+
# نموذج طلب الاستعلام (كما هو)
|
| 27 |
class QueryRequest(BaseModel):
|
| 28 |
message: str
|
| 29 |
+
system_prompt: Optional[str] = "You are an expert assistant providing detailed, comprehensive, and well-structured responses."
|
| 30 |
+
history: Optional[List[dict]] = []
|
| 31 |
+
temperature: Optional[float] = 0.7
|
| 32 |
+
max_new_tokens: Optional[int] = 128000
|
| 33 |
+
enable_browsing: Optional[bool] = True
|
| 34 |
+
output_format: Optional[str] = "text"
|
data/mgzon_users.db
ADDED
|
File without changes
|
main.py
CHANGED
|
@@ -1,15 +1,22 @@
|
|
| 1 |
import os
|
| 2 |
import logging
|
| 3 |
-
from fastapi import FastAPI, Request
|
| 4 |
-
from fastapi.responses import HTMLResponse, RedirectResponse
|
| 5 |
from fastapi.staticfiles import StaticFiles
|
| 6 |
from fastapi.templating import Jinja2Templates
|
| 7 |
from starlette.middleware.base import BaseHTTPMiddleware
|
|
|
|
| 8 |
from fastapi.openapi.docs import get_swagger_ui_html
|
| 9 |
-
|
| 10 |
from api.endpoints import router as api_router
|
| 11 |
-
from
|
| 12 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
# إعداد التسجيل
|
| 15 |
logging.basicConfig(level=logging.INFO)
|
|
@@ -20,354 +27,83 @@ logger.info("Files in /app/: %s", os.listdir("/app"))
|
|
| 20 |
|
| 21 |
# إعداد العميل لـ Hugging Face Inference API
|
| 22 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
| 23 |
-
BACKUP_HF_TOKEN = os.getenv("BACKUP_HF_TOKEN")
|
| 24 |
if not HF_TOKEN:
|
| 25 |
logger.error("HF_TOKEN is not set in environment variables.")
|
| 26 |
raise ValueError("HF_TOKEN is required for Inference API.")
|
| 27 |
|
| 28 |
-
#
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
css = """
|
| 34 |
-
.gradio-container {
|
| 35 |
-
max-width: 800px;
|
| 36 |
-
margin: 0 auto;
|
| 37 |
-
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
| 38 |
-
background: #f5f7fa;
|
| 39 |
-
padding: 20px;
|
| 40 |
-
}
|
| 41 |
-
.chatbot {
|
| 42 |
-
border-radius: 12px;
|
| 43 |
-
background: #ffffff;
|
| 44 |
-
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
| 45 |
-
height: 70vh;
|
| 46 |
-
overflow-y: auto;
|
| 47 |
-
padding: 20px;
|
| 48 |
-
}
|
| 49 |
-
.chatbot .message {
|
| 50 |
-
margin-bottom: 15px;
|
| 51 |
-
padding: 10px 15px;
|
| 52 |
-
border-radius: 8px;
|
| 53 |
-
}
|
| 54 |
-
.chatbot .user {
|
| 55 |
-
background: #25D366;
|
| 56 |
-
color: white;
|
| 57 |
-
margin-left: 20%;
|
| 58 |
-
border-radius: 8px 8px 0 8px;
|
| 59 |
-
}
|
| 60 |
-
.chatbot .assistant {
|
| 61 |
-
background: #f1f0f0;
|
| 62 |
-
margin-right: 20%;
|
| 63 |
-
border-radius: 8px 8px 8px 0;
|
| 64 |
-
}
|
| 65 |
-
.input-container {
|
| 66 |
-
display: flex;
|
| 67 |
-
align-items: center;
|
| 68 |
-
gap: 10px;
|
| 69 |
-
background: #ffffff;
|
| 70 |
-
border: 1px solid #e0e0e0;
|
| 71 |
-
border-radius: 50px;
|
| 72 |
-
padding: 10px;
|
| 73 |
-
margin: 20px 0;
|
| 74 |
-
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
|
| 75 |
-
}
|
| 76 |
-
.input-textbox {
|
| 77 |
-
flex-grow: 1;
|
| 78 |
-
border: none;
|
| 79 |
-
outline: none;
|
| 80 |
-
font-size: 16px;
|
| 81 |
-
padding: 12px 15px;
|
| 82 |
-
background: transparent;
|
| 83 |
-
}
|
| 84 |
-
.input-icon, .submit-btn {
|
| 85 |
-
background: none;
|
| 86 |
-
border: none;
|
| 87 |
-
cursor: pointer;
|
| 88 |
-
font-size: 20px;
|
| 89 |
-
padding: 10px;
|
| 90 |
-
color: #333;
|
| 91 |
-
transition: color 0.2s;
|
| 92 |
-
}
|
| 93 |
-
.input-icon:hover, .submit-btn:hover {
|
| 94 |
-
color: #25D366;
|
| 95 |
-
}
|
| 96 |
-
.submit-btn {
|
| 97 |
-
background: #25D366;
|
| 98 |
-
color: white;
|
| 99 |
-
border-radius: 50%;
|
| 100 |
-
width: 40px;
|
| 101 |
-
height: 40px;
|
| 102 |
-
display: flex;
|
| 103 |
-
align-items: center;
|
| 104 |
-
justify-content: center;
|
| 105 |
-
}
|
| 106 |
-
.output-container {
|
| 107 |
-
background: #f9f9f9;
|
| 108 |
-
border-radius: 8px;
|
| 109 |
-
padding: 15px;
|
| 110 |
-
margin: 10px 0;
|
| 111 |
-
}
|
| 112 |
-
.audio-output-container {
|
| 113 |
-
display: flex;
|
| 114 |
-
align-items: center;
|
| 115 |
-
gap: 10px;
|
| 116 |
-
background: #ffffff;
|
| 117 |
-
padding: 10px;
|
| 118 |
-
border-radius: 8px;
|
| 119 |
-
margin-top: 10px;
|
| 120 |
-
}
|
| 121 |
-
.settings-accordion {
|
| 122 |
-
background: #ffffff;
|
| 123 |
-
border-radius: 8px;
|
| 124 |
-
padding: 15px;
|
| 125 |
-
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
|
| 126 |
-
}
|
| 127 |
-
.upload-preview {
|
| 128 |
-
max-width: 200px;
|
| 129 |
-
max-height: 200px;
|
| 130 |
-
border-radius: 8px;
|
| 131 |
-
margin: 10px 0;
|
| 132 |
-
}
|
| 133 |
-
"""
|
| 134 |
-
|
| 135 |
-
# دالة لمعالجة الإدخال
|
| 136 |
-
def process_input(message, audio_input=None, image_input=None, history=None, system_prompt=None, temperature=0.7, reasoning_effort="medium", enable_browsing=True, max_new_tokens=128000, output_format="text"):
|
| 137 |
-
input_type = "text"
|
| 138 |
-
audio_data = None
|
| 139 |
-
image_data = None
|
| 140 |
-
if audio_input:
|
| 141 |
-
input_type = "audio"
|
| 142 |
-
try:
|
| 143 |
-
with open(audio_input, "rb") as f:
|
| 144 |
-
audio_data = f.read()
|
| 145 |
-
message = "Transcribe this audio"
|
| 146 |
-
except Exception as e:
|
| 147 |
-
logger.error(f"Failed to read audio file: {e}")
|
| 148 |
-
return f"Error: Failed to read audio file: {e}", None, [], ""
|
| 149 |
-
elif image_input:
|
| 150 |
-
input_type = "image"
|
| 151 |
-
try:
|
| 152 |
-
with open(image_input, "rb") as f:
|
| 153 |
-
image_data = f.read()
|
| 154 |
-
message = "Analyze this image"
|
| 155 |
-
except Exception as e:
|
| 156 |
-
logger.error(f"Failed to read image file: {e}")
|
| 157 |
-
return f"Error: Failed to read image file: {e}", None, [], ""
|
| 158 |
-
|
| 159 |
-
response_text = ""
|
| 160 |
-
audio_response = None
|
| 161 |
-
chatbot_history = history or []
|
| 162 |
-
try:
|
| 163 |
-
for chunk in generate(
|
| 164 |
-
message=message,
|
| 165 |
-
history=history,
|
| 166 |
-
system_prompt=system_prompt,
|
| 167 |
-
temperature=temperature,
|
| 168 |
-
reasoning_effort=reasoning_effort,
|
| 169 |
-
enable_browsing=enable_browsing,
|
| 170 |
-
max_new_tokens=max_new_tokens,
|
| 171 |
-
input_type=input_type,
|
| 172 |
-
audio_data=audio_data,
|
| 173 |
-
image_data=image_data,
|
| 174 |
-
output_format=output_format
|
| 175 |
-
):
|
| 176 |
-
if isinstance(chunk, bytes):
|
| 177 |
-
audio_response = io.BytesIO(chunk)
|
| 178 |
-
audio_response.name = "response.wav"
|
| 179 |
-
else:
|
| 180 |
-
response_text += chunk
|
| 181 |
-
chatbot_history.append({"role": "assistant", "content": response_text})
|
| 182 |
-
yield response_text or "Processing...", audio_response, chatbot_history, ""
|
| 183 |
-
except Exception as e:
|
| 184 |
-
logger.error(f"Generation failed: {e}")
|
| 185 |
-
return f"Error: Generation failed: {e}", None, [], ""
|
| 186 |
-
|
| 187 |
-
# دالة لتنظيف المدخلات بعد الإرسال
|
| 188 |
-
def clear_inputs(response_text, audio_response, chatbot, message):
|
| 189 |
-
return response_text, audio_response, [], ""
|
| 190 |
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
if file_input:
|
| 194 |
-
return gr.update(value=f"<img src='{file_input}' class='upload-preview'>", visible=True), gr.update(visible=False)
|
| 195 |
-
if audio_input:
|
| 196 |
-
return gr.update(visible=False), gr.update(value=f"<audio controls src='{audio_input}'></audio>", visible=True)
|
| 197 |
-
return gr.update(visible=False), gr.update(visible=False)
|
| 198 |
|
| 199 |
-
#
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
return "Please upload or record an audio file.", None, [], ""
|
| 203 |
-
response_text = ""
|
| 204 |
-
audio_response = None
|
| 205 |
-
chatbot_history = []
|
| 206 |
-
try:
|
| 207 |
-
for text, audio in process_input(message="", audio_input=audio_input, output_format=output_format):
|
| 208 |
-
response_text = text or "No text response generated."
|
| 209 |
-
audio_response = audio
|
| 210 |
-
chatbot_history.append({"role": "assistant", "content": response_text})
|
| 211 |
-
return response_text, audio_response, chatbot_history, ""
|
| 212 |
-
except Exception as e:
|
| 213 |
-
logger.error(f"Audio submission failed: {e}")
|
| 214 |
-
return f"Error: Audio processing failed: {e}", None, [], ""
|
| 215 |
-
|
| 216 |
-
# دالة لمعالجة زر إرسال الصورة
|
| 217 |
-
def submit_image(image_input, output_format):
|
| 218 |
-
if not image_input:
|
| 219 |
-
return "Please upload an image.", None, [], ""
|
| 220 |
-
response_text = ""
|
| 221 |
-
audio_response = None
|
| 222 |
-
chatbot_history = []
|
| 223 |
-
try:
|
| 224 |
-
for text, audio in process_input(message="", image_input=image_input, output_format=output_format):
|
| 225 |
-
response_text = text or "No text response generated."
|
| 226 |
-
audio_response = audio
|
| 227 |
-
chatbot_history.append({"role": "assistant", "content": response_text})
|
| 228 |
-
return response_text, audio_response, chatbot_history, ""
|
| 229 |
-
except Exception as e:
|
| 230 |
-
logger.error(f"Image submission failed: {e}")
|
| 231 |
-
return f"Error: Image processing failed: {e}", None, [], ""
|
| 232 |
|
| 233 |
-
#
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
</div>
|
| 242 |
-
"""
|
| 243 |
-
)
|
| 244 |
-
with gr.Row():
|
| 245 |
-
with gr.Column(scale=3):
|
| 246 |
-
chatbot = gr.Chatbot(
|
| 247 |
-
label="Chat",
|
| 248 |
-
height=600,
|
| 249 |
-
latex_delimiters=LATEX_DELIMS,
|
| 250 |
-
elem_classes="chatbot",
|
| 251 |
-
type="messages"
|
| 252 |
-
)
|
| 253 |
-
with gr.Column(scale=1):
|
| 254 |
-
with gr.Accordion("⚙️ Settings", open=False, elem_classes="settings-accordion"):
|
| 255 |
-
system_prompt = gr.Textbox(
|
| 256 |
-
label="System Prompt",
|
| 257 |
-
value="You are an expert assistant providing detailed, comprehensive, and well-structured responses. Support text, audio, image, and file inputs. For audio, transcribe using Whisper. For text-to-speech, use TTS. For images, analyze content appropriately. Respond in the requested output format (text or audio).",
|
| 258 |
-
lines=4
|
| 259 |
-
)
|
| 260 |
-
temperature = gr.Slider(label="Temperature", minimum=0.0, maximum=1.0, step=0.1, value=0.7)
|
| 261 |
-
reasoning_effort = gr.Radio(label="Reasoning Effort", choices=["low", "medium", "high"], value="medium")
|
| 262 |
-
enable_browsing = gr.Checkbox(label="Enable DeepSearch (web browsing)", value=True)
|
| 263 |
-
max_new_tokens = gr.Slider(label="Max New Tokens", minimum=50, maximum=128000, step=50, value=128000)
|
| 264 |
-
output_format = gr.Radio(label="Output Format", choices=["text", "audio"], value="text")
|
| 265 |
-
with gr.Row():
|
| 266 |
-
with gr.Column():
|
| 267 |
-
with gr.Group(elem_classes="input-container"):
|
| 268 |
-
message = gr.Textbox(
|
| 269 |
-
placeholder="Type your message, or use icons to upload files/audio...",
|
| 270 |
-
lines=1,
|
| 271 |
-
elem_classes="input-textbox",
|
| 272 |
-
show_label=False
|
| 273 |
-
)
|
| 274 |
-
file_input = gr.File(
|
| 275 |
-
file_types=["image", ".mp3", ".wav"],
|
| 276 |
-
show_label=False,
|
| 277 |
-
elem_classes="input-icon",
|
| 278 |
-
visible=False
|
| 279 |
-
)
|
| 280 |
-
audio_input = gr.Audio(
|
| 281 |
-
type="filepath",
|
| 282 |
-
show_label=False,
|
| 283 |
-
elem_classes="input-icon",
|
| 284 |
-
visible=False
|
| 285 |
-
)
|
| 286 |
-
file_preview = gr.HTML(label="File Preview", visible=False)
|
| 287 |
-
audio_preview = gr.HTML(label="Audio Preview", visible=False)
|
| 288 |
-
file_btn = gr.Button("📎", elem_classes="input-icon")
|
| 289 |
-
audio_btn = gr.Button("🎤", elem_classes="input-icon")
|
| 290 |
-
submit_btn = gr.Button("➡️", elem_classes="submit-btn")
|
| 291 |
-
output_text = gr.Textbox(label="Response", lines=10, elem_classes="output-container")
|
| 292 |
-
output_audio = gr.Audio(label="Voice Output", type="filepath", elem_classes="audio-output-container", autoplay=True)
|
| 293 |
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
outputs=file_input
|
| 298 |
-
)
|
| 299 |
-
audio_btn.click(
|
| 300 |
-
fn=lambda: gr.update(visible=True),
|
| 301 |
-
outputs=audio_input
|
| 302 |
-
)
|
| 303 |
-
file_input.change(
|
| 304 |
-
fn=preview_file,
|
| 305 |
-
inputs=[file_input, audio_input],
|
| 306 |
-
outputs=[file_preview, audio_preview]
|
| 307 |
-
)
|
| 308 |
-
audio_input.change(
|
| 309 |
-
fn=preview_file,
|
| 310 |
-
inputs=[file_input, audio_input],
|
| 311 |
-
outputs=[file_preview, audio_preview]
|
| 312 |
-
)
|
| 313 |
-
submit_btn.click(
|
| 314 |
-
fn=process_input,
|
| 315 |
-
inputs=[message, audio_input, file_input, chatbot, system_prompt, temperature, reasoning_effort, enable_browsing, max_new_tokens, output_format],
|
| 316 |
-
outputs=[output_text, output_audio, chatbot, message],
|
| 317 |
-
).then(
|
| 318 |
-
fn=clear_inputs,
|
| 319 |
-
inputs=[output_text, output_audio, chatbot, message],
|
| 320 |
-
outputs=[output_text, output_audio, chatbot, message]
|
| 321 |
-
).then(
|
| 322 |
-
fn=lambda: [gr.update(visible=False), gr.update(visible=False)],
|
| 323 |
-
outputs=[file_preview, audio_preview]
|
| 324 |
-
)
|
| 325 |
-
message.submit(
|
| 326 |
-
fn=process_input,
|
| 327 |
-
inputs=[message, audio_input, file_input, chatbot, system_prompt, temperature, reasoning_effort, enable_browsing, max_new_tokens, output_format],
|
| 328 |
-
outputs=[output_text, output_audio, chatbot, message],
|
| 329 |
-
).then(
|
| 330 |
-
fn=clear_inputs,
|
| 331 |
-
inputs=[output_text, output_audio, chatbot, message],
|
| 332 |
-
outputs=[output_text, output_audio, chatbot, message]
|
| 333 |
-
).then(
|
| 334 |
-
fn=lambda: [gr.update(visible=False), gr.update(visible=False)],
|
| 335 |
-
outputs=[file_preview, audio_preview]
|
| 336 |
-
)
|
| 337 |
-
file_input.change(
|
| 338 |
-
fn=submit_image,
|
| 339 |
-
inputs=[file_input, output_format],
|
| 340 |
-
outputs=[output_text, output_audio, chatbot, message],
|
| 341 |
-
).then(
|
| 342 |
-
fn=clear_inputs,
|
| 343 |
-
inputs=[output_text, output_audio, chatbot, message],
|
| 344 |
-
outputs=[output_text, output_audio, chatbot, message]
|
| 345 |
-
).then(
|
| 346 |
-
fn=lambda: [gr.update(visible=False), gr.update(visible=False)],
|
| 347 |
-
outputs=[file_preview, audio_preview]
|
| 348 |
-
)
|
| 349 |
-
audio_input.change(
|
| 350 |
-
fn=submit_audio,
|
| 351 |
-
inputs=[audio_input, output_format],
|
| 352 |
-
outputs=[output_text, output_audio, chatbot, message],
|
| 353 |
-
).then(
|
| 354 |
-
fn=clear_inputs,
|
| 355 |
-
inputs=[output_text, output_audio, chatbot, message],
|
| 356 |
-
outputs=[output_text, output_audio, chatbot, message]
|
| 357 |
-
).then(
|
| 358 |
-
fn=lambda: [gr.update(visible=False), gr.update(visible=False)],
|
| 359 |
-
outputs=[file_preview, audio_preview]
|
| 360 |
-
)
|
| 361 |
|
| 362 |
# إعداد FastAPI
|
| 363 |
app = FastAPI(title="MGZon Chatbot API")
|
| 364 |
|
| 365 |
-
#
|
| 366 |
-
app
|
| 367 |
|
| 368 |
-
#
|
|
|
|
|
|
|
|
|
|
| 369 |
app.mount("/static", StaticFiles(directory="static"), name="static")
|
| 370 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
|
| 372 |
# Middleware لمعالجة 404
|
| 373 |
class NotFoundMiddleware(BaseHTTPMiddleware):
|
|
@@ -386,8 +122,32 @@ app.add_middleware(NotFoundMiddleware)
|
|
| 386 |
|
| 387 |
# Root endpoint
|
| 388 |
@app.get("/", response_class=HTMLResponse)
|
| 389 |
-
async def root(request: Request):
|
| 390 |
-
return templates.TemplateResponse("index.html", {"request": request})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 391 |
|
| 392 |
# Docs endpoint
|
| 393 |
@app.get("/docs", response_class=HTMLResponse)
|
|
@@ -399,12 +159,72 @@ async def docs(request: Request):
|
|
| 399 |
async def swagger_ui():
|
| 400 |
return get_swagger_ui_html(openapi_url="/openapi.json", title="MGZon API Documentation")
|
| 401 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 402 |
# Redirect لـ /gradio
|
| 403 |
-
@app.get("/
|
| 404 |
async def launch_chatbot():
|
| 405 |
-
return RedirectResponse(url="/
|
|
|
|
|
|
|
|
|
|
| 406 |
|
| 407 |
# تشغيل الخادم
|
| 408 |
if __name__ == "__main__":
|
| 409 |
-
import uvicorn
|
| 410 |
uvicorn.run(app, host="0.0.0.0", port=int(os.getenv("PORT", 7860)))
|
|
|
|
| 1 |
import os
|
| 2 |
import logging
|
| 3 |
+
from fastapi import FastAPI, Request, Depends, HTTPException, status, Query
|
| 4 |
+
from fastapi.responses import HTMLResponse, RedirectResponse, PlainTextResponse
|
| 5 |
from fastapi.staticfiles import StaticFiles
|
| 6 |
from fastapi.templating import Jinja2Templates
|
| 7 |
from starlette.middleware.base import BaseHTTPMiddleware
|
| 8 |
+
from starlette.middleware.sessions import SessionMiddleware
|
| 9 |
from fastapi.openapi.docs import get_swagger_ui_html
|
| 10 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 11 |
from api.endpoints import router as api_router
|
| 12 |
+
from api.auth import fastapi_users, auth_backend, current_active_user, google_oauth_client, github_oauth_client
|
| 13 |
+
from api.database import get_db, engine, Base
|
| 14 |
+
from api.models import User
|
| 15 |
+
from motor.motor_asyncio import AsyncIOMotorClient
|
| 16 |
+
from pydantic import BaseModel
|
| 17 |
+
from typing import List
|
| 18 |
+
import uvicorn
|
| 19 |
+
import markdown2
|
| 20 |
|
| 21 |
# إعداد التسجيل
|
| 22 |
logging.basicConfig(level=logging.INFO)
|
|
|
|
| 27 |
|
| 28 |
# إعداد العميل لـ Hugging Face Inference API
|
| 29 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
|
|
|
| 30 |
if not HF_TOKEN:
|
| 31 |
logger.error("HF_TOKEN is not set in environment variables.")
|
| 32 |
raise ValueError("HF_TOKEN is required for Inference API.")
|
| 33 |
|
| 34 |
+
# إعداد MongoDB
|
| 35 |
+
MONGO_URI = os.getenv("MONGODB_URI")
|
| 36 |
+
if not MONGO_URI:
|
| 37 |
+
logger.error("MONGODB_URI is not set in environment variables.")
|
| 38 |
+
raise ValueError("MONGODB_URI is required for MongoDB.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
+
client = AsyncIOMotorClient(MONGO_URI)
|
| 41 |
+
db = client["hager"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
+
# إعداد Jinja2 مع دعم Markdown
|
| 44 |
+
templates = Jinja2Templates(directory="templates")
|
| 45 |
+
templates.env.filters['markdown'] = lambda text: markdown2.markdown(text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
+
# موديل للمقالات
|
| 48 |
+
class BlogPost(BaseModel):
|
| 49 |
+
id: str
|
| 50 |
+
title: str
|
| 51 |
+
content: str
|
| 52 |
+
author: str
|
| 53 |
+
date: str
|
| 54 |
+
created_at: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
+
# إعدادات الـ queue
|
| 57 |
+
QUEUE_SIZE = int(os.getenv("QUEUE_SIZE", 80))
|
| 58 |
+
CONCURRENCY_LIMIT = int(os.getenv("CONCURRENCY_LIMIT", 20))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
# إعداد FastAPI
|
| 61 |
app = FastAPI(title="MGZon Chatbot API")
|
| 62 |
|
| 63 |
+
# إضافة SessionMiddleware
|
| 64 |
+
app.add_middleware(SessionMiddleware, secret_key=os.getenv("JWT_SECRET"))
|
| 65 |
|
| 66 |
+
# إنشاء الجداول ��لقائيًا
|
| 67 |
+
Base.metadata.create_all(bind=engine)
|
| 68 |
+
|
| 69 |
+
# ربط الملفات الثابتة
|
| 70 |
app.mount("/static", StaticFiles(directory="static"), name="static")
|
| 71 |
+
|
| 72 |
+
# إضافة CORS middleware
|
| 73 |
+
app.add_middleware(
|
| 74 |
+
CORSMiddleware,
|
| 75 |
+
allow_origins=["https://mgzon-mgzon-app.hf.space"],
|
| 76 |
+
allow_credentials=True,
|
| 77 |
+
allow_methods=["*"],
|
| 78 |
+
allow_headers=["*"],
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
# إضافة auth routers
|
| 82 |
+
app.include_router(
|
| 83 |
+
fastapi_users.get_auth_router(auth_backend),
|
| 84 |
+
prefix="/auth/jwt",
|
| 85 |
+
tags=["auth"],
|
| 86 |
+
)
|
| 87 |
+
app.include_router(
|
| 88 |
+
fastapi_users.get_register_router(),
|
| 89 |
+
prefix="/auth",
|
| 90 |
+
tags=["auth"],
|
| 91 |
+
)
|
| 92 |
+
app.include_router(
|
| 93 |
+
fastapi_users.get_users_router(),
|
| 94 |
+
prefix="/users",
|
| 95 |
+
tags=["users"],
|
| 96 |
+
)
|
| 97 |
+
app.include_router(
|
| 98 |
+
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"),
|
| 99 |
+
prefix="/auth/google",
|
| 100 |
+
tags=["auth"],
|
| 101 |
+
)
|
| 102 |
+
app.include_router(
|
| 103 |
+
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"),
|
| 104 |
+
prefix="/auth/github",
|
| 105 |
+
tags=["auth"],
|
| 106 |
+
)
|
| 107 |
|
| 108 |
# Middleware لمعالجة 404
|
| 109 |
class NotFoundMiddleware(BaseHTTPMiddleware):
|
|
|
|
| 122 |
|
| 123 |
# Root endpoint
|
| 124 |
@app.get("/", response_class=HTMLResponse)
|
| 125 |
+
async def root(request: Request, user: User = Depends(fastapi_users.current_user(optional=True))):
|
| 126 |
+
return templates.TemplateResponse("index.html", {"request": request, "user": user})
|
| 127 |
+
|
| 128 |
+
# Chat endpoint
|
| 129 |
+
@app.get("/chat", response_class=HTMLResponse)
|
| 130 |
+
async def chat(request: Request, user: User = Depends(fastapi_users.current_user(optional=True))):
|
| 131 |
+
return templates.TemplateResponse("chat.html", {"request": request, "user": user})
|
| 132 |
+
|
| 133 |
+
# About endpoint
|
| 134 |
+
@app.get("/about", response_class=HTMLResponse)
|
| 135 |
+
async def about(request: Request, user: User = Depends(fastapi_users.current_user(optional=True))):
|
| 136 |
+
return templates.TemplateResponse("about.html", {"request": request, "user": user})
|
| 137 |
+
|
| 138 |
+
# Blog endpoint (قائمة المقالات)
|
| 139 |
+
@app.get("/blog", response_class=HTMLResponse)
|
| 140 |
+
async def blog(request: Request, skip: int = Query(0, ge=0), limit: int = Query(10, ge=1, le=100)):
|
| 141 |
+
posts = await db.blog_posts.find().skip(skip).limit(limit).to_list(limit)
|
| 142 |
+
return templates.TemplateResponse("blog.html", {"request": request, "posts": posts})
|
| 143 |
+
|
| 144 |
+
# Blog post endpoint (عرض مقالة كاملة)
|
| 145 |
+
@app.get("/blog/{post_id}", response_class=HTMLResponse)
|
| 146 |
+
async def blog_post(request: Request, post_id: str):
|
| 147 |
+
post = await db.blog_posts.find_one({"id": post_id})
|
| 148 |
+
if not post:
|
| 149 |
+
raise HTTPException(status_code=404, detail="Post not found")
|
| 150 |
+
return templates.TemplateResponse("blog_post.html", {"request": request, "post": post})
|
| 151 |
|
| 152 |
# Docs endpoint
|
| 153 |
@app.get("/docs", response_class=HTMLResponse)
|
|
|
|
| 159 |
async def swagger_ui():
|
| 160 |
return get_swagger_ui_html(openapi_url="/openapi.json", title="MGZon API Documentation")
|
| 161 |
|
| 162 |
+
# Sitemap endpoint (ديناميكي)
|
| 163 |
+
@app.get("/sitemap.xml", response_class=PlainTextResponse)
|
| 164 |
+
async def sitemap():
|
| 165 |
+
posts = await db.blog_posts.find().to_list(100)
|
| 166 |
+
xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
|
| 167 |
+
xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'
|
| 168 |
+
xml += ' <url>\n'
|
| 169 |
+
xml += ' <loc>https://mgzon-mgzon-app.hf.space/</loc>\n'
|
| 170 |
+
xml += ' <lastmod>2025-09-01</lastmod>\n'
|
| 171 |
+
xml += ' <changefreq>daily</changefreq>\n'
|
| 172 |
+
xml += ' <priority>1.0</priority>\n'
|
| 173 |
+
xml += ' </url>\n'
|
| 174 |
+
xml += ' <url>\n'
|
| 175 |
+
xml += ' <loc>https://mgzon-mgzon-app.hf.space/chat</loc>\n'
|
| 176 |
+
xml += ' <lastmod>2025-09-01</lastmod>\n'
|
| 177 |
+
xml += ' <changefreq>daily</changefreq>\n'
|
| 178 |
+
xml += ' <priority>0.8</priority>\n'
|
| 179 |
+
xml += ' </url>\n'
|
| 180 |
+
xml += ' <url>\n'
|
| 181 |
+
xml += ' <loc>https://mgzon-mgzon-app.hf.space/about</loc>\n'
|
| 182 |
+
xml += ' <lastmod>2025-09-01</lastmod>\n'
|
| 183 |
+
xml += ' <changefreq>weekly</changefreq>\n'
|
| 184 |
+
xml += ' <priority>0.7</priority>\n'
|
| 185 |
+
xml += ' </url>\n'
|
| 186 |
+
xml += ' <url>\n'
|
| 187 |
+
xml += ' <loc>https://mgzon-mgzon-app.hf.space/login</loc>\n'
|
| 188 |
+
xml += ' <lastmod>2025-09-01</lastmod>\n'
|
| 189 |
+
xml += ' <changefreq>weekly</changefreq>\n'
|
| 190 |
+
xml += ' <priority>0.8</priority>\n'
|
| 191 |
+
xml += ' </url>\n'
|
| 192 |
+
xml += ' <url>\n'
|
| 193 |
+
xml += ' <loc>https://mgzon-mgzon-app.hf.space/register</loc>\n'
|
| 194 |
+
xml += ' <lastmod>2025-09-01</lastmod>\n'
|
| 195 |
+
xml += ' <changefreq>weekly</changefreq>\n'
|
| 196 |
+
xml += ' <priority>0.8</priority>\n'
|
| 197 |
+
xml += ' </url>\n'
|
| 198 |
+
xml += ' <url>\n'
|
| 199 |
+
xml += ' <loc>https://mgzon-mgzon-app.hf.space/docs</loc>\n'
|
| 200 |
+
xml += ' <lastmod>2025-09-01</lastmod>\n'
|
| 201 |
+
xml += ' <changefreq>weekly</changefreq>\n'
|
| 202 |
+
xml += ' <priority>0.9</priority>\n'
|
| 203 |
+
xml += ' </url>\n'
|
| 204 |
+
xml += ' <url>\n'
|
| 205 |
+
xml += ' <loc>https://mgzon-mgzon-app.hf.space/blog</loc>\n'
|
| 206 |
+
xml += ' <lastmod>2025-09-01</lastmod>\n'
|
| 207 |
+
xml += ' <changefreq>daily</changefreq>\n'
|
| 208 |
+
xml += ' <priority>0.9</priority>\n'
|
| 209 |
+
xml += ' </url>\n'
|
| 210 |
+
for post in posts:
|
| 211 |
+
xml += ' <url>\n'
|
| 212 |
+
xml += f' <loc>https://mgzon-mgzon-app.hf.space/blog/{post["id"]}</loc>\n'
|
| 213 |
+
xml += f' <lastmod>{post["date"]}</lastmod>\n'
|
| 214 |
+
xml += ' <changefreq>weekly</changefreq>\n'
|
| 215 |
+
xml += ' <priority>0.9</priority>\n'
|
| 216 |
+
xml += ' </url>\n'
|
| 217 |
+
xml += '</urlset>'
|
| 218 |
+
return xml
|
| 219 |
+
|
| 220 |
# Redirect لـ /gradio
|
| 221 |
+
@app.get("/gradio", response_class=RedirectResponse)
|
| 222 |
async def launch_chatbot():
|
| 223 |
+
return RedirectResponse(url="/chat", status_code=302)
|
| 224 |
+
|
| 225 |
+
# ربط API endpoints
|
| 226 |
+
app.include_router(api_router)
|
| 227 |
|
| 228 |
# تشغيل الخادم
|
| 229 |
if __name__ == "__main__":
|
|
|
|
| 230 |
uvicorn.run(app, host="0.0.0.0", port=int(os.getenv("PORT", 7860)))
|
requirements.txt
CHANGED
|
@@ -16,10 +16,20 @@ pydub==0.25.1
|
|
| 16 |
ffmpeg-python==0.2.0
|
| 17 |
numpy==1.26.4
|
| 18 |
parler-tts @ git+https://github.com/huggingface/parler-tts.git@5d0aca9753ab74ded179732f5bd797f7a8c6f8ee
|
| 19 |
-
torch
|
| 20 |
torchaudio==2.4.1
|
| 21 |
transformers==4.43.3
|
| 22 |
webrtcvad==2.0.10
|
| 23 |
Pillow==10.4.0
|
| 24 |
urllib3==2.0.7
|
| 25 |
protobuf==3.19.6
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
ffmpeg-python==0.2.0
|
| 17 |
numpy==1.26.4
|
| 18 |
parler-tts @ git+https://github.com/huggingface/parler-tts.git@5d0aca9753ab74ded179732f5bd797f7a8c6f8ee
|
| 19 |
+
torch==2.4.1
|
| 20 |
torchaudio==2.4.1
|
| 21 |
transformers==4.43.3
|
| 22 |
webrtcvad==2.0.10
|
| 23 |
Pillow==10.4.0
|
| 24 |
urllib3==2.0.7
|
| 25 |
protobuf==3.19.6
|
| 26 |
+
fastapi-users[sqlalchemy]>=13.0.0
|
| 27 |
+
sqlalchemy>=2.0.0
|
| 28 |
+
python-jose[cryptography]>=3.3.0
|
| 29 |
+
passlib[bcrypt]>=1.7.4
|
| 30 |
+
httpx-oauth
|
| 31 |
+
python-multipart
|
| 32 |
+
aiofiles
|
| 33 |
+
motor
|
| 34 |
+
redis
|
| 35 |
+
markdown2
|
space.yaml
CHANGED
|
@@ -7,4 +7,9 @@ sdk: fastapi
|
|
| 7 |
sdk_version: "0.101.0"
|
| 8 |
app_file: main.py
|
| 9 |
pinned: false
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
sdk_version: "0.101.0"
|
| 8 |
app_file: main.py
|
| 9 |
pinned: false
|
| 10 |
+
python_version: "3.10"
|
| 11 |
+
resources:
|
| 12 |
+
cpu: 2
|
| 13 |
+
memory: 8Gi
|
| 14 |
+
disk: 20Gi
|
| 15 |
+
---
|
static/css/styles.css
CHANGED
|
@@ -234,3 +234,181 @@ footer {
|
|
| 234 |
margin-left: 0;
|
| 235 |
}
|
| 236 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
margin-left: 0;
|
| 235 |
}
|
| 236 |
}
|
| 237 |
+
|
| 238 |
+
/* /static/css/style.css */
|
| 239 |
+
.chat-title {
|
| 240 |
+
font-weight: 700;
|
| 241 |
+
font-size: 1.2rem;
|
| 242 |
+
color: #e6eefc;
|
| 243 |
+
display: flex;
|
| 244 |
+
align-items: center;
|
| 245 |
+
gap: 0.5rem;
|
| 246 |
+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
| 247 |
+
white-space: nowrap;
|
| 248 |
+
overflow: hidden;
|
| 249 |
+
text-overflow: ellipsis;
|
| 250 |
+
padding: 10px 0;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
.chat-controls {
|
| 254 |
+
display: flex;
|
| 255 |
+
align-items: center;
|
| 256 |
+
gap: 0.5rem;
|
| 257 |
+
padding: 10px;
|
| 258 |
+
background: #ffffff;
|
| 259 |
+
border-radius: 50px;
|
| 260 |
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
| 261 |
+
}
|
| 262 |
+
|
| 263 |
+
.chat-section {
|
| 264 |
+
display: flex;
|
| 265 |
+
flex-direction: column;
|
| 266 |
+
width: 100%;
|
| 267 |
+
height: 70vh;
|
| 268 |
+
max-width: 800px;
|
| 269 |
+
margin: 0 auto;
|
| 270 |
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
| 271 |
+
background: #f5f7fa;
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
#chatArea {
|
| 275 |
+
flex: 1;
|
| 276 |
+
display: flex;
|
| 277 |
+
flex-direction: column;
|
| 278 |
+
overflow-y: auto;
|
| 279 |
+
width: 100%;
|
| 280 |
+
box-sizing: border-box;
|
| 281 |
+
overflow-wrap: break-word;
|
| 282 |
+
word-wrap: break-word;
|
| 283 |
+
word-break: break-word;
|
| 284 |
+
padding: 20px;
|
| 285 |
+
background: #ffffff;
|
| 286 |
+
border-radius: 12px;
|
| 287 |
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
#chatBox {
|
| 291 |
+
display: flex;
|
| 292 |
+
flex-direction: column;
|
| 293 |
+
width: 100%;
|
| 294 |
+
overflow-y: auto;
|
| 295 |
+
padding: 0.75rem 0.75rem calc(var(--footer-height) + 1rem) 1rem;
|
| 296 |
+
box-sizing: border-box;
|
| 297 |
+
overflow-wrap: break-word;
|
| 298 |
+
word-wrap: break-word;
|
| 299 |
+
word-break: break-word;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
.bubble {
|
| 303 |
+
margin-bottom: 15px;
|
| 304 |
+
padding: 10px 15px;
|
| 305 |
+
border-radius: 8px;
|
| 306 |
+
max-width: 80%;
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
.bubble-user {
|
| 310 |
+
background: #25D366;
|
| 311 |
+
color: white;
|
| 312 |
+
margin-left: 20%;
|
| 313 |
+
border-radius: 8px 8px 0 8px;
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
.bubble-assist {
|
| 317 |
+
background: #f1f0f0;
|
| 318 |
+
margin-right: 20%;
|
| 319 |
+
border-radius: 8px 8px 8px 0;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
#inputContainer {
|
| 323 |
+
display: flex;
|
| 324 |
+
align-items: center;
|
| 325 |
+
gap: 10px;
|
| 326 |
+
background: #ffffff;
|
| 327 |
+
border: 1px solid #e0e0e0;
|
| 328 |
+
border-radius: 50px;
|
| 329 |
+
padding: 10px;
|
| 330 |
+
margin: 20px 0;
|
| 331 |
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
#userInput {
|
| 335 |
+
flex-grow: 1;
|
| 336 |
+
border: none;
|
| 337 |
+
outline: none;
|
| 338 |
+
font-size: 16px;
|
| 339 |
+
padding: 12px 15px;
|
| 340 |
+
background: transparent;
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
#rightIconGroup button {
|
| 344 |
+
background: none;
|
| 345 |
+
border: none;
|
| 346 |
+
cursor: pointer;
|
| 347 |
+
font-size: 20px;
|
| 348 |
+
padding: 10px;
|
| 349 |
+
color: #333;
|
| 350 |
+
transition: color 0.2s;
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
#rightIconGroup button:hover {
|
| 354 |
+
color: #25D366;
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
#sendBtn {
|
| 358 |
+
background: #25D366;
|
| 359 |
+
color: white;
|
| 360 |
+
border-radius: 50%;
|
| 361 |
+
width: 40px;
|
| 362 |
+
height: 40px;
|
| 363 |
+
display: flex;
|
| 364 |
+
align-items: center;
|
| 365 |
+
justify-content: center;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
.upload-preview {
|
| 369 |
+
max-width: 200px;
|
| 370 |
+
max-height: 200px;
|
| 371 |
+
border-radius: 8px;
|
| 372 |
+
margin: 10px 0;
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
.audio-preview {
|
| 376 |
+
margin: 10px 0;
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
.loading {
|
| 380 |
+
display: inline-block;
|
| 381 |
+
width: 20px;
|
| 382 |
+
height: 20px;
|
| 383 |
+
border: 3px solid #f3f3f3;
|
| 384 |
+
border-top: 3px solid #25D366;
|
| 385 |
+
border-radius: 50%;
|
| 386 |
+
animation: spin 1s linear infinite;
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
@keyframes spin {
|
| 390 |
+
0% { transform: rotate(0deg); }
|
| 391 |
+
100% { transform: rotate(360deg); }
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
.md-content table {
|
| 395 |
+
border-collapse: collapse;
|
| 396 |
+
width: 100%;
|
| 397 |
+
margin: 10px 0;
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
.md-content th, .md-content td {
|
| 401 |
+
border: 1px solid #ddd;
|
| 402 |
+
padding: 8px;
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
.md-content th {
|
| 406 |
+
background: #f1f0f0;
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
.styled-hr {
|
| 410 |
+
border: none;
|
| 411 |
+
height: 1px;
|
| 412 |
+
background: #ddd;
|
| 413 |
+
margin: 20px 0;
|
| 414 |
+
}
|
static/favicon.ico
ADDED
|
|
static/google97468ef1f6b6e804.html
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
google-site-verification: google97468ef1f6b6e804.html
|
static/images/mg.svg
ADDED
|
|
static/images/screenshot.png
ADDED
|
static/js/chat.js
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// static/js/chat.js
|
| 2 |
+
// SPDX-FileCopyrightText: Hadad <hadad@linuxmail.org>
|
| 3 |
+
// SPDX-License-Identifier: Apache-2.0
|
| 4 |
+
|
| 5 |
+
// Prism.
|
| 6 |
+
Prism.plugins.autoloader.languages_path = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/';
|
| 7 |
+
|
| 8 |
+
// UI elements.
|
| 9 |
+
const chatArea = document.getElementById('chatArea');
|
| 10 |
+
const chatBox = document.getElementById('chatBox');
|
| 11 |
+
const initialContent = document.getElementById('initialContent');
|
| 12 |
+
const form = document.getElementById('footerForm');
|
| 13 |
+
const input = document.getElementById('userInput');
|
| 14 |
+
const btn = document.getElementById('sendBtn');
|
| 15 |
+
const stopBtn = document.getElementById('stopBtn');
|
| 16 |
+
const fileBtn = document.getElementById('fileBtn');
|
| 17 |
+
const audioBtn = document.getElementById('audioBtn');
|
| 18 |
+
const fileInput = document.getElementById('fileInput');
|
| 19 |
+
const audioInput = document.getElementById('audioInput');
|
| 20 |
+
const filePreview = document.getElementById('filePreview');
|
| 21 |
+
const audioPreview = document.getElementById('audioPreview');
|
| 22 |
+
const promptItems = document.querySelectorAll('.prompt-item');
|
| 23 |
+
const mainHeader = document.getElementById('mainHeader');
|
| 24 |
+
const chatHeader = document.getElementById('chatHeader');
|
| 25 |
+
const homeBtn = document.getElementById('homeBtn');
|
| 26 |
+
const clearBtn = document.getElementById('clearBtn');
|
| 27 |
+
const loginBtn = document.getElementById('loginBtn');
|
| 28 |
+
const messageLimitWarning = document.getElementById('messageLimitWarning');
|
| 29 |
+
|
| 30 |
+
// Track state.
|
| 31 |
+
let streamMsg = null;
|
| 32 |
+
let conversationHistory = JSON.parse(sessionStorage.getItem('conversationHistory') || '[]');
|
| 33 |
+
let currentAssistantText = "";
|
| 34 |
+
let isRequestActive = false;
|
| 35 |
+
let abortController = null;
|
| 36 |
+
|
| 37 |
+
// تحميل المحادثة عند تحميل الصفحة
|
| 38 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 39 |
+
AOS.init({
|
| 40 |
+
duration: 800,
|
| 41 |
+
easing: 'ease-out-cubic',
|
| 42 |
+
once: true,
|
| 43 |
+
offset: 50
|
| 44 |
+
});
|
| 45 |
+
if (conversationHistory.length > 0) {
|
| 46 |
+
enterChatView();
|
| 47 |
+
conversationHistory.forEach(msg => {
|
| 48 |
+
addMsg(msg.role, msg.content);
|
| 49 |
+
});
|
| 50 |
+
}
|
| 51 |
+
});
|
| 52 |
+
|
| 53 |
+
// تحقق من الـ token
|
| 54 |
+
function checkAuth() {
|
| 55 |
+
return localStorage.getItem('token');
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
// Render markdown content.
|
| 59 |
+
function renderMarkdown(el) {
|
| 60 |
+
const raw = el.dataset.text || "";
|
| 61 |
+
const html = marked.parse(raw, {
|
| 62 |
+
gfm: true,
|
| 63 |
+
breaks: true,
|
| 64 |
+
smartLists: true,
|
| 65 |
+
smartypants: false,
|
| 66 |
+
headerIds: false
|
| 67 |
+
});
|
| 68 |
+
el.innerHTML = '<div class="md-content">' + html + '</div>';
|
| 69 |
+
const wrapper = el.querySelector('.md-content');
|
| 70 |
+
|
| 71 |
+
// Wrap tables.
|
| 72 |
+
const tables = wrapper.querySelectorAll('table');
|
| 73 |
+
tables.forEach(t => {
|
| 74 |
+
if (t.parentNode && t.parentNode.classList && t.parentNode.classList.contains('table-wrapper')) return;
|
| 75 |
+
const div = document.createElement('div');
|
| 76 |
+
div.className = 'table-wrapper';
|
| 77 |
+
t.parentNode.insertBefore(div, t);
|
| 78 |
+
div.appendChild(t);
|
| 79 |
+
});
|
| 80 |
+
|
| 81 |
+
// Style horizontal rules.
|
| 82 |
+
const hrs = wrapper.querySelectorAll('hr');
|
| 83 |
+
hrs.forEach(h => {
|
| 84 |
+
if (!h.classList.contains('styled-hr')) {
|
| 85 |
+
h.classList.add('styled-hr');
|
| 86 |
+
}
|
| 87 |
+
});
|
| 88 |
+
|
| 89 |
+
// Highlight code.
|
| 90 |
+
Prism.highlightAllUnder(wrapper);
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
// Chat view.
|
| 94 |
+
function enterChatView() {
|
| 95 |
+
mainHeader.style.display = 'none';
|
| 96 |
+
chatHeader.style.display = 'flex';
|
| 97 |
+
chatHeader.setAttribute('aria-hidden', 'false');
|
| 98 |
+
chatBox.style.display = 'flex';
|
| 99 |
+
initialContent.style.display = 'none';
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
// Home view.
|
| 103 |
+
function leaveChatView() {
|
| 104 |
+
mainHeader.style.display = 'flex';
|
| 105 |
+
chatHeader.style.display = 'none';
|
| 106 |
+
chatHeader.setAttribute('aria-hidden', 'true');
|
| 107 |
+
chatBox.style.display = 'none';
|
| 108 |
+
initialContent.style.display = 'flex';
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
// Chat bubble.
|
| 112 |
+
function addMsg(who, text) {
|
| 113 |
+
const div = document.createElement('div');
|
| 114 |
+
div.className = 'bubble ' + (who === 'user' ? 'bubble-user' : 'bubble-assist');
|
| 115 |
+
div.dataset.text = text;
|
| 116 |
+
renderMarkdown(div);
|
| 117 |
+
chatBox.appendChild(div);
|
| 118 |
+
chatBox.style.display = 'flex';
|
| 119 |
+
chatBox.scrollTop = chatBox.scrollHeight;
|
| 120 |
+
return div;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
// Clear all chat.
|
| 124 |
+
function clearAllMessages() {
|
| 125 |
+
stopStream(true);
|
| 126 |
+
conversationHistory = [];
|
| 127 |
+
sessionStorage.setItem('conversationHistory', JSON.stringify(conversationHistory));
|
| 128 |
+
currentAssistantText = "";
|
| 129 |
+
if (streamMsg) {
|
| 130 |
+
const loadingEl = streamMsg.querySelector('.loading');
|
| 131 |
+
if (loadingEl) loadingEl.remove();
|
| 132 |
+
streamMsg = null;
|
| 133 |
+
}
|
| 134 |
+
chatBox.innerHTML = "";
|
| 135 |
+
input.value = "";
|
| 136 |
+
btn.disabled = true;
|
| 137 |
+
stopBtn.style.display = 'none';
|
| 138 |
+
btn.style.display = 'inline-flex';
|
| 139 |
+
filePreview.style.display = 'none';
|
| 140 |
+
audioPreview.style.display = 'none';
|
| 141 |
+
messageLimitWarning.classList.add('hidden');
|
| 142 |
+
enterChatView();
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
// File preview.
|
| 146 |
+
function previewFile() {
|
| 147 |
+
if (fileInput.files.length > 0) {
|
| 148 |
+
const file = fileInput.files[0];
|
| 149 |
+
if (file.type.startsWith('image/')) {
|
| 150 |
+
const reader = new FileReader();
|
| 151 |
+
reader.onload = (e) => {
|
| 152 |
+
filePreview.innerHTML = `<img src="${e.target.result}" class="upload-preview">`;
|
| 153 |
+
filePreview.style.display = 'block';
|
| 154 |
+
audioPreview.style.display = 'none';
|
| 155 |
+
};
|
| 156 |
+
reader.readAsDataURL(file);
|
| 157 |
+
}
|
| 158 |
+
}
|
| 159 |
+
if (audioInput.files.length > 0) {
|
| 160 |
+
const file = audioInput.files[0];
|
| 161 |
+
if (file.type.startsWith('audio/')) {
|
| 162 |
+
const reader = new FileReader();
|
| 163 |
+
reader.onload = (e) => {
|
| 164 |
+
audioPreview.innerHTML = `<audio controls src="${e.target.result}"></audio>`;
|
| 165 |
+
audioPreview.style.display = 'block';
|
| 166 |
+
filePreview.style.display = 'none';
|
| 167 |
+
};
|
| 168 |
+
reader.readAsDataURL(file);
|
| 169 |
+
}
|
| 170 |
+
}
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
// Send user message.
|
| 174 |
+
async function submitMessage() {
|
| 175 |
+
if (isRequestActive) return;
|
| 176 |
+
let message = input.value.trim();
|
| 177 |
+
let formData = new FormData();
|
| 178 |
+
let endpoint = '/api/chat';
|
| 179 |
+
let inputType = 'text';
|
| 180 |
+
let outputFormat = 'text';
|
| 181 |
+
|
| 182 |
+
if (fileInput.files.length > 0) {
|
| 183 |
+
const file = fileInput.files[0];
|
| 184 |
+
if (file.type.startsWith('image/')) {
|
| 185 |
+
endpoint = '/api/image-analysis';
|
| 186 |
+
inputType = 'image';
|
| 187 |
+
message = 'Analyze this image';
|
| 188 |
+
formData.append('file', file);
|
| 189 |
+
formData.append('output_format', 'text');
|
| 190 |
+
}
|
| 191 |
+
} else if (audioInput.files.length > 0) {
|
| 192 |
+
const file = audioInput.files[0];
|
| 193 |
+
if (file.type.startsWith('audio/')) {
|
| 194 |
+
endpoint = '/api/audio-transcription';
|
| 195 |
+
inputType = 'audio';
|
| 196 |
+
message = 'Transcribe this audio';
|
| 197 |
+
formData.append('file', file);
|
| 198 |
+
}
|
| 199 |
+
} else if (message) {
|
| 200 |
+
formData.append('message', message);
|
| 201 |
+
formData.append('system_prompt', 'You are an expert assistant providing detailed, comprehensive, and well-structured responses.');
|
| 202 |
+
formData.append('history', JSON.stringify(conversationHistory));
|
| 203 |
+
formData.append('temperature', '0.7');
|
| 204 |
+
formData.append('max_new_tokens', '128000');
|
| 205 |
+
formData.append('enable_browsing', 'true');
|
| 206 |
+
formData.append('output_format', 'text');
|
| 207 |
+
} else {
|
| 208 |
+
return;
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
enterChatView();
|
| 212 |
+
addMsg('user', message);
|
| 213 |
+
conversationHistory.push({ role: 'user', content: message });
|
| 214 |
+
sessionStorage.setItem('conversationHistory', JSON.stringify(conversationHistory));
|
| 215 |
+
streamMsg = addMsg('assistant', '');
|
| 216 |
+
const loadingEl = document.createElement('span');
|
| 217 |
+
loadingEl.className = 'loading';
|
| 218 |
+
streamMsg.appendChild(loadingEl);
|
| 219 |
+
stopBtn.style.display = 'inline-flex';
|
| 220 |
+
btn.style.display = 'none';
|
| 221 |
+
input.value = '';
|
| 222 |
+
btn.disabled = true;
|
| 223 |
+
filePreview.style.display = 'none';
|
| 224 |
+
audioPreview.style.display = 'none';
|
| 225 |
+
|
| 226 |
+
isRequestActive = true;
|
| 227 |
+
abortController = new AbortController();
|
| 228 |
+
|
| 229 |
+
try {
|
| 230 |
+
const token = checkAuth();
|
| 231 |
+
const headers = token ? { 'Authorization': `Bearer ${token}` } : {};
|
| 232 |
+
const response = await fetch(endpoint, {
|
| 233 |
+
method: 'POST',
|
| 234 |
+
body: formData,
|
| 235 |
+
headers: headers,
|
| 236 |
+
signal: abortController.signal
|
| 237 |
+
});
|
| 238 |
+
|
| 239 |
+
if (!response.ok) {
|
| 240 |
+
if (response.status === 403) {
|
| 241 |
+
messageLimitWarning.classList.remove('hidden');
|
| 242 |
+
input.disabled = true;
|
| 243 |
+
const loadingEl = streamMsg.querySelector('.loading');
|
| 244 |
+
if (loadingEl) loadingEl.remove();
|
| 245 |
+
streamMsg = null;
|
| 246 |
+
isRequestActive = false;
|
| 247 |
+
abortController = null;
|
| 248 |
+
btn.style.display = 'inline-flex';
|
| 249 |
+
stopBtn.style.display = 'none';
|
| 250 |
+
return;
|
| 251 |
+
}
|
| 252 |
+
if (response.status === 401) {
|
| 253 |
+
localStorage.removeItem('token');
|
| 254 |
+
window.location.href = '/login';
|
| 255 |
+
return;
|
| 256 |
+
}
|
| 257 |
+
throw new Error('Request failed');
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
if (endpoint === '/api/audio-transcription') {
|
| 261 |
+
const data = await response.json();
|
| 262 |
+
const transcription = data.transcription || 'Error: No transcription generated.';
|
| 263 |
+
streamMsg.dataset.text = transcription;
|
| 264 |
+
renderMarkdown(streamMsg);
|
| 265 |
+
streamMsg.dataset.done = '1';
|
| 266 |
+
conversationHistory.push({ role: 'assistant', content: transcription });
|
| 267 |
+
sessionStorage.setItem('conversationHistory', JSON.stringify(conversationHistory));
|
| 268 |
+
} else if (endpoint === '/api/image-analysis') {
|
| 269 |
+
const data = await response.json();
|
| 270 |
+
const analysis = data.image_analysis || 'Error: No analysis generated.';
|
| 271 |
+
streamMsg.dataset.text = analysis;
|
| 272 |
+
renderMarkdown(streamMsg);
|
| 273 |
+
streamMsg.dataset.done = '1';
|
| 274 |
+
conversationHistory.push({ role: 'assistant', content: analysis });
|
| 275 |
+
sessionStorage.setItem('conversationHistory', JSON.stringify(conversationHistory));
|
| 276 |
+
} else {
|
| 277 |
+
const reader = response.body.getReader();
|
| 278 |
+
const decoder = new TextDecoder();
|
| 279 |
+
let buffer = '';
|
| 280 |
+
|
| 281 |
+
while (true) {
|
| 282 |
+
const { done, value } = await reader.read();
|
| 283 |
+
if (done) break;
|
| 284 |
+
buffer += decoder.decode(value, { stream: true });
|
| 285 |
+
streamMsg.dataset.text = buffer;
|
| 286 |
+
currentAssistantText = buffer;
|
| 287 |
+
const loadingEl = streamMsg.querySelector('.loading');
|
| 288 |
+
if (loadingEl) loadingEl.remove();
|
| 289 |
+
renderMarkdown(streamMsg);
|
| 290 |
+
chatBox.scrollTop = chatBox.scrollHeight;
|
| 291 |
+
}
|
| 292 |
+
streamMsg.dataset.done = '1';
|
| 293 |
+
conversationHistory.push({ role: 'assistant', content: buffer });
|
| 294 |
+
sessionStorage.setItem('conversationHistory', JSON.stringify(conversationHistory));
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
streamMsg = null;
|
| 298 |
+
isRequestActive = false;
|
| 299 |
+
abortController = null;
|
| 300 |
+
btn.style.display = 'inline-flex';
|
| 301 |
+
stopBtn.style.display = 'none';
|
| 302 |
+
} catch (error) {
|
| 303 |
+
if (streamMsg) {
|
| 304 |
+
const loadingEl = streamMsg.querySelector('.loading');
|
| 305 |
+
if (loadingEl) loadingEl.remove();
|
| 306 |
+
streamMsg.dataset.text = error.message || 'An error occurred during the request.';
|
| 307 |
+
renderMarkdown(streamMsg);
|
| 308 |
+
streamMsg.dataset.done = '1';
|
| 309 |
+
streamMsg = null;
|
| 310 |
+
isRequestActive = false;
|
| 311 |
+
abortController = null;
|
| 312 |
+
}
|
| 313 |
+
btn.style.display = 'inline-flex';
|
| 314 |
+
stopBtn.style.display = 'none';
|
| 315 |
+
}
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
// Stop streaming and cancel the ongoing request.
|
| 319 |
+
function stopStream(forceCancel = false) {
|
| 320 |
+
if (!isRequestActive) return;
|
| 321 |
+
isRequestActive = false;
|
| 322 |
+
if (abortController) {
|
| 323 |
+
abortController.abort();
|
| 324 |
+
abortController = null;
|
| 325 |
+
}
|
| 326 |
+
if (streamMsg && !forceCancel) {
|
| 327 |
+
const loadingEl = streamMsg.querySelector('.loading');
|
| 328 |
+
if (loadingEl) loadingEl.remove();
|
| 329 |
+
streamMsg.dataset.text += '';
|
| 330 |
+
renderMarkdown(streamMsg);
|
| 331 |
+
streamMsg.dataset.done = '1';
|
| 332 |
+
streamMsg = null;
|
| 333 |
+
}
|
| 334 |
+
stopBtn.style.display = 'none';
|
| 335 |
+
btn.style.display = 'inline-flex';
|
| 336 |
+
stopBtn.style.pointerEvents = 'auto';
|
| 337 |
+
}
|
| 338 |
+
|
| 339 |
+
// Prompts.
|
| 340 |
+
promptItems.forEach(p => {
|
| 341 |
+
p.addEventListener('click', () => {
|
| 342 |
+
input.value = p.dataset.prompt;
|
| 343 |
+
submitMessage();
|
| 344 |
+
});
|
| 345 |
+
});
|
| 346 |
+
|
| 347 |
+
// File and audio inputs.
|
| 348 |
+
fileBtn.addEventListener('click', () => {
|
| 349 |
+
fileInput.click();
|
| 350 |
+
});
|
| 351 |
+
audioBtn.addEventListener('click', () => {
|
| 352 |
+
audioInput.click();
|
| 353 |
+
});
|
| 354 |
+
fileInput.addEventListener('change', previewFile);
|
| 355 |
+
audioInput.addEventListener('change', previewFile);
|
| 356 |
+
|
| 357 |
+
// Submit.
|
| 358 |
+
form.addEventListener('submit', e => {
|
| 359 |
+
e.preventDefault();
|
| 360 |
+
submitMessage();
|
| 361 |
+
});
|
| 362 |
+
|
| 363 |
+
// Stop.
|
| 364 |
+
stopBtn.addEventListener('click', () => {
|
| 365 |
+
stopBtn.style.pointerEvents = 'none';
|
| 366 |
+
stopStream();
|
| 367 |
+
});
|
| 368 |
+
|
| 369 |
+
// Home.
|
| 370 |
+
homeBtn.addEventListener('click', () => {
|
| 371 |
+
window.location.href = '/';
|
| 372 |
+
});
|
| 373 |
+
|
| 374 |
+
// Clear messages.
|
| 375 |
+
clearBtn.addEventListener('click', () => {
|
| 376 |
+
clearAllMessages();
|
| 377 |
+
});
|
| 378 |
+
|
| 379 |
+
// Login button.
|
| 380 |
+
if (loginBtn) {
|
| 381 |
+
loginBtn.addEventListener('click', () => {
|
| 382 |
+
window.location.href = '/login';
|
| 383 |
+
});
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
// Enable send button only if input has text.
|
| 387 |
+
input.addEventListener('input', () => {
|
| 388 |
+
btn.disabled = input.value.trim() === '' && fileInput.files.length === 0 && audioInput.files.length === 0;
|
| 389 |
+
});
|
static/robots.txt
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
User-agent: *
|
| 2 |
+
Allow: /
|
| 3 |
+
Disallow: /utils/
|
| 4 |
+
Disallow: /api/
|
| 5 |
+
Disallow: /main.py
|
| 6 |
+
Disallow: /mgzon_users.db
|
| 7 |
+
Disallow: /data/
|
| 8 |
+
Disallow: /Dockerfile
|
| 9 |
+
Disallow: /space.yaml
|
| 10 |
+
Disallow: /requirements.txt
|
| 11 |
+
Allow: /static/robots.txt
|
| 12 |
+
Allow: /static/sitemap.xml
|
| 13 |
+
Allow: /static/google97468ef1f6b6e804.html
|
| 14 |
+
Allow: /static/favicon.ico
|
| 15 |
+
Allow: /static/css/
|
| 16 |
+
Allow: /static/js/
|
| 17 |
+
Sitemap: https://mgzon-mgzon-app.hf.space/static/sitemap.xml
|
static/sitemap.xml
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
| 3 |
+
<url>
|
| 4 |
+
<loc>https://mgzon-mgzon-app.hf.space/</loc>
|
| 5 |
+
<lastmod>2025-09-01</lastmod>
|
| 6 |
+
<changefreq>daily</changefreq>
|
| 7 |
+
<priority>1.0</priority>
|
| 8 |
+
</url>
|
| 9 |
+
<url>
|
| 10 |
+
<loc>https://mgzon-mgzon-app.hf.space/chat</loc>
|
| 11 |
+
<lastmod>2025-09-01</lastmod>
|
| 12 |
+
<changefreq>daily</changefreq>
|
| 13 |
+
<priority>0.8</priority>
|
| 14 |
+
</url>
|
| 15 |
+
<url>
|
| 16 |
+
<loc>https://mgzon-mgzon-app.hf.space/about</loc>
|
| 17 |
+
<lastmod>2025-09-01</lastmod>
|
| 18 |
+
<changefreq>weekly</changefreq>
|
| 19 |
+
<priority>0.7</priority>
|
| 20 |
+
</url>
|
| 21 |
+
<url>
|
| 22 |
+
<loc>https://mgzon-mgzon-app.hf.space/login</loc>
|
| 23 |
+
<lastmod>2025-09-01</lastmod>
|
| 24 |
+
<changefreq>weekly</changefreq>
|
| 25 |
+
<priority>0.8</priority>
|
| 26 |
+
</url>
|
| 27 |
+
<url>
|
| 28 |
+
<loc>https://mgzon-mgzon-app.hf.space/register</loc>
|
| 29 |
+
<lastmod>2025-09-01</lastmod>
|
| 30 |
+
<changefreq>weekly</changefreq>
|
| 31 |
+
<priority>0.8</priority>
|
| 32 |
+
</url>
|
| 33 |
+
<url>
|
| 34 |
+
<loc>https://mgzon-mgzon-app.hf.space/blog/mgzon-ai-revolution-2025</loc>
|
| 35 |
+
<lastmod>2025-09-01</lastmod>
|
| 36 |
+
<changefreq>weekly</changefreq>
|
| 37 |
+
<priority>0.9</priority>
|
| 38 |
+
</url>
|
| 39 |
+
<url>
|
| 40 |
+
<loc>https://mgzon-mgzon-app.hf.space/docs</loc>
|
| 41 |
+
<lastmod>2025-09-01</lastmod>
|
| 42 |
+
<changefreq>weekly</changefreq>
|
| 43 |
+
<priority>0.9</priority>
|
| 44 |
+
</url>
|
| 45 |
+
<url>
|
| 46 |
+
<loc>https://mgzon-mgzon-app.hf.space/blog</loc>
|
| 47 |
+
<lastmod>2025-09-01</lastmod>
|
| 48 |
+
<changefreq>daily</changefreq>
|
| 49 |
+
<priority>0.9</priority>
|
| 50 |
+
</url>
|
| 51 |
+
</urlset>
|
templates/500.html
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- templates/500.html -->
|
| 2 |
+
<!DOCTYPE html>
|
| 3 |
+
<html lang="en">
|
| 4 |
+
<head>
|
| 5 |
+
<meta charset="UTF-8">
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 7 |
+
<title>500 - Server Error</title>
|
| 8 |
+
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
| 9 |
+
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
|
| 10 |
+
</head>
|
| 11 |
+
<body class="bg-gray-900 text-white min-h-screen flex flex-col">
|
| 12 |
+
<div class="container max-w-6xl mx-auto text-center py-12 flex-1">
|
| 13 |
+
<img src="https://raw.githubusercontent.com/Mark-Lasfar/MGZon/main/public/icons/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 14 |
+
<h1 class="text-5xl font-bold mb-4">500 - Server Error 😓</h1>
|
| 15 |
+
<p class="text-lg mb-8">Something went wrong on our end. Please try again later or contact support.</p>
|
| 16 |
+
<a href="/" class="inline-block bg-gradient-to-r from-orange-500 to-red-500 text-white px-8 py-4 rounded-full text-lg font-semibold hover:scale-105 transition transform">Back to Home</a>
|
| 17 |
+
</div>
|
| 18 |
+
<footer class="bg-gradient-to-r from-blue-900 to-gray-900 py-12">
|
| 19 |
+
<div class="container max-w-6xl mx-auto text-center">
|
| 20 |
+
<img src="https://raw.githubusercontent.com/Mark-Lasfar/MGZon/main/public/icons/mg.svg" alt="MGZon Logo" class="w-24 h-24 mx-auto mb-6 animate-pulse">
|
| 21 |
+
<p class="mb-4">Developed by <a href="https://mark-elasfar.web.app/" target="_blank" class="text-orange-500 hover:underline">Mark Al-Asfar</a> | Powered by <a href="https://hager-zon.vercel.app/" target="_blank" class="text-orange-500 hover:underline">MGZon AI</a></p>
|
| 22 |
+
<div class="flex justify-center gap-6">
|
| 23 |
+
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-orange-500 transition"><i class="bx bxl-github"></i></a>
|
| 24 |
+
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-orange-500 transition"><i class="bx bxl-twitter"></i></a>
|
| 25 |
+
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-orange-500 transition"><i class="bx bxl-facebook"></i></a>
|
| 26 |
+
</div>
|
| 27 |
+
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 28 |
+
</div>
|
| 29 |
+
</footer>
|
| 30 |
+
<script src="/static/js/scripts.js"></script>
|
| 31 |
+
</body>
|
| 32 |
+
</html>
|
templates/about.html
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<meta name="description" content="Learn about MGZon AI, founded by Mark Al-Asfar in Alexandria, Egypt. Discover our mission, team, and achievements in AI and e-commerce.">
|
| 7 |
+
<meta name="keywords" content="MGZon AI, Mark Al-Asfar, AI chatbot, e-commerce, code generation, Alexandria, technology, team, achievements">
|
| 8 |
+
<meta name="author" content="Mark Al-Asfar">
|
| 9 |
+
<meta name="robots" content="index, follow">
|
| 10 |
+
<title>About MGZon AI – Our Story</title>
|
| 11 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 12 |
+
<link rel="apple-touch-icon" href="static/images/mg.svg">
|
| 13 |
+
<!-- Open Graph -->
|
| 14 |
+
<meta property="og:title" content="About MGZon AI – Our Story">
|
| 15 |
+
<meta property="og:description" content="Learn about MGZon AI, its founder Mark Al-Asfar, and our mission to innovate in AI and e-commerce.">
|
| 16 |
+
<meta property="og:image" content="static/images/mg.svg">
|
| 17 |
+
<meta property="og:url" content="https://mgzon-mgzon-app.hf.space/about">
|
| 18 |
+
<meta property="og:type" content="website">
|
| 19 |
+
<!-- Twitter Card -->
|
| 20 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 21 |
+
<meta name="twitter:title" content="About MGZon AI – Our Story">
|
| 22 |
+
<meta name="twitter:description" content="Learn about MGZon AI, its founder Mark Al-Asfar, and our mission to innovate in AI and e-commerce.">
|
| 23 |
+
<meta name="twitter:image" content="static/images/mg.svg">
|
| 24 |
+
<!-- JSON-LD -->
|
| 25 |
+
<script type="application/ld+json">
|
| 26 |
+
{
|
| 27 |
+
"@context": "https://schema.org",
|
| 28 |
+
"@type": "Organization",
|
| 29 |
+
"name": "MGZon AI",
|
| 30 |
+
"url": "https://mgzon-mgzon-app.hf.space",
|
| 31 |
+
"logo": "static/images/mg.svg",
|
| 32 |
+
"founder": {
|
| 33 |
+
"@type": "Person",
|
| 34 |
+
"name": "Mark Al-Asfar",
|
| 35 |
+
"sameAs": "https://mark-elasfar.web.app/"
|
| 36 |
+
},
|
| 37 |
+
"description": "MGZon AI develops AI-powered solutions for e-commerce and coding, founded by Mark Al-Asfar from Alexandria, Egypt.",
|
| 38 |
+
"keywords": ["MGZon AI", "Mark Al-Asfar", "AI chatbot", "e-commerce", "code generation", "Alexandria", "technology", "team", "MGZon", "MGZon chatbot", "E-commerce chatbot", "5G", "6G", "2025 AI trends"],
|
| 39 |
+
"address": {
|
| 40 |
+
"@type": "PostalAddress",
|
| 41 |
+
"addressLocality": "Alexandria",
|
| 42 |
+
"addressCountry": "Egypt"
|
| 43 |
+
}
|
| 44 |
+
}
|
| 45 |
+
</script>
|
| 46 |
+
<!-- Tailwind (v3) -->
|
| 47 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 48 |
+
<!-- Boxicons -->
|
| 49 |
+
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
|
| 50 |
+
<style>
|
| 51 |
+
@keyframes gradientShift {
|
| 52 |
+
0% { background-position: 0% 50%; }
|
| 53 |
+
50% { background-position: 100% 50%; }
|
| 54 |
+
100% { background-position: 0% 50%; }
|
| 55 |
+
}
|
| 56 |
+
body {
|
| 57 |
+
background: linear-gradient(135deg, #0f172a, #0e7490, #065f46, #064e3b);
|
| 58 |
+
background-size: 400% 400%;
|
| 59 |
+
animation: gradientShift 15s ease infinite;
|
| 60 |
+
font-family: system-ui, sans-serif;
|
| 61 |
+
}
|
| 62 |
+
.glass {
|
| 63 |
+
background: rgba(255, 255, 255, 0.07);
|
| 64 |
+
border-radius: 1rem;
|
| 65 |
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
| 66 |
+
backdrop-filter: blur(12px);
|
| 67 |
+
-webkit-backdrop-filter: blur(12px);
|
| 68 |
+
}
|
| 69 |
+
.sidebar {
|
| 70 |
+
transition: transform 0.3s ease-in-out;
|
| 71 |
+
}
|
| 72 |
+
.sidebar.collapsed .logo {
|
| 73 |
+
opacity: 0;
|
| 74 |
+
transition: opacity 0.2s ease;
|
| 75 |
+
}
|
| 76 |
+
.main-content {
|
| 77 |
+
min-height: calc(100vh - 4rem);
|
| 78 |
+
}
|
| 79 |
+
.glass:hover {
|
| 80 |
+
transform: scale(1.05);
|
| 81 |
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
| 82 |
+
background: rgba(255, 255, 255, 0.15);
|
| 83 |
+
}
|
| 84 |
+
@media (max-width: 768px) {
|
| 85 |
+
.sidebar {
|
| 86 |
+
transform: translateX(-100%);
|
| 87 |
+
}
|
| 88 |
+
.sidebar.active {
|
| 89 |
+
transform: translateX(0);
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
</style>
|
| 93 |
+
</head>
|
| 94 |
+
<body class="text-white flex flex-col min-h-screen">
|
| 95 |
+
<!-- Mobile toggle button -->
|
| 96 |
+
<button id="sidebarToggle" class="md:hidden fixed top-4 left-4 z-50 p-2 text-2xl text-white rounded bg-gray-800/60 hover:bg-gray-700/80 transition" aria-label="Toggle navigation">
|
| 97 |
+
<i class="bx bx-menu"></i>
|
| 98 |
+
</button>
|
| 99 |
+
<!-- Sidebar -->
|
| 100 |
+
<aside id="sidebar" class="sidebar fixed inset-y-0 left-0 w-64 bg-gradient-to-b from-teal-800 to-emerald-900 p-6 flex flex-col overflow-y-auto z-40">
|
| 101 |
+
<button id="closeSidebar" class="md:hidden text-white text-2xl absolute top-4 right-4" aria-label="Close sidebar">✕</button>
|
| 102 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="logo w-20 h-20 mx-auto mb-8 animate-pulse">
|
| 103 |
+
<nav class="flex flex-col gap-3">
|
| 104 |
+
<a href="/" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Home</a>
|
| 105 |
+
<a href="/docs" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">API Documentation</a>
|
| 106 |
+
<a href="/about" class="px-4 py-2 rounded-lg bg-emerald-600">About MGZon</a>
|
| 107 |
+
<a href="/login" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Login</a>
|
| 108 |
+
<a href="/register" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Register</a>
|
| 109 |
+
<a href="https://hager-zon.vercel.app/community" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Community</a>
|
| 110 |
+
<a href="https://mark-elasfar.web.app/" target="_blank" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Mark Al-Asfar</a>
|
| 111 |
+
</nav>
|
| 112 |
+
</aside>
|
| 113 |
+
<!-- Main content -->
|
| 114 |
+
<main class="flex-1 md:ml-64 p-6 main-content">
|
| 115 |
+
<section class="container max-w-6xl mx-auto">
|
| 116 |
+
<div class="text-center py-12">
|
| 117 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 118 |
+
<h1 class="text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-teal-300 to-emerald-400">About MGZon AI</h1>
|
| 119 |
+
<p class="text-lg max-w-2xl mx-auto mb-8">Founded by Mark Al-Asfar in Alexandria, Egypt, MGZon AI is revolutionizing e-commerce and coding with AI-driven solutions.</p>
|
| 120 |
+
</div>
|
| 121 |
+
<!-- Story Section -->
|
| 122 |
+
<section class="my-12">
|
| 123 |
+
<h2 class="text-3xl font-bold text-center mb-8">Our Story</h2>
|
| 124 |
+
<div class="glass p-6">
|
| 125 |
+
<p class="mb-4">MGZon AI was founded in 2023 in Alexandria, Egypt, by Mark Al-Asfar with a vision to empower developers and businesses through AI-driven solutions like MGZon Chatbot. We leverage technologies like DeepSeek, FastAPI, and 5G/6G innovations to deliver cutting-edge e-commerce and code generation tools.</p>
|
| 126 |
+
<p>From a small startup to a global player, we now operate warehouses in the USA, Canada, and China, serving thousands of users worldwide.</p>
|
| 127 |
+
</div>
|
| 128 |
+
</section>
|
| 129 |
+
<!-- Founder Section -->
|
| 130 |
+
<section class="my-12">
|
| 131 |
+
<h2 class="text-3xl font-bold text-center mb-8">Meet Our Founder</h2>
|
| 132 |
+
<div class="glass p-6 text-center">
|
| 133 |
+
<img src="static/images/mg.svg" alt="Mark Al-Asfar" class="w-24 h-24 mx-auto mb-4 rounded-full">
|
| 134 |
+
<h3 class="text-xl font-semibold mb-2">Mark Al-Asfar</h3>
|
| 135 |
+
<p class="mb-4">A visionary developer from Alexandria, Mark Al-Asfar founded MGZon AI to bridge the gap between AI innovation and practical applications in coding and e-commerce.</p>
|
| 136 |
+
<a href="https://mark-elasfar.web.app/" target="_blank" class="text-emerald-300 hover:underline">Learn More About Mark</a>
|
| 137 |
+
</div>
|
| 138 |
+
</section>
|
| 139 |
+
<!-- Team Section -->
|
| 140 |
+
<section class="my-12">
|
| 141 |
+
<h2 class="text-3xl font-bold text-center mb-8">Our Team</h2>
|
| 142 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
| 143 |
+
<div class="glass p-6 text-center">
|
| 144 |
+
<img src="https://via.placeholder.com/96" alt="Team Member" class="w-24 h-24 mx-auto mb-4 rounded-full">
|
| 145 |
+
<h3 class="text-xl font-semibold mb-2">Hager Mohamed</h3>
|
| 146 |
+
<p class="mb-4">Lead AI Engineer, specializing in machine learning and chatbot development.</p>
|
| 147 |
+
</div>
|
| 148 |
+
<div class="glass p-6 text-center">
|
| 149 |
+
<img src="https://via.placeholder.com/96" alt="Team Member" class="w-24 h-24 mx-auto mb-4 rounded-full">
|
| 150 |
+
<h3 class="text-xl font-semibold mb-2">Ahmed Khaled</h3>
|
| 151 |
+
<p class="mb-4">E-commerce Specialist, driving innovative solutions for online businesses.</p>
|
| 152 |
+
</div>
|
| 153 |
+
</div>
|
| 154 |
+
</section>
|
| 155 |
+
<!-- Achievements Section -->
|
| 156 |
+
<section class="my-12">
|
| 157 |
+
<h2 class="text-3xl font-bold text-center mb-8">Our Achievements</h2>
|
| 158 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
| 159 |
+
<div class="glass p-6">
|
| 160 |
+
<h3 class="text-xl font-semibold mb-2">Global Reach</h3>
|
| 161 |
+
<p>Serving over 10,000 users across 50 countries with our AI tools.</p>
|
| 162 |
+
</div>
|
| 163 |
+
<div class="glass p-6">
|
| 164 |
+
<h3 class="text-xl font-semibold mb-2">Award-Winning Innovation</h3>
|
| 165 |
+
<p>Recognized as a top AI startup in MENA by TechCrunch in 2024.</p>
|
| 166 |
+
</div>
|
| 167 |
+
</div>
|
| 168 |
+
</section>
|
| 169 |
+
<!-- Mission Section -->
|
| 170 |
+
<section class="my-12">
|
| 171 |
+
<h2 class="text-3xl font-bold text-center mb-8">Our Mission</h2>
|
| 172 |
+
<div class="glass p-6">
|
| 173 |
+
<p>At MGZon AI, we aim to make AI accessible to developers and businesses, simplifying coding and enhancing e-commerce with cutting-edge technology.</p>
|
| 174 |
+
</div>
|
| 175 |
+
</section>
|
| 176 |
+
</section>
|
| 177 |
+
</main>
|
| 178 |
+
<!-- Footer -->
|
| 179 |
+
<footer class="bg-gradient-to-r from-teal-900 to-emerald-900 py-12 mt-8">
|
| 180 |
+
<div class="container max-w-6xl mx-auto text-center">
|
| 181 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="w-24 h-24 mx-auto mb-6 animate-pulse">
|
| 182 |
+
<p class="mb-4">
|
| 183 |
+
Developed by <a href="https://mark-elasfar.web.app/" target="_blank" class="text-emerald-300 hover:underline">Mark Al-Asfar</a>
|
| 184 |
+
| Powered by <a href="https://hager-zon.vercel.app/" target="_blank" class="text-emerald-300 hover:underline">MGZon AI</a>
|
| 185 |
+
</p>
|
| 186 |
+
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
| 187 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('email')">
|
| 188 |
+
<i class="bx bx-mail-send text-3xl text-emerald-300 mb-2"></i>
|
| 189 |
+
<h4 class="font-semibold mb-1">Email Us</h4>
|
| 190 |
+
<p><a href="mailto:support@mgzon.com" class="text-emerald-300 hover:underline">support@mgzon.com</a></p>
|
| 191 |
+
<div id="email-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 192 |
+
<p>Reach out to our support team for any inquiries or assistance.</p>
|
| 193 |
+
<button onclick="closeCardDetails('email')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 194 |
+
</div>
|
| 195 |
+
</div>
|
| 196 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('phone')">
|
| 197 |
+
<i class="bx bx-phone text-3xl text-emerald-300 mb-2"></i>
|
| 198 |
+
<h4 class="font-semibold mb-1">Phone Support</h4>
|
| 199 |
+
<p>+1-800-123-4567</p>
|
| 200 |
+
<div id="phone-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 201 |
+
<p>Contact our support team via phone for immediate assistance.</p>
|
| 202 |
+
<button onclick="closeCardDetails('phone')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 203 |
+
</div>
|
| 204 |
+
</div>
|
| 205 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('community')">
|
| 206 |
+
<i class="bx bx-group text-3xl text-emerald-300 mb-2"></i>
|
| 207 |
+
<h4 class="font-semibold mb-1">Community</h4>
|
| 208 |
+
<p><a href="https://hager-zon.vercel.app/community" class="text-emerald-300 hover:underline">Join us</a></p>
|
| 209 |
+
<div id="community-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 210 |
+
<p>Join our vibrant community to share ideas and collaborate.</p>
|
| 211 |
+
<button onclick="closeCardDetails('community')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 212 |
+
</div>
|
| 213 |
+
</div>
|
| 214 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('api-docs')">
|
| 215 |
+
<i class="bx bx-code-alt text-3xl text-emerald-300 mb-2"></i>
|
| 216 |
+
<h4 class="font-semibold mb-1">API Docs</h4>
|
| 217 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Explore Docs</a></p>
|
| 218 |
+
<div id="api-docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 219 |
+
<p>Explore our API documentation for seamless integration.</p>
|
| 220 |
+
<button onclick="closeCardDetails('api-docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 221 |
+
</div>
|
| 222 |
+
</div>
|
| 223 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('faq')">
|
| 224 |
+
<i class="bx bx-help-circle text-3xl text-emerald-300 mb-2"></i>
|
| 225 |
+
<h4 class="font-semibold mb-1">FAQ</h4>
|
| 226 |
+
<p><a href="https://hager-zon.vercel.app/faq" target="_blank" class="text-emerald-300 hover:underline">Read FAQ</a></p>
|
| 227 |
+
<div id="faq-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 228 |
+
<p>Find answers to common questions in our FAQ section.</p>
|
| 229 |
+
<button onclick="closeCardDetails('faq')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 230 |
+
</div>
|
| 231 |
+
</div>
|
| 232 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('docs')">
|
| 233 |
+
<i class="bx bx-book text-3xl text-emerald-300 mb-2"></i>
|
| 234 |
+
<h4 class="font-semibold mb-1">Documentation</h4>
|
| 235 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Full Docs</a></p>
|
| 236 |
+
<div id="docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 237 |
+
<p>Access comprehensive documentation for MGZon Chatbot.</p>
|
| 238 |
+
<button onclick="closeCardDetails('docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 239 |
+
</div>
|
| 240 |
+
</div>
|
| 241 |
+
</div>
|
| 242 |
+
<div class="flex justify-center gap-6 mt-6">
|
| 243 |
+
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-github"></i></a>
|
| 244 |
+
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-twitter"></i></a>
|
| 245 |
+
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-facebook"></i></a>
|
| 246 |
+
</div>
|
| 247 |
+
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 248 |
+
</div>
|
| 249 |
+
</footer>
|
| 250 |
+
<script>
|
| 251 |
+
const sidebar = document.getElementById('sidebar');
|
| 252 |
+
const toggleBtn = document.getElementById('sidebarToggle');
|
| 253 |
+
const closeSidebarBtn = document.getElementById('closeSidebar');
|
| 254 |
+
toggleBtn.addEventListener('click', () => {
|
| 255 |
+
sidebar.classList.toggle('active');
|
| 256 |
+
sidebar.classList.toggle('-translate-x-full');
|
| 257 |
+
sidebar.classList.toggle('translate-x-0');
|
| 258 |
+
});
|
| 259 |
+
closeSidebarBtn.addEventListener('click', () => {
|
| 260 |
+
sidebar.classList.remove('active');
|
| 261 |
+
sidebar.classList.add('-translate-x-full');
|
| 262 |
+
sidebar.classList.remove('translate-x-0');
|
| 263 |
+
});
|
| 264 |
+
document.addEventListener('click', (e) => {
|
| 265 |
+
if (!sidebar.contains(e.target) && !toggleBtn.contains(e.target) && window.innerWidth < 768) {
|
| 266 |
+
sidebar.classList.remove('active');
|
| 267 |
+
sidebar.classList.add('-translate-x-full');
|
| 268 |
+
sidebar.classList.remove('translate-x-0');
|
| 269 |
+
}
|
| 270 |
+
});
|
| 271 |
+
function showCardDetails(cardId) {
|
| 272 |
+
document.getElementById(`${cardId}-details`).classList.remove('hidden');
|
| 273 |
+
}
|
| 274 |
+
function closeCardDetails(cardId) {
|
| 275 |
+
document.getElementById(`${cardId}-details`).classList.add('hidden');
|
| 276 |
+
}
|
| 277 |
+
</script>
|
| 278 |
+
</body>
|
| 279 |
+
</html>
|
templates/blog.html
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<meta name="description" content="Read the latest blog posts from MGZon AI about AI, coding, and e-commerce trends.">
|
| 7 |
+
<meta name="keywords" content="MGZon AI, blog, AI trends, code generation, e-commerce, Mark Al-Asfar">
|
| 8 |
+
<meta name="author" content="Mark Al-Asfar">
|
| 9 |
+
<meta name="robots" content="index, follow">
|
| 10 |
+
<title>Blog - MGZon AI</title>
|
| 11 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 12 |
+
<link rel="apple-touch-icon" href="/static/images/mg.svg">
|
| 13 |
+
<!-- Open Graph -->
|
| 14 |
+
<meta property="og:title" content="Blog - MGZon AI">
|
| 15 |
+
<meta property="og:description" content="Read the latest blog posts from MGZon AI about AI, coding, and e-commerce trends.">
|
| 16 |
+
<meta property="og:image" content="/static/images/mg.svg">
|
| 17 |
+
<meta property="og:url" content="https://mgzon-mgzon-app.hf.space/blog">
|
| 18 |
+
<meta property="og:type" content="website">
|
| 19 |
+
<!-- Twitter Card -->
|
| 20 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 21 |
+
<meta name="twitter:title" content="Blog - MGZon AI">
|
| 22 |
+
<meta name="twitter:description" content="Read the latest blog posts from MGZon AI about AI, coding, and e-commerce trends.">
|
| 23 |
+
<meta name="twitter:image" content="/static/images/mg.svg">
|
| 24 |
+
<!-- JSON-LD -->
|
| 25 |
+
<script type="application/ld+json">
|
| 26 |
+
{
|
| 27 |
+
"@context": "https://schema.org",
|
| 28 |
+
"@type": "Blog",
|
| 29 |
+
"name": "MGZon AI Blog",
|
| 30 |
+
"url": "https://mgzon-mgzon-app.hf.space/blog",
|
| 31 |
+
"description": "Read the latest blog posts from MGZon AI about AI, coding, and e-commerce trends.",
|
| 32 |
+
"keywords": ["MGZon Chatbot", "blog", "AI trends", "code generation", "e-commerce", "Mark Al-Asfar", "MGZon", "MGZon AI", "AI chatbot", "Code generation bot", "E-commerce chatbot", "Python AI chatbot", "AI for coding", "E-commerce automation", "2025 AI trends", "chatgpt", "grok", "deepseek", "text generation"],
|
| 33 |
+
"isPartOf": {
|
| 34 |
+
"@type": "WebSite",
|
| 35 |
+
"name": "MGZon Chatbot",
|
| 36 |
+
"url": "https://mgzon-mgzon-app.hf.space/"
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
</script>
|
| 40 |
+
<!-- Tailwind (v3) -->
|
| 41 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 42 |
+
<!-- Boxicons -->
|
| 43 |
+
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
|
| 44 |
+
<style>
|
| 45 |
+
@keyframes gradientShift {
|
| 46 |
+
0% { background-position: 0% 50%; }
|
| 47 |
+
50% { background-position: 100% 50%; }
|
| 48 |
+
100% { background-position: 0% 50%; }
|
| 49 |
+
}
|
| 50 |
+
body {
|
| 51 |
+
background: linear-gradient(135deg, #0f172a, #0e7490, #065f46, #064e3b);
|
| 52 |
+
background-size: 400% 400%;
|
| 53 |
+
animation: gradientShift 15s ease infinite;
|
| 54 |
+
font-family: system-ui, sans-serif;
|
| 55 |
+
}
|
| 56 |
+
.glass {
|
| 57 |
+
background: rgba(255, 255, 255, 0.07);
|
| 58 |
+
border-radius: 1rem;
|
| 59 |
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
| 60 |
+
backdrop-filter: blur(12px);
|
| 61 |
+
-webkit-backdrop-filter: blur(12px);
|
| 62 |
+
}
|
| 63 |
+
.sidebar {
|
| 64 |
+
transition: transform 0.3s ease-in-out;
|
| 65 |
+
}
|
| 66 |
+
.sidebar.collapsed .logo {
|
| 67 |
+
opacity: 0;
|
| 68 |
+
transition: opacity 0.2s ease;
|
| 69 |
+
}
|
| 70 |
+
.main-content {
|
| 71 |
+
min-height: calc(100vh - 4rem);
|
| 72 |
+
}
|
| 73 |
+
.glass:hover {
|
| 74 |
+
transform: scale(1.05);
|
| 75 |
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
| 76 |
+
background: rgba(255, 255, 255, 0.15);
|
| 77 |
+
}
|
| 78 |
+
@media (max-width: 768px) {
|
| 79 |
+
.sidebar {
|
| 80 |
+
transform: translateX(-100%);
|
| 81 |
+
}
|
| 82 |
+
.sidebar.active {
|
| 83 |
+
transform: translateX(0);
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
</style>
|
| 87 |
+
</head>
|
| 88 |
+
<body class="text-white flex flex-col min-h-screen">
|
| 89 |
+
<!-- Mobile toggle button -->
|
| 90 |
+
<button id="sidebarToggle" class="md:hidden fixed top-4 left-4 z-50 p-2 text-2xl text-white rounded bg-gray-800/60 hover:bg-gray-700/80 transition" aria-label="Toggle navigation">
|
| 91 |
+
<i class="bx bx-menu"></i>
|
| 92 |
+
</button>
|
| 93 |
+
<!-- Sidebar -->
|
| 94 |
+
<aside id="sidebar" class="sidebar fixed inset-y-0 left-0 w-64 bg-gradient-to-b from-teal-800 to-emerald-900 p-6 flex flex-col overflow-y-auto z-40">
|
| 95 |
+
<button id="closeSidebar" class="md:hidden text-white text-2xl absolute top-4 right-4" aria-label="Close sidebar">✕</button>
|
| 96 |
+
<img src="/static/images/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 97 |
+
<nav class="flex flex-col gap-3">
|
| 98 |
+
<a href="/" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Home</a>
|
| 99 |
+
<a href="/docs" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">API Documentation</a>
|
| 100 |
+
<a href="/about" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">About MGZon</a>
|
| 101 |
+
<a href="/login" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Login</a>
|
| 102 |
+
<a href="/register" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Register</a>
|
| 103 |
+
<a href="/blog" class="px-4 py-2 rounded-lg bg-emerald-600">Blog</a>
|
| 104 |
+
<a href="https://hager-zon.vercel.app/community" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Community</a>
|
| 105 |
+
<a href="https://mark-elasfar.web.app/" target="_blank" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Mark Al-Asfar</a>
|
| 106 |
+
</nav>
|
| 107 |
+
</aside>
|
| 108 |
+
<!-- Main content -->
|
| 109 |
+
<main class="flex-1 md:ml-64 p-6 main-content">
|
| 110 |
+
<section class="container max-w-6xl mx-auto">
|
| 111 |
+
<div class="text-center py-12">
|
| 112 |
+
<img src="/static/images/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 113 |
+
<h1 class="text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-teal-300 to-emerald-400">
|
| 114 |
+
MGZon AI Blog
|
| 115 |
+
</h1>
|
| 116 |
+
<p class="text-lg max-w-2xl mx-auto mb-8">
|
| 117 |
+
Stay updated with the latest trends in AI, coding, and e-commerce from MGZon AI. Explore topics like text generation, Python AI chatbots, and 2025 AI trends with insights from Mark Al-Asfar.
|
| 118 |
+
</p>
|
| 119 |
+
</div>
|
| 120 |
+
<!-- Blog Posts -->
|
| 121 |
+
<section class="my-12">
|
| 122 |
+
<h2 class="text-3xl font-bold text-center mb-8">Latest Posts</h2>
|
| 123 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
| 124 |
+
{% for post in posts %}
|
| 125 |
+
<div class="glass p-6">
|
| 126 |
+
<h3 class="text-xl font-semibold mb-2">{{ post.title }}</h3>
|
| 127 |
+
<p class="mb-4">{{ post.content | truncate(100) }}</p>
|
| 128 |
+
<p class="text-sm text-gray-300">By {{ post.author }} | {{ post.date }}</p>
|
| 129 |
+
<a href="/blog/{{ post.id }}" class="text-emerald-300 hover:underline">Read More →</a>
|
| 130 |
+
</div>
|
| 131 |
+
{% endfor %}
|
| 132 |
+
</div>
|
| 133 |
+
</section>
|
| 134 |
+
</section>
|
| 135 |
+
</main>
|
| 136 |
+
<!-- Footer -->
|
| 137 |
+
<footer class="bg-gradient-to-r from-teal-900 to-emerald-900 py-12 mt-8">
|
| 138 |
+
<div class="container max-w-6xl mx-auto text-center">
|
| 139 |
+
<img src="/static/images/mg.svg" alt="MGZon Chatbot Logo by Mark Al-Asfar" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 140 |
+
<p class="mb-4">
|
| 141 |
+
Developed by <a href="https://mark-elasfar.web.app/" target="_blank" class="text-emerald-300 hover:underline">Mark Al-Asfar</a>
|
| 142 |
+
| Powered by <a href="https://hager-zon.vercel.app/" target="_blank" class="text-emerald-300 hover:underline">MGZon AI</a>
|
| 143 |
+
</p>
|
| 144 |
+
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
| 145 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('email')">
|
| 146 |
+
<i class="bx bx-mail-send text-3xl text-emerald-300 mb-2"></i>
|
| 147 |
+
<h4 class="font-semibold mb-1">Email Us</h4>
|
| 148 |
+
<p><a href="mailto:support@mgzon.com" class="text-emerald-300 hover:underline">support@mgzon.com</a></p>
|
| 149 |
+
<div id="email-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 150 |
+
<p>Reach out to our support team for any inquiries or assistance.</p>
|
| 151 |
+
<button onclick="closeCardDetails('email')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 152 |
+
</div>
|
| 153 |
+
</div>
|
| 154 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('phone')">
|
| 155 |
+
<i class="bx bx-phone text-3xl text-emerald-300 mb-2"></i>
|
| 156 |
+
<h4 class="font-semibold mb-1">Phone Support</h4>
|
| 157 |
+
<p>+1-800-123-4567</p>
|
| 158 |
+
<div id="phone-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 159 |
+
<p>Contact our support team via phone for immediate assistance.</p>
|
| 160 |
+
<button onclick="closeCardDetails('phone')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 161 |
+
</div>
|
| 162 |
+
</div>
|
| 163 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('community')">
|
| 164 |
+
<i class="bx bx-group text-3xl text-emerald-300 mb-2"></i>
|
| 165 |
+
<h4 class="font-semibold mb-1">Community</h4>
|
| 166 |
+
<p><a href="https://hager-zon.vercel.app/community" class="text-emerald-300 hover:underline">Join us</a></p>
|
| 167 |
+
<div id="community-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 168 |
+
<p>Join our vibrant community to share ideas and collaborate.</p>
|
| 169 |
+
<button onclick="closeCardDetails('community')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 170 |
+
</div>
|
| 171 |
+
</div>
|
| 172 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('api-docs')">
|
| 173 |
+
<i class="bx bx-code-alt text-3xl text-emerald-300 mb-2"></i>
|
| 174 |
+
<h4 class="font-semibold mb-1">API Docs</h4>
|
| 175 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Explore Docs</a></p>
|
| 176 |
+
<div id="api-docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 177 |
+
<p>Explore our API documentation for seamless integration.</p>
|
| 178 |
+
<button onclick="closeCardDetails('api-docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 179 |
+
</div>
|
| 180 |
+
</div>
|
| 181 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('faq')">
|
| 182 |
+
<i class="bx bx-help-circle text-3xl text-emerald-300 mb-2"></i>
|
| 183 |
+
<h4 class="font-semibold mb-1">FAQ</h4>
|
| 184 |
+
<p><a href="https://hager-zon.vercel.app/faq" target="_blank" class="text-emerald-300 hover:underline">Read FAQ</a></p>
|
| 185 |
+
<div id="faq-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 186 |
+
<p>Find answers to common questions in our FAQ section.</p>
|
| 187 |
+
<button onclick="closeCardDetails('faq')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 188 |
+
</div>
|
| 189 |
+
</div>
|
| 190 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('docs')">
|
| 191 |
+
<i class="bx bx-book text-3xl text-emerald-300 mb-2"></i>
|
| 192 |
+
<h4 class="font-semibold mb-1">Documentation</h4>
|
| 193 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Full Docs</a></p>
|
| 194 |
+
<div id="docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 195 |
+
<p>Access comprehensive documentation for MGZon Chatbot.</p>
|
| 196 |
+
<button onclick="closeCardDetails('docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 197 |
+
</div>
|
| 198 |
+
</div>
|
| 199 |
+
</div>
|
| 200 |
+
<div class="flex justify-center gap-6 mt-6">
|
| 201 |
+
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-github"></i></a>
|
| 202 |
+
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-twitter"></i></a>
|
| 203 |
+
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-facebook"></i></a>
|
| 204 |
+
</div>
|
| 205 |
+
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 206 |
+
</div>
|
| 207 |
+
</footer>
|
| 208 |
+
<script>
|
| 209 |
+
const sidebar = document.getElementById('sidebar');
|
| 210 |
+
const toggleBtn = document.getElementById('sidebarToggle');
|
| 211 |
+
const closeSidebarBtn = document.getElementById('closeSidebar');
|
| 212 |
+
toggleBtn.addEventListener('click', () => {
|
| 213 |
+
sidebar.classList.toggle('active');
|
| 214 |
+
sidebar.classList.toggle('-translate-x-full');
|
| 215 |
+
sidebar.classList.toggle('translate-x-0');
|
| 216 |
+
});
|
| 217 |
+
closeSidebarBtn.addEventListener('click', () => {
|
| 218 |
+
sidebar.classList.remove('active');
|
| 219 |
+
sidebar.classList.add('-translate-x-full');
|
| 220 |
+
sidebar.classList.remove('translate-x-0');
|
| 221 |
+
});
|
| 222 |
+
document.addEventListener('click', (e) => {
|
| 223 |
+
if (!sidebar.contains(e.target) && !toggleBtn.contains(e.target) && window.innerWidth < 768) {
|
| 224 |
+
sidebar.classList.remove('active');
|
| 225 |
+
sidebar.classList.add('-translate-x-full');
|
| 226 |
+
sidebar.classList.remove('translate-x-0');
|
| 227 |
+
}
|
| 228 |
+
});
|
| 229 |
+
function showCardDetails(cardId) {
|
| 230 |
+
document.getElementById(`${cardId}-details`).classList.remove('hidden');
|
| 231 |
+
}
|
| 232 |
+
function closeCardDetails(cardId) {
|
| 233 |
+
document.getElementById(`${cardId}-details`).classList.add('hidden');
|
| 234 |
+
}
|
| 235 |
+
</script>
|
| 236 |
+
</body>
|
| 237 |
+
</html>
|
templates/blog_post.html
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<meta name="description" content="{{ post.title }} - Read about AI, coding, and e-commerce trends from MGZon AI by Mark Al-Asfar.">
|
| 7 |
+
<meta name="keywords" content="MGZon Chatbot, MGZon AI, blog, AI trends, code generation, e-commerce, Mark Al-Asfar, AI chatbot, code generation bot, e-commerce chatbot, Python AI chatbot, AI for coding, e-commerce automation, 2025 AI trends, chatgpt, grok, deepseek, text generation">
|
| 8 |
+
<meta name="author" content="Mark Al-Asfar">
|
| 9 |
+
<meta name="robots" content="index, follow">
|
| 10 |
+
<title>{{ post.title }} - MGZon AI</title>
|
| 11 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 12 |
+
<link rel="apple-touch-icon" href="/static/images/mg.svg">
|
| 13 |
+
<!-- Open Graph -->
|
| 14 |
+
<meta property="og:title" content="{{ post.title }} - MGZon AI">
|
| 15 |
+
<meta property="og:description" content="{{ post.content | truncate(150) }}">
|
| 16 |
+
<meta property="og:image" content="/static/images/mg.svg">
|
| 17 |
+
<meta property="og:url" content="https://mgzon-mgzon-app.hf.space/blog/{{ post.id }}">
|
| 18 |
+
<meta property="og:type" content="article">
|
| 19 |
+
<!-- Twitter Card -->
|
| 20 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 21 |
+
<meta name="twitter:title" content="{{ post.title }} - MGZon AI">
|
| 22 |
+
<meta name="twitter:description" content="{{ post.content | truncate(150) }}">
|
| 23 |
+
<meta name="twitter:image" content="/static/images/mg.svg">
|
| 24 |
+
<!-- JSON-LD -->
|
| 25 |
+
<script type="application/ld+json">
|
| 26 |
+
{
|
| 27 |
+
"@context": "https://schema.org",
|
| 28 |
+
"@type": "BlogPosting",
|
| 29 |
+
"headline": "{{ post.title }}",
|
| 30 |
+
"url": "https://mgzon-mgzon-app.hf.space/blog/{{ post.id }}",
|
| 31 |
+
"description": "{{ post.content | truncate(150) }}",
|
| 32 |
+
"keywords": ["MGZon Chatbot", "MGZon AI", "blog", "AI trends", "code generation", "e-commerce", "Mark Al-Asfar", "AI chatbot", "code generation bot", "e-commerce chatbot", "Python AI chatbot", "AI for coding", "e-commerce automation", "2025 AI trends", "chatgpt", "grok", "deepseek", "text generation"],
|
| 33 |
+
"author": {
|
| 34 |
+
"@type": "Person",
|
| 35 |
+
"name": "Mark Al-Asfar",
|
| 36 |
+
"url": "https://mark-elasfar.web.app/"
|
| 37 |
+
},
|
| 38 |
+
"datePublished": "{{ post.date }}",
|
| 39 |
+
"publisher": {
|
| 40 |
+
"@type": "Organization",
|
| 41 |
+
"name": "MGZon AI",
|
| 42 |
+
"logo": {
|
| 43 |
+
"@type": "ImageObject",
|
| 44 |
+
"url": "/static/images/mg.svg"
|
| 45 |
+
}
|
| 46 |
+
},
|
| 47 |
+
"isPartOf": {
|
| 48 |
+
"@type": "WebSite",
|
| 49 |
+
"name": "MGZon Chatbot",
|
| 50 |
+
"url": "https://mgzon-mgzon-app.hf.space/"
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
</script>
|
| 54 |
+
<!-- Tailwind (v3) -->
|
| 55 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 56 |
+
<!-- Boxicons -->
|
| 57 |
+
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
|
| 58 |
+
<style>
|
| 59 |
+
@keyframes gradientShift {
|
| 60 |
+
0% { background-position: 0% 50%; }
|
| 61 |
+
50% { background-position: 100% 50%; }
|
| 62 |
+
100% { background-position: 0% 50%; }
|
| 63 |
+
}
|
| 64 |
+
body {
|
| 65 |
+
background: linear-gradient(135deg, #0f172a, #0e7490, #065f46, #064e3b);
|
| 66 |
+
background-size: 400% 400%;
|
| 67 |
+
animation: gradientShift 15s ease infinite;
|
| 68 |
+
font-family: system-ui, sans-serif;
|
| 69 |
+
}
|
| 70 |
+
.glass {
|
| 71 |
+
background: rgba(255, 255, 255, 0.07);
|
| 72 |
+
border-radius: 1rem;
|
| 73 |
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
| 74 |
+
backdrop-filter: blur(12px);
|
| 75 |
+
-webkit-backdrop-filter: blur(12px);
|
| 76 |
+
}
|
| 77 |
+
.sidebar {
|
| 78 |
+
transition: transform 0.3s ease-in-out;
|
| 79 |
+
}
|
| 80 |
+
.sidebar.collapsed .logo {
|
| 81 |
+
opacity: 0;
|
| 82 |
+
transition: opacity 0.2s ease;
|
| 83 |
+
}
|
| 84 |
+
.main-content {
|
| 85 |
+
min-height: calc(100vh - 4rem);
|
| 86 |
+
}
|
| 87 |
+
.glass:hover {
|
| 88 |
+
transform: scale(1.05);
|
| 89 |
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
| 90 |
+
background: rgba(255, 255, 255, 0.15);
|
| 91 |
+
}
|
| 92 |
+
@media (max-width: 768px) {
|
| 93 |
+
.sidebar {
|
| 94 |
+
transform: translateX(-100%);
|
| 95 |
+
}
|
| 96 |
+
.sidebar.active {
|
| 97 |
+
transform: translateX(0);
|
| 98 |
+
}
|
| 99 |
+
}
|
| 100 |
+
.markdown-content img {
|
| 101 |
+
max-width: 100%;
|
| 102 |
+
height: auto;
|
| 103 |
+
margin: 1rem 0;
|
| 104 |
+
}
|
| 105 |
+
.markdown-content h2 {
|
| 106 |
+
font-size: 1.875rem;
|
| 107 |
+
font-weight: bold;
|
| 108 |
+
margin-top: 2rem;
|
| 109 |
+
margin-bottom: 1rem;
|
| 110 |
+
}
|
| 111 |
+
.markdown-content p {
|
| 112 |
+
margin-bottom: 1rem;
|
| 113 |
+
}
|
| 114 |
+
.markdown-content a {
|
| 115 |
+
color: #34d399;
|
| 116 |
+
text-decoration: underline;
|
| 117 |
+
}
|
| 118 |
+
.markdown-content blockquote {
|
| 119 |
+
border-left: 4px solid #34d399;
|
| 120 |
+
padding-left: 1rem;
|
| 121 |
+
margin: 1rem 0;
|
| 122 |
+
color: #d1d5db;
|
| 123 |
+
}
|
| 124 |
+
</style>
|
| 125 |
+
</head>
|
| 126 |
+
<body class="text-white flex flex-col min-h-screen">
|
| 127 |
+
<!-- Mobile toggle button -->
|
| 128 |
+
<button id="sidebarToggle" class="md:hidden fixed top-4 left-4 z-50 p-2 text-2xl text-white rounded bg-gray-800/60 hover:bg-gray-700/80 transition" aria-label="Toggle navigation">
|
| 129 |
+
<i class="bx bx-menu"></i>
|
| 130 |
+
</button>
|
| 131 |
+
<!-- Sidebar -->
|
| 132 |
+
<aside id="sidebar" class="sidebar fixed inset-y-0 left-0 w-64 bg-gradient-to-b from-teal-800 to-emerald-900 p-6 flex flex-col overflow-y-auto z-40">
|
| 133 |
+
<button id="closeSidebar" class="md:hidden text-white text-2xl absolute top-4 right-4" aria-label="Close sidebar">✕</button>
|
| 134 |
+
<img src="/static/images/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 135 |
+
<nav class="flex flex-col gap-3">
|
| 136 |
+
<a href="/" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Home</a>
|
| 137 |
+
<a href="/docs" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">API Documentation</a>
|
| 138 |
+
<a href="/about" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">About MGZon</a>
|
| 139 |
+
<a href="/login" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Login</a>
|
| 140 |
+
<a href="/register" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Register</a>
|
| 141 |
+
<a href="/blog" class="px-4 py-2 rounded-lg bg-emerald-600">Blog</a>
|
| 142 |
+
<a href="https://hager-zon.vercel.app/community" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Community</a>
|
| 143 |
+
<a href="https://mark-elasfar.web.app/" target="_blank" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Mark Al-Asfar</a>
|
| 144 |
+
</nav>
|
| 145 |
+
</aside>
|
| 146 |
+
<!-- Main content -->
|
| 147 |
+
<main class="flex-1 md:ml-64 p-6 main-content">
|
| 148 |
+
<section class="container max-w-6xl mx-auto">
|
| 149 |
+
<div class="text-center py-12">
|
| 150 |
+
<img src="/static/images/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 151 |
+
<h1 class="text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-teal-300 to-emerald-400">
|
| 152 |
+
{{ post.title }}
|
| 153 |
+
</h1>
|
| 154 |
+
<p class="text-sm text-gray-300">By {{ post.author }} | {{ post.date }}</p>
|
| 155 |
+
</div>
|
| 156 |
+
<!-- Blog Post Content -->
|
| 157 |
+
<section class="my-12 glass p-8 markdown-content">
|
| 158 |
+
{{ post.content | markdown | safe }}
|
| 159 |
+
</section>
|
| 160 |
+
</section>
|
| 161 |
+
</main>
|
| 162 |
+
<!-- Footer -->
|
| 163 |
+
<footer class="bg-gradient-to-r from-teal-900 to-emerald-900 py-12 mt-8">
|
| 164 |
+
<div class="container max-w-6xl mx-auto text-center">
|
| 165 |
+
<img src="/static/images/mg.svg" alt="MGZon Chatbot Logo by Mark Al-Asfar" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 166 |
+
<p class="mb-4">
|
| 167 |
+
Developed by <a href="https://mark-elasfar.web.app/" target="_blank" class="text-emerald-300 hover:underline">Mark Al-Asfar</a>
|
| 168 |
+
| Powered by <a href="https://hager-zon.vercel.app/" target="_blank" class="text-emerald-300 hover:underline">MGZon AI</a>
|
| 169 |
+
</p>
|
| 170 |
+
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
| 171 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('email')">
|
| 172 |
+
<i class="bx bx-mail-send text-3xl text-emerald-300 mb-2"></i>
|
| 173 |
+
<h4 class="font-semibold mb-1">Email Us</h4>
|
| 174 |
+
<p><a href="mailto:support@mgzon.com" class="text-emerald-300 hover:underline">support@mgzon.com</a></p>
|
| 175 |
+
<div id="email-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 176 |
+
<p>Reach out to our support team for any inquiries or assistance.</p>
|
| 177 |
+
<button onclick="closeCardDetails('email')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 178 |
+
</div>
|
| 179 |
+
</div>
|
| 180 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('phone')">
|
| 181 |
+
<i class="bx bx-phone text-3xl text-emerald-300 mb-2"></i>
|
| 182 |
+
<h4 class="font-semibold mb-1">Phone Support</h4>
|
| 183 |
+
<p>+1-800-123-4567</p>
|
| 184 |
+
<div id="phone-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 185 |
+
<p>Contact our support team via phone for immediate assistance.</p>
|
| 186 |
+
<button onclick="closeCardDetails('phone')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 187 |
+
</div>
|
| 188 |
+
</div>
|
| 189 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('community')">
|
| 190 |
+
<i class="bx bx-group text-3xl text-emerald-300 mb-2"></i>
|
| 191 |
+
<h4 class="font-semibold mb-1">Community</h4>
|
| 192 |
+
<p><a href="https://hager-zon.vercel.app/community" class="text-emerald-300 hover:underline">Join us</a></p>
|
| 193 |
+
<div id="community-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 194 |
+
<p>Join our vibrant community to share ideas and collaborate.</p>
|
| 195 |
+
<button onclick="closeCardDetails('community')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 196 |
+
</div>
|
| 197 |
+
</div>
|
| 198 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('api-docs')">
|
| 199 |
+
<i class="bx bx-code-alt text-3xl text-emerald-300 mb-2"></i>
|
| 200 |
+
<h4 class="font-semibold mb-1">API Docs</h4>
|
| 201 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Explore Docs</a></p>
|
| 202 |
+
<div id="api-docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 203 |
+
<p>Explore our API documentation for seamless integration.</p>
|
| 204 |
+
<button onclick="closeCardDetails('api-docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 205 |
+
</div>
|
| 206 |
+
</div>
|
| 207 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('faq')">
|
| 208 |
+
<i class="bx bx-help-circle text-3xl text-emerald-300 mb-2"></i>
|
| 209 |
+
<h4 class="font-semibold mb-1">FAQ</h4>
|
| 210 |
+
<p><a href="https://hager-zon.vercel.app/faq" target="_blank" class="text-emerald-300 hover:underline">Read FAQ</a></p>
|
| 211 |
+
<div id="faq-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 212 |
+
<p>Find answers to common questions in our FAQ section.</p>
|
| 213 |
+
<button onclick="closeCardDetails('faq')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 214 |
+
</div>
|
| 215 |
+
</div>
|
| 216 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('docs')">
|
| 217 |
+
<i class="bx bx-book text-3xl text-emerald-300 mb-2"></i>
|
| 218 |
+
<h4 class="font-semibold mb-1">Documentation</h4>
|
| 219 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Full Docs</a></p>
|
| 220 |
+
<div id="docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 221 |
+
<p>Access comprehensive documentation for MGZon Chatbot.</p>
|
| 222 |
+
<button onclick="closeCardDetails('docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 223 |
+
</div>
|
| 224 |
+
</div>
|
| 225 |
+
</div>
|
| 226 |
+
<div class="flex justify-center gap-6 mt-6">
|
| 227 |
+
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-github"></i></a>
|
| 228 |
+
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-twitter"></i></a>
|
| 229 |
+
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-facebook"></i></a>
|
| 230 |
+
</div>
|
| 231 |
+
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 232 |
+
</div>
|
| 233 |
+
</footer>
|
| 234 |
+
<script>
|
| 235 |
+
const sidebar = document.getElementById('sidebar');
|
| 236 |
+
const toggleBtn = document.getElementById('sidebarToggle');
|
| 237 |
+
const closeSidebarBtn = document.getElementById('closeSidebar');
|
| 238 |
+
toggleBtn.addEventListener('click', () => {
|
| 239 |
+
sidebar.classList.toggle('active');
|
| 240 |
+
sidebar.classList.toggle('-translate-x-full');
|
| 241 |
+
sidebar.classList.toggle('translate-x-0');
|
| 242 |
+
});
|
| 243 |
+
closeSidebarBtn.addEventListener('click', () => {
|
| 244 |
+
sidebar.classList.remove('active');
|
| 245 |
+
sidebar.classList.add('-translate-x-full');
|
| 246 |
+
sidebar.classList.remove('translate-x-0');
|
| 247 |
+
});
|
| 248 |
+
document.addEventListener('click', (e) => {
|
| 249 |
+
if (!sidebar.contains(e.target) && !toggleBtn.contains(e.target) && window.innerWidth < 768) {
|
| 250 |
+
sidebar.classList.remove('active');
|
| 251 |
+
sidebar.classList.add('-translate-x-full');
|
| 252 |
+
sidebar.classList.remove('translate-x-0');
|
| 253 |
+
}
|
| 254 |
+
});
|
| 255 |
+
function showCardDetails(cardId) {
|
| 256 |
+
document.getElementById(`${cardId}-details`).classList.remove('hidden');
|
| 257 |
+
}
|
| 258 |
+
function closeCardDetails(cardId) {
|
| 259 |
+
document.getElementById(`${cardId}-details`).classList.add('hidden');
|
| 260 |
+
}
|
| 261 |
+
</script>
|
| 262 |
+
</body>
|
| 263 |
+
</html>
|
templates/chat.html
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<meta name="description" content="Chat with MGZon Chatbot, an AI-powered tool for coding, analysis, and e-commerce queries. Supports text, image, and audio inputs." />
|
| 7 |
+
<meta name="keywords" content="MGZon Chatbot, AI chatbot, code generation, DeepSeek, Gradio, FastAPI, e-commerce, programming, Mark Al-Asfar" />
|
| 8 |
+
<meta name="author" content="Mark Al-Asfar" />
|
| 9 |
+
<meta name="robots" content="index, follow" />
|
| 10 |
+
<title>MGZon Chatbot – AI Assistant</title>
|
| 11 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico" />
|
| 12 |
+
<link rel="apple-touch-icon" href="static/images/mg.svg" />
|
| 13 |
+
<!-- Open Graph -->
|
| 14 |
+
<meta property="og:title" content="MGZon Chatbot – AI Assistant" />
|
| 15 |
+
<meta property="og:description" content="Chat with MGZon Chatbot for coding, analysis, and e-commerce queries with text, image, and audio support." />
|
| 16 |
+
<meta property="og:image" content="static/images/mg.svg" />
|
| 17 |
+
<meta property="og:url" content="https://mgzon-mgzon-app.hf.space/chat" />
|
| 18 |
+
<meta property="og:type" content="website" />
|
| 19 |
+
<!-- Twitter Card -->
|
| 20 |
+
<meta name="twitter:card" content="summary_large_image" />
|
| 21 |
+
<meta name="twitter:title" content="MGZon Chatbot – AI Assistant" />
|
| 22 |
+
<meta name="twitter:description" content="Chat with MGZon Chatbot for coding, analysis, and e-commerce queries with text, image, and audio support." />
|
| 23 |
+
<meta name="twitter:image" content="static/images/mg.svg
|
| 24 |
+
|
| 25 |
+
" />
|
| 26 |
+
<!-- JSON-LD -->
|
| 27 |
+
<script type="application/ld+json">
|
| 28 |
+
{
|
| 29 |
+
"@context": "https://schema.org",
|
| 30 |
+
"@type": "WebPage",
|
| 31 |
+
"name": "MGZon Chatbot",
|
| 32 |
+
"url": "https://mgzon-mgzon-app.hf.space/chat",
|
| 33 |
+
"description": "An AI-powered chatbot for coding, analysis, and e-commerce queries."
|
| 34 |
+
}
|
| 35 |
+
</script>
|
| 36 |
+
<link rel="stylesheet" href="/static/css/style.css">
|
| 37 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css">
|
| 38 |
+
<link rel="stylesheet" href="https://unpkg.com/aos@2.3.1/dist/aos.css">
|
| 39 |
+
</head>
|
| 40 |
+
<body>
|
| 41 |
+
<div id="mainHeader" style="display: flex; align-items: center; justify-content: center; padding: 20px;">
|
| 42 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" style="width: 100px; margin-bottom: 10px;">
|
| 43 |
+
<h1>MGZon Chatbot</h1>
|
| 44 |
+
</div>
|
| 45 |
+
<div id="chatHeader" style="display: none;" aria-hidden="true">
|
| 46 |
+
<div class="chat-title">MGZon Chatbot</div>
|
| 47 |
+
<div class="chat-controls">
|
| 48 |
+
<button id="homeBtn" aria-label="Home">🏠</button>
|
| 49 |
+
<button id="clearBtn" aria-label="Clear Chat">🗑️</button>
|
| 50 |
+
{% if not user %}
|
| 51 |
+
<button id="loginBtn" class="bg-gradient-to-r from-blue-500 to-cyan-600 text-white px-4 py-2 rounded" aria-label="Login">Login</button>
|
| 52 |
+
{% endif %}
|
| 53 |
+
</div>
|
| 54 |
+
</div>
|
| 55 |
+
<div id="initialContent" style="text-align: center; padding: 20px;">
|
| 56 |
+
<p>A versatile chatbot powered by DeepSeek, GPT-OSS, CLIP, Whisper, and TTS. Type your query, upload images/files, or record audio!</p>
|
| 57 |
+
<div class="prompt-item" data-prompt="What's the capital of France?">Capital of France</div>
|
| 58 |
+
<div class="prompt-item" data-prompt="Generate a Python script for a simple web server">Python Web Server</div>
|
| 59 |
+
</div>
|
| 60 |
+
<div class="chat-section">
|
| 61 |
+
<div id="chatArea">
|
| 62 |
+
<div id="chatBox" class="flex-col" aria-live="polite"></div>
|
| 63 |
+
<div id="messageLimitWarning" class="text-red-500 text-center hidden">You have reached the message limit. Please <a href="/login" class="text-blue-300 underline">login</a> to continue.</div>
|
| 64 |
+
</div>
|
| 65 |
+
<form id="footerForm" class="flex p-3 bg-transparent" autocomplete="off" style="position: relative; margin-top: auto; width: 100%;">
|
| 66 |
+
<div id="inputContainer">
|
| 67 |
+
<input type="text" id="userInput" placeholder="Ask anything..." required style="word-break:break-word;" />
|
| 68 |
+
<div id="rightIconGroup">
|
| 69 |
+
<button type="button" id="fileBtn" aria-label="Upload File">📎</button>
|
| 70 |
+
<input type="file" id="fileInput" accept="image/*,.mp3,.wav" style="display: none;" />
|
| 71 |
+
<button type="button" id="audioBtn" aria-label="Record Audio">🎤</button>
|
| 72 |
+
<input type="file" id="audioInput" accept="audio/*" style="display: none;" />
|
| 73 |
+
<button type="submit" id="sendBtn" disabled aria-label="Send">
|
| 74 |
+
<svg id="sendIcon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
| 75 |
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7-7 7M3 12h11" />
|
| 76 |
+
</svg>
|
| 77 |
+
</button>
|
| 78 |
+
<button id="stopBtn" class="icon-btn" aria-label="Stop" title="Stop" style="display: none;">
|
| 79 |
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="white" xmlns="http://www.w3.org/2000/svg">
|
| 80 |
+
<rect x="6" y="6" width="12" height="12" rx="2" fill="white" />
|
| 81 |
+
</svg>
|
| 82 |
+
</button>
|
| 83 |
+
</div>
|
| 84 |
+
</div>
|
| 85 |
+
</form>
|
| 86 |
+
<div id="filePreview" class="upload-preview" style="display: none;"></div>
|
| 87 |
+
<div id="audioPreview" class="audio-preview" style="display: none;"></div>
|
| 88 |
+
</div>
|
| 89 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.0/marked.min.js"></script>
|
| 90 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
|
| 91 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
|
| 92 |
+
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
| 93 |
+
<script src="/static/js/chat.js"></script>
|
| 94 |
+
</body>
|
| 95 |
+
</html>
|
templates/docs.html
CHANGED
|
@@ -1,319 +1,284 @@
|
|
| 1 |
<!DOCTYPE html>
|
| 2 |
<html lang="en">
|
| 3 |
<head>
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
<div class="sidebar fixed top-0 left-0 h-full w-64 bg-gradient-to-b from-blue-800 to-orange-500 text-white p-6 flex flex-col md:translate-x-0 transition-transform duration-300">
|
| 27 |
-
<img src="https://raw.githubusercontent.com/Mark-Lasfar/MGZon/main/public/icons/mg.svg" alt="MGZon Logo" class="w-20 h-20 mb-6 animate-pulse">
|
| 28 |
-
<nav class="flex flex-col gap-4">
|
| 29 |
-
<a href="/" class="px-4 py-2 rounded-lg hover:bg-orange-600 transition">Home</a>
|
| 30 |
-
<a href="/docs" class="px-4 py-2 rounded-lg bg-orange-600">API Documentation</a>
|
| 31 |
-
<a href="https://hager-zon.vercel.app/about" class="px-4 py-2 rounded-lg hover:bg-orange-600 transition">About MGZon</a>
|
| 32 |
-
<a href="https://hager-zon.vercel.app/community" class="px-4 py-2 rounded-lg hover:bg-orange-600 transition">Community</a>
|
| 33 |
-
<a href="https://mark-elasfar.web.app/" target="_blank" class="px-4 py-2 rounded-lg hover:bg-orange-600 transition">Mark Al-Asfar</a>
|
| 34 |
-
</nav>
|
| 35 |
-
</div>
|
| 36 |
-
<div class="flex-1 md:ml-64 p-6">
|
| 37 |
-
<div class="container max-w-6xl mx-auto">
|
| 38 |
-
<div class="text-center py-12">
|
| 39 |
-
<img src="https://raw.githubusercontent.com/Mark-Lasfar/MGZon/main/public/icons/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 40 |
-
<h1 class="text-5xl font-bold mb-4 animate-fade-in">MGZon API Documentation 📚</h1>
|
| 41 |
-
<p class="text-lg mb-8">
|
| 42 |
-
Integrate MGZon Chatbot into your projects with our API. Supports Python (Django, Flask, FastAPI), JavaScript (React, Node.js, Express), Ruby (Rails), PHP (Laravel), and more.
|
| 43 |
-
</p>
|
| 44 |
-
</div>
|
| 45 |
-
<div class="docs my-12">
|
| 46 |
-
<h2 class="text-3xl font-bold text-center mb-8">Endpoints</h2>
|
| 47 |
-
<div class="flex flex-wrap gap-4 mb-8">
|
| 48 |
-
<button class="tab-btn bg-orange-500 text-white px-4 py-2 rounded-lg" data-tab="chat">Chat</button>
|
| 49 |
-
<button class="tab-btn bg-gray-700 text-white px-4 py-2 rounded-lg" data-tab="code">Code</button>
|
| 50 |
-
<button class="tab-btn bg-gray-700 text-white px-4 py-2 rounded-lg" data-tab="analysis">Analysis</button>
|
| 51 |
-
<button class="tab-btn bg-gray-700 text-white px-4 py-2 rounded-lg" data-tab="oauth">OAuth</button>
|
| 52 |
-
</div>
|
| 53 |
-
<div id="chat" class="tab-content active">
|
| 54 |
-
<div class="code-block bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
| 55 |
-
<h3 class="text-xl font-semibold text-orange-500 mb-2">POST /api/chat</h3>
|
| 56 |
-
<p>Send a chat message to the MGZon Chatbot and get a response.</p>
|
| 57 |
-
<pre><code class="language-json">{
|
| 58 |
-
"message": "Your query here",
|
| 59 |
-
"system_prompt": "You are a helpful assistant",
|
| 60 |
-
"history": [{"role": "user", "content": "Previous message"}, {"role": "assistant", "content": "Previous response"}],
|
| 61 |
-
"temperature": 0.7,
|
| 62 |
-
"max_new_tokens": 4096,
|
| 63 |
-
"enable_browsing": false
|
| 64 |
-
}</code></pre>
|
| 65 |
-
<button class="copy-btn bg-orange-500 text-white px-4 py-2 rounded-lg mt-4">Copy</button>
|
| 66 |
-
</div>
|
| 67 |
-
<div class="code-block bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
| 68 |
-
<h3 class="text-xl font-semibold text-orange-500 mb-2">Python (requests)</h3>
|
| 69 |
-
<pre><code class="language-python">import requests
|
| 70 |
-
|
| 71 |
-
response = requests.post(
|
| 72 |
-
"https://hager-zon.vercel.app/api/chat",
|
| 73 |
-
json={
|
| 74 |
-
"message": "Generate a React component",
|
| 75 |
-
"system_prompt": "You are a coding expert",
|
| 76 |
-
"temperature": 0.7,
|
| 77 |
-
"max_new_tokens": 4096
|
| 78 |
-
}
|
| 79 |
-
)
|
| 80 |
-
print(response.json())</code></pre>
|
| 81 |
-
<button class="copy-btn bg-orange-500 text-white px-4 py-2 rounded-lg mt-4">Copy</button>
|
| 82 |
-
</div>
|
| 83 |
-
<div class="code-block bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
| 84 |
-
<h3 class="text-xl font-semibold text-orange-500 mb-2">Python (Django)</h3>
|
| 85 |
-
<pre><code class="language-python">import requests
|
| 86 |
-
from django.http import JsonResponse
|
| 87 |
-
from django.views import View
|
| 88 |
-
|
| 89 |
-
class ChatView(View):
|
| 90 |
-
def post(self, request):
|
| 91 |
-
data = request.POST.get('message')
|
| 92 |
-
response = requests.post(
|
| 93 |
-
"https://hager-zon.vercel.app/api/chat",
|
| 94 |
-
json={"message": data, "system_prompt": "You are a coding expert", "temperature": 0.7}
|
| 95 |
-
)
|
| 96 |
-
return JsonResponse(response.json())</code></pre>
|
| 97 |
-
<button class="copy-btn bg-orange-500 text-white px-4 py-2 rounded-lg mt-4">Copy</button>
|
| 98 |
-
</div>
|
| 99 |
-
<div class="code-block bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
| 100 |
-
<h3 class="text-xl font-semibold text-orange-500 mb-2">Python (Flask)</h3>
|
| 101 |
-
<pre><code class="language-python">from flask import Flask, request, jsonify
|
| 102 |
-
import requests
|
| 103 |
-
|
| 104 |
-
app = Flask(__name__)
|
| 105 |
-
|
| 106 |
-
@app.route('/chat', methods=['POST'])
|
| 107 |
-
def chat():
|
| 108 |
-
data = request.json.get('message')
|
| 109 |
-
response = requests.post(
|
| 110 |
-
"https://hager-zon.vercel.app/api/chat",
|
| 111 |
-
json={"message": data, "system_prompt": "You are a coding expert", "temperature": 0.7}
|
| 112 |
-
)
|
| 113 |
-
return jsonify(response.json())</code></pre>
|
| 114 |
-
<button class="copy-btn bg-orange-500 text-white px-4 py-2 rounded-lg mt-4">Copy</button>
|
| 115 |
-
</div>
|
| 116 |
-
<div class="code-block bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
| 117 |
-
<h3 class="text-xl font-semibold text-orange-500 mb-2">JavaScript (React)</h3>
|
| 118 |
-
<pre><code class="language-javascript">import React, { useState } from 'react';
|
| 119 |
-
|
| 120 |
-
function ChatComponent() {
|
| 121 |
-
const [message, setMessage] = useState('');
|
| 122 |
-
const [response, setResponse] = useState('');
|
| 123 |
-
|
| 124 |
-
const handleSubmit = async () => {
|
| 125 |
-
const res = await fetch('https://hager-zon.vercel.app/api/chat', {
|
| 126 |
-
method: 'POST',
|
| 127 |
-
headers: { 'Content-Type': 'application/json' },
|
| 128 |
-
body: JSON.stringify({
|
| 129 |
-
message,
|
| 130 |
-
system_prompt: 'You are a coding expert',
|
| 131 |
-
temperature: 0.7,
|
| 132 |
-
max_new_tokens: 4096
|
| 133 |
-
})
|
| 134 |
-
});
|
| 135 |
-
const data = await res.json();
|
| 136 |
-
setResponse(data.response);
|
| 137 |
-
};
|
| 138 |
-
|
| 139 |
-
return (
|
| 140 |
-
<div>
|
| 141 |
-
<input type="text" value={message} onChange={(e) => setMessage(e.target.value)} />
|
| 142 |
-
<button onClick={handleSubmit}>Send</button>
|
| 143 |
-
<p>{response}</p>
|
| 144 |
-
</div>
|
| 145 |
-
);
|
| 146 |
-
}
|
| 147 |
-
|
| 148 |
-
export default ChatComponent;</code></pre>
|
| 149 |
-
<button class="copy-btn bg-orange-500 text-white px-4 py-2 rounded-lg mt-4">Copy</button>
|
| 150 |
-
</div>
|
| 151 |
-
<div class="code-block bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
| 152 |
-
<h3 class="text-xl font-semibold text-orange-500 mb-2">JavaScript (Node.js/Express)</h3>
|
| 153 |
-
<pre><code class="language-javascript">const express = require('express');
|
| 154 |
-
const fetch = require('node-fetch');
|
| 155 |
-
const app = express();
|
| 156 |
-
|
| 157 |
-
app.use(express.json());
|
| 158 |
-
|
| 159 |
-
app.post('/chat', async (req, res) => {
|
| 160 |
-
const { message } = req.body;
|
| 161 |
-
const response = await fetch('https://hager-zon.vercel.app/api/chat', {
|
| 162 |
-
method: 'POST',
|
| 163 |
-
headers: { 'Content-Type': 'application/json' },
|
| 164 |
-
body: JSON.stringify({
|
| 165 |
-
message,
|
| 166 |
-
system_prompt: 'You are a coding expert',
|
| 167 |
-
temperature: 0.7,
|
| 168 |
-
max_new_tokens: 4096
|
| 169 |
-
})
|
| 170 |
-
});
|
| 171 |
-
const data = await response.json();
|
| 172 |
-
res.json(data);
|
| 173 |
-
});
|
| 174 |
-
|
| 175 |
-
app.listen(3000, () => console.log('Server running on port 3000'));</code></pre>
|
| 176 |
-
<button class="copy-btn bg-orange-500 text-white px-4 py-2 rounded-lg mt-4">Copy</button>
|
| 177 |
-
</div>
|
| 178 |
-
<div class="code-block bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
| 179 |
-
<h3 class="text-xl font-semibold text-orange-500 mb-2">Ruby (Rails)</h3>
|
| 180 |
-
<pre><code class="language-ruby">require 'httparty'
|
| 181 |
-
|
| 182 |
-
class ChatController < ApplicationController
|
| 183 |
-
def create
|
| 184 |
-
response = HTTParty.post(
|
| 185 |
-
'https://hager-zon.vercel.app/api/chat',
|
| 186 |
-
body: {
|
| 187 |
-
message: params[:message],
|
| 188 |
-
system_prompt: 'You are a coding expert',
|
| 189 |
-
temperature: 0.7,
|
| 190 |
-
max_new_tokens: 4096
|
| 191 |
-
}.to_json,
|
| 192 |
-
headers: { 'Content-Type' => 'application/json' }
|
| 193 |
-
)
|
| 194 |
-
render json: response.parsed_response
|
| 195 |
-
end
|
| 196 |
-
end</code></pre>
|
| 197 |
-
<button class="copy-btn bg-orange-500 text-white px-4 py-2 rounded-lg mt-4">Copy</button>
|
| 198 |
-
</div>
|
| 199 |
-
<div class="code-block bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
| 200 |
-
<h3 class="text-xl font-semibold text-orange-500 mb-2">PHP (Laravel)</h3>
|
| 201 |
-
<pre><code class="language-php">use Illuminate\Support\Facades\Http;
|
| 202 |
-
|
| 203 |
-
class ChatController extends Controller
|
| 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 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
}
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
</div>
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 304 |
</div>
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
</body>
|
| 319 |
</html>
|
|
|
|
| 1 |
<!DOCTYPE html>
|
| 2 |
<html lang="en">
|
| 3 |
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<meta name="description" content="Explore MGZon Chatbot API documentation for integrating AI-powered code generation and e-commerce tools.">
|
| 7 |
+
<meta name="keywords" content="MGZon Chatbot, API documentation, code generation, e-commerce, FastAPI, Mark Al-Asfar">
|
| 8 |
+
<meta name="author" content="Mark Al-Asfar">
|
| 9 |
+
<meta name="robots" content="index, follow">
|
| 10 |
+
<title>API Documentation - MGZon Chatbot</title>
|
| 11 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 12 |
+
<link rel="apple-touch-icon" href="static/images/mg.svg">
|
| 13 |
+
<!-- Open Graph -->
|
| 14 |
+
<meta property="og:title" content="API Documentation - MGZon Chatbot">
|
| 15 |
+
<meta property="og:description" content="Explore MGZon Chatbot API documentation for integrating AI-powered code generation and e-commerce tools.">
|
| 16 |
+
<meta property="og:image" content="static/images/mg.svg">
|
| 17 |
+
<meta property="og:url" content="https://mgzon-mgzon-app.hf.space/docs">
|
| 18 |
+
<meta property="og:type" content="website">
|
| 19 |
+
<!-- Twitter Card -->
|
| 20 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 21 |
+
<meta name="twitter:title" content="API Documentation - MGZon Chatbot">
|
| 22 |
+
<meta name="twitter:description" content="Explore MGZon Chatbot API documentation for integrating AI-powered code generation and e-commerce tools.">
|
| 23 |
+
<meta name="twitter:image" content="https://raw.githubusercontent.com/Mark-Lasfar/MGZon/main/public/icons/mg.svg">
|
| 24 |
+
<!-- JSON-LD -->
|
| 25 |
+
<script type="application/ld+json">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
{
|
| 27 |
+
"@context": "https://schema.org",
|
| 28 |
+
"@type": "WebPage",
|
| 29 |
+
"name": "API Documentation - MGZon Chatbot",
|
| 30 |
+
"url": "https://mgzon-mgzon-app.hf.space/docs",
|
| 31 |
+
"description": "Explore MGZon Chatbot API documentation for integrating AI-powered code generation and e-commerce tools.",
|
| 32 |
+
"keywords": ["MGZon Chatbot", "API documentation", "code generation", "e-commerce", "FastAPI", "Mark Al-Asfar", "MGZon", "MGZon AI", "AI chatbot", "Code generation bot", "Python AI chatbot", "FastAPI integration", "AI for coding", "AI developer tools", "text generation"],
|
| 33 |
+
"isPartOf": {
|
| 34 |
+
"@type": "WebSite",
|
| 35 |
+
"name": "MGZon Chatbot",
|
| 36 |
+
"url": "https://mgzon-mgzon-app.hf.space/"
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
</script>
|
| 40 |
+
<!-- Tailwind (v3) -->
|
| 41 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 42 |
+
<!-- Boxicons -->
|
| 43 |
+
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
|
| 44 |
+
<!-- Prism (for code highlighting) -->
|
| 45 |
+
<link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css" rel="stylesheet">
|
| 46 |
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js"></script>
|
| 47 |
+
<style>
|
| 48 |
+
@keyframes gradientShift {
|
| 49 |
+
0% { background-position: 0% 50%; }
|
| 50 |
+
50% { background-position: 100% 50%; }
|
| 51 |
+
100% { background-position: 0% 50%; }
|
| 52 |
+
}
|
| 53 |
+
body {
|
| 54 |
+
background: linear-gradient(135deg, #0f172a, #0e7490, #065f46, #064e3b);
|
| 55 |
+
background-size: 400% 400%;
|
| 56 |
+
animation: gradientShift 15s ease infinite;
|
| 57 |
+
font-family: system-ui, sans-serif;
|
| 58 |
}
|
| 59 |
+
.glass {
|
| 60 |
+
background: rgba(255, 255, 255, 0.07);
|
| 61 |
+
border-radius: 1rem;
|
| 62 |
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
| 63 |
+
backdrop-filter: blur(12px);
|
| 64 |
+
-webkit-backdrop-filter: blur(12px);
|
| 65 |
+
}
|
| 66 |
+
.sidebar {
|
| 67 |
+
transition: transform 0.3s ease-in-out;
|
| 68 |
+
}
|
| 69 |
+
.sidebar.collapsed .logo {
|
| 70 |
+
opacity: 0;
|
| 71 |
+
transition: opacity 0.2s ease;
|
| 72 |
+
}
|
| 73 |
+
.main-content {
|
| 74 |
+
min-height: calc(100vh - 4rem);
|
| 75 |
+
}
|
| 76 |
+
.glass:hover {
|
| 77 |
+
transform: scale(1.05);
|
| 78 |
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
| 79 |
+
background: rgba(255, 255, 255, 0.15);
|
| 80 |
+
}
|
| 81 |
+
@media (max-width: 768px) {
|
| 82 |
+
.sidebar {
|
| 83 |
+
transform: translateX(-100%);
|
| 84 |
+
}
|
| 85 |
+
.sidebar.active {
|
| 86 |
+
transform: translateX(0);
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
</style>
|
| 90 |
+
</head>
|
| 91 |
+
<body class="text-white flex flex-col min-h-screen">
|
| 92 |
+
<!-- Mobile toggle button -->
|
| 93 |
+
<button id="sidebarToggle" class="md:hidden fixed top-4 left-4 z-50 p-2 text-2xl text-white rounded bg-gray-800/60 hover:bg-gray-700/80 transition" aria-label="Toggle navigation">
|
| 94 |
+
<i class="bx bx-menu"></i>
|
| 95 |
+
</button>
|
| 96 |
+
<!-- Sidebar -->
|
| 97 |
+
<aside id="sidebar" class="sidebar fixed inset-y-0 left-0 w-64 bg-gradient-to-b from-teal-800 to-emerald-900 p-6 flex flex-col overflow-y-auto z-40">
|
| 98 |
+
<button id="closeSidebar" class="md:hidden text-white text-2xl absolute top-4 right-4" aria-label="Close sidebar">✕</button>
|
| 99 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="logo w-20 h-20 mx-auto mb-8 animate-pulse">
|
| 100 |
+
<nav class="flex flex-col gap-3">
|
| 101 |
+
<a href="/" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Home</a>
|
| 102 |
+
<a href="/docs" class="px-4 py-2 rounded-lg bg-emerald-600">API Documentation</a>
|
| 103 |
+
<a href="/about" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">About MGZon</a>
|
| 104 |
+
<a href="/login" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Login</a>
|
| 105 |
+
<a href="/register" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Register</a>
|
| 106 |
+
<a href="https://hager-zon.vercel.app/community" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Community</a>
|
| 107 |
+
<a href="https://mark-elasfar.web.app/" target="_blank" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Mark Al-Asfar</a>
|
| 108 |
+
</nav>
|
| 109 |
+
</aside>
|
| 110 |
+
<!-- Main content -->
|
| 111 |
+
<main class="flex-1 md:ml-64 p-6 main-content">
|
| 112 |
+
<section class="container max-w-6xl mx-auto">
|
| 113 |
+
<div class="text-center py-12">
|
| 114 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 115 |
+
<h1 class="text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-teal-300 to-emerald-400">About MGZon AI by Mark Al-Asfar</h1>
|
| 116 |
+
MGZon Chatbot API Documentation
|
| 117 |
+
</h1>
|
| 118 |
+
<p class="text-lg max-w-2xl mx-auto mb-8">
|
| 119 |
+
Integrate MGZon Chatbot's AI-powered features into your applications. Learn how to use our APIs for code generation, web search, and e-commerce solutions.
|
| 120 |
+
</p>
|
| 121 |
+
<p>Explore the MGZon Chatbot API for seamless integration of AI-powered code generation, text generation, and e-commerce automation. Built by Mark Al-Asfar using FastAPI and Hugging Face AI.</p>
|
| 122 |
+
<a href="https://x.ai/api" target="_blank" class="inline-flex items-center bg-gradient-to-r from-emerald-500 to-teal-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:scale-105 transition-transform shadow-lg hover:shadow-xl">
|
| 123 |
+
Get API Key <i class="bx bx-key ml-2"></i>
|
| 124 |
+
</a>
|
| 125 |
+
</div>
|
| 126 |
+
<!-- API Overview -->
|
| 127 |
+
<section class="my-12">
|
| 128 |
+
<h2 class="text-3xl font-bold text-center mb-8">API Overview</h2>
|
| 129 |
+
<div class="glass p-6">
|
| 130 |
+
<p class="mb-4">The MGZon Chatbot API provides endpoints for code generation, real-time web search, and e-commerce functionalities. Built with FastAPI, it offers secure and scalable integration.</p>
|
| 131 |
+
<p>Base URL: <code class="bg-gray-800/60 p-1 rounded">https://mgzon-mgzon-app.hf.space/api</code></p>
|
| 132 |
</div>
|
| 133 |
+
</section>
|
| 134 |
+
<!-- Authentication -->
|
| 135 |
+
<section class="my-12">
|
| 136 |
+
<h2 class="text-3xl font-bold text-center mb-8">Authentication</h2>
|
| 137 |
+
<div class="glass p-6">
|
| 138 |
+
<p class="mb-4">Use JWT tokens for authentication. Register or login to obtain a token.</p>
|
| 139 |
+
<pre><code class="language-bash">
|
| 140 |
+
curl -X POST "https://mgzon-mgzon-app.hf.space/auth/jwt/login" \
|
| 141 |
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
| 142 |
+
-d "username=your_email&password=your_password"
|
| 143 |
+
</code></pre>
|
| 144 |
+
</div>
|
| 145 |
+
</section>
|
| 146 |
+
<!-- Endpoints -->
|
| 147 |
+
<section class="my-12">
|
| 148 |
+
<h2 class="text-3xl font-bold text-center mb-8">Endpoints</h2>
|
| 149 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
| 150 |
+
<div class="glass p-6">
|
| 151 |
+
<h3 class="text-xl font-semibold mb-2">/chat (POST)</h3>
|
| 152 |
+
<p class="mb-4">Interact with the AI chatbot for code generation or queries.</p>
|
| 153 |
+
<pre><code class="language-bash">
|
| 154 |
+
curl -X POST "https://mgzon-mgzon-app.hf.space/chat" \
|
| 155 |
+
-H "Authorization: Bearer your_token" \
|
| 156 |
+
-H "Content-Type: application/json" \
|
| 157 |
+
-d '{"message": "Generate a Python function"}'
|
| 158 |
+
</code></pre>
|
| 159 |
+
</div>
|
| 160 |
+
<div class="glass p-6">
|
| 161 |
+
<h3 class="text-xl font-semibold mb-2">/web_search (POST)</h3>
|
| 162 |
+
<p class="mb-4">Perform real-time web searches.</p>
|
| 163 |
+
<pre><code class="language-bash">
|
| 164 |
+
curl -X POST "https://mgzon-mgzon-app.hf.space/web_search" \
|
| 165 |
+
-H "Authorization: Bearer your_token" \
|
| 166 |
+
-H "Content-Type: application/json" \
|
| 167 |
+
-d '{"query": "AI trends 2025"}'
|
| 168 |
+
</code></pre>
|
| 169 |
+
</div>
|
| 170 |
+
</div>
|
| 171 |
+
</section>
|
| 172 |
+
<!-- Getting Started -->
|
| 173 |
+
<section class="my-12">
|
| 174 |
+
<h2 class="text-3xl font-bold text-center mb-8">Getting Started</h2>
|
| 175 |
+
<div class="glass p-6">
|
| 176 |
+
<p class="mb-4">1. Register at <a href="/register" class="text-emerald-300 hover:underline">/register</a>.</p>
|
| 177 |
+
<p class="mb-4">2. Obtain your API key from <a href="https://x.ai/api" target="_blank" class="text-emerald-300 hover:underline">xAI API</a>.</p>
|
| 178 |
+
<p>3. Use the endpoints above to integrate MGZon Chatbot into your application.</p>
|
| 179 |
+
</div>
|
| 180 |
+
</section>
|
| 181 |
+
</section>
|
| 182 |
+
</main>
|
| 183 |
+
<!-- Footer -->
|
| 184 |
+
<footer class="bg-gradient-to-r from-teal-900 to-emerald-900 py-12 mt-8">
|
| 185 |
+
<div class="container max-w-6xl mx-auto text-center">
|
| 186 |
+
<img src="static/images/mg.svg" alt="MGZon Chatbot Logo by Mark Al-Asfar" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 187 |
+
<p class="mb-4">
|
| 188 |
+
Developed by <a href="https://mark-elasfar.web.app/" target="_blank" class="text-emerald-300 hover:underline">Mark Al-Asfar</a>
|
| 189 |
+
| Powered by <a href="https://hager-zon.vercel.app/" target="_blank" class="text-emerald-300 hover:underline">MGZon AI</a>
|
| 190 |
+
</p>
|
| 191 |
+
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
| 192 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('email')">
|
| 193 |
+
<i class="bx bx-mail-send text-3xl text-emerald-300 mb-2"></i>
|
| 194 |
+
<h4 class="font-semibold mb-1">Email Us</h4>
|
| 195 |
+
<p><a href="mailto:support@mgzon.com" class="text-emerald-300 hover:underline">support@mgzon.com</a></p>
|
| 196 |
+
<div id="email-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 197 |
+
<p>Reach out to our support team for any inquiries or assistance.</p>
|
| 198 |
+
<button onclick="closeCardDetails('email')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 199 |
+
</div>
|
| 200 |
+
</div>
|
| 201 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('phone')">
|
| 202 |
+
<i class="bx bx-phone text-3xl text-emerald-300 mb-2"></i>
|
| 203 |
+
<h4 class="font-semibold mb-1">Phone Support</h4>
|
| 204 |
+
<p>+1-800-123-4567</p>
|
| 205 |
+
<div id="phone-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 206 |
+
<p>Contact our support team via phone for immediate assistance.</p>
|
| 207 |
+
<button onclick="closeCardDetails('phone')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 208 |
+
</div>
|
| 209 |
+
</div>
|
| 210 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('community')">
|
| 211 |
+
<i class="bx bx-group text-3xl text-emerald-300 mb-2"></i>
|
| 212 |
+
<h4 class="font-semibold mb-1">Community</h4>
|
| 213 |
+
<p><a href="https://hager-zon.vercel.app/community" class="text-emerald-300 hover:underline">Join us</a></p>
|
| 214 |
+
<div id="community-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 215 |
+
<p>Join our vibrant community to share ideas and collaborate.</p>
|
| 216 |
+
<button onclick="closeCardDetails('community')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 217 |
+
</div>
|
| 218 |
+
</div>
|
| 219 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('api-docs')">
|
| 220 |
+
<i class="bx bx-code-alt text-3xl text-emerald-300 mb-2"></i>
|
| 221 |
+
<h4 class="font-semibold mb-1">API Docs</h4>
|
| 222 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Explore Docs</a></p>
|
| 223 |
+
<div id="api-docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 224 |
+
<p>Explore our API documentation for seamless integration.</p>
|
| 225 |
+
<button onclick="closeCardDetails('api-docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 226 |
+
</div>
|
| 227 |
+
</div>
|
| 228 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('faq')">
|
| 229 |
+
<i class="bx bx-help-circle text-3xl text-emerald-300 mb-2"></i>
|
| 230 |
+
<h4 class="font-semibold mb-1">FAQ</h4>
|
| 231 |
+
<p><a href="https://hager-zon.vercel.app/faq" target="_blank" class="text-emerald-300 hover:underline">Read FAQ</a></p>
|
| 232 |
+
<div id="faq-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 233 |
+
<p>Find answers to common questions in our FAQ section.</p>
|
| 234 |
+
<button onclick="closeCardDetails('faq')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 235 |
+
</div>
|
| 236 |
</div>
|
| 237 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('docs')">
|
| 238 |
+
<i class="bx bx-book text-3xl text-emerald-300 mb-2"></i>
|
| 239 |
+
<h4 class="font-semibold mb-1">Documentation</h4>
|
| 240 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Full Docs</a></p>
|
| 241 |
+
<div id="docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 242 |
+
<p>Access comprehensive documentation for MGZon Chatbot.</p>
|
| 243 |
+
<button onclick="closeCardDetails('docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 244 |
+
</div>
|
| 245 |
+
</div>
|
| 246 |
+
</div>
|
| 247 |
+
<div class="flex justify-center gap-6 mt-6">
|
| 248 |
+
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-github"></i></a>
|
| 249 |
+
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-twitter"></i></a>
|
| 250 |
+
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-facebook"></i></a>
|
| 251 |
+
</div>
|
| 252 |
+
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 253 |
+
</div>
|
| 254 |
+
</footer>
|
| 255 |
+
<script>
|
| 256 |
+
const sidebar = document.getElementById('sidebar');
|
| 257 |
+
const toggleBtn = document.getElementById('sidebarToggle');
|
| 258 |
+
const closeSidebarBtn = document.getElementById('closeSidebar');
|
| 259 |
+
toggleBtn.addEventListener('click', () => {
|
| 260 |
+
sidebar.classList.toggle('active');
|
| 261 |
+
sidebar.classList.toggle('-translate-x-full');
|
| 262 |
+
sidebar.classList.toggle('translate-x-0');
|
| 263 |
+
});
|
| 264 |
+
closeSidebarBtn.addEventListener('click', () => {
|
| 265 |
+
sidebar.classList.remove('active');
|
| 266 |
+
sidebar.classList.add('-translate-x-full');
|
| 267 |
+
sidebar.classList.remove('translate-x-0');
|
| 268 |
+
});
|
| 269 |
+
document.addEventListener('click', (e) => {
|
| 270 |
+
if (!sidebar.contains(e.target) && !toggleBtn.contains(e.target) && window.innerWidth < 768) {
|
| 271 |
+
sidebar.classList.remove('active');
|
| 272 |
+
sidebar.classList.add('-translate-x-full');
|
| 273 |
+
sidebar.classList.remove('translate-x-0');
|
| 274 |
+
}
|
| 275 |
+
});
|
| 276 |
+
function showCardDetails(cardId) {
|
| 277 |
+
document.getElementById(`${cardId}-details`).classList.remove('hidden');
|
| 278 |
+
}
|
| 279 |
+
function closeCardDetails(cardId) {
|
| 280 |
+
document.getElementById(`${cardId}-details`).classList.add('hidden');
|
| 281 |
+
}
|
| 282 |
+
</script>
|
| 283 |
</body>
|
| 284 |
</html>
|
templates/index.html
CHANGED
|
@@ -1,22 +1,59 @@
|
|
| 1 |
<!DOCTYPE html>
|
| 2 |
<html lang="en">
|
| 3 |
<head>
|
| 4 |
-
<meta charset="UTF-8"
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
<title>MGZon Chatbot – Powered by AI</title>
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
<!-- Tailwind (v3) -->
|
| 9 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
-
|
| 11 |
<!-- Boxicons -->
|
| 12 |
-
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet"
|
| 13 |
-
|
| 14 |
<!-- Prism (for code highlighting) -->
|
| 15 |
-
<link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css" rel="stylesheet"
|
| 16 |
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js"></script>
|
| 17 |
-
|
| 18 |
<style>
|
| 19 |
-
/* Animated gradient background */
|
| 20 |
@keyframes gradientShift {
|
| 21 |
0% { background-position: 0% 50%; }
|
| 22 |
50% { background-position: 100% 50%; }
|
|
@@ -28,8 +65,6 @@
|
|
| 28 |
animation: gradientShift 15s ease infinite;
|
| 29 |
font-family: system-ui, sans-serif;
|
| 30 |
}
|
| 31 |
-
|
| 32 |
-
/* Glass-morphism helpers */
|
| 33 |
.glass {
|
| 34 |
background: rgba(255, 255, 255, 0.07);
|
| 35 |
border-radius: 1rem;
|
|
@@ -37,24 +72,16 @@
|
|
| 37 |
backdrop-filter: blur(12px);
|
| 38 |
-webkit-backdrop-filter: blur(12px);
|
| 39 |
}
|
| 40 |
-
|
| 41 |
-
/* Sidebar transition */
|
| 42 |
.sidebar {
|
| 43 |
transition: transform 0.3s ease-in-out;
|
| 44 |
}
|
| 45 |
-
|
| 46 |
-
/* Hide logo when sidebar is collapsed */
|
| 47 |
.sidebar.collapsed .logo {
|
| 48 |
opacity: 0;
|
| 49 |
transition: opacity 0.2s ease;
|
| 50 |
}
|
| 51 |
-
|
| 52 |
-
/* Prevent sidebar from covering the footer */
|
| 53 |
.main-content {
|
| 54 |
-
min-height: calc(100vh - 4rem);
|
| 55 |
}
|
| 56 |
-
|
| 57 |
-
/* Loading spinner for button */
|
| 58 |
.loading {
|
| 59 |
display: inline-block;
|
| 60 |
width: 1rem;
|
|
@@ -68,15 +95,11 @@
|
|
| 68 |
@keyframes spin {
|
| 69 |
to { transform: rotate(360deg); }
|
| 70 |
}
|
| 71 |
-
|
| 72 |
-
/* Card hover and transition effects */
|
| 73 |
.glass:hover {
|
| 74 |
transform: scale(1.05);
|
| 75 |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
| 76 |
background: rgba(255, 255, 255, 0.15);
|
| 77 |
}
|
| 78 |
-
|
| 79 |
-
/* Responsive adjustments */
|
| 80 |
@media (max-width: 768px) {
|
| 81 |
.sidebar {
|
| 82 |
transform: translateX(-100%);
|
|
@@ -87,166 +110,141 @@
|
|
| 87 |
}
|
| 88 |
</style>
|
| 89 |
</head>
|
| 90 |
-
|
| 91 |
<body class="text-white flex flex-col min-h-screen">
|
| 92 |
<!-- Mobile toggle button -->
|
| 93 |
-
<button
|
| 94 |
-
id="sidebarToggle"
|
| 95 |
-
class="md:hidden fixed top-4 left-4 z-50 p-2 text-2xl text-white rounded bg-gray-800/60 hover:bg-gray-700/80 transition"
|
| 96 |
-
aria-label="Toggle navigation"
|
| 97 |
-
>
|
| 98 |
<i class="bx bx-menu"></i>
|
| 99 |
</button>
|
| 100 |
-
|
| 101 |
<!-- Sidebar -->
|
| 102 |
-
<aside
|
| 103 |
-
id="sidebar"
|
| 104 |
-
|
| 105 |
-
>
|
| 106 |
-
<!-- Close button for mobile -->
|
| 107 |
-
<button
|
| 108 |
-
id="closeSidebar"
|
| 109 |
-
class="md:hidden text-white text-2xl absolute top-4 right-4"
|
| 110 |
-
aria-label="Close sidebar"
|
| 111 |
-
>
|
| 112 |
-
✕
|
| 113 |
-
</button>
|
| 114 |
-
<!-- Logo (optional: hidden in homepage) -->
|
| 115 |
-
<img
|
| 116 |
-
src="https://raw.githubusercontent.com/Mark-Lasfar/MGZon/main/public/icons/mg.svg"
|
| 117 |
-
alt="MGZon Logo"
|
| 118 |
-
class="logo w-20 h-20 mx-auto mb-8 animate-pulse"
|
| 119 |
-
/>
|
| 120 |
<nav class="flex flex-col gap-3">
|
| 121 |
-
<a href="/" class="px-4 py-2 rounded-lg
|
| 122 |
<a href="/docs" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">API Documentation</a>
|
| 123 |
-
<a href="
|
|
|
|
|
|
|
| 124 |
<a href="https://hager-zon.vercel.app/community" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Community</a>
|
| 125 |
<a href="https://mark-elasfar.web.app/" target="_blank" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Mark Al-Asfar</a>
|
| 126 |
</nav>
|
| 127 |
</aside>
|
| 128 |
-
|
| 129 |
<!-- Main content -->
|
| 130 |
<main class="flex-1 md:ml-64 p-6 main-content">
|
| 131 |
<section class="container max-w-6xl mx-auto">
|
| 132 |
<!-- Hero -->
|
| 133 |
<div class="text-center py-12">
|
| 134 |
-
<img
|
| 135 |
-
src="https://raw.githubusercontent.com/Mark-Lasfar/MGZon/main/public/icons/mg.svg"
|
| 136 |
-
alt="MGZon Logo"
|
| 137 |
-
class="w-32 h-32 mx-auto mb-6 animate-bounce"
|
| 138 |
-
/>
|
| 139 |
<h1 class="text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-teal-300 to-emerald-400">
|
| 140 |
Welcome to MGZon Chatbot 🚀
|
| 141 |
</h1>
|
| 142 |
<p class="text-lg max-w-2xl mx-auto mb-8">
|
| 143 |
-
MGZon Chatbot is an AI-powered assistant for code generation,
|
|
|
|
|
|
|
| 144 |
</p>
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
</div>
|
| 154 |
-
|
| 155 |
<!-- Features -->
|
| 156 |
<section class="my-12">
|
| 157 |
-
<h2 class="text-3xl font-bold text-center mb-8">
|
| 158 |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
| 159 |
<div class="glass p-6 relative group cursor-pointer" onclick="showCardDetails('code-generation')">
|
| 160 |
-
<button
|
| 161 |
-
class="absolute top-2 right-2 text-gray-300 hover:text-white transition"
|
| 162 |
-
onclick="event.stopPropagation(); closeCardDetails('code-generation')"
|
| 163 |
-
aria-label="Close card"
|
| 164 |
-
>
|
| 165 |
-
×
|
| 166 |
-
</button>
|
| 167 |
<i class="bx bx-code-alt text-4xl text-emerald-300 mb-4"></i>
|
| 168 |
<h3 class="text-xl font-semibold mb-2">Code Generation</h3>
|
| 169 |
-
<p>Generate code for React, Django, Flask, and more.</p>
|
| 170 |
<div id="code-generation-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 171 |
-
<p>Supports multiple frameworks
|
| 172 |
<button onclick="closeCardDetails('code-generation')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 173 |
</div>
|
| 174 |
</div>
|
| 175 |
<div class="glass p-6 relative group cursor-pointer" onclick="showCardDetails('web-search')">
|
| 176 |
-
<button
|
| 177 |
-
class="absolute top-2 right-2 text-gray-300 hover:text-white transition"
|
| 178 |
-
onclick="event.stopPropagation(); closeCardDetails('web-search')"
|
| 179 |
-
aria-label="Close card"
|
| 180 |
-
>
|
| 181 |
-
×
|
| 182 |
-
</button>
|
| 183 |
<i class="bx bx-search text-4xl text-emerald-300 mb-4"></i>
|
| 184 |
<h3 class="text-xl font-semibold mb-2">Web Search</h3>
|
| 185 |
-
<p>
|
| 186 |
<div id="web-search-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 187 |
-
<p>
|
| 188 |
<button onclick="closeCardDetails('web-search')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 189 |
</div>
|
| 190 |
</div>
|
| 191 |
-
<div class="glass p-6 relative group cursor-pointer" onclick="showCardDetails('
|
| 192 |
-
<button
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
>
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
<i class="bx bx-analyse text-4xl text-emerald-300 mb-4"></i>
|
| 200 |
-
<h3 class="text-xl font-semibold mb-2">Analysis & Review</h3>
|
| 201 |
-
<p>Detailed code and data analysis with insights.</p>
|
| 202 |
-
<div id="analysis-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 203 |
-
<p>Provides in-depth code reviews and data analysis with actionable insights.</p>
|
| 204 |
-
<button onclick="closeCardDetails('analysis')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 205 |
</div>
|
| 206 |
</div>
|
| 207 |
</div>
|
| 208 |
</section>
|
| 209 |
-
|
| 210 |
<!-- News -->
|
| 211 |
<section class="my-12">
|
| 212 |
-
<h2 class="text-3xl font-bold text-center mb-8">Latest MGZon
|
| 213 |
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
| 214 |
<div class="glass p-6">
|
| 215 |
-
<h3 class="text-xl font-semibold mb-2">New
|
| 216 |
-
<p>Explore our
|
| 217 |
<a href="https://hager-zon.vercel.app/blog" target="_blank" class="text-emerald-300 hover:underline">Read More →</a>
|
| 218 |
</div>
|
| 219 |
<div class="glass p-6">
|
| 220 |
-
<h3 class="text-xl font-semibold mb-2">
|
| 221 |
-
<p>
|
| 222 |
-
<a href="https://hager-zon.vercel.app/community" target="_blank" class="text-emerald-300 hover:underline">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
</div>
|
| 224 |
</div>
|
| 225 |
</section>
|
| 226 |
</section>
|
| 227 |
</main>
|
| 228 |
-
|
| 229 |
<!-- Footer -->
|
| 230 |
<footer class="bg-gradient-to-r from-teal-900 to-emerald-900 py-12 mt-8">
|
| 231 |
<div class="container max-w-6xl mx-auto text-center">
|
| 232 |
-
|
| 233 |
-
src="https://raw.githubusercontent.com/Mark-Lasfar/MGZon/main/public/icons/mg.svg"
|
| 234 |
-
alt="MGZon Logo"
|
| 235 |
-
class="w-24 h-24 mx-auto mb-6 animate-pulse"
|
| 236 |
-
/>
|
| 237 |
<p class="mb-4">
|
| 238 |
-
Developed by
|
| 239 |
-
<a href="https://
|
| 240 |
-
| Powered by
|
| 241 |
-
<a href="https://hager-zon.vercel.app/" target="_blank" class="text-emerald-300 hover:underline">MGZon AI</a>
|
| 242 |
</p>
|
| 243 |
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
| 244 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('email')">
|
| 245 |
<i class="bx bx-mail-send text-3xl text-emerald-300 mb-2"></i>
|
| 246 |
<h4 class="font-semibold mb-1">Email Us</h4>
|
| 247 |
-
<p>
|
| 248 |
-
<a href="mailto:support@mgzon.com" class="text-emerald-300 hover:underline">support@mgzon.com</a>
|
| 249 |
-
</p>
|
| 250 |
<div id="email-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 251 |
<p>Reach out to our support team for any inquiries or assistance.</p>
|
| 252 |
<button onclick="closeCardDetails('email')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
@@ -264,9 +262,7 @@
|
|
| 264 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('community')">
|
| 265 |
<i class="bx bx-group text-3xl text-emerald-300 mb-2"></i>
|
| 266 |
<h4 class="font-semibold mb-1">Community</h4>
|
| 267 |
-
<p>
|
| 268 |
-
<a href="https://hager-zon.vercel.app/community" class="text-emerald-300 hover:underline">Join us</a>
|
| 269 |
-
</p>
|
| 270 |
<div id="community-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 271 |
<p>Join our vibrant community to share ideas and collaborate.</p>
|
| 272 |
<button onclick="closeCardDetails('community')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
@@ -275,9 +271,7 @@
|
|
| 275 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('api-docs')">
|
| 276 |
<i class="bx bx-code-alt text-3xl text-emerald-300 mb-2"></i>
|
| 277 |
<h4 class="font-semibold mb-1">API Docs</h4>
|
| 278 |
-
<p>
|
| 279 |
-
<a href="/docs" class="text-emerald-300 hover:underline">Explore Docs</a>
|
| 280 |
-
</p>
|
| 281 |
<div id="api-docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 282 |
<p>Explore our API documentation for seamless integration.</p>
|
| 283 |
<button onclick="closeCardDetails('api-docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
@@ -286,9 +280,7 @@
|
|
| 286 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('faq')">
|
| 287 |
<i class="bx bx-help-circle text-3xl text-emerald-300 mb-2"></i>
|
| 288 |
<h4 class="font-semibold mb-1">FAQ</h4>
|
| 289 |
-
<p>
|
| 290 |
-
<a href="https://hager-zon.vercel.app/faq" target="_blank" class="text-emerald-300 hover:underline">Read FAQ</a>
|
| 291 |
-
</p>
|
| 292 |
<div id="faq-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 293 |
<p>Find answers to common questions in our FAQ section.</p>
|
| 294 |
<button onclick="closeCardDetails('faq')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
@@ -297,78 +289,54 @@
|
|
| 297 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('docs')">
|
| 298 |
<i class="bx bx-book text-3xl text-emerald-300 mb-2"></i>
|
| 299 |
<h4 class="font-semibold mb-1">Documentation</h4>
|
| 300 |
-
<p>
|
| 301 |
-
<a href="/docs" class="text-emerald-300 hover:underline">Full Docs</a>
|
| 302 |
-
</p>
|
| 303 |
<div id="docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 304 |
<p>Access comprehensive documentation for MGZon Chatbot.</p>
|
| 305 |
<button onclick="closeCardDetails('docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 306 |
</div>
|
| 307 |
</div>
|
| 308 |
</div>
|
| 309 |
-
<!-- Social icons -->
|
| 310 |
<div class="flex justify-center gap-6 mt-6">
|
| 311 |
-
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-emerald-300 transition">
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-emerald-300 transition">
|
| 315 |
-
<i class="bx bxl-twitter"></i>
|
| 316 |
-
</a>
|
| 317 |
-
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-emerald-300 transition">
|
| 318 |
-
<i class="bx bxl-facebook"></i>
|
| 319 |
-
</a>
|
| 320 |
</div>
|
| 321 |
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 322 |
</div>
|
| 323 |
</footer>
|
| 324 |
-
|
| 325 |
-
<!-- Scripts -->
|
| 326 |
<script>
|
| 327 |
-
// Sidebar toggle for mobile
|
| 328 |
const sidebar = document.getElementById('sidebar');
|
| 329 |
const toggleBtn = document.getElementById('sidebarToggle');
|
| 330 |
const closeSidebarBtn = document.getElementById('closeSidebar');
|
| 331 |
-
|
| 332 |
toggleBtn.addEventListener('click', () => {
|
| 333 |
sidebar.classList.toggle('active');
|
| 334 |
sidebar.classList.toggle('-translate-x-full');
|
| 335 |
sidebar.classList.toggle('translate-x-0');
|
| 336 |
});
|
| 337 |
-
|
| 338 |
closeSidebarBtn.addEventListener('click', () => {
|
| 339 |
sidebar.classList.remove('active');
|
| 340 |
sidebar.classList.add('-translate-x-full');
|
| 341 |
sidebar.classList.remove('translate-x-0');
|
| 342 |
});
|
| 343 |
-
|
| 344 |
-
// Close sidebar when clicking outside
|
| 345 |
document.addEventListener('click', (e) => {
|
| 346 |
-
if (
|
| 347 |
-
!sidebar.contains(e.target) &&
|
| 348 |
-
!toggleBtn.contains(e.target) &&
|
| 349 |
-
window.innerWidth < 768
|
| 350 |
-
) {
|
| 351 |
sidebar.classList.remove('active');
|
| 352 |
sidebar.classList.add('-translate-x-full');
|
| 353 |
sidebar.classList.remove('translate-x-0');
|
| 354 |
}
|
| 355 |
});
|
| 356 |
-
|
| 357 |
-
// Launch button spinner
|
| 358 |
-
const launchBtn = document.getElementById('launchBtn');
|
| 359 |
-
const spinner = document.getElementById('spinner');
|
| 360 |
-
launchBtn.addEventListener('click', (e) => {
|
| 361 |
-
spinner.classList.remove('hidden');
|
| 362 |
-
setTimeout(() => spinner.classList.add('hidden'), 2000); // Simulate loading
|
| 363 |
-
});
|
| 364 |
-
|
| 365 |
-
// Card details toggle
|
| 366 |
function showCardDetails(cardId) {
|
| 367 |
document.getElementById(`${cardId}-details`).classList.remove('hidden');
|
| 368 |
}
|
| 369 |
function closeCardDetails(cardId) {
|
| 370 |
document.getElementById(`${cardId}-details`).classList.add('hidden');
|
| 371 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 372 |
</script>
|
| 373 |
</body>
|
| 374 |
</html>
|
|
|
|
| 1 |
<!DOCTYPE html>
|
| 2 |
<html lang="en">
|
| 3 |
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<meta name="description" content="MGZon Chatbot – AI-powered assistant for code generation, web search, and e-commerce solutions by Mark Al-Asfar from Alexandria, Egypt.">
|
| 7 |
+
<meta name="keywords" content="MGZon Chatbot, AI assistant, code generation, e-commerce, Mark Al-Asfar,
|
| 8 |
+
United States, FastAPI, Gradio">
|
| 9 |
+
<meta name="author" content="Mark Al-Asfar">
|
| 10 |
+
<meta name="robots" content="index, follow">
|
| 11 |
<title>MGZon Chatbot – Powered by AI</title>
|
| 12 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 13 |
+
<link rel="apple-touch-icon" href="static/images/mg.svg">
|
| 14 |
+
<!-- Open Graph -->
|
| 15 |
+
<meta property="og:title" content="MGZon Chatbot – AI-Powered Solutions">
|
| 16 |
+
<meta property="og:description" content="Explore MGZon Chatbot for code generation, web search, and e-commerce solutions by Mark Al-Asfar.">
|
| 17 |
+
<meta property="og:image" content="static/images/mg.svg">
|
| 18 |
+
<meta property="og:url" content="https://mgzon-mgzon-app.hf.space/">
|
| 19 |
+
<meta property="og:type" content="website">
|
| 20 |
+
<!-- Twitter Card -->
|
| 21 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 22 |
+
<meta name="twitter:title" content="MGZon Chatbot – AI-Powered Solutions">
|
| 23 |
+
<meta name="twitter:description" content="Explore MGZon Chatbot for code generation, web search, and e-commerce solutions by Mark Al-Asfar.">
|
| 24 |
+
<meta name="twitter:image" content="static/images/mg.svg">
|
| 25 |
+
<!-- JSON-LD -->
|
| 26 |
+
<script type="application/ld+json">
|
| 27 |
+
{
|
| 28 |
+
"@context": "https://schema.org",
|
| 29 |
+
"@type": "WebSite",
|
| 30 |
+
"name": "MGZon Chatbot",
|
| 31 |
+
"url": "https://mgzon-mgzon-app.hf.space/",
|
| 32 |
+
"description": "MGZon Chatbot by Mark Al-Asfar: Your AI assistant for code generation, real-time web search, and e-commerce solutions.",
|
| 33 |
+
"keywords": ["MGZon Chatbot", "AI chatbot", "Code generation AI", "E-commerce AI solutions", "Mark Al-Asfar", "AI assistant for developers", "FastAPI chatbot", "Real-time web search AI", "MGZon AI", "Python AI chatbot", "AI for coding", "E-commerce automation", "Hugging Face AI", "2025 AI trends", "chatgpt", "grok", "deepseek", "text generation"],
|
| 34 |
+
"potentialAction": {
|
| 35 |
+
"@type": "SearchAction",
|
| 36 |
+
"target": "https://mgzon-mgzon-app.hf.space/?q={search_term_string}",
|
| 37 |
+
"query-input": "required name=search_term_string"
|
| 38 |
+
},
|
| 39 |
+
"publisher": {
|
| 40 |
+
"@type": "Organization",
|
| 41 |
+
"name": "MGZon AI",
|
| 42 |
+
"logo": {
|
| 43 |
+
"@type": "ImageObject",
|
| 44 |
+
"url": "static/images/mg.svg"
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
</script>
|
| 49 |
<!-- Tailwind (v3) -->
|
| 50 |
<script src="https://cdn.tailwindcss.com"></script>
|
|
|
|
| 51 |
<!-- Boxicons -->
|
| 52 |
+
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
|
|
|
|
| 53 |
<!-- Prism (for code highlighting) -->
|
| 54 |
+
<link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css" rel="stylesheet">
|
| 55 |
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js"></script>
|
|
|
|
| 56 |
<style>
|
|
|
|
| 57 |
@keyframes gradientShift {
|
| 58 |
0% { background-position: 0% 50%; }
|
| 59 |
50% { background-position: 100% 50%; }
|
|
|
|
| 65 |
animation: gradientShift 15s ease infinite;
|
| 66 |
font-family: system-ui, sans-serif;
|
| 67 |
}
|
|
|
|
|
|
|
| 68 |
.glass {
|
| 69 |
background: rgba(255, 255, 255, 0.07);
|
| 70 |
border-radius: 1rem;
|
|
|
|
| 72 |
backdrop-filter: blur(12px);
|
| 73 |
-webkit-backdrop-filter: blur(12px);
|
| 74 |
}
|
|
|
|
|
|
|
| 75 |
.sidebar {
|
| 76 |
transition: transform 0.3s ease-in-out;
|
| 77 |
}
|
|
|
|
|
|
|
| 78 |
.sidebar.collapsed .logo {
|
| 79 |
opacity: 0;
|
| 80 |
transition: opacity 0.2s ease;
|
| 81 |
}
|
|
|
|
|
|
|
| 82 |
.main-content {
|
| 83 |
+
min-height: calc(100vh - 4rem);
|
| 84 |
}
|
|
|
|
|
|
|
| 85 |
.loading {
|
| 86 |
display: inline-block;
|
| 87 |
width: 1rem;
|
|
|
|
| 95 |
@keyframes spin {
|
| 96 |
to { transform: rotate(360deg); }
|
| 97 |
}
|
|
|
|
|
|
|
| 98 |
.glass:hover {
|
| 99 |
transform: scale(1.05);
|
| 100 |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
| 101 |
background: rgba(255, 255, 255, 0.15);
|
| 102 |
}
|
|
|
|
|
|
|
| 103 |
@media (max-width: 768px) {
|
| 104 |
.sidebar {
|
| 105 |
transform: translateX(-100%);
|
|
|
|
| 110 |
}
|
| 111 |
</style>
|
| 112 |
</head>
|
|
|
|
| 113 |
<body class="text-white flex flex-col min-h-screen">
|
| 114 |
<!-- Mobile toggle button -->
|
| 115 |
+
<button id="sidebarToggle" class="md:hidden fixed top-4 left-4 z-50 p-2 text-2xl text-white rounded bg-gray-800/60 hover:bg-gray-700/80 transition" aria-label="Toggle navigation">
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
<i class="bx bx-menu"></i>
|
| 117 |
</button>
|
|
|
|
| 118 |
<!-- Sidebar -->
|
| 119 |
+
<aside id="sidebar" class="sidebar fixed inset-y-0 left-0 w-64 bg-gradient-to-b from-teal-800 to-emerald-900 p-6 flex flex-col overflow-y-auto z-40">
|
| 120 |
+
<button id="closeSidebar" class="md:hidden text-white text-2xl absolute top-4 right-4" aria-label="Close sidebar">✕</button>
|
| 121 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="logo w-20 h-20 mx-auto mb-8 animate-pulse">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
<nav class="flex flex-col gap-3">
|
| 123 |
+
<a href="/" class="px-4 py-2 rounded-lg bg-emerald-600">Home</a>
|
| 124 |
<a href="/docs" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">API Documentation</a>
|
| 125 |
+
<a href="/about" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">About MGZon</a>
|
| 126 |
+
<a href="/login" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Login</a>
|
| 127 |
+
<a href="/register" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Register</a>
|
| 128 |
<a href="https://hager-zon.vercel.app/community" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Community</a>
|
| 129 |
<a href="https://mark-elasfar.web.app/" target="_blank" class="px-4 py-2 rounded-lg hover:bg-emerald-600 transition">Mark Al-Asfar</a>
|
| 130 |
</nav>
|
| 131 |
</aside>
|
|
|
|
| 132 |
<!-- Main content -->
|
| 133 |
<main class="flex-1 md:ml-64 p-6 main-content">
|
| 134 |
<section class="container max-w-6xl mx-auto">
|
| 135 |
<!-- Hero -->
|
| 136 |
<div class="text-center py-12">
|
| 137 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
<h1 class="text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-teal-300 to-emerald-400">
|
| 139 |
Welcome to MGZon Chatbot 🚀
|
| 140 |
</h1>
|
| 141 |
<p class="text-lg max-w-2xl mx-auto mb-8">
|
| 142 |
+
MGZon Chatbot is an AI-powered assistant for code generation, web search, and e-commerce solutions. Built with Gradio and FastAPI by Mark Al-Asfar from
|
| 143 |
+
United States. Ready to code smarter and shop better?
|
| 144 |
+
Discover MGZon Chatbot, an AI-powered assistant by Mark Al-Asfar for code generation, real-time web search, and e-commerce automation. Built with FastAPI and Hugging Face AI, MGZon rivals tools like ChatGPT, Grok, and DeepSeek.
|
| 145 |
</p>
|
| 146 |
+
{% if user %}
|
| 147 |
+
<div class="flex justify-center gap-4">
|
| 148 |
+
<a href="/chat" id="launchBtn" class="inline-flex items-center bg-gradient-to-r from-emerald-500 to-teal-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:scale-105 transition-transform shadow-lg hover:shadow-xl">
|
| 149 |
+
Launch Chatbot <i class="bx bx-rocket ml-2"></i>
|
| 150 |
+
<span id="spinner" class="loading hidden"></span>
|
| 151 |
+
</a>
|
| 152 |
+
<a href="/auth/jwt/logout" class="inline-flex items-center bg-gradient-to-r from-red-500 to-orange-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:scale-105 transition-transform shadow-lg hover:shadow-xl">
|
| 153 |
+
Logout <i class="bx bx-log-out ml-2"></i>
|
| 154 |
+
</a>
|
| 155 |
+
</div>
|
| 156 |
+
{% else %}
|
| 157 |
+
<div class="flex justify-center gap-4">
|
| 158 |
+
<a href="/login" class="inline-flex items-center bg-gradient-to-r from-blue-500 to-cyan-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:scale-105 transition-transform shadow-lg hover:shadow-xl">
|
| 159 |
+
Login <i class="bx bx-log-in ml-2"></i>
|
| 160 |
+
</a>
|
| 161 |
+
<a href="/register" class="inline-flex items-center bg-gradient-to-r from-emerald-500 to-teal-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:scale-105 transition-transform shadow-lg hover:shadow-xl">
|
| 162 |
+
Sign Up <i class="bx bx-user-plus ml-2"></i>
|
| 163 |
+
</a>
|
| 164 |
+
</div>
|
| 165 |
+
{% endif %}
|
| 166 |
</div>
|
|
|
|
| 167 |
<!-- Features -->
|
| 168 |
<section class="my-12">
|
| 169 |
+
<h2 class="text-3xl font-bold text-center mb-8">Why Choose MGZon?</h2>
|
| 170 |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
| 171 |
<div class="glass p-6 relative group cursor-pointer" onclick="showCardDetails('code-generation')">
|
| 172 |
+
<button class="absolute top-2 right-2 text-gray-300 hover:text-white transition" onclick="event.stopPropagation(); closeCardDetails('code-generation')" aria-label="Close card">×</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
<i class="bx bx-code-alt text-4xl text-emerald-300 mb-4"></i>
|
| 174 |
<h3 class="text-xl font-semibold mb-2">Code Generation</h3>
|
| 175 |
+
<p>Generate clean, well-commented code for React, Django, Flask, Node.js, and more.</p>
|
| 176 |
<div id="code-generation-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 177 |
+
<p>Supports multiple frameworks with examples and best practices for seamless integration.</p>
|
| 178 |
<button onclick="closeCardDetails('code-generation')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 179 |
</div>
|
| 180 |
</div>
|
| 181 |
<div class="glass p-6 relative group cursor-pointer" onclick="showCardDetails('web-search')">
|
| 182 |
+
<button class="absolute top-2 right-2 text-gray-300 hover:text-white transition" onclick="event.stopPropagation(); closeCardDetails('web-search')" aria-label="Close card">×</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
<i class="bx bx-search text-4xl text-emerald-300 mb-4"></i>
|
| 184 |
<h3 class="text-xl font-semibold mb-2">Web Search</h3>
|
| 185 |
+
<p>Real-time web search for MGZon queries and industry insights.</p>
|
| 186 |
<div id="web-search-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 187 |
+
<p>Get up-to-date answers and insights tailored to your needs.</p>
|
| 188 |
<button onclick="closeCardDetails('web-search')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 189 |
</div>
|
| 190 |
</div>
|
| 191 |
+
<div class="glass p-6 relative group cursor-pointer" onclick="showCardDetails('ecommerce')">
|
| 192 |
+
<button class="absolute top-2 right-2 text-gray-300 hover:text-white transition" onclick="event.stopPropagation(); closeCardDetails('ecommerce')" aria-label="Close card">×</button>
|
| 193 |
+
<i class="bx bx-cart text-4xl text-emerald-300 mb-4"></i>
|
| 194 |
+
<h3 class="text-xl font-semibold mb-2">E-commerce Solutions</h3>
|
| 195 |
+
<p>AI-driven tools to optimize your online store and boost sales.</p>
|
| 196 |
+
<div id="ecommerce-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 197 |
+
<p>From product recommendations to inventory management, MGZon enhances your e-commerce experience.</p>
|
| 198 |
+
<button onclick="closeCardDetails('ecommerce')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
</div>
|
| 200 |
</div>
|
| 201 |
</div>
|
| 202 |
</section>
|
|
|
|
| 203 |
<!-- News -->
|
| 204 |
<section class="my-12">
|
| 205 |
+
<h2 class="text-3xl font-bold text-center mb-8">Latest MGZon Updates</h2>
|
| 206 |
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
| 207 |
<div class="glass p-6">
|
| 208 |
+
<h3 class="text-xl font-semibold mb-2">New AI Features</h3>
|
| 209 |
+
<p>Explore our latest AI updates for smarter code and e-commerce tools.</p>
|
| 210 |
<a href="https://hager-zon.vercel.app/blog" target="_blank" class="text-emerald-300 hover:underline">Read More →</a>
|
| 211 |
</div>
|
| 212 |
<div class="glass p-6">
|
| 213 |
+
<h3 class="text-xl font-semibold mb-2">Global Expansion</h3>
|
| 214 |
+
<p>New warehouses in the USA, Canada, and China to serve you better.</p>
|
| 215 |
+
<a href="https://hager-zon.vercel.app/community" target="_blank" class="text-emerald-300 hover:underline">Learn More →</a>
|
| 216 |
+
</div>
|
| 217 |
+
</div>
|
| 218 |
+
</section>
|
| 219 |
+
<!-- Testimonials -->
|
| 220 |
+
<section class="my-12">
|
| 221 |
+
<h2 class="text-3xl font-bold text-center mb-8">What Our Users Say</h2>
|
| 222 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
| 223 |
+
<div class="glass p-6">
|
| 224 |
+
<p class="mb-4">"MGZon Chatbot transformed how I code. The AI-generated snippets are accurate and save hours!"</p>
|
| 225 |
+
<p class="font-semibold">– Ahmed, Developer</p>
|
| 226 |
+
</div>
|
| 227 |
+
<div class="glass p-6">
|
| 228 |
+
<p class="mb-4">"The e-commerce tools helped me optimize my store and boost sales by 30%."</p>
|
| 229 |
+
<p class="font-semibold">– Sarah, Store Owner</p>
|
| 230 |
</div>
|
| 231 |
</div>
|
| 232 |
</section>
|
| 233 |
</section>
|
| 234 |
</main>
|
|
|
|
| 235 |
<!-- Footer -->
|
| 236 |
<footer class="bg-gradient-to-r from-teal-900 to-emerald-900 py-12 mt-8">
|
| 237 |
<div class="container max-w-6xl mx-auto text-center">
|
| 238 |
+
<img src="static/images/mg.svg" alt="MGZon Chatbot Logo by Mark Al-Asfar" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
<p class="mb-4">
|
| 240 |
+
Developed by <a href="https://mark-elasfar.web.app/" target="_blank" class="text-emerald-300 hover:underline">Mark Al-Asfar</a>
|
| 241 |
+
| Powered by <a href="https://hager-zon.vercel.app/" target="_blank" class="text-emerald-300 hover:underline">MGZon AI</a>
|
|
|
|
|
|
|
| 242 |
</p>
|
| 243 |
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
| 244 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('email')">
|
| 245 |
<i class="bx bx-mail-send text-3xl text-emerald-300 mb-2"></i>
|
| 246 |
<h4 class="font-semibold mb-1">Email Us</h4>
|
| 247 |
+
<p><a href="mailto:support@mgzon.com" class="text-emerald-300 hover:underline">support@mgzon.com</a></p>
|
|
|
|
|
|
|
| 248 |
<div id="email-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 249 |
<p>Reach out to our support team for any inquiries or assistance.</p>
|
| 250 |
<button onclick="closeCardDetails('email')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
|
|
| 262 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('community')">
|
| 263 |
<i class="bx bx-group text-3xl text-emerald-300 mb-2"></i>
|
| 264 |
<h4 class="font-semibold mb-1">Community</h4>
|
| 265 |
+
<p><a href="https://hager-zon.vercel.app/community" class="text-emerald-300 hover:underline">Join us</a></p>
|
|
|
|
|
|
|
| 266 |
<div id="community-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 267 |
<p>Join our vibrant community to share ideas and collaborate.</p>
|
| 268 |
<button onclick="closeCardDetails('community')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
|
|
| 271 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('api-docs')">
|
| 272 |
<i class="bx bx-code-alt text-3xl text-emerald-300 mb-2"></i>
|
| 273 |
<h4 class="font-semibold mb-1">API Docs</h4>
|
| 274 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Explore Docs</a></p>
|
|
|
|
|
|
|
| 275 |
<div id="api-docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 276 |
<p>Explore our API documentation for seamless integration.</p>
|
| 277 |
<button onclick="closeCardDetails('api-docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
|
|
| 280 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('faq')">
|
| 281 |
<i class="bx bx-help-circle text-3xl text-emerald-300 mb-2"></i>
|
| 282 |
<h4 class="font-semibold mb-1">FAQ</h4>
|
| 283 |
+
<p><a href="https://hager-zon.vercel.app/faq" target="_blank" class="text-emerald-300 hover:underline">Read FAQ</a></p>
|
|
|
|
|
|
|
| 284 |
<div id="faq-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 285 |
<p>Find answers to common questions in our FAQ section.</p>
|
| 286 |
<button onclick="closeCardDetails('faq')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
|
|
|
| 289 |
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('docs')">
|
| 290 |
<i class="bx bx-book text-3xl text-emerald-300 mb-2"></i>
|
| 291 |
<h4 class="font-semibold mb-1">Documentation</h4>
|
| 292 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Full Docs</a></p>
|
|
|
|
|
|
|
| 293 |
<div id="docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 294 |
<p>Access comprehensive documentation for MGZon Chatbot.</p>
|
| 295 |
<button onclick="closeCardDetails('docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 296 |
</div>
|
| 297 |
</div>
|
| 298 |
</div>
|
|
|
|
| 299 |
<div class="flex justify-center gap-6 mt-6">
|
| 300 |
+
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-github"></i></a>
|
| 301 |
+
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-twitter"></i></a>
|
| 302 |
+
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-facebook"></i></a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 303 |
</div>
|
| 304 |
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 305 |
</div>
|
| 306 |
</footer>
|
|
|
|
|
|
|
| 307 |
<script>
|
|
|
|
| 308 |
const sidebar = document.getElementById('sidebar');
|
| 309 |
const toggleBtn = document.getElementById('sidebarToggle');
|
| 310 |
const closeSidebarBtn = document.getElementById('closeSidebar');
|
|
|
|
| 311 |
toggleBtn.addEventListener('click', () => {
|
| 312 |
sidebar.classList.toggle('active');
|
| 313 |
sidebar.classList.toggle('-translate-x-full');
|
| 314 |
sidebar.classList.toggle('translate-x-0');
|
| 315 |
});
|
|
|
|
| 316 |
closeSidebarBtn.addEventListener('click', () => {
|
| 317 |
sidebar.classList.remove('active');
|
| 318 |
sidebar.classList.add('-translate-x-full');
|
| 319 |
sidebar.classList.remove('translate-x-0');
|
| 320 |
});
|
|
|
|
|
|
|
| 321 |
document.addEventListener('click', (e) => {
|
| 322 |
+
if (!sidebar.contains(e.target) && !toggleBtn.contains(e.target) && window.innerWidth < 768) {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
sidebar.classList.remove('active');
|
| 324 |
sidebar.classList.add('-translate-x-full');
|
| 325 |
sidebar.classList.remove('translate-x-0');
|
| 326 |
}
|
| 327 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
function showCardDetails(cardId) {
|
| 329 |
document.getElementById(`${cardId}-details`).classList.remove('hidden');
|
| 330 |
}
|
| 331 |
function closeCardDetails(cardId) {
|
| 332 |
document.getElementById(`${cardId}-details`).classList.add('hidden');
|
| 333 |
}
|
| 334 |
+
const launchBtn = document.getElementById('launchBtn');
|
| 335 |
+
const spinner = document.getElementById('spinner');
|
| 336 |
+
launchBtn.addEventListener('click', (e) => {
|
| 337 |
+
spinner.classList.remove('hidden');
|
| 338 |
+
setTimeout(() => spinner.classList.add('hidden'), 2000);
|
| 339 |
+
});
|
| 340 |
</script>
|
| 341 |
</body>
|
| 342 |
</html>
|
templates/login.html
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<meta name="description" content="Login to MGZon Chatbot to access AI-powered code generation and e-commerce tools. Sign in with email, Google, or GitHub.">
|
| 7 |
+
<meta name="keywords" content="MGZon Chatbot, login, AI assistant, code generation, e-commerce, Mark Al-Asfar">
|
| 8 |
+
<meta name="author" content="Mark Al-Asfar">
|
| 9 |
+
<meta name="robots" content="index, follow">
|
| 10 |
+
<title>Login - MGZon Chatbot</title>
|
| 11 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 12 |
+
<link rel="apple-touch-icon" href="static/images/mg.svg">
|
| 13 |
+
<!-- Open Graph -->
|
| 14 |
+
<meta property="og:title" content="Login - MGZon Chatbot">
|
| 15 |
+
<meta property="og:description" content="Login to MGZon Chatbot to access AI-powered code generation and e-commerce tools.">
|
| 16 |
+
<meta property="og:image" content="static/images/mg.svg">
|
| 17 |
+
<meta property="og:url" content="https://mgzon-mgzon-app.hf.space/login">
|
| 18 |
+
<meta property="og:type" content="website">
|
| 19 |
+
<!-- Twitter Card -->
|
| 20 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 21 |
+
<meta name="twitter:title" content="Login - MGZon Chatbot">
|
| 22 |
+
<meta name="twitter:description" content="Login to MGZon Chatbot to access AI-powered code generation and e-commerce tools.">
|
| 23 |
+
<meta name="twitter:image" content="static/images/mg.svg">
|
| 24 |
+
<!-- JSON-LD -->
|
| 25 |
+
<script type="application/ld+json">
|
| 26 |
+
{
|
| 27 |
+
"@context": "https://schema.org",
|
| 28 |
+
"@type": "WebPage",
|
| 29 |
+
"name": "Login - MGZon Chatbot",
|
| 30 |
+
"url": "https://mgzon-mgzon-app.hf.space/login",
|
| 31 |
+
"description": "Login to MGZon Chatbot to access AI-powered code generation and e-commerce tools. Sign in with email, Google, or GitHub.",
|
| 32 |
+
"keywords": ["MGZon Chatbot", "login", "AI chatbot", "code generation", "e-commerce", "Mark Al-Asfar", "MGZon", "MGZon AI", "E-commerce chatbot", "Python AI chatbot", "FastAPI integration"],
|
| 33 |
+
"isPartOf": {
|
| 34 |
+
"@type": "WebSite",
|
| 35 |
+
"name": "MGZon Chatbot",
|
| 36 |
+
"url": "https://mgzon-mgzon-app.hf.space/"
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
</script>
|
| 40 |
+
<!-- Tailwind (v3) -->
|
| 41 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 42 |
+
<!-- Boxicons -->
|
| 43 |
+
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
|
| 44 |
+
<style>
|
| 45 |
+
@keyframes gradientShift {
|
| 46 |
+
0% { background-position: 0% 50%; }
|
| 47 |
+
50% { background-position: 100% 50%; }
|
| 48 |
+
100% { background-position: 0% 50%; }
|
| 49 |
+
}
|
| 50 |
+
body {
|
| 51 |
+
background: linear-gradient(135deg, #0f172a, #0e7490, #065f46, #064e3b);
|
| 52 |
+
background-size: 400% 400%;
|
| 53 |
+
animation: gradientShift 15s ease infinite;
|
| 54 |
+
font-family: system-ui, sans-serif;
|
| 55 |
+
}
|
| 56 |
+
.glass {
|
| 57 |
+
background: rgba(255, 255, 255, 0.07);
|
| 58 |
+
border-radius: 1rem;
|
| 59 |
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
| 60 |
+
backdrop-filter: blur(12px);
|
| 61 |
+
-webkit-backdrop-filter: blur(12px);
|
| 62 |
+
}
|
| 63 |
+
.loading {
|
| 64 |
+
display: inline-block;
|
| 65 |
+
width: 1rem;
|
| 66 |
+
height: 1rem;
|
| 67 |
+
border: 2px solid currentColor;
|
| 68 |
+
border-top-color: transparent;
|
| 69 |
+
border-radius: 50%;
|
| 70 |
+
animation: spin 0.8s linear infinite;
|
| 71 |
+
margin-left: 0.5rem;
|
| 72 |
+
}
|
| 73 |
+
@keyframes spin {
|
| 74 |
+
to { transform: rotate(360deg); }
|
| 75 |
+
}
|
| 76 |
+
.glass:hover {
|
| 77 |
+
transform: scale(1.05);
|
| 78 |
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
| 79 |
+
background: rgba(255, 255, 255, 0.15);
|
| 80 |
+
}
|
| 81 |
+
</style>
|
| 82 |
+
</head>
|
| 83 |
+
<body class="text-white min-h-screen flex flex-col justify-center items-center">
|
| 84 |
+
<div class="container max-w-md mx-auto text-center py-12">
|
| 85 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 86 |
+
<h1 class="text-4xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-teal-300 to-emerald-400">
|
| 87 |
+
Login to MGZon Chatbot
|
| 88 |
+
</h1>
|
| 89 |
+
<div class="glass p-8">
|
| 90 |
+
<form id="loginForm" action="/auth/jwt/login" method="POST" class="flex flex-col gap-4">
|
| 91 |
+
<input type="email" name="username" id="email" placeholder="Email" class="p-3 rounded-lg bg-gray-800/60 text-white border border-gray-700 focus:outline-none focus:ring-2 focus:ring-emerald-500" required>
|
| 92 |
+
<input type="password" name="password" id="password" placeholder="Password" class="p-3 rounded-lg bg-gray-800/60 text-white border border-gray-700 focus:outline-none focus:ring-2 focus:ring-emerald-500" required>
|
| 93 |
+
<button type="submit" id="loginBtn" class="bg-gradient-to-r from-emerald-500 to-teal-600 text-white px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
|
| 94 |
+
Login <i class="bx bx-log-in ml-2"></i>
|
| 95 |
+
<span id="spinner" class="loading hidden"></span>
|
| 96 |
+
</button>
|
| 97 |
+
</form>
|
| 98 |
+
<div class="flex justify-center gap-4 mt-4 flex-wrap">
|
| 99 |
+
<a href="/auth/google/login" class="inline-flex items-center bg-gradient-to-r from-white to-gray-200 text-gray-800 px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
|
| 100 |
+
Login with Google <i class="bx bxl-google ml-2"></i>
|
| 101 |
+
</a>
|
| 102 |
+
<a href="/auth/github/login" class="inline-flex items-center bg-gradient-to-r from-gray-800 to-black text-white px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
|
| 103 |
+
Login with GitHub <i class="bx bxl-github ml-2"></i>
|
| 104 |
+
</a>
|
| 105 |
+
</div>
|
| 106 |
+
<p class="mt-4">Don't have an account? <a href="/register" class="text-emerald-300 hover:underline">Register</a></p>
|
| 107 |
+
<p id="errorMsg" class="text-red-500 mt-4 hidden"></p>
|
| 108 |
+
</div>
|
| 109 |
+
</div>
|
| 110 |
+
<footer class="bg-gradient-to-r from-teal-900 to-emerald-900 py-12 mt-8 w-full">
|
| 111 |
+
<div class="container max-w-6xl mx-auto text-center">
|
| 112 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="w-24 h-24 mx-auto mb-6 animate-pulse">
|
| 113 |
+
<p class="mb-4">
|
| 114 |
+
Developed by <a href="https://mark-elasfar.web.app/" target="_blank" class="text-emerald-300 hover:underline">Mark Al-Asfar</a>
|
| 115 |
+
| Powered by <a href="https://hager-zon.vercel.app/" target="_blank" class="text-emerald-300 hover:underline">MGZon AI</a>
|
| 116 |
+
</p>
|
| 117 |
+
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
| 118 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('email')">
|
| 119 |
+
<i class="bx bx-mail-send text-3xl text-emerald-300 mb-2"></i>
|
| 120 |
+
<h4 class="font-semibold mb-1">Email Us</h4>
|
| 121 |
+
<p><a href="mailto:support@mgzon.com" class="text-emerald-300 hover:underline">support@mgzon.com</a></p>
|
| 122 |
+
<div id="email-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 123 |
+
<p>Reach out to our support team for any inquiries or assistance.</p>
|
| 124 |
+
<button onclick="closeCardDetails('email')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 125 |
+
</div>
|
| 126 |
+
</div>
|
| 127 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('phone')">
|
| 128 |
+
<i class="bx bx-phone text-3xl text-emerald-300 mb-2"></i>
|
| 129 |
+
<h4 class="font-semibold mb-1">Phone Support</h4>
|
| 130 |
+
<p>+1-800-123-4567</p>
|
| 131 |
+
<div id="phone-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 132 |
+
<p>Contact our support team via phone for immediate assistance.</p>
|
| 133 |
+
<button onclick="closeCardDetails('phone')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 134 |
+
</div>
|
| 135 |
+
</div>
|
| 136 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('community')">
|
| 137 |
+
<i class="bx bx-group text-3xl text-emerald-300 mb-2"></i>
|
| 138 |
+
<h4 class="font-semibold mb-1">Community</h4>
|
| 139 |
+
<p><a href="https://hager-zon.vercel.app/community" class="text-emerald-300 hover:underline">Join us</a></p>
|
| 140 |
+
<div id="community-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 141 |
+
<p>Join our vibrant community to share ideas and collaborate.</p>
|
| 142 |
+
<button onclick="closeCardDetails('community')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 143 |
+
</div>
|
| 144 |
+
</div>
|
| 145 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('api-docs')">
|
| 146 |
+
<i class="bx bx-code-alt text-3xl text-emerald-300 mb-2"></i>
|
| 147 |
+
<h4 class="font-semibold mb-1">API Docs</h4>
|
| 148 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Explore Docs</a></p>
|
| 149 |
+
<div id="api-docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 150 |
+
<p>Explore our API documentation for seamless integration.</p>
|
| 151 |
+
<button onclick="closeCardDetails('api-docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 152 |
+
</div>
|
| 153 |
+
</div>
|
| 154 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('faq')">
|
| 155 |
+
<i class="bx bx-help-circle text-3xl text-emerald-300 mb-2"></i>
|
| 156 |
+
<h4 class="font-semibold mb-1">FAQ</h4>
|
| 157 |
+
<p><a href="https://hager-zon.vercel.app/faq" target="_blank" class="text-emerald-300 hover:underline">Read FAQ</a></p>
|
| 158 |
+
<div id="faq-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 159 |
+
<p>Find answers to common questions in our FAQ section.</p>
|
| 160 |
+
<button onclick="closeCardDetails('faq')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 161 |
+
</div>
|
| 162 |
+
</div>
|
| 163 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('docs')">
|
| 164 |
+
<i class="bx bx-book text-3xl text-emerald-300 mb-2"></i>
|
| 165 |
+
<h4 class="font-semibold mb-1">Documentation</h4>
|
| 166 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Full Docs</a></p>
|
| 167 |
+
<div id="docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 168 |
+
<p>Access comprehensive documentation for MGZon Chatbot.</p>
|
| 169 |
+
<button onclick="closeCardDetails('docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 170 |
+
</div>
|
| 171 |
+
</div>
|
| 172 |
+
</div>
|
| 173 |
+
<div class="flex justify-center gap-6 mt-6">
|
| 174 |
+
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-github"></i></a>
|
| 175 |
+
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-twitter"></i></a>
|
| 176 |
+
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-facebook"></i></a>
|
| 177 |
+
</div>
|
| 178 |
+
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 179 |
+
</div>
|
| 180 |
+
</footer>
|
| 181 |
+
<script>
|
| 182 |
+
const loginForm = document.getElementById('loginForm');
|
| 183 |
+
const loginBtn = document.getElementById('loginBtn');
|
| 184 |
+
const spinner = document.getElementById('spinner');
|
| 185 |
+
const errorMsg = document.getElementById('errorMsg');
|
| 186 |
+
loginForm.addEventListener('submit', async (e) => {
|
| 187 |
+
e.preventDefault();
|
| 188 |
+
spinner.classList.remove('hidden');
|
| 189 |
+
errorMsg.classList.add('hidden');
|
| 190 |
+
const formData = new FormData(loginForm);
|
| 191 |
+
try {
|
| 192 |
+
const response = await fetch('/auth/jwt/login', {
|
| 193 |
+
method: 'POST',
|
| 194 |
+
body: formData
|
| 195 |
+
});
|
| 196 |
+
spinner.classList.add('hidden');
|
| 197 |
+
if (response.ok) {
|
| 198 |
+
window.location.href = '/chat';
|
| 199 |
+
} else {
|
| 200 |
+
const error = await response.json();
|
| 201 |
+
errorMsg.textContent = error.detail || 'Login failed. Please try again.';
|
| 202 |
+
errorMsg.classList.remove('hidden');
|
| 203 |
+
}
|
| 204 |
+
} catch (error) {
|
| 205 |
+
spinner.classList.add('hidden');
|
| 206 |
+
errorMsg.textContent = 'An error occurred. Please try again.';
|
| 207 |
+
errorMsg.classList.remove('hidden');
|
| 208 |
+
}
|
| 209 |
+
});
|
| 210 |
+
function showCardDetails(cardId) {
|
| 211 |
+
document.getElementById(`${cardId}-details`).classList.remove('hidden');
|
| 212 |
+
}
|
| 213 |
+
function closeCardDetails(cardId) {
|
| 214 |
+
document.getElementById(`${cardId}-details`).classList.add('hidden');
|
| 215 |
+
}
|
| 216 |
+
</script>
|
| 217 |
+
</body>
|
| 218 |
+
</html>
|
templates/register.html
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<meta name="description" content="Register for MGZon Chatbot to access AI-powered code generation and e-commerce tools. Sign up with email, Google, or GitHub.">
|
| 7 |
+
<meta name="keywords" content="MGZon Chatbot, register, sign up, AI assistant, code generation, e-commerce, Mark Al-Asfar">
|
| 8 |
+
<meta name="author" content="Mark Al-Asfar">
|
| 9 |
+
<meta name="robots" content="index, follow">
|
| 10 |
+
<title>Register - MGZon Chatbot</title>
|
| 11 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 12 |
+
<link rel="apple-touch-icon" href="static/images/mg.svg">
|
| 13 |
+
<!-- Open Graph -->
|
| 14 |
+
<meta property="og:title" content="Register - MGZon Chatbot">
|
| 15 |
+
<meta property="og:description" content="Register for MGZon Chatbot to access AI-powered code generation and e-commerce tools.">
|
| 16 |
+
<meta property="og:image" content="static/images/mg.svg">
|
| 17 |
+
<meta property="og:url" content="https://mgzon-mgzon-app.hf.space/register">
|
| 18 |
+
<meta property="og:type" content="website">
|
| 19 |
+
<!-- Twitter Card -->
|
| 20 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 21 |
+
<meta name="twitter:title" content="Register - MGZon Chatbot">
|
| 22 |
+
<meta name="twitter:description" content="Register for MGZon Chatbot to access AI-powered code generation and e-commerce tools.">
|
| 23 |
+
<meta name="twitter:image" content="static/images/mg.svg">
|
| 24 |
+
<!-- JSON-LD -->
|
| 25 |
+
<script type="application/ld+json">
|
| 26 |
+
{
|
| 27 |
+
"@context": "https://schema.org",
|
| 28 |
+
"@type": "WebPage",
|
| 29 |
+
"name": "Register - MGZon Chatbot",
|
| 30 |
+
"url": "https://mgzon-mgzon-app.hf.space/register",
|
| 31 |
+
"description": "Register for MGZon Chatbot to access AI-powered code generation and e-commerce tools. Sign up with email, Google, or GitHub.",
|
| 32 |
+
"keywords": ["MGZon Chatbot", "register", "sign up", "AI chatbot", "code generation", "e-commerce", "Mark Al-Asfar", "MGZon", "MGZon AI", "E-commerce chatbot", "Python AI chatbot", "FastAPI integration"],
|
| 33 |
+
"isPartOf": {
|
| 34 |
+
"@type": "WebSite",
|
| 35 |
+
"name": "MGZon Chatbot",
|
| 36 |
+
"url": "https://mgzon-mgzon-app.hf.space/"
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
</script>
|
| 40 |
+
@keyframes gradientShift {
|
| 41 |
+
0% { background-position: 0% 50%; }
|
| 42 |
+
50% { background-position: 100% 50%; }
|
| 43 |
+
100% { background-position: 0% 50%; }
|
| 44 |
+
}
|
| 45 |
+
body {
|
| 46 |
+
background: linear-gradient(135deg, #0f172a, #0e7490, #065f46, #064e3b);
|
| 47 |
+
background-size: 400% 400%;
|
| 48 |
+
animation: gradientShift 15s ease infinite;
|
| 49 |
+
font-family: system-ui, sans-serif;
|
| 50 |
+
}
|
| 51 |
+
.glass {
|
| 52 |
+
background: rgba(255, 255, 255, 0.07);
|
| 53 |
+
border-radius: 1rem;
|
| 54 |
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
| 55 |
+
backdrop-filter: blur(12px);
|
| 56 |
+
-webkit-backdrop-filter: blur(12px);
|
| 57 |
+
}
|
| 58 |
+
.loading {
|
| 59 |
+
display: inline-block;
|
| 60 |
+
width: 1rem;
|
| 61 |
+
height: 1rem;
|
| 62 |
+
border: 2px solid currentColor;
|
| 63 |
+
border-top-color: transparent;
|
| 64 |
+
border-radius: 50%;
|
| 65 |
+
animation: spin 0.8s linear infinite;
|
| 66 |
+
margin-left: 0.5rem;
|
| 67 |
+
}
|
| 68 |
+
@keyframes spin {
|
| 69 |
+
to { transform: rotate(360deg); }
|
| 70 |
+
}
|
| 71 |
+
.glass:hover {
|
| 72 |
+
transform: scale(1.05);
|
| 73 |
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
| 74 |
+
background: rgba(255, 255, 255, 0.15);
|
| 75 |
+
}
|
| 76 |
+
</style>
|
| 77 |
+
</head>
|
| 78 |
+
<body class="text-white min-h-screen flex flex-col justify-center items-center">
|
| 79 |
+
<div class="container max-w-md mx-auto text-center py-12">
|
| 80 |
+
<img src="static/images/mg.svg" alt="MGZon Chatbot Logo by Mark Al-Asfar" class="w-32 h-32 mx-auto mb-6 animate-bounce">
|
| 81 |
+
<h1 class="text-4xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-teal-300 to-emerald-400">
|
| 82 |
+
Register for MGZon Chatbot
|
| 83 |
+
</h1>
|
| 84 |
+
<div class="glass p-8">
|
| 85 |
+
<form id="registerForm" action="/auth/register" method="POST" class="flex flex-col gap-4">
|
| 86 |
+
<input type="text" name="username" id="username" placeholder="Username" class="p-3 rounded-lg bg-gray-800/60 text-white border border-gray-700 focus:outline-none focus:ring-2 focus:ring-emerald-500" required>
|
| 87 |
+
<input type="email" name="email" id="email" placeholder="Email" class="p-3 rounded-lg bg-gray-800/60 text-white border border-gray-700 focus:outline-none focus:ring-2 focus:ring-emerald-500" required>
|
| 88 |
+
<input type="password" name="password" id="password" placeholder="Password" class="p-3 rounded-lg bg-gray-800/60 text-white border border-gray-700 focus:outline-none focus:ring-2 focus:ring-emerald-500" required>
|
| 89 |
+
<button type="submit" id="registerBtn" class="bg-gradient-to-r from-emerald-500 to-teal-600 text-white px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
|
| 90 |
+
Register <i class="bx bx-user-plus ml-2"></i>
|
| 91 |
+
<span id="spinner" class="loading hidden"></span>
|
| 92 |
+
</button>
|
| 93 |
+
</form>
|
| 94 |
+
<div class="flex justify-center gap-4 mt-4 flex-wrap">
|
| 95 |
+
<a href="/auth/google/login" class="inline-flex items-center bg-gradient-to-r from-white to-gray-200 text-gray-800 px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
|
| 96 |
+
Sign Up with Google <i class="bx bxl-google ml-2"></i>
|
| 97 |
+
</a>
|
| 98 |
+
<a href="/auth/github/login" class="inline-flex items-center bg-gradient-to-r from-gray-800 to-black text-white px-6 py-3 rounded-full font-semibold hover:scale-105 transition-transform">
|
| 99 |
+
Sign Up with GitHub <i class="bx bxl-github ml-2"></i>
|
| 100 |
+
</a>
|
| 101 |
+
</div>
|
| 102 |
+
<p class="mt-4">Already have an account? <a href="/login" class="text-emerald-300 hover:underline">Login</a></p>
|
| 103 |
+
<p id="errorMsg" class="text-red-500 mt-4 hidden"></p>
|
| 104 |
+
</div>
|
| 105 |
+
</div>
|
| 106 |
+
<footer class="bg-gradient-to-r from-teal-900 to-emerald-900 py-12 mt-8 w-full">
|
| 107 |
+
<div class="container max-w-6xl mx-auto text-center">
|
| 108 |
+
<img src="static/images/mg.svg" alt="MGZon Logo" class="w-24 h-24 mx-auto mb-6 animate-pulse">
|
| 109 |
+
<p class="mb-4">
|
| 110 |
+
Developed by <a href="https://mark-elasfar.web.app/" target="_blank" class="text-emerald-300 hover:underline">Mark Al-Asfar</a>
|
| 111 |
+
| Powered by <a href="https://hager-zon.vercel.app/" target="_blank" class="text-emerald-300 hover:underline">MGZon AI</a>
|
| 112 |
+
</p>
|
| 113 |
+
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
| 114 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('email')">
|
| 115 |
+
<i class="bx bx-mail-send text-3xl text-emerald-300 mb-2"></i>
|
| 116 |
+
<h4 class="font-semibold mb-1">Email Us</h4>
|
| 117 |
+
<p><a href="mailto:support@mgzon.com" class="text-emerald-300 hover:underline">support@mgzon.com</a></p>
|
| 118 |
+
<div id="email-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 119 |
+
<p>Reach out to our support team for any inquiries or assistance.</p>
|
| 120 |
+
<button onclick="closeCardDetails('email')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 121 |
+
</div>
|
| 122 |
+
</div>
|
| 123 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('phone')">
|
| 124 |
+
<i class="bx bx-phone text-3xl text-emerald-300 mb-2"></i>
|
| 125 |
+
<h4 class="font-semibold mb-1">Phone Support</h4>
|
| 126 |
+
<p>+1-800-123-4567</p>
|
| 127 |
+
<div id="phone-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 128 |
+
<p>Contact our support team via phone for immediate assistance.</p>
|
| 129 |
+
<button onclick="closeCardDetails('phone')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 130 |
+
</div>
|
| 131 |
+
</div>
|
| 132 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('community')">
|
| 133 |
+
<i class="bx bx-group text-3xl text-emerald-300 mb-2"></i>
|
| 134 |
+
<h4 class="font-semibold mb-1">Community</h4>
|
| 135 |
+
<p><a href="https://hager-zon.vercel.app/community" class="text-emerald-300 hover:underline">Join us</a></p>
|
| 136 |
+
<div id="community-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 137 |
+
<p>Join our vibrant community to share ideas and collaborate.</p>
|
| 138 |
+
<button onclick="closeCardDetails('community')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 139 |
+
</div>
|
| 140 |
+
</div>
|
| 141 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('api-docs')">
|
| 142 |
+
<i class="bx bx-code-alt text-3xl text-emerald-300 mb-2"></i>
|
| 143 |
+
<h4 class="font-semibold mb-1">API Docs</h4>
|
| 144 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Explore Docs</a></p>
|
| 145 |
+
<div id="api-docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 146 |
+
<p>Explore our API documentation for seamless integration.</p>
|
| 147 |
+
<button onclick="closeCardDetails('api-docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 148 |
+
</div>
|
| 149 |
+
</div>
|
| 150 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('faq')">
|
| 151 |
+
<i class="bx bx-help-circle text-3xl text-emerald-300 mb-2"></i>
|
| 152 |
+
<h4 class="font-semibold mb-1">FAQ</h4>
|
| 153 |
+
<p><a href="https://hager-zon.vercel.app/faq" target="_blank" class="text-emerald-300 hover:underline">Read FAQ</a></p>
|
| 154 |
+
<div id="faq-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 155 |
+
<p>Find answers to common questions in our FAQ section.</p>
|
| 156 |
+
<button onclick="closeCardDetails('faq')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 157 |
+
</div>
|
| 158 |
+
</div>
|
| 159 |
+
<div class="glass p-4 cursor-pointer" onclick="showCardDetails('docs')">
|
| 160 |
+
<i class="bx bx-book text-3xl text-emerald-300 mb-2"></i>
|
| 161 |
+
<h4 class="font-semibold mb-1">Documentation</h4>
|
| 162 |
+
<p><a href="/docs" class="text-emerald-300 hover:underline">Full Docs</a></p>
|
| 163 |
+
<div id="docs-details" class="hidden mt-4 p-4 bg-gray-700/80 rounded-lg">
|
| 164 |
+
<p>Access comprehensive documentation for MGZon Chatbot.</p>
|
| 165 |
+
<button onclick="closeCardDetails('docs')" class="bg-emerald-500 text-white px-4 py-2 rounded-lg mt-2">Close</button>
|
| 166 |
+
</div>
|
| 167 |
+
</div>
|
| 168 |
+
</div>
|
| 169 |
+
<div class="flex justify-center gap-6 mt-6">
|
| 170 |
+
<a href="https://github.com/Mark-Lasfar/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-github"></i></a>
|
| 171 |
+
<a href="https://x.com/MGZon" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-twitter"></i></a>
|
| 172 |
+
<a href="https://www.facebook.com/people/Mark-Al-Asfar/pfbid02GMisUQ8AqWkNZjoKtWFHH1tbdHuVscN1cjcFnZWy9HkRaAsmanBfT6mhySAyqpg4l/" class="text-2xl text-white hover:text-emerald-300 transition"><i class="bx bxl-facebook"></i></a>
|
| 173 |
+
</div>
|
| 174 |
+
<p class="mt-6">© 2025 Mark Al-Asfar & MGZon AI. All rights reserved.</p>
|
| 175 |
+
</div>
|
| 176 |
+
</footer>
|
| 177 |
+
<script>
|
| 178 |
+
const registerForm = document.getElementById('registerForm');
|
| 179 |
+
const registerBtn = document.getElementById('registerBtn');
|
| 180 |
+
const spinner = document.getElementById('spinner');
|
| 181 |
+
const errorMsg = document.getElementById('errorMsg');
|
| 182 |
+
registerForm.addEventListener('submit', async (e) => {
|
| 183 |
+
e.preventDefault();
|
| 184 |
+
spinner.classList.remove('hidden');
|
| 185 |
+
errorMsg.classList.add('hidden');
|
| 186 |
+
const formData = new FormData(registerForm);
|
| 187 |
+
try {
|
| 188 |
+
const response = await fetch('/auth/register', {
|
| 189 |
+
method: 'POST',
|
| 190 |
+
body: formData
|
| 191 |
+
});
|
| 192 |
+
spinner.classList.add('hidden');
|
| 193 |
+
if (response.ok) {
|
| 194 |
+
window.location.href = '/chat';
|
| 195 |
+
} else {
|
| 196 |
+
const error = await response.json();
|
| 197 |
+
errorMsg.textContent = error.detail || 'Registration failed. Please try again.';
|
| 198 |
+
errorMsg.classList.remove('hidden');
|
| 199 |
+
}
|
| 200 |
+
} catch (error) {
|
| 201 |
+
spinner.classList.add('hidden');
|
| 202 |
+
errorMsg.textContent = 'An error occurred. Please try again.';
|
| 203 |
+
errorMsg.classList.remove('hidden');
|
| 204 |
+
}
|
| 205 |
+
});
|
| 206 |
+
function showCardDetails(cardId) {
|
| 207 |
+
document.getElementById(`${cardId}-details`).classList.remove('hidden');
|
| 208 |
+
}
|
| 209 |
+
function closeCardDetails(cardId) {
|
| 210 |
+
document.getElementById(`${cardId}-details`).classList.add('hidden');
|
| 211 |
+
}
|
| 212 |
+
</script>
|
| 213 |
+
</body>
|
| 214 |
+
</html>
|
utils/generation.py
CHANGED
|
@@ -35,13 +35,13 @@ HF_TOKEN = os.getenv("HF_TOKEN")
|
|
| 35 |
BACKUP_HF_TOKEN = os.getenv("BACKUP_HF_TOKEN")
|
| 36 |
API_ENDPOINT = os.getenv("API_ENDPOINT", "https://router.huggingface.co/v1")
|
| 37 |
FALLBACK_API_ENDPOINT = os.getenv("FALLBACK_API_ENDPOINT", "https://api-inference.huggingface.co")
|
| 38 |
-
MODEL_NAME = os.getenv("MODEL_NAME", "openai/gpt-oss-120b:
|
| 39 |
-
SECONDARY_MODEL_NAME = os.getenv("SECONDARY_MODEL_NAME", "mistralai/Mistral-7B-Instruct-v0.2")
|
| 40 |
-
TERTIARY_MODEL_NAME = os.getenv("TERTIARY_MODEL_NAME", "openai/gpt-oss-20b:
|
| 41 |
CLIP_BASE_MODEL = os.getenv("CLIP_BASE_MODEL", "Salesforce/blip-image-captioning-large")
|
| 42 |
CLIP_LARGE_MODEL = os.getenv("CLIP_LARGE_MODEL", "openai/clip-vit-large-patch14")
|
| 43 |
ASR_MODEL = os.getenv("ASR_MODEL", "openai/whisper-large-v3")
|
| 44 |
-
TTS_MODEL = os.getenv("TTS_MODEL", "
|
| 45 |
|
| 46 |
def check_model_availability(model_name: str, api_base: str, api_key: str) -> tuple[bool, str]:
|
| 47 |
try:
|
|
@@ -165,23 +165,23 @@ def request_generation(
|
|
| 165 |
return
|
| 166 |
|
| 167 |
# معالجة تحويل النص إلى صوت (TTS)
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
|
| 186 |
# معالجة الصور
|
| 187 |
if model_name in [CLIP_BASE_MODEL, CLIP_LARGE_MODEL] and image_data:
|
|
|
|
| 35 |
BACKUP_HF_TOKEN = os.getenv("BACKUP_HF_TOKEN")
|
| 36 |
API_ENDPOINT = os.getenv("API_ENDPOINT", "https://router.huggingface.co/v1")
|
| 37 |
FALLBACK_API_ENDPOINT = os.getenv("FALLBACK_API_ENDPOINT", "https://api-inference.huggingface.co")
|
| 38 |
+
MODEL_NAME = os.getenv("MODEL_NAME", "openai/gpt-oss-120b:together")
|
| 39 |
+
SECONDARY_MODEL_NAME = os.getenv("SECONDARY_MODEL_NAME", "mistralai/Mistral-7B-Instruct-v0.2:featherless-ai")
|
| 40 |
+
TERTIARY_MODEL_NAME = os.getenv("TERTIARY_MODEL_NAME", "openai/gpt-oss-20b:together")
|
| 41 |
CLIP_BASE_MODEL = os.getenv("CLIP_BASE_MODEL", "Salesforce/blip-image-captioning-large")
|
| 42 |
CLIP_LARGE_MODEL = os.getenv("CLIP_LARGE_MODEL", "openai/clip-vit-large-patch14")
|
| 43 |
ASR_MODEL = os.getenv("ASR_MODEL", "openai/whisper-large-v3")
|
| 44 |
+
TTS_MODEL = os.getenv("TTS_MODEL", "facebook/mms-tts-ara")
|
| 45 |
|
| 46 |
def check_model_availability(model_name: str, api_base: str, api_key: str) -> tuple[bool, str]:
|
| 47 |
try:
|
|
|
|
| 165 |
return
|
| 166 |
|
| 167 |
# معالجة تحويل النص إلى صوت (TTS)
|
| 168 |
+
if model_name == TTS_MODEL or output_format == "audio":
|
| 169 |
+
task_type = "text_to_speech"
|
| 170 |
+
try:
|
| 171 |
+
model = ParlerTTSForConditionalGeneration.from_pretrained(TTS_MODEL)
|
| 172 |
+
processor = AutoProcessor.from_pretrained(TTS_MODEL)
|
| 173 |
+
inputs = processor(text=message, return_tensors="pt")
|
| 174 |
+
audio = model.generate(**inputs)
|
| 175 |
+
audio_file = io.BytesIO()
|
| 176 |
+
torchaudio.save(audio_file, audio[0], sample_rate=22050, format="wav")
|
| 177 |
+
audio_file.seek(0)
|
| 178 |
+
yield audio_file.read()
|
| 179 |
+
cache[cache_key] = [audio_file.read()]
|
| 180 |
+
return
|
| 181 |
+
except Exception as e:
|
| 182 |
+
logger.error(f"Text-to-speech failed: {e}")
|
| 183 |
+
yield f"Error: Text-to-speech failed: {e}"
|
| 184 |
+
return
|
| 185 |
|
| 186 |
# معالجة الصور
|
| 187 |
if model_name in [CLIP_BASE_MODEL, CLIP_LARGE_MODEL] and image_data:
|