202 lines
7.0 KiB
Python
202 lines
7.0 KiB
Python
import cherrypy
|
|
import requests
|
|
import os
|
|
import math
|
|
import pycountry
|
|
import json
|
|
import re
|
|
import threading
|
|
import time
|
|
import urllib.request
|
|
import xml.etree.ElementTree as ET
|
|
import subprocess
|
|
import yt_dlp
|
|
from bs4 import BeautifulSoup
|
|
|
|
|
|
class download():
|
|
def dropout(show,season,episode):
|
|
directory='/mnt/plex/tv/'+show+'/Season '+season+'/'
|
|
with open('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':
|
|
[
|
|
'Behind the Scenes',
|
|
'Behind The Scenes',
|
|
'Trailer',
|
|
'Recap'
|
|
],
|
|
'outtmpl': show + ' - S'+f"{int(season):02}"+'E'+episode+' - %(title)s.%(ext)s'
|
|
}
|
|
with yt_dlp.YoutubeDL(dl_ops) as ydl:
|
|
ydl.download(url)
|
|
|
|
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/music/podcast":
|
|
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/music/asmr":
|
|
dl_ops['format'] = 'bestaudio/best[ext=mp3]'
|
|
dl_ops['postprocessors'] = [{
|
|
'key': 'FFmpegExtractAudio',
|
|
'preferredcodec': 'mp3',
|
|
'preferredquality': '192',
|
|
}, {
|
|
'key': 'FFmpegMetadata',
|
|
'add_metadata': True,
|
|
}]
|
|
else:
|
|
dl_ops['format'] = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best'
|
|
|
|
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.")
|
|
|
|
|
|
|
|
|
|
|
|
def navbar(json=None):
|
|
movieCount =''
|
|
movieCount = '<b id="matches">'+str(json['data']['movie_count'])+' Matches</b>' if json != None else ""
|
|
return open('html/navbar.html').read().format(movieCount=movieCount)
|
|
|
|
def shows(json_data):
|
|
html = ''
|
|
accepted_D20 = ('Dimension 20', 'Dimension 20 Animated', "Dimension 20's Adventuring Party")
|
|
for item in json_data:
|
|
if 'Dimension 20' in item['SHOW']:
|
|
if item['SHOW'] in accepted_D20:
|
|
name = item['SHOW']
|
|
url = item['URL']
|
|
html += '<option value="' + name + '">' + name + '</option>'
|
|
else:
|
|
name = item['SHOW']
|
|
url = item['URL']
|
|
html += '<option value="' + name + '">' + name + '</option>'
|
|
return html
|
|
|
|
|
|
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]
|
|
print(seasons)
|
|
return seasons
|
|
|
|
|
|
|
|
|
|
class MovieApp:
|
|
@cherrypy.expose
|
|
def index(self):
|
|
|
|
return open('html/index.html').read().format(navBar=navbar())
|
|
|
|
@cherrypy.expose
|
|
def downloader(self):
|
|
return open('html/ydl.html').read().format(navBar=navbar())
|
|
|
|
@cherrypy.expose
|
|
def dropout(self):
|
|
with open('dropout.json', 'r') as json_file:
|
|
json_data = json.load(json_file)
|
|
return open('html/dropout.html').read().format(navBar=navbar(),shows=shows(json_data))
|
|
|
|
@cherrypy.expose
|
|
def seriesInfo(self):
|
|
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('dropout.json', 'w') as json_file:
|
|
json.dump(sorted_json_data, json_file, indent=4)
|
|
|
|
@cherrypy.expose
|
|
def tester(self):
|
|
grab.season('https://www.dropout.tv/adventuring-academy')
|
|
|
|
@cherrypy.expose
|
|
def dropoutDownloader(self,show,season,episode=None):
|
|
download.dropout(show,season,episode)
|
|
|
|
@cherrypy.expose
|
|
def ydl(self, url, location='/mnt/plex/youtube'):
|
|
download.ydl(url,location)
|
|
|
|
cherrypy.config.update({
|
|
'tools.staticdir.on': True,
|
|
'tools.staticdir.dir': os.getcwd(),
|
|
'server.socket_host': '0.0.0.0',
|
|
'server.socket_port': 8008,
|
|
'favicon.ico': 'favicon.ico',
|
|
})
|
|
if __name__ == '__main__':
|
|
cherrypy.quickstart(MovieApp())
|