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 from PyMovieDb import IMDB import subprocess import yt_dlp from downloadScript import download imdb = IMDB() top_movies = [] recent_movies = [] priorities = [ {"type": "web", "video_codec": "x264"}, {"type": "web", "video_codec": "x265"}, {"type": "bluray", "video_codec": "x264"}, {"type": "bluray", "video_codec": "x265"}, ] def createMoviePoster(json_format): movie_data = json_format movie_readout = "" plex_movies = json.load(open('/mnt/moviehub/plex_movies.json', 'r')) for movie in movie_data: res720 = {} res1080 = {} resOther = {} availableRes = [] downButton = "" plex_server_resolution = [] title = movie["title_english"] rating = movie["rating"] year = movie["year"] imdb = movie["imdb_code"] language = pycountry.languages.get(alpha_2=movie['language']) language = language.name if language is not None else language poster_url = movie["large_cover_image"] for movie_match in plex_movies["movies"]: if str(movie_match["video"]["title"].lower()) == str(movie["title"].lower()) and abs(int(movie_match["video"]["year"]) - year) <= 1: plex_server_resolution.append(movie_match["media"]["videoResolution"]+"p") for priority in priorities: for resolution in movie["torrents"]: if (resolution["quality"] == "720p" and resolution["type"] == priority["type"] and resolution["video_codec"] == priority["video_codec"]): res720["res"] = resolution["quality"] res720["url"] = resolution["url"] break for priority in priorities: for resolution in movie["torrents"]: if (resolution["quality"] == "1080p" and resolution["type"] == priority["type"] and resolution["video_codec"] == priority["video_codec"]): res1080["res"] = resolution["quality"] res1080["url"] = resolution["url"] break if len(res720) == 0 and len(res1080) == 0: for resolution in movie["torrents"]: resOther["res"] = resolution["quality"] resOther["url"] = resolution["url"] break availableRes.append(res720) availableRes.append(res1080) availableRes.append(resOther) if availableRes: for resolution in availableRes: res = resolution.get('res') url = resolution.get('url') if res is not None and url is not None: extra_class = "resolution_exists" if res in plex_server_resolution else "download-link resolution_available" downButton += f"""{res}\n""" # Create the movie readout HTML for each movie movie_readout += f"""
{rating} {year} {language}
{title} Poster

{title}

