backup
This commit is contained in:
parent
ad995affd5
commit
c5e6057dff
22
Dockerfile
22
Dockerfile
@ -0,0 +1,22 @@
|
|||||||
|
# Use official Python image
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
# Set work directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy project files
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
# Run the app with Uvicorn
|
||||||
|
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
BIN
app/.DS_Store
vendored
Normal file
BIN
app/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
app/__pycache__/download.cpython-313.pyc
Normal file
BIN
app/__pycache__/download.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
531
app/data/dropout.json
Normal file
531
app/data/dropout.json
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"SHOW": "Adventuring Academy",
|
||||||
|
"URL": "https://www.dropout.tv/adventuring-academy",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Bad Internet",
|
||||||
|
"URL": "https://www.dropout.tv/bad-internet",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Breaking News No Laugh Newsroom",
|
||||||
|
"URL": "https://www.dropout.tv/breaking-news-no-laugh-newsroom",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Cartoon Hell",
|
||||||
|
"URL": "https://www.dropout.tv/cartoon-hell",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20",
|
||||||
|
"SEASONS": [
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 A Court of Fey Flowers",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-a-court-of-fey-flowers",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 A Crown of Candy",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-a-crown-of-candy",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 A Starstruck Odyssey",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-a-starstruck-odyssey",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Animated",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-animated",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Audio Only",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-audio-only",
|
||||||
|
"SEASONS": [
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Burrow's End",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-burrow-s-end",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Coffin Run",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-coffin-run",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Dungeons And Drag Queens",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-dungeons-and-drag-queens",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Escape From The Bloodkeep",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-escape-from-the-bloodkeep",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Fantasy High",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-fantasy-high",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Fantasy High Junior Year",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-fantasy-high-junior-year",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Leviathan",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-leviathan",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Mentopolis",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-mentopolis",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Misfits And Magic",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-misfits-and-magic",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Never Stop Blowing Up",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-never-stop-blowing-up",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Neverafter",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-neverafter",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Shriek Week",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-shriek-week",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 The Ravening War",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-the-ravening-war",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 The Seven",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-the-seven",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 The Unsleeping City",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-the-unsleeping-city",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Time Quangle",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-time-quangle",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Tiny Heist",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-tiny-heist",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20 Titan Takedown",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-titan-takedown",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dimension 20's Adventuring Party",
|
||||||
|
"URL": "https://www.dropout.tv/dimension-20-s-adventuring-party",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
|
"10",
|
||||||
|
"11",
|
||||||
|
"12",
|
||||||
|
"13",
|
||||||
|
"14",
|
||||||
|
"15",
|
||||||
|
"16",
|
||||||
|
"17",
|
||||||
|
"18",
|
||||||
|
"19",
|
||||||
|
"20"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dirty Laundry",
|
||||||
|
"URL": "https://www.dropout.tv/dirty-laundry",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"69"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Dropout Music",
|
||||||
|
"URL": "https://www.dropout.tv/dropout-music",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Erotic Clubhouse",
|
||||||
|
"URL": "https://www.dropout.tv/erotic-clubhouse",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Fantasy High Extra Credit",
|
||||||
|
"URL": "https://www.dropout.tv/fantasy-high-extra-credit",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Game Changer",
|
||||||
|
"URL": "https://www.dropout.tv/game-changer",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Game Changer Animated",
|
||||||
|
"URL": "https://www.dropout.tv/game-changer-animated",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Game Changer Battle Royale",
|
||||||
|
"URL": "https://www.dropout.tv/game-changer-battle-royale",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Gastronauts",
|
||||||
|
"URL": "https://www.dropout.tv/gastronauts",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Gods of Food",
|
||||||
|
"URL": "https://www.dropout.tv/gods-of-food",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Kingpin Katie",
|
||||||
|
"URL": "https://www.dropout.tv/kingpin-katie",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Kingpin Katie The Web Series",
|
||||||
|
"URL": "https://www.dropout.tv/kingpin-katie-the-web-series",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Make Some Noise",
|
||||||
|
"URL": "https://www.dropout.tv/make-some-noise",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Mice Murder",
|
||||||
|
"URL": "https://www.dropout.tv/mice-murder",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Monet's Slumber Party",
|
||||||
|
"URL": "https://www.dropout.tv/monet-s-slumber-party",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Nobody Asked",
|
||||||
|
"URL": "https://www.dropout.tv/nobody-asked",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Paranoia",
|
||||||
|
"URL": "https://www.dropout.tv/paranoia",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Parlor Room",
|
||||||
|
"URL": "https://www.dropout.tv/parlor-room",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Play It By Ear",
|
||||||
|
"URL": "https://www.dropout.tv/play-it-by-ear",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "See Plum Run",
|
||||||
|
"URL": "https://www.dropout.tv/see-plum-run",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Smartypants",
|
||||||
|
"URL": "https://www.dropout.tv/smartypants",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Thousandaires",
|
||||||
|
"URL": "https://www.dropout.tv/thousandaires",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Total Forgiveness",
|
||||||
|
"URL": "https://www.dropout.tv/total-forgiveness",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Total Forgiveness Early Payoff",
|
||||||
|
"URL": "https://www.dropout.tv/total-forgiveness-early-payoff",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Troopers 1",
|
||||||
|
"URL": "https://www.dropout.tv/troopers-1",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Troopers Animated",
|
||||||
|
"URL": "https://www.dropout.tv/troopers-animated",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Ultramechatron Team Go 1",
|
||||||
|
"URL": "https://www.dropout.tv/ultramechatron-team-go-1",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Um Actually",
|
||||||
|
"URL": "https://www.dropout.tv/um-actually",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
|
"10"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Very Important People",
|
||||||
|
"URL": "https://www.dropout.tv/very-important-people",
|
||||||
|
"SEASONS": [
|
||||||
|
"1",
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "What The Facts 101",
|
||||||
|
"URL": "https://www.dropout.tv/what-the-facts-101",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Where In The Eff Is Sarah Cincinnati",
|
||||||
|
"URL": "https://www.dropout.tv/where-in-the-eff-is-sarah-cincinnati",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHOW": "Wtf 101",
|
||||||
|
"URL": "https://www.dropout.tv/wtf-101",
|
||||||
|
"SEASONS": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
131
app/download.py
Normal file
131
app/download.py
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
import os, yt_dlp, json, requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
class grab():
|
||||||
|
def season(url):
|
||||||
|
page_html=requests.get(url)
|
||||||
|
soup = BeautifulSoup(page_html.text, 'html.parser')
|
||||||
|
select_element = soup.find('select', class_='js-switch-season')
|
||||||
|
options = select_element.find_all('option')
|
||||||
|
option_values = [option['value'] for option in options if option.has_attr('value')]
|
||||||
|
seasons = [item.replace(url+'/season:', '') for item in option_values]
|
||||||
|
return seasons
|
||||||
|
|
||||||
|
class dropout():
|
||||||
|
def show(show,season,episode):
|
||||||
|
directory='/mnt/plex/tv/'+show+'/Season '+season+'/'
|
||||||
|
with open('data/dropout.json', 'r') as json_file:
|
||||||
|
url_mapping = json.load(json_file)
|
||||||
|
url = next((item['URL'] for item in url_mapping if item['SHOW'] == show), None)
|
||||||
|
if url is not None:
|
||||||
|
url = f'{url}/season:{season}'
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Show '{show}' not found in the JSON data.")
|
||||||
|
if not os.path.exists(directory):
|
||||||
|
os.makedirs(directory)
|
||||||
|
if episode is None or episode == '':
|
||||||
|
episode = '%(playlist_index)02d'
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
dl_ops['playliststart'] = int(episode)
|
||||||
|
except ValueError:
|
||||||
|
# Handle the error, e.g., log it or set a default value
|
||||||
|
dl_ops['playliststart'] = 0 # or some appropriate default value
|
||||||
|
dl_ops = {
|
||||||
|
'format': 'bestvideo+bestaudio/best',
|
||||||
|
'audio_quality': '256K',
|
||||||
|
'paths': {
|
||||||
|
'temp': '/mnt/data/downloader/temp',
|
||||||
|
'home': directory
|
||||||
|
},
|
||||||
|
'cookiefile': 'cookies.txt',
|
||||||
|
'reject_title': [
|
||||||
|
r'(?i).*behind.?the.?scenes.*', # Reject titles with "behind the scenes" (case-insensitive)
|
||||||
|
r'(?i).*trailer.*', # Reject titles with "trailer" (case-insensitive)
|
||||||
|
r'(?i).*recap.*', # Reject titles with "recap" (case-insensitive)
|
||||||
|
r'(?i).*last.looks.*' # Reject titles with "last looks" (case-insensitive)
|
||||||
|
],
|
||||||
|
'outtmpl': show + ' - S'+f"{int(season):02}"+'E'+episode+' - %(title)s.%(ext)s',
|
||||||
|
'noplaylist': True,
|
||||||
|
# Additional options for downloading subtitles
|
||||||
|
'writesubtitles': True, # Download subtitles
|
||||||
|
'subtitleslangs': ['en'] # Specify the language for subtitles (e.g., 'en' for English)
|
||||||
|
}
|
||||||
|
with yt_dlp.YoutubeDL(dl_ops) as ydl:
|
||||||
|
ydl.download([url])
|
||||||
|
|
||||||
|
def series():
|
||||||
|
json_data=[]
|
||||||
|
page_html=requests.get('https://www.dropout.tv/series')
|
||||||
|
# If you want to parse the HTML
|
||||||
|
soup = BeautifulSoup(page_html.text, 'html.parser')
|
||||||
|
# Example: Find all elements with a specific class
|
||||||
|
elements = soup.find_all(class_='browse-item-link')
|
||||||
|
# Extract URLs from href attributes
|
||||||
|
urls = [element['href'] for element in elements if 'href' in element.attrs]
|
||||||
|
|
||||||
|
for url in urls:
|
||||||
|
info_data={}
|
||||||
|
name=url.replace('https://www.dropout.tv/','').replace('-s-',"'s-").replace('-',' ').title().replace('Of','of').replace("'S","'s")
|
||||||
|
info_data['SHOW'] = name
|
||||||
|
info_data['URL'] = url
|
||||||
|
info_data['SEASONS'] = grab.season(url)
|
||||||
|
json_data.append(info_data)
|
||||||
|
|
||||||
|
# Sort the json_data by the 'SHOW' key
|
||||||
|
sorted_json_data = sorted(json_data, key=lambda x: x['SHOW'])
|
||||||
|
|
||||||
|
with open('data/dropout.json', 'w') as json_file:
|
||||||
|
json.dump(sorted_json_data, json_file, indent=4)
|
||||||
|
return sorted_json_data
|
||||||
|
|
||||||
|
def ydl(url, location):
|
||||||
|
dl_ops = {'paths': {'temp': '/mnt/data/downloader/temp', 'home': location}, 'outtmpl': '%(uploader)s/%(title)s.%(ext)s'}
|
||||||
|
if location == "/mnt/plex/podcasts":
|
||||||
|
dl_ops['format'] = 'bestaudio/best[ext=mp3]'
|
||||||
|
dl_ops['postprocessors'] = [{
|
||||||
|
'key': 'FFmpegExtractAudio',
|
||||||
|
'preferredcodec': 'mp3',
|
||||||
|
'preferredquality': '192',
|
||||||
|
}, {
|
||||||
|
'key': 'FFmpegMetadata',
|
||||||
|
'add_metadata': True,
|
||||||
|
}]
|
||||||
|
elif location == "/mnt/plex/asmr":
|
||||||
|
dl_ops['format'] = 'bestaudio/best[ext=mp3]'
|
||||||
|
dl_ops['postprocessors'] = [{
|
||||||
|
'key': 'FFmpegExtractAudio',
|
||||||
|
'preferredcodec': 'mp3',
|
||||||
|
'preferredquality': '192',
|
||||||
|
}, {
|
||||||
|
'key': 'FFmpegMetadata',
|
||||||
|
'add_metadata': True,
|
||||||
|
}]
|
||||||
|
elif location == "/mnt/nsfw":
|
||||||
|
dl_ops['format'] = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best'
|
||||||
|
|
||||||
|
else:
|
||||||
|
dl_ops = {
|
||||||
|
'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best',
|
||||||
|
'cookiefile': 'yt-cookies.txt'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
with yt_dlp.YoutubeDL(dl_ops) as ydl:
|
||||||
|
ydl.download(url)
|
||||||
|
|
||||||
|
# Extracting video information
|
||||||
|
video_info = ydl.extract_info(url, download=False)
|
||||||
|
thumbnail_url = video_info.get('thumbnail')
|
||||||
|
|
||||||
|
# Download the thumbnail image
|
||||||
|
if thumbnail_url:
|
||||||
|
try:
|
||||||
|
thumbnail_filename = os.path.join(location, f"{video_info['id']}.jpg")
|
||||||
|
with open(thumbnail_filename, 'wb') as thumbnail_file:
|
||||||
|
thumbnail_file.write(requests.get(thumbnail_url).content)
|
||||||
|
print("Downloaded MP4 and downloaded thumbnail successfully!")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error downloading thumbnail: {str(e)}")
|
||||||
|
else:
|
||||||
|
print("Downloaded MP4 but no thumbnail found.")
|
||||||
25
app/main.py
25
app/main.py
@ -1,7 +1,10 @@
|
|||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
from fastapi.responses import HTMLResponse
|
from fastapi.responses import HTMLResponse, JSONResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
from pathlib import Path
|
||||||
|
import download
|
||||||
|
import json
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
@ -11,6 +14,26 @@ app.mount("/static", StaticFiles(directory="static"), name="static")
|
|||||||
# Jinja2 template directory
|
# Jinja2 template directory
|
||||||
templates = Jinja2Templates(directory="templates")
|
templates = Jinja2Templates(directory="templates")
|
||||||
|
|
||||||
|
|
||||||
|
# api
|
||||||
|
@app.get("/dropoutUpdate")
|
||||||
|
async def grab():
|
||||||
|
return download.dropout.series()
|
||||||
|
|
||||||
|
@app.get("/dropoutSeries", response_class=JSONResponse)
|
||||||
|
async def read():
|
||||||
|
file_path = Path("data/dropout.json")
|
||||||
|
if file_path.exists():
|
||||||
|
with file_path.open("r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return JSONResponse(content=data)
|
||||||
|
return JSONResponse(content={"error": "File not found"}, status_code=404)
|
||||||
|
|
||||||
|
@app.get("/dropoutDownload")
|
||||||
|
async def download(show: str, season: str, episode: str):
|
||||||
|
download.dropout.show(show,season,episode)
|
||||||
|
|
||||||
|
# html
|
||||||
@app.get("/", response_class=HTMLResponse)
|
@app.get("/", response_class=HTMLResponse)
|
||||||
async def read_root(request: Request):
|
async def read_root(request: Request):
|
||||||
return templates.TemplateResponse("index.html", {"request": request, "message": "Hello from FastAPI + Jinja2!"})
|
return templates.TemplateResponse("index.html", {"request": request, "message": "Hello from FastAPI + Jinja2!"})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user