From 8acfb438faacc602741bc533b7d949c1a822da34 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Wed, 20 Mar 2019 16:09:29 +0100 Subject: [PATCH] after failing through the regular approach it will open a webview. --- coursera/cookies.py | 45 +++++++++++++++++++++++++++++++++++++++++++-- requirements.txt | 1 + 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/coursera/cookies.py b/coursera/cookies.py index f12ed8f..b3f636d 100644 --- a/coursera/cookies.py +++ b/coursera/cookies.py @@ -6,10 +6,15 @@ Cookie handling module. import logging import os +import re import ssl +import time + +from multiprocessing.pool import ThreadPool import requests from requests.adapters import HTTPAdapter +import webview try: # Workaround for broken Debian/Ubuntu packages? (See issue #331) from requests.packages.urllib3.poolmanager import PoolManager @@ -22,6 +27,8 @@ from six.moves import http_cookiejar as cookielib from .define import CLASS_URL, AUTH_REDIRECT_URL, PATH_COOKIES, AUTH_URL_V3 from .utils import mkdir_p, random_string + + # Monkey patch cookielib.Cookie.__init__. # Reason: The expires value may be a decimal string, # but the Cookie class uses int() ... @@ -108,6 +115,39 @@ def prepare_auth_headers(session, include_cauth=False): return headers +def login_with_webview(): + """ + Creates a physical login window for the use to login. + """ + url = "https://www.coursera.org/?authMode=login" + + def get_cookies(): + timeout = 120 + + def is_logged_in(): + return webview.evaluate_js("document.querySelector('#logout-btn') !== null") + + while not webview.webview_ready() or not is_logged_in(): + time.sleep(1) + timeout -= 1 + if timeout == 0: + raise AuthenticationFailed("Can't login, timeout exceeded.") + + cookies = webview.evaluate_js("document.cookie") + webview.destroy_window() + return cookies + + def create_login_window(): + webview.create_window("Login to Coursera", url) + + pool = ThreadPool(processes=1) + async_result = pool.apply_async(get_cookies) + create_login_window() + cookies = async_result.get() + parsed_cookies = dict(re.findall(r"([^\=]+)\=([^;]+);\s?", cookies)) + return parsed_cookies + + def login(session, username, password, class_name=None): """ Login on coursera.org with the given credentials. @@ -151,8 +191,9 @@ def login(session, username, password, class_name=None): # for coursera!!! v = session.cookies.pop('CAUTH') session.cookies.set('CAUTH', v) - except requests.exceptions.HTTPError as e: - raise AuthenticationFailed('Cannot login on coursera.org: %s' % e) + except requests.exceptions.HTTPError: + logging.debug("Can't login through api, try to login using webview.") + session.cookies.update(login_with_webview()) logging.info('Logged in on coursera.org.') diff --git a/requirements.txt b/requirements.txt index dc3ac2a..e2f99d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ pyasn1>=0.1.7 keyring>=4.0 configargparse>=0.12.0 attrs==18.1.0 +pywebview>=2.4