Add media sync, docker conf
This commit is contained in:
parent
3d324f3554
commit
56632f21e6
|
@ -0,0 +1,2 @@
|
||||||
|
FROM bitnami/python:latest
|
||||||
|
#RUN apt-get update && apt-get install -y openssh rsync
|
84
app.py
84
app.py
|
@ -64,14 +64,17 @@ cmd = {
|
||||||
|
|
||||||
DEBUG = app.config['DEFAULT']['DEBUG']
|
DEBUG = app.config['DEFAULT']['DEBUG']
|
||||||
media_folder_remote = app.config['DEFAULT']['media_folder_remote']
|
media_folder_remote = app.config['DEFAULT']['media_folder_remote']
|
||||||
media_folder_local = app.config['DEFAULT']['media_folder_local']
|
media_folder_local = os.path.expanduser(app.config['DEFAULT']['media_folder_local'])
|
||||||
media_ext = app.config['DEFAULT']['media_ext']
|
media_exts = app.config['DEFAULT']['media_exts']
|
||||||
auth = str(base64.b64encode(str(":" + app.config['DEFAULT']['auth']).encode('utf-8')), 'utf-8')
|
auth = str(base64.b64encode(str(":" + app.config['DEFAULT']['auth']).encode('utf-8')), 'utf-8')
|
||||||
cmd_auth = str(base64.b64encode(str(":" + app.config['DEFAULT']['cmd_auth']).encode('utf-8')), 'utf-8')
|
cmd_auth = str(base64.b64encode(str(":" + app.config['DEFAULT']['cmd_auth']).encode('utf-8')), 'utf-8')
|
||||||
hosts = app.config['DEFAULT']['hosts']
|
hosts = app.config['DEFAULT']['hosts']
|
||||||
port = app.config['DEFAULT']['port']
|
port = app.config['DEFAULT']['port']
|
||||||
cmd_port = app.config['DEFAULT']['cmd_port']
|
cmd_port = app.config['DEFAULT']['cmd_port']
|
||||||
useSSL = app.config['DEFAULT']['useSSL']
|
useSSL = app.config['DEFAULT']['useSSL']
|
||||||
|
sync_facility = app.config['DEFAULT']['sync_facility']
|
||||||
|
|
||||||
|
headers = {"Authorization":"Basic " + auth}
|
||||||
|
|
||||||
# Network/link utilities
|
# Network/link utilities
|
||||||
# https://www.metageek.com/training/resources/understanding-rssi/
|
# https://www.metageek.com/training/resources/understanding-rssi/
|
||||||
|
@ -115,10 +118,65 @@ def listMediaFiles(folder):
|
||||||
medias = []
|
medias = []
|
||||||
for fd in files:
|
for fd in files:
|
||||||
if len(fd.split('.')) > 1:
|
if len(fd.split('.')) > 1:
|
||||||
if fd.split('.')[1] in media_ext:
|
if fd.split('.')[1] in media_exts:
|
||||||
medias.append(fd)
|
medias.append(fd)
|
||||||
return medias
|
return medias
|
||||||
|
|
||||||
|
def httpUpload(filename, hostl, trailing_slash=1):
|
||||||
|
import requests
|
||||||
|
url = "https://" + hostl + ":" + str(cmd_port) + "/upload"
|
||||||
|
if not trailing_slash:
|
||||||
|
filename = "/" + filename
|
||||||
|
files = { "file":( filename, open( media_folder_local + filename, "rb"), "multipart/form-data") }
|
||||||
|
print(files)
|
||||||
|
# ~ resp = requests.post(url, files=files, auth=('', auth ), verify=hostl + ".crt")
|
||||||
|
resp = requests.post(url, files=files, headers=headers, verify=hostl + ".crt")
|
||||||
|
print(resp.text)
|
||||||
|
if resp.ok:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def syncMediaFolder(media_folder_local, media_folder_remote, hostl, sync_facility=sync_facility):
|
||||||
|
trailing_slash = 1
|
||||||
|
# Check for trailing / and add it if missing
|
||||||
|
if media_folder_local[-1:] != "/":
|
||||||
|
media_folder_local += "/"
|
||||||
|
trailing_slash = 0
|
||||||
|
if media_folder_remote[-1:] != "/":
|
||||||
|
media_folder_remote += "/"
|
||||||
|
if sync_facility == "http":
|
||||||
|
media_list = listMediaFiles(media_folder_local)
|
||||||
|
transfer_ok = 0
|
||||||
|
for media in media_list:
|
||||||
|
transfer_ok += httpUpload(media, hostl, trailing_slash)
|
||||||
|
return str(transfer_ok) + " files uploaded."
|
||||||
|
|
||||||
|
# Check sync utility exists
|
||||||
|
elif which(sync_facility):
|
||||||
|
from shutil import whichdb
|
||||||
|
# Build subprocess arg list accroding to facility
|
||||||
|
if sync_facility == "rsync":
|
||||||
|
scrape_str = "total size is "
|
||||||
|
sync_args = [sync_facility, "-zharm", "--include='*/'"]
|
||||||
|
for media_type in media_exts:
|
||||||
|
sync_args.append( "--include='*." + media_type + "'" )
|
||||||
|
sync_args.extend(["--exclude='*'", media_folder_local, hostl + ":" + media_folder_remote])
|
||||||
|
if sync_facility == "scp":
|
||||||
|
media_list = listMediaFiles(media_folder_local)
|
||||||
|
sync_args = [sync_facility, "-Crp", "-o IdentitiesOnly=yes"]
|
||||||
|
for media in media_list:
|
||||||
|
sync_args.append( media_folder_local + media )
|
||||||
|
sync_args.append( hostl + ":" + media_folder_remote )
|
||||||
|
|
||||||
|
sync_proc = subprocess.run( sync_args , capture_output=True)
|
||||||
|
if len(sync_proc.stdout):
|
||||||
|
scrape_index = str(sync_proc.stdout).index(scrape_str)+len(scrape_str)
|
||||||
|
total_size = str(sync_proc.stdout)[ scrape_index: ].split(" ")[0][:-1]
|
||||||
|
else:
|
||||||
|
total_size = "N/A";
|
||||||
|
return total_size
|
||||||
|
|
||||||
# /requests/status.xml?command=in_enqueue&input=file:///home/pi/tst1.mp4
|
# /requests/status.xml?command=in_enqueue&input=file:///home/pi/tst1.mp4
|
||||||
def writeM3U(m3u_content : str, host : str):
|
def writeM3U(m3u_content : str, host : str):
|
||||||
filename = host.replace(".", "_") + ".m3u"
|
filename = host.replace(".", "_") + ".m3u"
|
||||||
|
@ -173,7 +231,8 @@ def sendCommand(host, arg0, arg1, arg2):
|
||||||
else:
|
else:
|
||||||
conn = http.client.HTTPConnection( host + ":" + str(portl), timeout=3 )
|
conn = http.client.HTTPConnection( host + ":" + str(portl), timeout=3 )
|
||||||
try:
|
try:
|
||||||
conn.request( "GET", req, headers={"Authorization":"Basic " + auth} )
|
# ~ conn.request( "GET", req, headers={"Authorization":"Basic " + auth} )
|
||||||
|
conn.request( "GET", req, headers = headers )
|
||||||
except:
|
except:
|
||||||
return "Connection to " + host + " was refused on port " + str(portl)
|
return "Connection to " + host + " was refused on port " + str(portl)
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
|
@ -272,10 +331,20 @@ def scan():
|
||||||
|
|
||||||
@app.route("/browse")
|
@app.route("/browse")
|
||||||
def browse():
|
def browse():
|
||||||
files = listMediaFiles(media_folder_local);
|
files = listMediaFiles(media_folder_local)
|
||||||
return files;
|
return files;
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/sync/<host>")
|
||||||
|
def sync(host):
|
||||||
|
if host == "all":
|
||||||
|
for hostl in hosts_available:
|
||||||
|
size = syncMediaFolder(media_folder_local, media_folder_remote, hostl)
|
||||||
|
else:
|
||||||
|
size = syncMediaFolder(media_folder_local, media_folder_remote, host)
|
||||||
|
return size;
|
||||||
|
|
||||||
|
|
||||||
@app.route("/<host>/<arg0>/", defaults = { "arg1": "null", "arg2": "null" })
|
@app.route("/<host>/<arg0>/", defaults = { "arg1": "null", "arg2": "null" })
|
||||||
@app.route("/<host>/<arg0>/<arg1>/", defaults = { "arg2": "null" })
|
@app.route("/<host>/<arg0>/<arg1>/", defaults = { "arg2": "null" })
|
||||||
@app.route("/<host>/<arg0>/<arg1>/<arg2>")
|
@app.route("/<host>/<arg0>/<arg1>/<arg2>")
|
||||||
|
@ -298,5 +367,6 @@ def action(host, arg0, arg1, arg2):
|
||||||
return status_message
|
return status_message
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run()
|
# ~ app.run()
|
||||||
# ~ serve(app, host='127.0.0.1', port=8080)
|
#serve(app, host='127.0.0.1', port=8080)
|
||||||
|
serve(app, host='0.0.0.0', port=8080)
|
|
@ -1,9 +1,11 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
DEBUG = 0
|
DEBUG = 0
|
||||||
useSSL = false
|
useSSL = false
|
||||||
|
# Could be scp, sftp ?
|
||||||
|
sync_facility = "rsync"
|
||||||
media_folder_local = "~/Videos"
|
media_folder_local = "~/Videos"
|
||||||
media_folder_remote = "~/Videos"
|
media_folder_remote = "~/Videos"
|
||||||
media_ext = []
|
media_exts = []
|
||||||
auth = ""
|
auth = ""
|
||||||
cmd_auth = ""
|
cmd_auth = ""
|
||||||
hosts = []
|
hosts = []
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
version: '3.8' # or '2.4' # add
|
||||||
|
services: # add
|
||||||
|
videopi:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
command: "sh -c 'pip install -r requirements.txt && python app.py'"
|
||||||
|
volumes:
|
||||||
|
- .:/app
|
||||||
|
- ../medias:/medias
|
|
@ -0,0 +1,3 @@
|
||||||
|
flask
|
||||||
|
waitress
|
||||||
|
toml
|
|
@ -32,6 +32,7 @@
|
||||||
<button value="/all/enqueue/tst1.mp4" class="command btn btn-block btn-lg btn-default" role="button">β<span class="btn_txt">tst1.mp4</span></button>
|
<button value="/all/enqueue/tst1.mp4" class="command btn btn-block btn-lg btn-default" role="button">β<span class="btn_txt">tst1.mp4</span></button>
|
||||||
<button value="/all/enqueue/sangliers_1080.mp4" class="command btn btn-block btn-lg btn-default" role="button">β<span class="btn_txt">sangli.mp4</span></button>
|
<button value="/all/enqueue/sangliers_1080.mp4" class="command btn btn-block btn-lg btn-default" role="button">β<span class="btn_txt">sangli.mp4</span></button>
|
||||||
<button value="/move/0/1" class="command btn btn-block btn-lg btn-default" role="button">β<span class="btn_txt">movePl</span></button>
|
<button value="/move/0/1" class="command btn btn-block btn-lg btn-default" role="button">β<span class="btn_txt">movePl</span></button>
|
||||||
|
<button value="/sync/all" class="command btn btn-block btn-lg btn-default" role="button">↭<span class="btn_txt">Sync</span></button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
DEBUG = 0
|
DEBUG = 0
|
||||||
useSSL = true
|
useSSL = true
|
||||||
|
# Can be rsync, scp, http
|
||||||
|
sync_facility = "http"
|
||||||
media_folder_local = "../medias"
|
media_folder_local = "../medias"
|
||||||
media_folder_remote = "/home/pi/Videos/"
|
media_folder_remote = "/home/pi/Videos/"
|
||||||
media_ext = ["mp4", "avi", "mkv"]
|
media_exts = ["mp4", "avi", "mkv"]
|
||||||
auth = "secret"
|
auth = "secret"
|
||||||
|
# OnNlY3JldA==
|
||||||
cmd_auth = "secret"
|
cmd_auth = "secret"
|
||||||
hosts = ["10.42.0.135", "10.42.0.156"]
|
hosts = ["10.42.0.135", "10.42.0.156"]
|
||||||
# VLC http LUA port
|
# VLC http LUA port
|
||||||
|
|
Loading…
Reference in New Issue