This commit is contained in:
TylerCG 2025-04-24 14:04:37 -04:00
parent 5dffde4a55
commit 082576061e
5 changed files with 50 additions and 21 deletions

5
.gitignore vendored
View File

@ -1,5 +1,6 @@
__pycache__ __pycache__
.DS_Store
data/* data/*
# macOS # macOS
.DS_Store .DS_Store
dropout_cookies.txt

View File

@ -4,7 +4,8 @@ FROM python:3.11-slim
# Install ffmpeg and other dependencies # Install ffmpeg and other dependencies
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
ffmpeg \ ffmpeg \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/* \
&& pip install yt_dlp
# Set environment variables # Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONDONTWRITEBYTECODE=1
@ -13,7 +14,7 @@ ENV PYTHONUNBUFFERED=1
# Set work directory # Set work directory
WORKDIR /app WORKDIR /app
RUN mkdir /data /tv /youtube /asmr /nsfw /temp RUN mkdir /app/data /app/tv /app/youtube /app/asmr /app/nsfw /app/temp
# Install dependencies # Install dependencies
COPY requirements.txt . COPY requirements.txt .

View File

@ -56,7 +56,7 @@ class dropout():
'temp': '/temp', 'temp': '/temp',
'home': directory 'home': directory
}, },
'cookiefile': '/data/dropout_cookies.txt', 'cookiefile': '/data/dropout.cookies.txt',
'reject_title': [ 'reject_title': [
r'(?i).*behind.?the.?scenes.*', # Reject titles with "behind the scenes" (case-insensitive) r'(?i).*behind.?the.?scenes.*', # Reject titles with "behind the scenes" (case-insensitive)
r'(?i).*trailer.*', # Reject titles with "trailer" (case-insensitive) r'(?i).*trailer.*', # Reject titles with "trailer" (case-insensitive)
@ -100,7 +100,7 @@ class dropout():
class youtube(): class youtube():
def ydl(url, location): def ydl(url, location):
dl_ops = {'paths': {'temp': '/temp', 'home': location}, 'outtmpl': '%(uploader)s/%(title)s.%(ext)s'} dl_ops = {'paths': {'temp': '/temp', 'home': location}, 'outtmpl': '%(uploader)s/%(title)s.%(ext)s'}
if location == "/podcasts": if dl_ops['paths']['home'] == '/podcasts':
dl_ops['format'] = 'bestaudio/best[ext=mp3]' dl_ops['format'] = 'bestaudio/best[ext=mp3]'
dl_ops['postprocessors'] = [{ dl_ops['postprocessors'] = [{
'key': 'FFmpegExtractAudio', 'key': 'FFmpegExtractAudio',
@ -110,7 +110,7 @@ class youtube():
'key': 'FFmpegMetadata', 'key': 'FFmpegMetadata',
'add_metadata': True, 'add_metadata': True,
}] }]
elif location == "/asmr": elif dl_ops['paths']['home'] == '/asmr':
dl_ops['format'] = 'bestaudio/best[ext=mp3]' dl_ops['format'] = 'bestaudio/best[ext=mp3]'
dl_ops['postprocessors'] = [{ dl_ops['postprocessors'] = [{
'key': 'FFmpegExtractAudio', 'key': 'FFmpegExtractAudio',
@ -120,14 +120,42 @@ class youtube():
'key': 'FFmpegMetadata', 'key': 'FFmpegMetadata',
'add_metadata': True, 'add_metadata': True,
}] }]
elif location == "/nsfw": elif dl_ops['paths']['home'] == '/youtube':
dl_ops['format'] = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best'
dl_ops['cookiefile'] = '/data/youtube.cookies.txt'
else:
dl_ops['format'] = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best' dl_ops['format'] = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best'
with yt_dlp.YoutubeDL(dl_ops) as ydl:
ydl.download([url])
# grab.thumbnail(ydl,url,location)
def downloadOptions(dl_ops):
if dl_ops['paths']['home'] == "/podcasts":
dl_ops['format'] = 'bestaudio/best[ext=mp3]'
dl_ops['postprocessors'] = [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}, {
'key': 'FFmpegMetadata',
'add_metadata': True,
}]
elif dl_ops['paths']['home'] == "/asmr":
dl_ops['format'] = 'bestaudio/best[ext=mp3]'
dl_ops['postprocessors'] = [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}, {
'key': 'FFmpegMetadata',
'add_metadata': True,
}]
elif dl_ops['paths']['home'] == "/nsfw":
dl_ops['format'] = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best'
else: else:
dl_ops = { dl_ops = {
'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best', 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best',
} }
with yt_dlp.YoutubeDL(dl_ops) as ydl: return dl_ops
ydl.download([url])
# grab.thumbnail(ydl,url,location)

View File

@ -4,12 +4,14 @@ from fastapi.templating import Jinja2Templates
# from fastapi.staticfiles import StaticFiles # from fastapi.staticfiles import StaticFiles
# from fastapi.concurrency import run_in_threadpool # from fastapi.concurrency import run_in_threadpool
from pathlib import Path from pathlib import Path
import json, download from functools import partial
import json, download, asyncio
app = FastAPI() app = FastAPI()
# app.mount("/static", StaticFiles(directory="/app/app/static"), name="static") # app.mount("/static", StaticFiles(directory="/app/app/static"), name="static")
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory="templates")
loop = asyncio.get_running_loop()
# api # api
@ -33,7 +35,8 @@ async def dropoutSeries():
@app.post("/dropoutDownload") @app.post("/dropoutDownload")
async def dropoutDownload(show: str, season: str, episode: str = None): async def dropoutDownload(show: str, season: str, episode: str = None):
try: try:
download.dropout.show(show,season,episode) await loop.run_in_executor(None, partial(download.dropout.show,show,season,episode))
# download.dropout.show(show,season,episode)
return JSONResponse(status_code=200, content={"status": "success", "message": "Series downloading."}) return JSONResponse(status_code=200, content={"status": "success", "message": "Series downloading."})
except Exception as e: except Exception as e:
return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})
@ -41,8 +44,10 @@ async def dropoutDownload(show: str, season: str, episode: str = None):
@app.post("/ydl") @app.post("/ydl")
async def ydl(url: str, location: str): async def ydl(url: str, location: str):
try: try:
download.youtube.ydl(url,location) await loop.run_in_executor(None, partial(download.youtube.ydl, url, location))
return JSONResponse(status_code=200, content={"status": "success", "message": "Download completed."}) # download.youtube.ydl(url,location)
# grab.thumbnail(ydl,url,location)
return JSONResponse(status_code=200, content={"status": "success", "message": "Video download completed."})
except Exception as e: except Exception as e:
return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})

View File

@ -1,6 +0,0 @@
# Netscape HTTP Cookie File
# This file is generated by yt-dlp. Do not edit.
www.dropout.tv FALSE / FALSE 2376616194 locale_det en
.dropout.tv TRUE / TRUE 1777000194 _session UElXTTdFemwzenp3RTZPQWx6clJwN3d4WlFkaEV0SXVrd2tnMUNUazJQVldOZEVlVTNOS0ZXS2twUmFHczBuMUlSZXVmTmZIeEFUeFZlajVLRVhrT0VVcm9XYU1jMUZQcTQwQUJNUUhtZ091NWZGS0kwYkMyNmZQelkxbll2QmxXYTFwZlJKNVlmdXFnZkcrVVdld3FCaFB4QnJGb2FLTWxyNlBnOFNCSkNLd1EvTS9OaE1nbTgrcjNmSmR6bE9YLS11M2pSa2VBLzZNZkozeXBXWGF4amhRPT0%3D--9ff14eeca357a6d7d1e8eb3496b039a01b2f92ab
.www.dropout.tv TRUE / TRUE 1745465994 __cf_bm d9dI.ZmTB7AOvOULLAi6gzGen4gtP_wncSkUXNYGV18-1745464194-1.0.1.1-XU86MNGfB8sthsX_dgFr7z0XBFSuYt7yiI60jsNbL2WbD.SbKI57sVTLGBl8xYhDiD.bBN7pJRYJjKXKsn80n8C8RujDnn_55c_6rxwvcoo_pbexZbMpHbzcjc_SHxKH