File size: 5,864 Bytes
75a43dd
 
e519d79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75a43dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e519d79
 
 
 
 
 
 
 
 
 
 
 
 
 
75a43dd
e519d79
75a43dd
 
e519d79
 
 
 
 
 
 
75a43dd
 
 
 
 
e519d79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75a43dd
 
 
 
 
 
 
 
 
 
e519d79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import os
import random
import traceback
import logging
from fastapi import FastAPI, Depends, HTTPException, Security, Request
from fastapi.security.api_key import APIKeyHeader
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from moviebox_api import (
    Search, Session, SubjectType, 
    DownloadableMovieFilesDetail, DownloadableTVSeriesFilesDetail,
    Trending, Homepage, MovieDetails, TVSeriesDetails, 
    Recommend, PopularSearch, HotMoviesAndTVSeries
)

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Your residential proxy list to defeat the 403 DataCenter Ban!
RAW_PROXIES = [
    "31.59.20.176:6754:kfcqidym:pb146svuz0dy",
    "23.95.150.145:6114:kfcqidym:pb146svuz0dy",
    "198.23.239.134:6540:kfcqidym:pb146svuz0dy",
    "45.38.107.97:6014:kfcqidym:pb146svuz0dy",
    "107.172.163.27:6543:kfcqidym:pb146svuz0dy",
    "198.105.121.200:6462:kfcqidym:pb146svuz0dy",
    "64.137.96.74:6641:kfcqidym:pb146svuz0dy",
    "216.10.27.159:6837:kfcqidym:pb146svuz0dy",
    "142.111.67.146:5611:kfcqidym:pb146svuz0dy",
    "191.96.254.138:6185:kfcqidym:pb146svuz0dy"
]

selected = random.choice(RAW_PROXIES)
ip, port, user, pw = selected.split(":")
PROXY_URL = f"http://{user}:{pw}@{ip}:{port}"

app = FastAPI(title="TorchFlix API")
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

API_KEY = "elijah2909_secret_key"
api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)

async def get_api_key(api_key: str = Security(api_key_header)):
    if api_key == API_KEY: return api_key
    raise HTTPException(status_code=403, detail="Invalid API Key.")

# Start session with Residential Proxy
session = Session(proxy=PROXY_URL)

@app.middleware("http")
async def debug_requests(request: Request, call_next):
    return await call_next(request)

@app.get("/", response_class=HTMLResponse)
async def serve_ui():
    try:
        with open("index.html", "r") as f:
            return f.read()
    except Exception as e:
        return f"<h1>Error loading UI</h1><p>index.html not found! {e}</p>"

async def _get_target_item(query: str, type: str):
    sub_type = SubjectType.MOVIES if type == "movie" else SubjectType.TV_SERIES
    search = Search(session, query=query, subject_type=sub_type)
    results = await search.get_content_model()
    if not results.items: raise Exception(f"No {type} found for query: {query}")
    return results.first_item

@app.get("/api/search")
async def search_media(query: str, type: str = "all", api_key: str = Depends(get_api_key)):
    try:
        sub_type = SubjectType.ALL
        if type.lower() == "movie": sub_type = SubjectType.MOVIES
        elif type.lower() == "series": sub_type = SubjectType.TV_SERIES
        return await Search(session, query=query, subject_type=sub_type, per_page=15).get_content()
    except Exception as e: return JSONResponse(status_code=500, content={"error": str(e)})

@app.get("/api/trending")
async def get_trending(api_key: str = Depends(get_api_key)):
    try: return await Trending(session).get_content()
    except Exception as e: return JSONResponse(status_code=500, content={"error": str(e)})

@app.get("/api/media-files")
async def get_media_files(query: str, type: str = "movie", season: int = 1, episode: int = 1, api_key: str = Depends(get_api_key)):
    try:
        target_item = await _get_target_item(query, type)
        if type == "movie": 
            details = await DownloadableMovieFilesDetail(session, target_item).get_content_model()
        else: 
            details = await DownloadableTVSeriesFilesDetail(session, target_item).get_content_model(season=season, episode=episode)
            
        videos = [{"resolution": getattr(d, 'resolution', 0), "url": str(getattr(d, 'url', '')), "size": getattr(d, 'size', 0), "ext": getattr(d, 'ext', 'mp4')} for d in details.downloads]
        subs = [{"language": getattr(c, 'lanName', ''), "url": str(getattr(c, 'url', '')), "ext": getattr(c, 'ext', 'srt')} for c in details.captions]
        return {"status": "success", "title": target_item.title, "videos": videos, "subtitles": subs, "proxy_used": ip}
    except Exception as e: 
        return JSONResponse(status_code=500, content={"error": str(e), "trace": traceback.format_exc()})

@app.get("/api/homepage")
async def get_homepage(api_key: str = Depends(get_api_key)):
    try: return await Homepage(session).get_content()
    except Exception as e: return JSONResponse(status_code=500, content={"error": str(e)})

@app.get("/api/details")
async def get_details(query: str, type: str = "movie", api_key: str = Depends(get_api_key)):
    try:
        target_item = await _get_target_item(query, type)
        if type == "movie": return await MovieDetails(target_item, session).get_content()
        else: return await TVSeriesDetails(target_item, session).get_content()
    except Exception as e: return JSONResponse(status_code=500, content={"error": str(e)})

@app.get("/api/recommendations")
async def get_recommendations(query: str, type: str = "movie", api_key: str = Depends(get_api_key)):
    try: return await Recommend(session, await _get_target_item(query, type)).get_content()
    except Exception as e: return JSONResponse(status_code=500, content={"error": str(e)})

@app.get("/api/popular-searches")
async def get_popular_searches(api_key: str = Depends(get_api_key)):
    try: return await PopularSearch(session).get_content()
    except Exception as e: return JSONResponse(status_code=500, content={"error": str(e)})

@app.get("/api/hot")
async def get_hot(api_key: str = Depends(get_api_key)):
    try: return await HotMoviesAndTVSeries(session).get_content()
    except Exception as e: return JSONResponse(status_code=500, content={"error": str(e)})