Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gui: login with keyring #795

Merged
merged 1 commit into from
Feb 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 61 additions & 1 deletion feeluown/gui/widgets/login.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,46 @@
import json
from http.cookies import SimpleCookie
from urllib.parse import urlparse

from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtWidgets import QDialog, QTextEdit, QPushButton, \
QVBoxLayout, QLabel

try:
from feeluown.gui.widgets.weblogin import WebLoginView
except ImportError:
has_webengine = False
else:
has_webengine = True

try:
from feeluown.utils.yt_dlp_cookies import load_cookies # noqa
except ImportError:
can_load_keyring_cookies = False
else:
can_load_keyring_cookies = True

from feeluown.utils import aio


def try_get_domain_from_uri(uri):
"""
xx.yy.com -> yy.com
https://xx.yy.com -> yy.com
"""
try:
result = urlparse(uri)
except ValueError:
return ''
# When uri is 'xx.yy.com', then netloc is empty.
netloc = result.netloc
if not netloc:
netloc = result.path
if netloc:
return '.'.join(netloc.split('.')[-2:])
return netloc


class InvalidCookies(Exception):
pass

Expand Down Expand Up @@ -46,7 +73,7 @@ class CookiesLoginDialog(LoginDialog):
One usage example: feeluown-qqmusic.
"""

def __init__(self, uri=None, required_cookies_fields=None):
def __init__(self, uri=None, required_cookies_fields=None, domain=None):
if has_webengine and uri and required_cookies_fields:
use_webview = True
flags = Qt.Window
Expand All @@ -57,12 +84,17 @@ def __init__(self, uri=None, required_cookies_fields=None):
super().__init__(None, flags)
self._use_webview = use_webview
self._uri = uri
if domain is None and uri is not None:
self._domain = try_get_domain_from_uri(uri)
self._required_cookies_fields = required_cookies_fields

self.cookies_text_edit = QTextEdit(self)
self.hint_label = QLabel(self)
self.login_btn = QPushButton('登录', self)
self.weblogin_btn = QPushButton('网页登录', self)
self.chrome_btn = QPushButton('从 Chrome 中读取 Cookie')
self.firefox_btn = QPushButton('从 Firefox 中读取 Cookie')
self.edge_btn = QPushButton('从 Edge 中读取 Cookie')

self.hint_label.setTextFormat(Qt.RichText)

Expand All @@ -71,6 +103,9 @@ def __init__(self, uri=None, required_cookies_fields=None):
self._layout.addWidget(self.hint_label)
self._layout.addWidget(self.login_btn)
self._layout.addWidget(self.weblogin_btn)
self._layout.addWidget(self.chrome_btn)
self._layout.addWidget(self.firefox_btn)
self._layout.addWidget(self.edge_btn)

self.cookies_text_edit.setAcceptRichText(False)
self.cookies_text_edit.setPlaceholderText(
Expand All @@ -88,6 +123,15 @@ def __init__(self, uri=None, required_cookies_fields=None):
else:
# hide the button if provider does not support
self.weblogin_btn.hide()

if not (can_load_keyring_cookies and self._domain):
self.chrome_btn.setDisabled(True)
self.edge_btn.setDisabled(True)
self.firefox_btn.setDisabled(True)

self.chrome_btn.clicked.connect(lambda: self._start_keyring_login('chrome'))
self.firefox_btn.clicked.connect(lambda: self._start_keyring_login('firefox'))
self.edge_btn.clicked.connect(lambda: self._start_keyring_login('edge'))
self.login_btn.clicked.connect(lambda: aio.create_task(self.login()))
self.login_succeed.connect(self.hide)

Expand All @@ -96,6 +140,22 @@ def _start_web_login(self):
self._web_login.succeed.connect(self._on_web_login_succeed)
self._web_login.show()

def _start_keyring_login(self, browser):
cookie_dict = self._get_cookies_from_browser(browser)
self.cookies_text_edit.setText(json.dumps(cookie_dict, indent=2))
aio.create_task(self.login())

def _get_cookies_from_browser(self, browser):
"""
:param browser: chrome,firefox,edge
"""
jar = load_cookies(None, [browser], None)
cookie_dict = {}
for cookie in jar:
if self._domain in cookie.domain:
cookie_dict[cookie.name] = cookie.value
return cookie_dict

def _on_web_login_succeed(self, cookies):
self.cookies_text_edit.setText(json.dumps(cookies, indent=2))
self._web_login.close()
Expand Down
Loading