{downButton}
""" return movie_readout def navBar(json=None): movieCount ='' movieCount = ''+str(json['data']['movie_count'])+' Matches' if json != None else "" return open('html/navbar.html').read().format(movieCount=movieCount) def pageButton(json, query_term): pages = '' movieCount = json['data']['movie_count'] resultLimit = json['data']['limit'] activePage = json['data']['page_number'] pageLimit = math.ceil(movieCount / resultLimit) # Calculate the range of pages to display (5 pages) start_page = max(1, activePage - 2) end_page = min(pageLimit, start_page + 4) if end_page - start_page < 4: # Ensure we always show 5 pages if possible start_page = max(1, end_page - 4) for number in range(start_page, end_page + 1): if number == activePage: pages += "" pages += "" + str(number) + "" else: pages += "" + str(number) + "" if pageLimit == 1: return '' else: # Load your HTML template from the file 'pagebutton.html' and format it with the generated pages. return open('html/pagebutton.html').read().format(pages=pages, query_term=query_term, pageLimit=pageLimit) def eztv_json(): return 'pass' class fetch(): def imdb_data(query_term=None): json_data = imdb.search(query_term, tv=True) if query_term is not None else imdb.popular_movies(genre=None, sort_by=None) data = json.loads(json_data) results_data = data.get('results', []) return results_data def yts_movies(parameter=None, movie=None): movie_id = movie['id'] if movie is not None else "" url = f'https://yts.mx/api/v2/list_movies.json{parameter}{movie_id}' data = requests.get(url).json() if 'data' in data and data['data'].get('movie_count', 0) > 0: return data['data']['movies'][0] if movie is not None else data["data"]["movies"] else: return None def plex_data(): url = f'http://10.0.0.105:32400/library/sections/1/all' response = requests.get(url) if response.status_code == 200: plex_xml_data = response.text root = ET.fromstring(plex_xml_data) movies = [] for video_elem in root.findall('.//Video'): video_keys = {} media_keys = {} for key, value in video_elem.items(): video_keys[key] = value media_element = video_elem.find(".//Media") if media_element is not None: media_attributes = media_element.attrib for key, value in media_attributes.items(): media_keys[key] = value movie_info = { 'video': video_keys, 'media': media_keys } movies.append(movie_info) movie_dict = {'movies': movies} json_data = json.dumps(movie_dict, indent=2) with open('/mnt/moviehub/plex_movies.json', 'w') as json_file: json_file.write(json_data) else: print(f'Error: {response.status_code}') class background(): def update_top_movies(): while True: global top_movies # Access the global variable # Your code to fetch and update the top 18 movies new_top_movies = [] for movie in fetch.imdb_data(): if len(new_top_movies) >= 12: break movie_data = fetch.yts_movies('?query_term=', movie) if movie_data is not None: new_top_movies.append(movie_data) top_movies = new_top_movies # Update the global variable global recent_movies recent_movies = fetch.yts_movies('?sort_by=date_added&limit=18') fetch.plex_data() time.sleep(3600) background_thread = threading.Thread(target=background.update_top_movies) background_thread.daemon = True # Set the thread as a daemon to exit when the main program exits background_thread.start() class MovieApp: @cherrypy.expose def index(self): latestMoviesTiles = createMoviePoster(top_movies) recentMoviesTiles = createMoviePoster(recent_movies) return open('html/index.html').read().format(latestMoviesTiles=latestMoviesTiles,recentMoviesTiles=recentMoviesTiles,navBar=navBar()) @cherrypy.expose def movie(self, query_term='', page='1', genre=None, minimum_rating=None): api_url = f"https://yts.mx/api/v2/list_movies.json?limit=30&query_term={query_term}&page={page}" api_url += f"&genre={genre}" if genre is not None else "" api_url += f"&minimum_rating={minimum_rating}" if minimum_rating is not None else "" response = requests.get(api_url) if response.status_code == 200 and response.json()['status_message'] == "Query was successful" and response.json()['data']['movie_count'] > 0: movie_tiles = createMoviePoster(response.json()["data"]["movies"]) pageBar = pageButton(response.json(), query_term) else: movie_tiles = "

No matches found

" pageBar = "" return open('html/movie.html').read().format(movie_tiles=movie_tiles,navBar=navBar(response.json()),pageButton=pageBar) @cherrypy.expose def tv(self, query_term=''): poster_x, poster_y = '500', '750' results_data = fetch.imdb_data(query_term) html = '' regex_pattern = r'_V1_QL\d+_([A-Z]+)(\d+)_CR(\d+),(\d+),(\d+),(\d+)_' for result in results_data: extract = re.search(regex_pattern, result['poster']) item_id = result.get('id', '').replace('tt', '') zoom = int(extract.group(4)) move_x = int(extract.group(3)) if extract else 0 move_x = move_x * 9 if move_x != 0 else move_x + 6.5 upscale_num = '510' if extract.group(2) == extract.group(5) else poster_y resolution = f"""_V1_QL100_{extract.group(1)}{upscale_num}_CR{str(move_x)},{str(zoom)},{poster_x},{poster_y}_""" poster_url = re.sub(r'_V1[\w_,]+', resolution, result['poster']) title = result['name'] html += f"""{title} Poster""" return html @cherrypy.expose def download(self, url, filename): save_path = os.path.join('/mnt/data/deluge/watch/movies', filename) title = filename.replace('.torrent','') response = requests.get(url) if response.status_code == 200: with open(save_path, 'wb') as file: file.write(response.content) return(f"Download has been set for '{title}'.") else: print(f"Failed to download the file from '{url}'.") return(f"Failed to send download request. Contact your system administrator.") @cherrypy.expose def anime(self): rss = open('/mnt/deluge/config/yarss2.conf').read() config = {} # Create an empty dictionary to store configuration with open('/mnt/deluge/config/yarss2.conf', 'r') as file: lines = file.readlines() current_section = None for line in lines: line = line.strip() if line.startswith("{"): current_section = {} elif line.startswith("}"): if current_section: config.update(current_section) current_section = None elif current_section: key, value = line.split(":") current_section[key.strip()] = value.strip() # The 'config' dictionary now contains your configuration data print(config) return config @cherrypy.expose def downloader(self): return open('html/ydl.html').read().format(navBar=navBar()) @cherrypy.expose def dropout(self): return open('html/dropout.html').read().format(navBar=navBar()) @cherrypy.expose def dropoutDownloader(self,show,season,episode=None): download.dropout(show,season,episode) @cherrypy.expose def ydl(self, 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.") @cherrypy.expose def plex(self): fetch.plex_data() @cherrypy.expose def yts(self): background.update_top_movies() @cherrypy.expose def imdb(self): return fetch.imdb_data() 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())