mirror of
https://gitlab.com/RemixDev/deemix-gui-pyweb.git
synced 2024-12-28 02:16:16 +00:00
Moved version and deezer check from server to app
This commit is contained in:
parent
0be75208fb
commit
4f1d17f7c7
87
app.py
87
app.py
|
@ -1,4 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
import eventlet
|
||||
requests = eventlet.import_patched('requests')
|
||||
|
||||
from deemix.api.deezer import Deezer
|
||||
from deemix.app.settings import Settings
|
||||
from deemix.app.queuemanager import QueueManager
|
||||
|
@ -10,6 +13,35 @@ from deemix.utils.localpaths import getConfigFolder
|
|||
import os.path as path
|
||||
import json
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
def resource_path(relative_path):
|
||||
""" Get absolute path to resource, works for dev and for PyInstaller """
|
||||
try:
|
||||
# PyInstaller creates a temp folder and stores path in _MEIPASS
|
||||
base_path = sys._MEIPASS
|
||||
except Exception:
|
||||
base_path = path.dirname(path.abspath(path.realpath(__file__)))
|
||||
|
||||
return path.join(base_path, relative_path)
|
||||
|
||||
class LoginStatus():
|
||||
"""Login status codes"""
|
||||
|
||||
NOT_AVAILABLE = -1
|
||||
"""Deezer is not Available in your country"""
|
||||
|
||||
FAILED = 0
|
||||
"""Login Failed"""
|
||||
|
||||
SUCCESS = 1
|
||||
"""Login Successfull"""
|
||||
|
||||
ALREADY_LOGGED = 2
|
||||
"""Already logged in"""
|
||||
|
||||
FORCED_SUCCESS = 3
|
||||
"""Forced Login Successfull"""
|
||||
|
||||
class deemix:
|
||||
def __init__(self, portable):
|
||||
|
@ -21,6 +53,50 @@ class deemix:
|
|||
self.chartsList = []
|
||||
self.homeCache = None
|
||||
|
||||
self.currentVersion = None
|
||||
self.latestVersion = None
|
||||
self.updateAvailable = False
|
||||
self.isDeezerAvailable = True
|
||||
|
||||
def checkForUpdates(self):
|
||||
commitFile = resource_path('version.txt')
|
||||
if path.isfile(commitFile):
|
||||
print("Checking for updates...")
|
||||
with open(commitFile, 'r') as f:
|
||||
self.currentVersion = f.read().strip()
|
||||
try:
|
||||
latestVersion = requests.get("https://deemix.app/pyweb/latest")
|
||||
latestVersion.raise_for_status()
|
||||
self.latestVersion = latestVersion.text.strip()
|
||||
except:
|
||||
self.latestVersion = None
|
||||
self.updateAvailable = self.compare_versions()
|
||||
if self.updateAvailable:
|
||||
print("Update available! Commit: "+self.latestVersion)
|
||||
else:
|
||||
print("You're running the latest version")
|
||||
|
||||
def compareVersions():
|
||||
if not self.latestVersion or not self.currentVersion:
|
||||
return False
|
||||
(currentDate, currentCommit) = tuple(self.currentVersion.split('-'))
|
||||
(latestDate, latestCommit) = tuple(self.latestVersion.split('-'))
|
||||
currentDate = currentDate.split('.')
|
||||
latestDate = latestDate.split('.')
|
||||
current = datetime(int(currentDate[0]), int(currentDate[1]), int(currentDate[2]))
|
||||
latest = datetime(int(latestDate[0]), int(latestDate[1]), int(latestDate[2]))
|
||||
if latest > current:
|
||||
return True
|
||||
elif latest == current:
|
||||
return latestCommit != currentCommit
|
||||
else:
|
||||
return False
|
||||
|
||||
def checkDeezerAvailability(self):
|
||||
body = requests.get("https://www.deezer.com/", headers={'Cookie': 'dz_lang=en; Domain=deezer.com; Path=/; Secure; hostOnly=false;'}).text
|
||||
title = body[body.find('<title>')+7:body.find('</title>')]
|
||||
self.isDeezerAvailable = title.strip() != "Deezer will soon be available in your country."
|
||||
|
||||
def shutdown(self, interface=None):
|
||||
if self.set.settings['saveDownloadQueue']:
|
||||
self.qm.saveQueue(self.configFolder)
|
||||
|
@ -43,6 +119,11 @@ class deemix:
|
|||
f.write(arl)
|
||||
return arl
|
||||
|
||||
def login(self, dz, arl, child):
|
||||
if not dz.logged_in:
|
||||
return int(dz.login_via_arl(arl, child))
|
||||
else:
|
||||
return LoginStatus.ALREADY_LOGGED
|
||||
|
||||
def restoreDownloadQueue(self, dz, interface=None):
|
||||
self.qm.loadQueue(self.configFolder, self.set.settings, interface)
|
||||
|
@ -149,24 +230,22 @@ class deemix:
|
|||
url = url.split(";")
|
||||
self.qm.addToQueue(dz, url, self.set.settings, bitrate, interface, ack)
|
||||
|
||||
|
||||
def removeFromQueue(self, uuid, interface=None):
|
||||
self.qm.removeFromQueue(uuid, interface)
|
||||
|
||||
|
||||
def cancelAllDownloads(self, interface=None):
|
||||
self.qm.cancelAllDownloads(interface)
|
||||
|
||||
|
||||
def removeFinishedDownloads(self, interface=None):
|
||||
self.qm.removeFinishedDownloads(interface)
|
||||
|
||||
|
||||
def initDownloadQueue(self):
|
||||
(queue, queueComplete, queueList, currentItem) = self.qm.getQueue()
|
||||
return (queue, queueComplete, queueList, currentItem)
|
||||
|
||||
def analyzeLink(self, dz, link):
|
||||
if 'deezer.page.link' in link:
|
||||
link = requests.get(link).url
|
||||
type = getTypeFromLink(link)
|
||||
relID = getIDFromLink(link, type)
|
||||
if type in ["track", "album"]:
|
||||
|
|
|
@ -227,7 +227,7 @@ if __name__ == '__main__':
|
|||
configFolder = portable or getConfigFolder()
|
||||
x,y,w,h = get_position()
|
||||
window = MainWindow('deemix', 'http://'+url+':'+str(port), x,y,w,h)
|
||||
t = Thread(target=run_server, args=(port, url, portable, window))
|
||||
t = Thread(target=run_server, args=(url, port, portable, window))
|
||||
else:
|
||||
t = Thread(target=run_server, args=(port, url, portable))
|
||||
t.daemon = True
|
||||
|
|
225
server.py
225
server.py
|
@ -9,16 +9,13 @@ import eventlet
|
|||
from eventlet import tpool
|
||||
from eventlet.green import subprocess
|
||||
requests = eventlet.import_patched('requests')
|
||||
urlopen = eventlet.import_patched('urllib.request').urlopen
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from flask import Flask, render_template, request, session, redirect, copy_current_request_context
|
||||
from flask_socketio import SocketIO, emit
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
|
||||
from deemix import __version__ as deemixVersion
|
||||
from app import deemix
|
||||
from deemix import __version__ as deemix_version
|
||||
from app import deemix, LoginStatus, resource_path
|
||||
from deemix.api.deezer import Deezer
|
||||
from deemix.app.messageinterface import MessageInterface
|
||||
|
||||
|
@ -33,10 +30,21 @@ mimetypes.add_type('text/javascript', '.js')
|
|||
from engineio.payload import Payload
|
||||
Payload.max_decode_packets = 500
|
||||
|
||||
app = None
|
||||
gui = None
|
||||
arl = None
|
||||
# Disable logging
|
||||
serverLog = logging.getLogger('werkzeug')
|
||||
serverLog.disabled = True
|
||||
logging.getLogger('socketio').setLevel(logging.ERROR)
|
||||
logging.getLogger('engineio').setLevel(logging.ERROR)
|
||||
#server.logger.disabled = True
|
||||
|
||||
class SocketInterface(MessageInterface):
|
||||
def send(self, message, value=None):
|
||||
if value:
|
||||
socketio.emit(message, value)
|
||||
else:
|
||||
socketio.emit(message)
|
||||
|
||||
# This allows the frontend to use vue.js
|
||||
class CustomFlask(Flask):
|
||||
jinja_options = Flask.jinja_options.copy()
|
||||
jinja_options.update(dict(
|
||||
|
@ -48,99 +56,31 @@ class CustomFlask(Flask):
|
|||
comment_end_string='#$',
|
||||
))
|
||||
|
||||
def resource_path(relative_path):
|
||||
""" Get absolute path to resource, works for dev and for PyInstaller """
|
||||
try:
|
||||
# PyInstaller creates a temp folder and stores path in _MEIPASS
|
||||
base_path = sys._MEIPASS
|
||||
except Exception:
|
||||
base_path = path.dirname(path.abspath(path.realpath(__file__)))
|
||||
|
||||
return path.join(base_path, relative_path)
|
||||
|
||||
gui_dir = resource_path(path.join('webui', 'public'))
|
||||
if not path.exists(gui_dir):
|
||||
gui_dir = resource_path('webui')
|
||||
if not path.isfile(path.join(gui_dir, 'index.html')):
|
||||
# Retrocompatibility with old versions of the app
|
||||
# Check for public folder and fallback to webui
|
||||
GUI_DIR = resource_path(path.join('webui', 'public'))
|
||||
if not path.exists(GUI_DIR):
|
||||
GUI_DIR = resource_path('webui')
|
||||
if not path.isfile(path.join(GUI_DIR, 'index.html')):
|
||||
sys.exit("WebUI not found, please download and add a WebUI")
|
||||
server = CustomFlask(__name__, static_folder=gui_dir, template_folder=gui_dir, static_url_path="")
|
||||
|
||||
server = CustomFlask(__name__, static_folder=GUI_DIR, template_folder=GUI_DIR, static_url_path="")
|
||||
server.config['SEND_FILE_MAX_AGE_DEFAULT'] = 1 # disable caching
|
||||
socketio = SocketIO(server)
|
||||
server.wsgi_app = ProxyFix(server.wsgi_app, x_for=1, x_proto=1)
|
||||
|
||||
class SocketInterface(MessageInterface):
|
||||
def send(self, message, value=None):
|
||||
if value:
|
||||
socketio.emit(message, value)
|
||||
else:
|
||||
socketio.emit(message)
|
||||
|
||||
app = None
|
||||
gui = None
|
||||
arl = None
|
||||
|
||||
socket_interface = SocketInterface()
|
||||
loginWindow = False
|
||||
first_connection = True
|
||||
|
||||
serverLog = logging.getLogger('werkzeug')
|
||||
serverLog.disabled = True
|
||||
logging.getLogger('socketio').setLevel(logging.ERROR)
|
||||
logging.getLogger('engineio').setLevel(logging.ERROR)
|
||||
#server.logger.disabled = True
|
||||
|
||||
firstConnection = True
|
||||
|
||||
currentVersion = None
|
||||
latestVersion = None
|
||||
updateAvailable = False
|
||||
|
||||
def compare_versions(currentVersion, latestVersion):
|
||||
if not latestVersion or not currentVersion:
|
||||
return False
|
||||
(currentDate, currentCommit) = tuple(currentVersion.split('-'))
|
||||
(latestDate, latestCommit) = tuple(latestVersion.split('-'))
|
||||
currentDate = currentDate.split('.')
|
||||
latestDate = latestDate.split('.')
|
||||
current = datetime(int(currentDate[0]), int(currentDate[1]), int(currentDate[2]))
|
||||
latest = datetime(int(latestDate[0]), int(latestDate[1]), int(latestDate[2]))
|
||||
if latest > current:
|
||||
return True
|
||||
elif latest == current:
|
||||
return latestCommit != currentCommit
|
||||
else:
|
||||
return False
|
||||
|
||||
def check_for_updates():
|
||||
global currentVersion, latestVersion, updateAvailable
|
||||
commitFile = resource_path('version.txt')
|
||||
if path.isfile(commitFile):
|
||||
print("Checking for updates...")
|
||||
with open(commitFile, 'r') as f:
|
||||
currentVersion = f.read().strip()
|
||||
try:
|
||||
latestVersion = requests.get("https://deemix.app/pyweb/latest")
|
||||
latestVersion.raise_for_status()
|
||||
latestVersion = latestVersion.text.strip()
|
||||
except:
|
||||
latestVersion = None
|
||||
if currentVersion and latestVersion:
|
||||
updateAvailable = compare_versions(currentVersion, latestVersion)
|
||||
if updateAvailable:
|
||||
print("Update available! Commit: "+latestVersion)
|
||||
else:
|
||||
print("You're running the latest version")
|
||||
|
||||
is_deezer_available = True
|
||||
def check_deezer_availability():
|
||||
body = requests.get("https://www.deezer.com/", headers={'Cookie': 'dz_lang=en; Domain=deezer.com; Path=/; Secure; hostOnly=false;'}).text
|
||||
title = body[body.find('<title>')+7:body.find('</title>')]
|
||||
return title.strip() != "Deezer will soon be available in your country."
|
||||
|
||||
def shutdown(interface=None):
|
||||
def shutdown():
|
||||
if app is not None:
|
||||
app.shutdown(interface=interface)
|
||||
app.shutdown(socket_interface)
|
||||
socketio.stop()
|
||||
|
||||
def shutdown_handler(signalnum, frame):
|
||||
shutdown()
|
||||
|
||||
@server.route('/')
|
||||
def landing():
|
||||
return render_template('index.html')
|
||||
|
@ -151,27 +91,29 @@ def not_found_handler(e):
|
|||
|
||||
@server.route('/shutdown')
|
||||
def closing():
|
||||
shutdown(interface=socket_interface)
|
||||
shutdown()
|
||||
return 'Server Closed'
|
||||
|
||||
serverwide_arl = "--serverwide-arl" in sys.argv
|
||||
if serverwide_arl:
|
||||
print("Server-wide ARL enabled.")
|
||||
|
||||
@socketio.on('connect')
|
||||
def on_connect():
|
||||
session['dz'] = Deezer()
|
||||
(settings, spotifyCredentials, defaultSettings) = app.getAllSettings()
|
||||
session['dz'].set_accept_language(settings.get('tagsLanguage'))
|
||||
emit('init_settings', (settings, spotifyCredentials, defaultSettings))
|
||||
emit('init_update',
|
||||
{'currentCommit': currentVersion,
|
||||
'latestCommit': latestVersion,
|
||||
'updateAvailable': updateAvailable,
|
||||
'deemixVersion': deemixVersion}
|
||||
|
||||
if first_connection:
|
||||
app.checkForUpdates()
|
||||
app.checkDeezerAvailability()
|
||||
|
||||
emit('init_update',{
|
||||
'currentCommit': app.currentVersion,
|
||||
'latestCommit': app.latestVersion,
|
||||
'updateAvailable': app.updateAvailable,
|
||||
'deemixVersion': deemix_version
|
||||
}
|
||||
)
|
||||
|
||||
if serverwide_arl:
|
||||
if arl:
|
||||
login(arl)
|
||||
else:
|
||||
emit('init_autologin')
|
||||
|
@ -184,9 +126,11 @@ def on_connect():
|
|||
'queueList': queueList,
|
||||
'currentItem': currentItem
|
||||
})
|
||||
|
||||
emit('init_home', app.get_home(session['dz']))
|
||||
emit('init_charts', app.get_charts(session['dz']))
|
||||
if not is_deezer_available:
|
||||
|
||||
if not app.isDeezerAvailable:
|
||||
emit('deezerNotAvailable')
|
||||
|
||||
@socketio.on('get_home_data')
|
||||
|
@ -207,49 +151,38 @@ def get_settings_data():
|
|||
|
||||
@socketio.on('login')
|
||||
def login(arl, force=False, child=0):
|
||||
global firstConnection, is_deezer_available
|
||||
if not is_deezer_available:
|
||||
emit('logged_in', {'status': -1, 'arl': arl, 'user': session['dz'].user})
|
||||
global first_connection
|
||||
|
||||
if not app.isDeezerAvailable:
|
||||
emit('logged_in', {'status': LoginStatus.NOT_AVAILABLE, 'arl': arl, 'user': session['dz'].user})
|
||||
return
|
||||
if child == None:
|
||||
child = 0
|
||||
|
||||
if child == None: child = 0
|
||||
arl = arl.strip()
|
||||
emit('logging_in')
|
||||
if not session['dz'].logged_in:
|
||||
result = session['dz'].login_via_arl(arl, int(child))
|
||||
else:
|
||||
if force:
|
||||
session['dz'] = Deezer()
|
||||
result = session['dz'].login_via_arl(arl, int(child))
|
||||
if result == 1:
|
||||
result = 3
|
||||
else:
|
||||
result = 2
|
||||
|
||||
if force: session['dz'] = Deezer()
|
||||
result = app.login(session['dz'], arl, int(child))
|
||||
if force and result == LoginStatus.SUCCESS: result = LoginStatus.FORCED_SUCCESS
|
||||
|
||||
emit('logged_in', {'status': result, 'arl': arl, 'user': session['dz'].user})
|
||||
if firstConnection and result in [1, 3]:
|
||||
firstConnection = False
|
||||
if first_connection and result in [LoginStatus.SUCCESS, LoginStatus.FORCED_SUCCESS]:
|
||||
first_connection = False
|
||||
app.restoreDownloadQueue(session['dz'], socket_interface)
|
||||
if result != 0:
|
||||
emit('familyAccounts', session['dz'].childs)
|
||||
emit('init_favorites', app.getUserFavorites(session['dz']))
|
||||
|
||||
|
||||
@socketio.on('changeAccount')
|
||||
def changeAccount(child):
|
||||
emit('accountChanged', session['dz'].change_account(int(child)))
|
||||
emit('init_favorites', app.getUserFavorites(session['dz']))
|
||||
|
||||
|
||||
@socketio.on('logout')
|
||||
def logout():
|
||||
status = 0
|
||||
if session['dz'].logged_in:
|
||||
session['dz'] = Deezer()
|
||||
status = 0
|
||||
else:
|
||||
status = 1
|
||||
emit('logged_out', status)
|
||||
|
||||
emit('logged_out')
|
||||
|
||||
@socketio.on('mainSearch')
|
||||
def mainSearch(data):
|
||||
|
@ -258,7 +191,6 @@ def mainSearch(data):
|
|||
result['ack'] = data.get('ack')
|
||||
emit('mainSearch', result)
|
||||
|
||||
|
||||
@socketio.on('search')
|
||||
def search(data):
|
||||
if data['term'].strip() != "":
|
||||
|
@ -292,29 +224,22 @@ def newReleases(data):
|
|||
def queueRestored():
|
||||
app.queueRestored(session['dz'], socket_interface)
|
||||
|
||||
|
||||
@socketio.on('addToQueue')
|
||||
def addToQueue(data):
|
||||
result = app.addToQueue(session['dz'], data['url'], data['bitrate'], interface=socket_interface, ack=data.get('ack'))
|
||||
if result == "Not logged in":
|
||||
emit('loginNeededToDownload')
|
||||
|
||||
|
||||
@socketio.on('removeFromQueue')
|
||||
def removeFromQueue(uuid):
|
||||
app.removeFromQueue(uuid, interface=socket_interface)
|
||||
|
||||
|
||||
@socketio.on('removeFinishedDownloads')
|
||||
def removeFinishedDownloads():
|
||||
app.removeFinishedDownloads(interface=socket_interface)
|
||||
|
||||
|
||||
@socketio.on('cancelAllDownloads')
|
||||
def cancelAllDownloads():
|
||||
app.cancelAllDownloads(interface=socket_interface)
|
||||
|
||||
|
||||
@socketio.on('saveSettings')
|
||||
def saveSettings(settings, spotifyCredentials, spotifyUser):
|
||||
app.saveSettings(settings, session['dz'])
|
||||
|
@ -323,7 +248,6 @@ def saveSettings(settings, spotifyCredentials, spotifyUser):
|
|||
if spotifyUser != False:
|
||||
emit('updated_userSpotifyPlaylists', app.updateUserSpotifyPlaylists(spotifyUser))
|
||||
|
||||
|
||||
@socketio.on('getTracklist')
|
||||
def getTracklist(data):
|
||||
if data['type'] == 'artist':
|
||||
|
@ -355,8 +279,6 @@ def getTracklist(data):
|
|||
|
||||
@socketio.on('analyzeLink')
|
||||
def analyzeLink(link):
|
||||
if 'deezer.page.link' in link:
|
||||
link = urlopen(link).url
|
||||
(type, data) = app.analyzeLink(session['dz'], link)
|
||||
if len(data):
|
||||
emit('analyze_'+type, data)
|
||||
|
@ -411,7 +333,7 @@ def selectDownloadFolder():
|
|||
emit('downloadFolderSelected', result)
|
||||
else:
|
||||
print("Can't open folder selection, you're not running the gui")
|
||||
|
||||
|
||||
def doSelectDowloadFolder():
|
||||
gui.selectDownloadFolder_trigger.emit()
|
||||
gui._selectDownloadFolder_semaphore.acquire()
|
||||
|
@ -429,41 +351,42 @@ def applogin():
|
|||
emit('logged_in', {'status': 2, 'user': session['dz'].user})
|
||||
else:
|
||||
print("Can't open login page, you're not running the gui")
|
||||
|
||||
|
||||
def dologin():
|
||||
gui.appLogin_trigger.emit()
|
||||
gui._appLogin_semaphore.acquire()
|
||||
return gui.arl
|
||||
|
||||
def run_server(port, host="127.0.0.1", portable=None, mainWindow=None):
|
||||
global app, gui, arl, is_deezer_available
|
||||
def run_server(host="127.0.0.1", port=6595, portable=None, guiWindow=None, server_arl=False):
|
||||
global app, gui, arl
|
||||
app = deemix(portable)
|
||||
gui = mainWindow
|
||||
if serverwide_arl:
|
||||
gui = guiWindow
|
||||
if server_arl:
|
||||
print("Server-wide ARL enabled.")
|
||||
arl = app.getConfigArl()
|
||||
check_for_updates()
|
||||
if not check_deezer_availability():
|
||||
is_deezer_available = False
|
||||
print("Deezer is not available in your country, you should use a VPN to use this app.")
|
||||
print("Starting server at http://" + host + ":" + str(port))
|
||||
socketio.run(server, host=host, port=port)
|
||||
|
||||
def shutdown_handler(signalnum, frame):
|
||||
shutdown()
|
||||
|
||||
if __name__ == '__main__':
|
||||
port = 6595
|
||||
host = "127.0.0.1"
|
||||
portable = None
|
||||
port = 6595
|
||||
if len(sys.argv) >= 2:
|
||||
try:
|
||||
port = int(sys.argv[1])
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
portable = None
|
||||
if '--portable' in sys.argv:
|
||||
portable = path.join(path.dirname(path.realpath(__file__)), 'config')
|
||||
if '--host' in sys.argv:
|
||||
host = str(sys.argv[sys.argv.index("--host")+1])
|
||||
serverwide_arl = "--serverwide-arl" in sys.argv
|
||||
|
||||
signal.signal(signal.SIGINT, shutdown_handler)
|
||||
signal.signal(signal.SIGTERM, shutdown_handler)
|
||||
|
||||
run_server(port, host, portable)
|
||||
run_server(host, port, portable, server_arl=serverwide_arl)
|
||||
|
|
Loading…
Reference in a new issue