file manager and config updates, css changes, etc
This commit is contained in:
parent
840ffc8255
commit
f6f7cfda58
|
@ -1,7 +1,5 @@
|
|||
*.db
|
||||
*.pyc
|
||||
client_secrets.json
|
||||
webfm_config.json
|
||||
app.pid
|
||||
|
||||
|
||||
|
|
12
README.md
12
README.md
|
@ -3,11 +3,13 @@ WebFM is a media and file viewer aspiring to become a full fledged file manager
|
|||
|
||||
# Usage
|
||||
1. Install python, sqlite3, and ffmpeg on the system this will be on.
|
||||
3. Use ufw or gufw to open the port on your computer to the network.
|
||||
4. Place files or start uploading some to the folders.
|
||||
5. Place an image such as a jpg, png, or gif labeled "000.itsExtension" in a directory and the viewer will use it as the background image for that folder/directory.
|
||||
9. Password protect folder based on core/webfm_config.json file settings.
|
||||
10. Save paths to favorites list for quick access.
|
||||
3. Use ufw or gufw to open the port on your computer to the local network.
|
||||
4. Use hosts file (or other methods) to redirect webfm.com and ssoapps.com to local app.
|
||||
5. Update client_secrets.json > 'client_secret' field with your Keycloak key. (Current one is local to me and not public)
|
||||
6. Place files or start uploading some to the folders.
|
||||
7. Place an image such as a jpg, png, or gif labeled "000.itsExtension" in a directory and the viewer will use it as the background image for that folder/directory.
|
||||
7. Password protect folder based on core/utils/shellfm/windows/webfm_config.json file settings.
|
||||
8. Save paths to favorites list for quick access.
|
||||
|
||||
Notes:
|
||||
n/a
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"auth_uri": "https://www.ssoapps.com/auth/realms/apps/protocol/openid-connect/auth",
|
||||
"client_id": "apps",
|
||||
"issuer": "https://www.ssoapps.com/auth/realms/apps",
|
||||
"client_secret": "[Add your secret key here]",
|
||||
"client_secret": "ce6fdb7d-fdcb-46ea-bc80-b5df9649d50b",
|
||||
"redirect_uris": [
|
||||
"http://www.webfm.com/home",
|
||||
"https://www.webfm.com/home"
|
||||
"https://www.webfm.com/home",
|
||||
"http://www.webfm.com/home"
|
||||
],
|
||||
"userinfo_uri": "https://www.ssoapps.com/auth/realms/apps/protocol/openid-connect/userinfo",
|
||||
"token_uri": "https://www.ssoapps.com/auth/realms/apps/protocol/openid-connect/token",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# System import
|
||||
import os, secrets, json
|
||||
import os, secrets
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
|
@ -12,19 +12,9 @@ from datetime import timedelta
|
|||
APP_NAME = 'WebFM'
|
||||
# Configs
|
||||
ROOT_FILE_PTH = os.path.dirname(os.path.realpath(__file__))
|
||||
CONFIG_FILE = ROOT_FILE_PTH + "/webfm_config.json"
|
||||
# This path is submitted as the redirect URI in certain code flows.
|
||||
REDIRECT_LINK = "https%3A%2F%2Fwww.webfm.com%2F"
|
||||
|
||||
# Settings data
|
||||
def retrieveSettings():
|
||||
returnData = []
|
||||
with open(CONFIG_FILE) as infile:
|
||||
try:
|
||||
return json.load(infile)
|
||||
except Exception as e:
|
||||
print(repr(e))
|
||||
return ['', 'mplayer', 'xdg-open']
|
||||
|
||||
|
||||
|
||||
|
@ -50,10 +40,14 @@ class Config(object):
|
|||
'https://localhost:443/auth/realms/apps'
|
||||
]
|
||||
|
||||
WEBFM_CONFIG = retrieveSettings()
|
||||
STATIC_FPTH = ROOT_FILE_PTH + "/static"
|
||||
REMUX_FOLDER = STATIC_FPTH + "/remuxs"
|
||||
FFMPG_THUMBNLR = STATIC_FPTH + "/ffmpegthumbnailer"
|
||||
REMUX_FOLDER = STATIC_FPTH + "/remuxs" # Remuxed files folder
|
||||
FFMPG_THUMBNLR = STATIC_FPTH + "/ffmpegthumbnailer" # Thumbnail generator binary
|
||||
|
||||
ABS_THUMBS_PTH = STATIC_FPTH + "/imgs/thumbnails" # Used for thumbnail generation
|
||||
REL_THUMBS_PTH = "static/imgs/thumbnails" # Used for flask thumbnail return
|
||||
|
||||
|
||||
|
||||
|
||||
class ProductionConfig(Config):
|
||||
|
|
|
@ -30,7 +30,7 @@ def home():
|
|||
if request.method == 'GET':
|
||||
view = get_window_controller().get_window(1).get_view(0)
|
||||
_path = view.get_path()
|
||||
_files = view.get_files()
|
||||
_files = view.get_files_formatted()
|
||||
return render_template('pages/index.html', path=_path, files=_files)
|
||||
|
||||
return render_template('error.html',
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -999;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
#bg img {
|
||||
|
@ -19,7 +20,7 @@
|
|||
}
|
||||
|
||||
#master-container {
|
||||
height: 85vh;
|
||||
height: 90vh;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
@ -47,9 +48,9 @@
|
|||
|
||||
|
||||
.dir-style, .video-style, .image-style, .file-style {
|
||||
height: auto;
|
||||
width: 24vw;
|
||||
position: relative;
|
||||
/* max-width: 24vw; */
|
||||
/* height: auto;
|
||||
position: relative; */
|
||||
max-width: 20em;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
<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>
|
||||
<button title="Refresh..." id="refresh-btn" class="btn btn-sm btn-secondary" hash="{{files['files'][0][1]}}">↻</button>
|
||||
<button title="Back..." id="back-btn" class="btn btn-sm btn-secondary" hash="{{files['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">
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
{% block body_content_additional %}
|
||||
<div id="files" class="row">
|
||||
{% for file in files %}
|
||||
{% for file in files['files'] %}
|
||||
<div class="col-sm-12 col-md-6 col-lg-4">
|
||||
<div class="card">
|
||||
<div class="card-header">{{file[0]}}</div>
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
class Filters:
|
||||
fvideos = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
|
||||
foffice = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx', '.xlm', '.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf')
|
||||
fimages = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
|
||||
ftext = ('.txt', '.text', '.sh', '.cfg', '.conf')
|
||||
fmusic = ('.psf', '.mp3', '.ogg', '.flac', '.m4a')
|
||||
fpdf = ('.pdf')
|
||||
|
||||
subpath = "/LazyShare/Synced Backup/222_Photos/Backgrounds/HD-Wallpapers"
|
|
@ -1,29 +1,39 @@
|
|||
# System import
|
||||
import os, subprocess, threading
|
||||
|
||||
|
||||
# Lib imports
|
||||
|
||||
|
||||
# Apoplication imports
|
||||
|
||||
|
||||
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()
|
||||
if lowerName.endswith(self.fvideos):
|
||||
player = self.fm_config["settings"]["media_app"]
|
||||
options = self.fm_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]
|
||||
elif lowerName.endswith(self.fimages):
|
||||
command = [self.fm_config["settings"]["image_app"], file]
|
||||
elif lowerName.endswith(self.fmusic):
|
||||
command = [self.fm_config["settings"]["music_app"], file]
|
||||
elif lowerName.endswith(self.foffice):
|
||||
command = [self.fm_config["settings"]["office_app"], file]
|
||||
elif lowerName.endswith(self.ftext):
|
||||
command = [self.fm_config["settings"]["text_app"], file]
|
||||
elif lowerName.endswith(self.fpdf):
|
||||
command = [self.fm_config["settings"]["pdf_app"], file]
|
||||
else:
|
||||
command = [config["settings"]["file_manager_app"], file]
|
||||
command = [self.fm_config["settings"]["file_manager_app"], file]
|
||||
|
||||
self.logging.debug(command)
|
||||
DEVNULL = open(os.devnull, 'w')
|
||||
|
@ -32,25 +42,10 @@ class Launcher:
|
|||
|
||||
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)
|
||||
self.check_remux_space()
|
||||
|
||||
command = ["ffmpeg", "-i", file, "-hide_banner", "-movflags", "+faststart"]
|
||||
if file.endswith("mkv"):
|
||||
|
@ -67,11 +62,11 @@ class Launcher:
|
|||
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 False
|
||||
|
||||
return message
|
||||
return True
|
||||
|
||||
|
||||
def generateVideoThumbnail(self, fullPath, hashImgPth):
|
||||
|
@ -81,13 +76,29 @@ class Launcher:
|
|||
except Exception as e:
|
||||
self.logging.debug(repr(e))
|
||||
|
||||
|
||||
def check_remux_space(self):
|
||||
limit = self.fm_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)
|
||||
|
||||
|
||||
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):
|
||||
if not os.path.islink(fp): # Skip if it is symbolic link
|
||||
total_size += os.path.getsize(fp)
|
||||
|
||||
return total_size
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# System import
|
||||
import json
|
||||
from os import path
|
||||
|
||||
|
||||
# Lib imports
|
||||
|
||||
|
||||
# Apoplication imports
|
||||
|
||||
|
||||
|
||||
class Settings:
|
||||
ABS_THUMBS_PTH = None # Used for thumbnail generation and is set by passing in
|
||||
REMUX_FOLDER = None # Used for Remuxed files and is set by passing in
|
||||
FFMPG_THUMBNLR = None # Used for thumbnail generator binary and is set by passing in
|
||||
|
||||
CONFIG_FILE = path.dirname(__file__) + '/webfm_config.json'
|
||||
subpath = "/LazyShare" # modify 'home' folder path
|
||||
|
||||
fvideos = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
|
||||
foffice = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx', '.xlm', '.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf')
|
||||
fimages = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
|
||||
ftext = ('.txt', '.text', '.sh', '.cfg', '.conf')
|
||||
fmusic = ('.psf', '.mp3', '.ogg', '.flac', '.m4a')
|
||||
fpdf = ('.pdf')
|
|
@ -8,10 +8,10 @@ from os.path import isdir, isfile, join
|
|||
|
||||
|
||||
# Application imports
|
||||
from . import Path, Filters, Launcher
|
||||
from . import Path, Settings, Launcher
|
||||
|
||||
|
||||
class View(Filters, Path, Launcher):
|
||||
class View(Settings, Launcher, Path):
|
||||
def __init__(self):
|
||||
self.hideHiddenFiles = True
|
||||
self.files = []
|
||||
|
@ -20,8 +20,20 @@ class View(Filters, Path, Launcher):
|
|||
self.images = []
|
||||
self.desktop = []
|
||||
self.ungrouped = []
|
||||
self.fm_config = self.getFileManagerSettings()
|
||||
self.set_to_home()
|
||||
|
||||
|
||||
# Settings data
|
||||
def getFileManagerSettings(self):
|
||||
returnData = []
|
||||
with open(self.CONFIG_FILE) as infile:
|
||||
try:
|
||||
return json.load(infile)
|
||||
except Exception as e:
|
||||
print(repr(e))
|
||||
return ['', 'mplayer', 'xdg-open']
|
||||
|
||||
def load_directory(self):
|
||||
path = self.get_path()
|
||||
self.dirs = ['.', '..']
|
||||
|
@ -78,6 +90,16 @@ class View(Filters, Path, Launcher):
|
|||
return file[0]
|
||||
return None
|
||||
|
||||
def get_files_formatted(self):
|
||||
return {
|
||||
'files': self.hashSet(self.files),
|
||||
'dirs': self.hashSet(self.dirs),
|
||||
'videos': self.hashSet(self.vids),
|
||||
'images': self.hashSet(self.images),
|
||||
'desktops': self.hashSet(self.desktop),
|
||||
'ungrouped': self.hashSet(self.ungrouped)
|
||||
}
|
||||
|
||||
def get_files(self):
|
||||
return self.hashSet(self.files)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from .Settings import Settings
|
||||
from .Launcher import Launcher
|
||||
from .Filters import Filters
|
||||
from .Path import Path
|
||||
from .View import View
|
||||
from .Window import Window
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
"pdf_app": "evince",
|
||||
"text_app": "leafpad",
|
||||
"file_manager_app": "spacefm",
|
||||
"locked_folder_password": "toor",
|
||||
"do_refresh": "no",
|
||||
"remux_folder_max_disk_usage": "8589934592",
|
||||
"locked_folders": "venv::::flasks",
|
||||
"locked_folders": "Synced Backup::::venv::::flasks",
|
||||
"folders_locked": "true"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue