Skip to content

Commit

Permalink
feat: gathers files from torbox api
Browse files Browse the repository at this point in the history
  • Loading branch information
anonymous-org-za committed Jul 8, 2024
1 parent e851372 commit e39f148
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 4 deletions.
39 changes: 39 additions & 0 deletions functions/tinfoilFunctions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import asyncio
from functions.torboxFunctions import getDownloads
import logging
from library.tinfoil import errorMessage
from fastapi.responses import JSONResponse

ACCEPTABLE_SWITCH_FILES = [".nsp", ".nsz", ".xci", ".xcz"]


async def generateIndex(base_url: str):
"""
Generates a JSON index from your TorBox files. Matches only switch compatible files and returns a well-formatted JSON index for Tinfoil.
Requires:
- base_url: where the server is hosted, so it can create proper URLs.
Returns:
- dict: the generated index for Tinfoil to use.
"""

success_message = "Welcome to your self-hosted TorBox Tinfoil Server! You are now able to directly download your files from TorBox to your switch.\n\n"
files = []
try:
# runs all requests in parallel for faster responses
torrents, usenet_downloads, web_downloads = await asyncio.gather(getDownloads("torrents"), getDownloads("usenet"), getDownloads("webdl"))

file_list = torrents + usenet_downloads + web_downloads


except Exception as e:
logging.error(f"There was an error generating the index. Error: {str(e)}")
return JSONResponse(
status_code=500,
content=errorMessage(f"There was an error generating the index. Error: {str(e)}", error_code="UNKOWN_ERROR")
)




60 changes: 60 additions & 0 deletions functions/torboxFunctions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import httpx
from library.torbox import TORBOX_API_KEY, TORBOX_API_URL
import logging
import traceback

async def getDownloads(type: str):
"""
Gets a download type list from TorBox.
Requires:
- type: the download type to be retrieved, either "torrents", "usenet", or "webdl"
Returns:
- file_list: a list containing all of the files retrieved from the TorBox API.
"""

if type not in ["torrents", "usenet", "webdl"]:
logging.error("Please provide a type of either 'torrents', 'usenet' or 'webdl'.")
return []

try:
async with httpx.AsyncClient() as client:
response = await client.get(
url=f"{TORBOX_API_URL}/{type}/mylist",
headers={
"Authorization": f"Bearer {TORBOX_API_KEY}",
"User-Agent": "TorBox SelfHosted Tinfoil Server/1.0.0"
}
)
if response.status_code != httpx.codes.OK:
logging.error(f"Unable to retrieve TorBox {type} downloads. Response Code: {response.status_code}. Response: {response.json()}")
return []
files = []
json = response.json()
for download in json.get("data", {}):
# only get downloads that are completely ready for download
if not download.get("download_present", False):
continue
type = "download"
id = download.get("id", None)
for file in download.get("files", []):
if not file.get("s3_path", None):
continue
try:
files.append({
"type": type,
"id": id,
"file_id": file.get("id", 0),
"name": file.get("s3_path", None).split("/")[-1], # gets only the filename of the file
"size": file.get("size", 0)
})
except Exception:
logging.error(f"There was an error trying to add {type} download file to file list. Error: {str(e)}")
continue
return files
except Exception as e:
traceback.print_exc()
logging.error(f"There was an error getting {type} downloads from TorBox. Error: {str(e)}")
return []

3 changes: 2 additions & 1 deletion library/torbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
from dotenv import load_dotenv
load_dotenv()

TORBOX_API_KEY = os.getenv("TORBOX_API_KEY")
TORBOX_API_KEY = os.getenv("TORBOX_API_KEY")
TORBOX_API_URL = "https://api.torbox.app/v1/api"
9 changes: 6 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import uvicorn
from fastapi import FastAPI, HTTPException, status, Depends, Header
from fastapi import FastAPI, HTTPException, status, Depends, Header, Request
from fastapi.responses import JSONResponse
from typing_extensions import Annotated, Union
from library.tinfoil import errorMessage
from library.server import PORT
from functions.authFunctions import checkCorrectCredentials
from functions.serverFunctions import checkAllowed
import logging
from functions.tinfoilFunctions import generateIndex

app = FastAPI()
logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.INFO)

# Custom exemption handler to be well-formatted with Tinfoil so the user knows what has happened if no authentication is sent, as it is required.
@app.exception_handler(HTTPException)
Expand All @@ -23,16 +24,18 @@ async def custom_http_exception_handler(request, exc):

@app.get("/")
async def get_user_files(
request: Request,
authenticated: bool = Depends(checkCorrectCredentials),
uid: Annotated[Union[str, None], Header()] = None
):
logging.debug(f"Request from Switch with UID: {uid}")
logging.info(f"Request from Switch with UID: {uid}")
allowed, response = checkAllowed(authenticated=authenticated, switch_uid=uid)
if not allowed:
return JSONResponse(
content=response,
status_code=401
)
return await generateIndex(base_url=request.base_url)


if __name__ == "__main__":
Expand Down

0 comments on commit e39f148

Please sign in to comment.