Further file manager work
This commit is contained in:
parent
011a2ec370
commit
0ba35f8f1c
@ -2,7 +2,7 @@
|
|||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
from flask import request, session, render_template
|
from flask import request, session, render_template, send_from_directory, redirect
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
|
|
||||||
@ -22,18 +22,15 @@ def get_window_controller():
|
|||||||
session['win_controller_id'] = id
|
session['win_controller_id'] = id
|
||||||
window_controllers.update( {id: WindowController() } )
|
window_controllers.update( {id: WindowController() } )
|
||||||
|
|
||||||
return window_controllers[ session["win_controller_id"] ]
|
return window_controllers[ session["win_controller_id"] ]
|
||||||
|
|
||||||
|
|
||||||
@app.route('/', methods=['GET', 'POST'])
|
@app.route('/', methods=['GET', 'POST'])
|
||||||
def home():
|
def home():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
view = get_window_controller().get_window(1).get_view(0)
|
view = get_window_controller().get_window(1).get_view(0)
|
||||||
|
|
||||||
view.push_to_path("LazyShare")
|
|
||||||
_path = view.get_path()
|
_path = view.get_path()
|
||||||
_files = view.get_files()
|
_files = view.get_files()
|
||||||
|
|
||||||
return render_template('pages/index.html', path=_path, files=_files)
|
return render_template('pages/index.html', path=_path, files=_files)
|
||||||
|
|
||||||
return render_template('error.html',
|
return render_template('error.html',
|
||||||
@ -128,35 +125,38 @@ def manageFavoritesRoute(_action):
|
|||||||
@app.route('/api/reset-path', methods=['GET', 'POST'])
|
@app.route('/api/reset-path', methods=['GET', 'POST'])
|
||||||
def resetPath():
|
def resetPath():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
file_manager.reset_path()
|
view = get_window_controller().get_window(1).get_view(0)
|
||||||
|
view.set_to_home()
|
||||||
return redirect("/")
|
return redirect("/")
|
||||||
|
|
||||||
|
|
||||||
# Used to get files from non gunicorn root path...
|
# Used to get files from non gunicorn root path...
|
||||||
# Allows us to pull images and stuff to user without simlinking.
|
# Allows us to pull images and stuff to user without simlinking.
|
||||||
@app.route('/api/files/<hash>')
|
@app.route('/api/files/<hash>')
|
||||||
def returnFile(hash):
|
def returnFile(hash):
|
||||||
path = file_manager.getFullPath()
|
view = get_window_controller().get_window(1).get_view(0)
|
||||||
pathPart = file_manager.returnPathPartFromHash(hash)
|
folder = view.get_path()
|
||||||
return send_from_directory(path, pathPart)
|
file = view.returnPathPartFromHash(hash)
|
||||||
|
return send_from_directory(folder, file)
|
||||||
|
|
||||||
@app.route('/api/remux/<hash>')
|
@app.route('/api/remux/<hash>')
|
||||||
def remuxRoute(hash):
|
def remuxRoute(hash):
|
||||||
folder = file_manager.getFullPath()
|
view = get_window_controller().get_window(1).get_view(0)
|
||||||
file = file_manager.returnPathPartFromHash(hash)
|
folder = view.get_path()
|
||||||
fpath = os.path.join(folder, file)
|
file = view.returnPathPartFromHash(hash)
|
||||||
|
fpath = os.path.join(folder, file)
|
||||||
|
|
||||||
logging.debug(fpath)
|
logging.debug(fpath)
|
||||||
return file_manager.remuxVideo(hash, fpath)
|
return view.remuxVideo(hash, fpath)
|
||||||
|
|
||||||
@app.route('/api/run-locally/<hash>')
|
@app.route('/api/run-locally/<hash>')
|
||||||
def runLocallyRoute(hash):
|
def runLocallyRoute(hash):
|
||||||
path = file_manager.getFullPath()
|
view = get_window_controller().get_window(1).get_view(0)
|
||||||
pathPart = file_manager.returnPathPartFromHash(hash)
|
folder = view.get_path()
|
||||||
fullpath = path + "/" + pathPart
|
file = view.returnPathPartFromHash(hash)
|
||||||
|
fpath = os.path.join(folder, file)
|
||||||
|
|
||||||
logging.debug(fullpath)
|
logging.debug(fpath)
|
||||||
file_manager.openFilelocally(fullpath)
|
view.openFilelocally(fpath)
|
||||||
|
|
||||||
msg = "Opened media..."
|
msg = "Opened media..."
|
||||||
return msgHandler.createMessageJSON("success", msg)
|
return msgHandler.createMessageJSON("success", msg)
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
{% if files %}
|
||||||
<nav class="navbar navbar-expand-sm bg-dark navbar-dark justify-content-center text-center fixed-bottom">
|
<nav class="navbar navbar-expand-sm bg-dark navbar-dark justify-content-center text-center fixed-bottom">
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
||||||
data-target="#navbarTogglerFooter" aria-controls="navbarTogglerFooter"
|
data-target="#navbarTogglerFooter" aria-controls="navbarTogglerFooter"
|
||||||
aria-expanded="false" aria-label="Toggle Footer Navigation">
|
aria-expanded="false" aria-label="Toggle Footer Navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@ -15,3 +16,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
{% endif %}
|
||||||
|
@ -7,17 +7,34 @@
|
|||||||
|
|
||||||
<div id="navbarTogglerHeader" class="row collapse navbar-collapse">
|
<div id="navbarTogglerHeader" class="row collapse navbar-collapse">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
|
{% if files %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<div class="input-group input-group-sm justify-content-center">
|
||||||
|
<button title="Other Options..." class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#options-modal">⚙</button>
|
||||||
|
<button title="Refresh..." id="refresh-btn" class="btn btn-sm btn-secondary" hash="{{files[0][1]}}">↻</button>
|
||||||
|
<button title="Back..." id="back-btn" class="btn btn-sm btn-secondary" hash="{{files[1][1]}}">⇐</button>
|
||||||
|
|
||||||
|
<input id="search-files-field" type="text" class="form-control" aria-label="Search..." placeholder="Search..." style="max-width: 260px">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span id="clear-search-btn" class="input-group-text" title="Clears search...">X</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button title="File viewer..." class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#file-view-modal">🖼</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
<!-- Branding -->
|
<!-- Branding -->
|
||||||
<div class="navbar-brand">
|
<div class="navbar-brand">
|
||||||
<div class="site-branding">
|
<div class="site-branding">
|
||||||
<h1 class="site-title">
|
<h4 class="site-title">
|
||||||
<a href="{{ url_for('home') }}" title="{{TITLE}} Home" rel="home">
|
<a href="{{ url_for('home') }}" title="{{TITLE}} Home" rel="home">
|
||||||
Hello World!
|
{{TITLE}}
|
||||||
</a>
|
</a>
|
||||||
</h1>
|
</h4>
|
||||||
<h2 class="site-description">Your Slogan...</h2>
|
<h6 class="site-description">For the files!</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col col-lg-auto">
|
<div class="col col-lg-auto">
|
||||||
|
93
src/core/utils/shellfm/windows/Launcher.py
Normal file
93
src/core/utils/shellfm/windows/Launcher.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
class Launcher:
|
||||||
|
def openFilelocally(self, file):
|
||||||
|
lowerName = file.lower()
|
||||||
|
command = []
|
||||||
|
|
||||||
|
if lowerName.endswith(self.VEXTENSION):
|
||||||
|
player = config["settings"]["media_app"]
|
||||||
|
options = config["settings"]["mplayer_options"].split()
|
||||||
|
command = [player]
|
||||||
|
|
||||||
|
if "mplayer" in player:
|
||||||
|
command += options
|
||||||
|
|
||||||
|
command += [file]
|
||||||
|
elif lowerName.endswith(self.IEXTENSION):
|
||||||
|
command = [config["settings"]["image_app"], file]
|
||||||
|
elif lowerName.endswith(self.MEXTENSION):
|
||||||
|
command = [config["settings"]["music_app"], file]
|
||||||
|
elif lowerName.endswith(self.OEXTENSION):
|
||||||
|
command = [config["settings"]["office_app"], file]
|
||||||
|
elif lowerName.endswith(self.TEXTENSION):
|
||||||
|
command = [config["settings"]["text_app"], file]
|
||||||
|
elif lowerName.endswith(self.PEXTENSION):
|
||||||
|
command = [config["settings"]["pdf_app"], file]
|
||||||
|
else:
|
||||||
|
command = [config["settings"]["file_manager_app"], file]
|
||||||
|
|
||||||
|
self.logging.debug(command)
|
||||||
|
DEVNULL = open(os.devnull, 'w')
|
||||||
|
subprocess.Popen(command, start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||||
|
|
||||||
|
|
||||||
|
def remuxVideo(self, hash, file):
|
||||||
|
remux_vid_pth = self.REMUX_FOLDER + "/" + hash + ".mp4"
|
||||||
|
message = '{"path":"static/remuxs/' + hash + '.mp4"}'
|
||||||
|
|
||||||
|
self.logging.debug(remux_vid_pth)
|
||||||
|
self.logging.debug(message)
|
||||||
|
|
||||||
|
if not os.path.isfile(remux_vid_pth):
|
||||||
|
limit = config["settings"]["remux_folder_max_disk_usage"]
|
||||||
|
try:
|
||||||
|
limit = int(limit)
|
||||||
|
except Exception as e:
|
||||||
|
self.logging.debug(e)
|
||||||
|
return
|
||||||
|
|
||||||
|
usage = self.getRemuxFolderUsage(self.REMUX_FOLDER)
|
||||||
|
if usage > limit:
|
||||||
|
files = os.listdir(self.REMUX_FOLDER)
|
||||||
|
for file in files:
|
||||||
|
fp = os.path.join(self.REMUX_FOLDER, file)
|
||||||
|
os.unlink(fp)
|
||||||
|
|
||||||
|
command = ["ffmpeg", "-i", file, "-hide_banner", "-movflags", "+faststart"]
|
||||||
|
if file.endswith("mkv"):
|
||||||
|
command += ["-codec", "copy", "-strict", "-2"]
|
||||||
|
if file.endswith("avi"):
|
||||||
|
command += ["-c:v", "libx264", "-crf", "21", "-c:a", "aac", "-b:a", "192k", "-ac", "2"]
|
||||||
|
if file.endswith("wmv"):
|
||||||
|
command += ["-c:v", "libx264", "-crf", "23", "-c:a", "aac", "-strict", "-2", "-q:a", "100"]
|
||||||
|
if file.endswith("f4v") or file.endswith("flv"):
|
||||||
|
command += ["-vcodec", "copy"]
|
||||||
|
|
||||||
|
command += [remux_vid_pth]
|
||||||
|
try:
|
||||||
|
proc = subprocess.Popen(command)
|
||||||
|
proc.wait()
|
||||||
|
except Exception as e:
|
||||||
|
message = '{"message": {"type": "danger", "text":"' + str( repr(e) ) + '"}}'
|
||||||
|
self.logging.debug(message)
|
||||||
|
self.logging.debug(e)
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
def generateVideoThumbnail(self, fullPath, hashImgPth):
|
||||||
|
try:
|
||||||
|
proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPath, "-o", hashImgPth])
|
||||||
|
proc.wait()
|
||||||
|
except Exception as e:
|
||||||
|
self.logging.debug(repr(e))
|
||||||
|
|
||||||
|
def getRemuxFolderUsage(self, start_path = "."):
|
||||||
|
total_size = 0
|
||||||
|
for dirpath, dirnames, filenames in os.walk(start_path):
|
||||||
|
for f in filenames:
|
||||||
|
fp = os.path.join(dirpath, f)
|
||||||
|
# skip if it is symbolic link
|
||||||
|
if not os.path.islink(fp):
|
||||||
|
total_size += os.path.getsize(fp)
|
||||||
|
|
||||||
|
return total_size
|
@ -8,10 +8,10 @@ from os.path import isdir, isfile, join
|
|||||||
|
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from . import Path, Filters
|
from . import Path, Filters, Launcher
|
||||||
|
|
||||||
|
|
||||||
class View(Filters, Path):
|
class View(Filters, Path, Launcher):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.hideHiddenFiles = True
|
self.hideHiddenFiles = True
|
||||||
self.files = []
|
self.files = []
|
||||||
@ -20,10 +20,8 @@ class View(Filters, Path):
|
|||||||
self.images = []
|
self.images = []
|
||||||
self.desktop = []
|
self.desktop = []
|
||||||
self.ungrouped = []
|
self.ungrouped = []
|
||||||
|
|
||||||
self.set_to_home()
|
self.set_to_home()
|
||||||
|
|
||||||
|
|
||||||
def load_directory(self):
|
def load_directory(self):
|
||||||
path = self.get_path()
|
path = self.get_path()
|
||||||
self.dirs = ['.', '..']
|
self.dirs = ['.', '..']
|
||||||
@ -73,6 +71,13 @@ class View(Filters, Path):
|
|||||||
data.append([arr, self.hashText(arr)])
|
data.append([arr, self.hashText(arr)])
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def returnPathPartFromHash(self, hash):
|
||||||
|
files = self.get_files()
|
||||||
|
for file in files:
|
||||||
|
if hash == file[1]:
|
||||||
|
return file[0]
|
||||||
|
return None
|
||||||
|
|
||||||
def get_files(self):
|
def get_files(self):
|
||||||
return self.hashSet(self.files)
|
return self.hashSet(self.files)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
from .Launcher import Launcher
|
||||||
from .Filters import Filters
|
from .Filters import Filters
|
||||||
from .Path import Path
|
from .Path import Path
|
||||||
from .View import View
|
from .View import View
|
||||||
|
Loading…
Reference in New Issue
Block a user