Upload app
This commit is contained in:
132
src/app.py
Executable file
132
src/app.py
Executable file
@@ -0,0 +1,132 @@
|
||||
from flask import Flask
|
||||
from flask import render_template
|
||||
from flask import request
|
||||
from plexapi.server import PlexServer
|
||||
from werkzeug.utils import secure_filename
|
||||
from os import remove
|
||||
from os import environ
|
||||
from os import mkdir
|
||||
from os import path
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Parse environment variables
|
||||
ROOT = environ['PLEX_URL'].rstrip('/') if 'PLEX_URL' in environ else 'http://localhost:32400'
|
||||
SUBDOMAIN = environ['SUBDOMAIN'].rstrip('/') if 'SUBDOMAIN' in environ else ''
|
||||
TOKEN = environ['PLEX_TOKEN'] if 'PLEX_TOKEN' in environ else exit('PLEX_TOKEN environment variable not set!')
|
||||
|
||||
# Connect to Plex server
|
||||
plex = PlexServer(ROOT, TOKEN)
|
||||
|
||||
# Shows all libraries
|
||||
@app.route(SUBDOMAIN + "/")
|
||||
def index():
|
||||
libraries = plex.library.sections()
|
||||
final = {}
|
||||
for library in libraries:
|
||||
if library.type == 'movie' or library.type == 'show':
|
||||
final[library.title] = {'url': SUBDOMAIN + '/' + library.title}
|
||||
|
||||
return render_template('index.html', libraries=final)
|
||||
|
||||
# Shows all items in a library
|
||||
@app.route(SUBDOMAIN + "/<library>/")
|
||||
def library(library):
|
||||
library = plex.library.section(library)
|
||||
media = library.all()
|
||||
final = {}
|
||||
if library.type == 'movie':
|
||||
for item in media:
|
||||
final[item.title] = {'upload': SUBDOMAIN + '/upload/' + item.key.split('/')[-1],
|
||||
'manage': SUBDOMAIN + '/manage/' + item.key.split('/')[-1]}
|
||||
elif library.type == 'show':
|
||||
for item in media:
|
||||
final[item.title] = {'url': SUBDOMAIN + '/' + library.title + '/' + item.key.split('/')[-1]}
|
||||
else:
|
||||
return 'Invalid library type'
|
||||
|
||||
return render_template('library.html', library=library, media=final)
|
||||
|
||||
# Shows seasons for shows and upload menu for movies
|
||||
@app.route(SUBDOMAIN + "/<library>/<key>/")
|
||||
def media(library, key):
|
||||
library = plex.library.section(library)
|
||||
key = '/library/metadata/' + key
|
||||
item = plex.fetchItem(key)
|
||||
|
||||
if item.type == 'movie':
|
||||
return render_template('upload.html', item=item)
|
||||
|
||||
elif item.type == 'show':
|
||||
seasons = item.seasons()
|
||||
final = {}
|
||||
for season in seasons:
|
||||
final[season.title] = {'url': SUBDOMAIN + '/' + library.title + '/' + item.key.split('/')[-1] + '/' + season.key.split('/')[-1]}
|
||||
|
||||
return render_template('show.html', library=library, item=item, seasons=final)
|
||||
|
||||
else:
|
||||
return 'Unknown item type'
|
||||
|
||||
# Shows all episodes in a season
|
||||
@app.route(SUBDOMAIN + "/<library>/<key>/<season>/")
|
||||
def season(library, key, season):
|
||||
library = plex.library.section(library)
|
||||
key = '/library/metadata/' + key
|
||||
item = plex.fetchItem(key)
|
||||
season = plex.fetchItem('/library/metadata/' + season)
|
||||
|
||||
episodes = season.episodes()
|
||||
final = {}
|
||||
for episode in episodes:
|
||||
final[episode.title] = {'upload': SUBDOMAIN + '/upload/' + episode.key.split('/')[-1],
|
||||
'manage': SUBDOMAIN + '/manage/' + episode.key.split('/')[-1]}
|
||||
|
||||
return render_template('season.html', library=library, item=item, season=season, episodes=final)
|
||||
|
||||
# Uploads a file to Plex
|
||||
@app.route(SUBDOMAIN + "/upload/<key>", methods=['GET', 'POST'])
|
||||
def upload(key):
|
||||
key = '/library/metadata/' + key
|
||||
item = plex.fetchItem(key)
|
||||
if request.method == 'POST':
|
||||
# Create a temporary directory if it doesn't exist
|
||||
if not path.exists('tmp'):
|
||||
mkdir('tmp')
|
||||
|
||||
# Fetch uploaded file
|
||||
file = request.files['subtitles']
|
||||
file.save('./temp/' + secure_filename(file.filename))
|
||||
|
||||
# Upload file to Plex
|
||||
item.uploadSubtitles('./temp/' + secure_filename(file.filename))
|
||||
|
||||
# Remove temporary file
|
||||
remove('./temp/' + secure_filename(file.filename))
|
||||
|
||||
return render_template('success.html')
|
||||
|
||||
else:
|
||||
return render_template('upload.html', item=item)
|
||||
|
||||
# Manages subtitles for an item
|
||||
@app.route(SUBDOMAIN + "/manage/<key>")
|
||||
def manage(key):
|
||||
key = '/library/metadata/' + key
|
||||
item = plex.fetchItem(key)
|
||||
subtitles = item.subtitleStreams()
|
||||
final = {}
|
||||
for sub in subtitles:
|
||||
if sub.title:
|
||||
final[sub.extendedDisplayTitle] = {'url': SUBDOMAIN + '/delete/' + item.key.split('/')[-1] + '/' + sub.title}
|
||||
|
||||
return render_template('manage.html', item=item, subs=final)
|
||||
|
||||
# Deletes a subtitle from an item
|
||||
@app.route(SUBDOMAIN + "/delete/<key>/<sub>")
|
||||
def delete(key, sub):
|
||||
key = '/library/metadata/' + key
|
||||
item = plex.fetchItem(key)
|
||||
item.removeSubtitles(streamTitle=sub)
|
||||
|
||||
return render_template('success.html')
|
15
src/templates/index.html
Executable file
15
src/templates/index.html
Executable file
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Libraries</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1><a href="..">Libraries</a></h1>
|
||||
<ul>
|
||||
{% for title, prop in libraries.items() %}
|
||||
<li><a href="{{ prop['url'] }}">{{ title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
src/templates/library.html
Executable file
23
src/templates/library.html
Executable file
@@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ library.title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1><a href="..">Items</a></h1>
|
||||
<ul>
|
||||
{% for title, prop in media.items() %}
|
||||
{% if 'url' in prop %}
|
||||
<li><a href="{{ prop['url'] }}">{{ title }}</a></li>
|
||||
{% elif 'upload' in prop and 'manage' in prop %}
|
||||
<li>
|
||||
{{ title }} -
|
||||
<a href="{{ prop['upload'] }}">Upload</a> -
|
||||
<a href="{{ prop['manage'] }}">Manage</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
18
src/templates/manage.html
Executable file
18
src/templates/manage.html
Executable file
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ item.title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1><a href="..">{{ item.title }}</a></h1>
|
||||
</div>
|
||||
<ul>
|
||||
{% for item, prop in subs.items() %}
|
||||
<li>
|
||||
{{ item }} -
|
||||
<a href="{{ prop['url'] }}">Delete</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
19
src/templates/season.html
Executable file
19
src/templates/season.html
Executable file
@@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ item.title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1><a href="..">Episodes</a></h1>
|
||||
<ol>
|
||||
{% for title, prop in episodes.items() %}
|
||||
<li>
|
||||
{{ title }} -
|
||||
<a href="{{ prop['upload'] }}">Upload</a> -
|
||||
<a href="{{ prop['manage'] }}">Manage</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
15
src/templates/show.html
Executable file
15
src/templates/show.html
Executable file
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ item.title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1><a href="..">Seasons</a></h1>
|
||||
<ol>
|
||||
{% for title, prop in seasons.items() %}
|
||||
<li><a href="{{ prop['url'] }}">{{ title }}</a></li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
10
src/templates/success.html
Executable file
10
src/templates/success.html
Executable file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Success</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Success</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
17
src/templates/upload.html
Executable file
17
src/templates/upload.html
Executable file
@@ -0,0 +1,17 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ item.title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1><a href="..">{{ item.title }}</a></h1>
|
||||
</div>
|
||||
<!-- Upload subtitles form -->
|
||||
<div class="container">
|
||||
<form action="" method="post" enctype="multipart/form-data">
|
||||
<input type="file" name="subtitles" />
|
||||
<input type="submit" value="Upload" />
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user