Add authentication with netscape cookie file

This commit is contained in:
Joakim Holm 2023-04-19 22:53:33 +02:00
parent a8fbb690ec
commit 8d2fe3d7d5
3 changed files with 61 additions and 2 deletions

View File

@ -5,9 +5,10 @@ from .sources import load_source, Source
from .output import download_book from .output import download_book
from . import arguments, logging from . import arguments, logging
from typing import Tuple from typing import Tuple, Optional
from rich.progress import Progress from rich.progress import Progress
from functools import partial from functools import partial
import os
def get_login(source: Source, config: Config, options) -> Tuple[str, str]: def get_login(source: Source, config: Config, options) -> Tuple[str, str]:
@ -45,6 +46,20 @@ def get_urls(options) -> list[str]:
return urls return urls
def get_cookie_file(options) -> Optional[str]:
"""
Get path to cookie file
:param options: Cli arguments
:returns: Path to cookie file
"""
if options.cookie_file is not None and os.path.exists(options.cookie_file):
return options.cookie_file
if os.path.exists("./cookies.txt"):
return "./cookies.txt"
return None
def authenticate(source: Source, config: Config, options): def authenticate(source: Source, config: Config, options):
""" """
Authenticate with source Authenticate with source
@ -58,6 +73,10 @@ def authenticate(source: Source, config: Config, options):
username, password = get_login(source, config, options) username, password = get_login(source, config, options)
source.login(username, password) source.login(username, password)
source.authenticated = True source.authenticated = True
if source.supports_cookies:
cookie_file = get_cookie_file(options)
if cookie_file:
source.load_cookies(cookie_file)
else: else:
raise SourceNotAuthenticated raise SourceNotAuthenticated

View File

@ -39,6 +39,12 @@ def parse_arguments():
help = "Password for login", help = "Password for login",
dest = "password", dest = "password",
) )
parser.add_argument(
'-c',
'--cookies',
help = "Path to netscape cookie file",
dest = "cookie_file"
)
# Outputs # Outputs
parser.add_argument( parser.add_argument(
'-o', '-o',

View File

@ -1,7 +1,9 @@
from grawlix.book import Book, Series, Result from grawlix.book import Book, Series, Result
from typing import Generic, TypeVar, Tuple from typing import Generic, TypeVar, Tuple, Optional
from http.cookiejar import MozillaCookieJar
import requests import requests
import re
T = TypeVar("T") T = TypeVar("T")
@ -41,6 +43,25 @@ class Source(Generic[T]):
raise NotImplementedError raise NotImplementedError
@property
def supports_cookies(self) -> bool:
"""Does the source support authentication with cookie file"""
return "cookies" in self._authentication_methods
def load_cookies(self, cookie_file: str):
"""
Authenticate with source with netscape cookie file
:param cookie_file: Path to netscape cookie file
"""
if self.supports_cookies:
cookie_jar = MozillaCookieJar()
cookie_jar.load(cookie_file, ignore_expires=True)
self._session.cookies.update(cookie_jar)
self.authenticated = True
def download(self, url: str) -> Result[T]: def download(self, url: str) -> Result[T]:
""" """
Download book metadata from source Download book metadata from source
@ -59,3 +80,16 @@ class Source(Generic[T]):
:returns: Downloaded book metadata :returns: Downloaded book metadata
""" """
raise NotImplementedError raise NotImplementedError
def get_match_index(self, url: str) -> Optional[int]:
"""
Find the first regex in `self.match` that matches url
:param url: Url to match
:returns: Index of regex
"""
for index, match in enumerate(self.match):
if re.match(match, url):
return index
return None