Working on #94

This commit is contained in:
Lorenzo Di Fuccia 2019-06-06 19:02:21 +02:00 • committed by GitHub
commit 51d0b1c9df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -18,8 +18,14 @@ from urllib.parse import urljoin, urlsplit, urlparse
PATH = os.path.dirname(os.path.realpath(__file__)) PATH = os.path.dirname(os.path.realpath(__file__))
COOKIES_FILE = os.path.join(PATH, "cookies.json") COOKIES_FILE = os.path.join(PATH, "cookies.json")
SAFARI_BASE_HOST = "learning.oreilly.com" ORLY_BASE_HOST = "oreilly.com" # PLEASE INSERT URL HERE
SAFARI_BASE_HOST = "learning." + ORLY_BASE_HOST
API_ORIGIN_HOST = "api." + ORLY_BASE_HOST
ORLY_BASE_URL = "https://www." + ORLY_BASE_HOST
SAFARI_BASE_URL = "https://" + SAFARI_BASE_HOST SAFARI_BASE_URL = "https://" + SAFARI_BASE_HOST
API_ORIGIN_URL = "https://" + API_ORIGIN_HOST
class Display: class Display:
@ -181,8 +187,9 @@ class WinQueue(list): # TODO: error while use `process` in Windows: can't pickl
class SafariBooks: class SafariBooks:
LOGIN_URL = ORLY_BASE_URL + "/member/auth/login/"
LOGIN_ENTRY_URL = SAFARI_BASE_URL + "/login/unified/?next=/home/"
LOGIN_URL = SAFARI_BASE_URL + "/accounts/login/"
API_TEMPLATE = SAFARI_BASE_URL + "/api/v1/book/{0}/" API_TEMPLATE = SAFARI_BASE_URL + "/api/v1/book/{0}/"
HEADERS = { HEADERS = {
@ -193,7 +200,7 @@ class SafariBooks:
"cookie": "", "cookie": "",
"pragma": "no-cache", "pragma": "no-cache",
"origin": SAFARI_BASE_URL, "origin": SAFARI_BASE_URL,
"referer": LOGIN_URL, "referer": LOGIN_ENTRY_URL,
"upgrade-insecure-requests": "1", "upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/60.0.3112.113 Safari/537.36" "Chrome/60.0.3112.113 Safari/537.36"
@ -274,6 +281,7 @@ class SafariBooks:
self.display.intro() self.display.intro()
self.cookies = {} self.cookies = {}
self.jwt = {}
if not args.cred: if not args.cred:
if not os.path.isfile(COOKIES_FILE): if not os.path.isfile(COOKIES_FILE):
@ -368,7 +376,7 @@ class SafariBooks:
return " ".join(["{0}={1};".format(k, v) for k, v in self.cookies.items()]) return " ".join(["{0}={1};".format(k, v) for k, v in self.cookies.items()])
def return_headers(self, url): def return_headers(self, url):
if SAFARI_BASE_HOST in urlsplit(url).netloc: if ORLY_BASE_HOST in urlsplit(url).netloc:
self.HEADERS["cookie"] = self.return_cookies() self.HEADERS["cookie"] = self.return_cookies()
else: else:
@ -382,7 +390,7 @@ class SafariBooks:
cookie.name: cookie.value cookie.name: cookie.value
}) })
def requests_provider(self, url, post=False, data=None, update_cookies=True, **kwargs): def requests_provider(self, url, post=False, data=None, update_cookies=True, update_referer=False, **kwargs):
try: try:
response = getattr(requests, "post" if post else "get")( response = getattr(requests, "post" if post else "get")(
url, url,
@ -404,6 +412,10 @@ class SafariBooks:
if update_cookies: if update_cookies:
self.update_cookies(response.cookies) self.update_cookies(response.cookies)
if update_referer:
# TODO Update Referer HTTP Header
pass
return response return response
@staticmethod @staticmethod
@ -421,41 +433,41 @@ class SafariBooks:
return new_cred return new_cred
def do_login(self, email, password): def do_login(self, email, password):
response = self.requests_provider(self.LOGIN_URL) response = self.requests_provider(self.LOGIN_ENTRY_URL, allow_redirects=False)
if response == 0:
self.display.exit("Login: unable to reach Safari Books Online. Try again...")
elif not response.is_redirect:
self.display.exit("Login: error? LOGIN-UPDATE-01")
response = self.requests_provider(response.next.url, allow_redirects=False)
if response == 0:
self.display.exit("Login: unable to reach Safari Books Online. Try again...")
elif not response.is_redirect:
self.display.error("Login: error? LOGIN-UPDATE-02")
response = self.requests_provider(response.next.url, allow_redirects=False)
if response == 0: if response == 0:
self.display.exit("Login: unable to reach Safari Books Online. Try again...") self.display.exit("Login: unable to reach Safari Books Online. Try again...")
csrf = [] redirect_uri = response.request.path_url[response.request.path_url.index("redirect_uri"):] # TODO try...catch
try: redirect_uri = redirect_uri[:redirect_uri.index("&")]
csrf = html.fromstring(response.text).xpath("//input[@name='csrfmiddlewaretoken'][@value]") redirect_uri = "https://api.oreilly.com%2Fapi%2Fv1%2Fauth%2Fopenid%2Fauthorize%3F" + redirect_uri
except (html.etree.ParseError, html.etree.ParserError) as parsing_error:
self.display.error(parsing_error)
self.display.exit(
"Login: error trying to parse the home of Safari Books Online."
)
if not len(csrf):
self.display.exit("Login: no CSRF Token found in the page."
" Unable to continue the login."
" Try again...")
csrf = csrf[0].attrib["value"]
response = self.requests_provider( response = self.requests_provider(
self.LOGIN_URL, self.LOGIN_URL,
post=True, post=True,
data=( json={
("csrfmiddlewaretoken", csrf), "email": email,
("email", email), ("password1", password), "password": password,
("login", "Sign In"), ("next", "") "redirect_uri": redirect_uri
), },
allow_redirects=False allow_redirects=False
) )
if response == 0: if response == 0:
self.display.exit("Login: unable to perform auth to Safari Books Online.\n Try again...") self.display.exit("Login: unable to perform auth to Safari Books Online.\n Try again...")
if response.status_code != 302: if response.status_code != 200: # TODO To be reviewed
try: try:
error_page = html.fromstring(response.text) error_page = html.fromstring(response.text)
errors_message = error_page.xpath("//ul[@class='errorlist']//li/text()") errors_message = error_page.xpath("//ul[@class='errorlist']//li/text()")
@ -473,6 +485,25 @@ class SafariBooks:
" trying to parse the login details of Safari Books Online. Try again..." " trying to parse the login details of Safari Books Online. Try again..."
) )
self.jwt = response.json() # TODO: save JWT Tokens and use the refresh_token to restore user session
response = self.requests_provider(self.jwt["redirect_uri"], allow_redirects=False)
if response == 0:
self.display.exit("Login: unable to reach Safari Books Online. Try again...")
elif not response.is_redirect:
self.display.exit("Login: error? LOGIN-UPDATE-03")
response = self.requests_provider(response.next.url, allow_redirects=False)
if response == 0:
self.display.exit("Login: unable to reach Safari Books Online. Try again...")
elif not response.is_redirect:
self.display.exit("Login: error? LOGIN-UPDATE-04")
response = self.requests_provider(response.next.url)
if response == 0:
self.display.exit("Login: unable to reach Safari Books Online. Try again...")
elif not response.ok:
self.display.exit("Login: error? LOGIN-UPDATE-05")
def get_book_info(self): def get_book_info(self):
response = self.requests_provider(self.api_url) response = self.requests_provider(self.api_url)
if response == 0: if response == 0: