Spaces:
Sleeping
Sleeping
from typing import Optional | |
from fastapi import FastAPI, HTTPException, Request | |
from fastapi.responses import JSONResponse | |
import httpx | |
import random | |
import string | |
import json | |
app = FastAPI() | |
# Utility function to generate random hex strings | |
def random_hex(length=32): | |
return ''.join(random.choices(string.hexdigits, k=length)) | |
# Fetch JSON from the given URL with required headers | |
async def jsongen(url): | |
headers = { | |
"X-Signature-Version": "web2", | |
"X-Signature": random_hex(), | |
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", | |
} | |
try: | |
async with httpx.AsyncClient() as client: | |
response = await client.get(url, headers=headers) | |
response.raise_for_status() | |
return response.json() | |
except httpx.HTTPError as e: | |
raise HTTPException(status_code=500, detail=f"Error fetching data: {e}") | |
# Middleware to add custom fields globally | |
async def add_custom_fields(request: Request, call_next): | |
response = await call_next(request) | |
# Check if the response is JSON and has a body | |
if response.status_code == 200 and isinstance(response, JSONResponse): | |
original_body = await response.body() | |
try: | |
response_data = json.loads(original_body.decode("utf-8")) | |
except Exception: | |
return response # If the body is not JSON, return the original response | |
# Add custom fields to the response | |
modified_data = { | |
"creator": "my name", | |
"api_version": "1.0", | |
**response_data, | |
} | |
return JSONResponse(modified_data) | |
return response | |
# Route to fetch trending videos | |
async def get_trending(time: str, page: Optional[int] = 0): | |
trending_url = f"https://hanime.tv/api/v8/browse-trending?time={time}&page={page}&order_by=views&ordering=desc" | |
urldata = await jsongen(trending_url) | |
jsondata = [ | |
{ | |
"id": x["id"], | |
"name": x["name"], | |
"slug": x["slug"], | |
"cover_url": x["cover_url"], | |
"views": x["views"], | |
"link": f"/watch/{x['slug']}", | |
} | |
for x in urldata["hentai_videos"] | |
] | |
next_page = f"/trending/{time}/{page + 1}" | |
return {"results": jsondata, "next_page": next_page} | |
# Route to fetch video details | |
async def get_video(slug: str): | |
video_api_url = f"https://hanime.tv/api/v8/video?id={slug}" | |
video_data = await jsongen(video_api_url) | |
tags = [ | |
{"name": t["text"], "link": f"/hentai-tags/{t['text']}/0"} | |
for t in video_data["hentai_tags"] | |
] | |
streams = [ | |
{"width": s["width"], "height": s["height"], "size_mbs": s["filesize_mbs"], "url": s["url"]} | |
for s in video_data["videos_manifest"]["servers"][0]["streams"] | |
] | |
episodes = [ | |
{ | |
"id": e["id"], | |
"name": e["name"], | |
"slug": e["slug"], | |
"cover_url": e["cover_url"], | |
"views": e["views"], | |
"link": f"/watch/{e['slug']}", | |
} | |
for e in video_data["hentai_franchise_hentai_videos"] | |
] | |
jsondata = { | |
"id": video_data["hentai_video"]["id"], | |
"name": video_data["hentai_video"]["name"], | |
"description": video_data["hentai_video"]["description"], | |
"poster_url": video_data["hentai_video"]["poster_url"], | |
"cover_url": video_data["hentai_video"]["cover_url"], | |
"views": video_data["hentai_video"]["views"], | |
"streams": streams, | |
"tags": tags, | |
"episodes": episodes, | |
} | |
return {"results": [jsondata]} | |
# Route to fetch browse data | |
async def get_browse(type: str): | |
browse_url = "https://hanime.tv/api/v8/browse" | |
data = await jsongen(browse_url) | |
jsondata = data[type] | |
if type == "hentai_tags": | |
jsondata = [{"name": x["text"], "url": f"/hentai-tags/{x['text']}/0"} for x in jsondata] | |
elif type == "brands": | |
jsondata = [{"name": x["name"], "url": f"/brands/{x['slug']}/0"} for x in jsondata] | |
return {"results": jsondata} | |
# Route to fetch tags | |
async def get_tags(): | |
browse_url = "https://hanime.tv/api/v8/browse" | |
data = await jsongen(browse_url) | |
jsondata = [{"name": x["text"], "url": f"/tags/{x['text']}/0"} for x in data["hentai_tags"]] | |
return {"results": jsondata} | |
# Route to fetch browse videos | |
async def get_browse_videos(type: str, category: str, page: Optional[int] = 0): | |
browse_url = f"https://hanime.tv/api/v8/browse/{type}/{category}?page={page}&order_by=views&ordering=desc" | |
browsedata = await jsongen(browse_url) | |
jsondata = [ | |
{ | |
"id": x["id"], | |
"name": x["name"], | |
"slug": x["slug"], | |
"cover_url": x["cover_url"], | |
"views": x["views"], | |
"link": f"/watch/{x['slug']}", | |
} | |
for x in browsedata["hentai_videos"] | |
] | |
next_page = f"/{type}/{category}/{page + 1}" | |
return {"results": jsondata, "next_page": next_page} | |
# Root route | |
async def root(): | |
return {"message": "Welcome to Hanime API π"} | |
# Custom error handler | |
async def custom_exception_handler(request: Request, exc: Exception): | |
return JSONResponse( | |
status_code=500, | |
content={"error": "Something went wrong", "details": str(exc)}, | |
) | |