deemix-gui-pyweb/deemix-pyweb.py

261 lines
8.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QDialog, QVBoxLayout
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage, QWebEngineProfile
from PyQt5.QtCore import QUrl, pyqtSignal
from PyQt5.QtGui import QIcon
import json
2020-08-22 09:46:27 +00:00
import webbrowser
from threading import Thread, Semaphore
import signal
import sys
2020-09-27 21:45:01 +00:00
from pathlib import Path
from os.path import sep as pathSep
from os import makedirs
from time import sleep
from server import run_server
from http.client import HTTPConnection
from deemix.utils.localpaths import getConfigFolder
2020-08-22 13:19:33 +00:00
if sys.platform == "win32":
import ctypes
myappid = 'RemixDev.deemix'
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
class LoginWindow(QDialog):
class CustomPage(QWebEnginePage):
def acceptNavigationRequest(self, url, type, main):
if url.toString() == "https://www.deezer.com/":
url = QUrl('https://www.deezer.com/ajax/gw-light.php?method=user.getArl&input=3&api_version=1.0&api_token=null')
self.setUrl(url)
return False
return super().acceptNavigationRequest(url, type, main)
def __init__(self, parent):
super().__init__(parent)
self.webview = QWebEngineView()
profile = QWebEngineProfile(self.webview)
profile.setPersistentCookiesPolicy(QWebEngineProfile.NoPersistentCookies)
profile.setPersistentStoragePath(str(configFolder / "QtWebEngine" / "Storage" / "OffTheRecord"))
self.page = self.CustomPage(profile, self.webview)
self.page.loadFinished.connect(self.checkURL)
self.webview.setPage(self.page)
self.webview.setUrl(QUrl("https://deezer.com/login"))
layout = QVBoxLayout()
layout.addWidget(self.webview)
self.setLayout(layout)
self.arl = None
self.exec_()
def checkURL(self, ok):
url = self.webview.url().toString()
if 'user.getArl' in url:
sleep(1)
self.webview.page().toPlainText(self.saveARL)
def saveARL(self, body):
if body.startswith("{"):
self.arl = json.loads(body)['results']
self.accept()
class MainWindow(QMainWindow):
selectDownloadFolder_trigger = pyqtSignal()
appLogin_trigger = pyqtSignal()
2020-08-22 09:46:27 +00:00
class MainWebpage(QWebEnginePage):
def __init__(self, profile, parent):
super().__init__(profile, parent)
actions = [
QWebEnginePage.Back,
QWebEnginePage.Forward,
QWebEnginePage.Stop,
QWebEnginePage.Reload,
QWebEnginePage.ReloadAndBypassCache,
QWebEnginePage.PasteAndMatchStyle,
QWebEnginePage.OpenLinkInThisWindow,
QWebEnginePage.OpenLinkInNewWindow,
QWebEnginePage.OpenLinkInNewTab,
QWebEnginePage.OpenLinkInNewBackgroundTab,
QWebEnginePage.DownloadLinkToDisk,
QWebEnginePage.DownloadImageToDisk,
QWebEnginePage.DownloadMediaToDisk,
QWebEnginePage.InspectElement,
QWebEnginePage.RequestClose,
QWebEnginePage.SavePage
]
for a in actions:
self.action(a).setVisible(False)
2020-08-22 09:46:27 +00:00
class ExternalWebpage(QWebEnginePage):
def __init__(self, parent):
super().__init__(parent)
self.urlChanged.connect(self.open_browser)
def open_browser(self, url):
page = self.sender()
webbrowser.open(url.toString(), 2, True)
page.deleteLater()
def createWindow(self, _type):
page = None
if _type == QWebEnginePage.WebBrowserTab:
page = self.ExternalWebpage(self)
return page
def __init__(self, title, url, x=None, y=None, w=800, h=600):
super().__init__()
startMaximized = False
if w == -1 or h == -1:
self.resize(800, 600)
startMaximized = True
else:
self.resize(w, h)
self.setWindowTitle(title)
2020-09-27 21:45:01 +00:00
self.setWindowIcon(QIcon(str(appDir / 'icon.ico')))
self.setMinimumSize(800, 600)
self.webview = QWebEngineView()
self.profile = QWebEngineProfile("Default", self.webview)
self.profile.setCachePath(str(configFolder / "QtWebEngine" / "Cache" / "Default"))
self.profile.setPersistentStoragePath(str(configFolder / "QtWebEngine" / "Storage" / "Default"))
self.page = self.MainWebpage(self.profile, self.webview)
2020-08-22 09:46:27 +00:00
self.page.loadFinished.connect(self.finishLoading)
self.webview.setPage(self.page)
self.setCentralWidget(self.webview)
self.url = url
if dev:
self.dev_tools = QWebEngineView()
self.webview.page().setDevToolsPage(self.dev_tools.page())
self.dev_tools.show()
self.downloadFolder = None
self.selectDownloadFolder_trigger.connect(self.selectDownloadFolder)
self._selectDownloadFolder_semaphore = Semaphore(0)
self.arl = None
self.appLogin_trigger.connect(self.appLogin)
self._appLogin_semaphore = Semaphore(0)
if x is None or y is None or startMaximized:
center = QApplication.desktop().availableGeometry().center() - self.rect().center()
self.move(center.x(), center.y())
else:
self.move(x, y)
if startMaximized: self.showMaximized()
def showWindow(self):
self.webview.setUrl(QUrl(self.url))
self.show()
def selectDownloadFolder(self):
filename = QFileDialog.getExistingDirectory(self, "Select Download Folder", options=QFileDialog.ShowDirsOnly)
2020-09-27 21:45:01 +00:00
self.downloadFolder = filename.replace('/', pathSep)
self._selectDownloadFolder_semaphore.release()
def appLogin(self):
self.arl = None
loginWindow = LoginWindow(self)
self.arl = loginWindow.arl
self._appLogin_semaphore.release()
loginWindow.page.deleteLater()
loginWindow.webview.deleteLater()
loginWindow.deleteLater()
def closeEvent(self, event):
x = int(self.x())
y = int(self.y())
w = int(self.width())
h = int(self.height())
if x < 0: x = 0
if y < 0: y = 0
if self.isMaximized():
w = -1
h = -1
2020-09-27 21:45:01 +00:00
with open(configFolder / '.UIposition', 'w') as f:
f.write("|".join([str(x),str(y),str(w),str(h)]))
self.page.deleteLater()
event.accept()
def finishLoading(self, ok):
if ok: self.webview.page().runJavaScript("window.dispatchEvent(new Event('pywebviewready'))")
def url_ok(url, port):
try:
conn = HTTPConnection(url, port)
conn.request('GET', '/')
r = conn.getresponse()
return r.status == 200
except:
print("Server not started")
return False
def get_position():
2020-09-27 21:45:01 +00:00
if (configFolder / '.UIposition').is_file():
try:
2020-09-27 21:45:01 +00:00
with open(configFolder / '.UIposition', 'r') as f:
(x,y,w,h) = f.read().strip().split("|")
x = int(x)
y = int(y)
w = int(w)
h = int(h)
if x < 0: x = 0
if y < 0: y = 0
except:
x = None
y = None
w = 800
h = 600
else:
x = None
y = None
w = 800
h = 600
return (x,y,w,h)
url = "127.0.0.1"
port = 6595
def server_shutdown_handler(signalnum, frame):
conn = HTTPConnection(url, port)
conn.request('GET', '/shutdown')
if __name__ == '__main__':
if len(sys.argv) >= 2:
try:
port = int(sys.argv[1])
except ValueError:
pass
portable = None
2020-09-27 21:45:01 +00:00
appDir = Path(__file__).parent
if '--portable' in sys.argv:
2020-09-27 21:45:01 +00:00
portable = appDir / 'config'
server = '--server' in sys.argv or '-s' in sys.argv
dev = '--dev' in sys.argv
if not server:
signal.signal(signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGTERM, signal.SIG_DFL)
2020-09-20 20:35:50 +00:00
app = QApplication([])
configFolder = portable or getConfigFolder()
x,y,w,h = get_position()
makedirs(configFolder / "QtWebEngine", exist_ok=True)
window = MainWindow('deemix', 'http://localhost:'+str(port), x,y,w,h)
t = Thread(target=run_server, args=(url, port, portable, window))
else:
signal.signal(signal.SIGINT, server_shutdown_handler)
signal.signal(signal.SIGTERM, server_shutdown_handler)
t = Thread(target=run_server, args=(url, port, portable))
t.daemon = True
t.start()
if not server:
while not url_ok(url, port):
sleep(1)
window.showWindow()
app.exec_()
conn = HTTPConnection(url, port)
conn.request('GET', '/shutdown')
t.join()