Skip to content

Commit

Permalink
💡 Re-write docstring
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinNitroG committed Feb 17, 2024
1 parent 96630a2 commit 7590f80
Show file tree
Hide file tree
Showing 23 changed files with 245 additions and 216 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# THIS PROJECT
**/*test*
config.yml
VNULIB-DOWNLOADER/
**/*log*
VNULIB-Downloader/config.yml
Profiles/

**/__pycache__
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Python CLI tool download sách từ <strong>VNULIB</strong>
### 🗃️ Pre-config

1. Tạo file `config.yml` trong directory chứa file thực thi bằng 1 trong 2 cách:
1. Tạo file `config.yml` trong directory `VNULIB-Downloader` bằng 1 trong 2 cách:
- Chạy trước tool 1 lần sẽ tự tạo file `config.yml`
- Copy nội dung của file [`config-sample.yml`](../config-sample.yml) và paste vào file `config.yml`
2. Chỉnh các giá trị biến trong file `config.yml`
Expand Down
15 changes: 7 additions & 8 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
"""VNULIB Downloader"""
"""VNULIB Downloader
"""


from pprint import pformat
from src import (Browser, Login, Action,
PrintIntro,
ToolConfig, UserOptions, LinkParse,
PrintIntro, Config, UserOptions, LinkParse,
print_title,
logger)
from src.constants import CONFIG_FILE, CONFIG_FILE_URL


def main() -> None:
"""Main function to run VNULIB Downloader"""
"""Main function to run VNULIB Downloader
"""
PrintIntro().print_intro()

print_title(message='SETUP')
ToolConfig(
config_file_name=CONFIG_FILE, url=CONFIG_FILE_URL).setup()
Config().setup()
user_options = UserOptions()
user_options.setup()

Expand All @@ -33,7 +32,7 @@ def main() -> None:
user_options.links = LinkParse(links=user_options.links).parse()
user_options.links = Action(driver=driver,
links=user_options.links).action()
logger.debug(msg='LINKS AFTER PARSING:\n'
logger.debug(msg='LINKS OBJECT:\n'
f'{pformat(user_options.links)}')

print_title(message='DOWNLOAD')
Expand Down
5 changes: 3 additions & 2 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Contains classes, function, object to be imported in main"""
"""Contains classes, function, object to be imported in main
"""


from .bot import Browser, Login, Action
from .modules import PrintIntro, ToolConfig, UserOptions, LinkParse
from .modules import PrintIntro, Config, UserOptions, LinkParse
from .modules import setup_argparse
from .utils import logger, print_title
66 changes: 34 additions & 32 deletions src/bot/action.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Contains Bot actions: Book website -> Book preview -> Book page link"""
"""Contains Bot actions: Book website -> Book preview -> Book page link
"""


from urllib.parse import urlparse, urlunparse, parse_qs, urlencode
Expand All @@ -7,16 +8,15 @@
from selenium.webdriver.remote.webelement import WebElement
from ..modules.link_parse import Link, LinkFile
from .utils import wait_element_visible
from ..utils import logger
from ..utils.utils import datetime_name, slugify
from ..utils import logger, datetime_name, slugify


class Action:
"""Bot actions for the bot to perform
"""Bot actions to process links
Params:
Args:
- driver (WebDriver): Selenium WebDriver
- links (list[Link]): List of links to process
- links (list[Link]): List of links object
"""

def __init__(self, driver: WebDriver, links: list[Link]) -> None:
Expand All @@ -27,7 +27,7 @@ def __init__(self, driver: WebDriver, links: list[Link]) -> None:
def remove_page_query(link: str) -> str:
"""Parse the link to remove "page" query
Params:
Args:
- link (str): Link to parse
Returns:
Expand All @@ -44,27 +44,27 @@ def remove_page_query(link: str) -> str:

@staticmethod
def __book_preview_to_page(link: str) -> str:
"""Book preview link to book page link and return number of pages
"""Book preview link to book page link
Params:
Args:
- link (str): Book preview link
Returns:
- list[str]: Book page link
- str: Book page link without "page" query
"""
parser = urlparse(link)
query = parse_qs(parser.query)
subfolder_value: str = query.get('subfolder', '')[0]
doc_value: str = query.get('doc', '')[0]
page_link: str = f'https: // ir.vnulib.edu.vn/flowpaper/services/view.php?doc = {
doc_value} & format = jpg & subfolder = {subfolder_value}'
page_link: str = f'https//ir.vnulib.edu.vn/flowpaper/services/view.php?doc={
doc_value}&format =jpg&subfolder={subfolder_value}'
return page_link

@staticmethod
def __get_num_pages(driver: WebDriver) -> int:
"""Get number of pages from book preview link
"""Get number of pages from book preview link, aready in book preview link
Params:
Args:
- driver (WebDriver): Selenium WebDriver
Returns:
Expand All @@ -75,10 +75,9 @@ def __get_num_pages(driver: WebDriver) -> int:
return int(pages)

def book_preview_to_page_and_book_pages(self, link: str) -> tuple[str, int]:
"""Book preview link to book page link and return number of pages
"""Book preview link to book page link and get number of pages
Params:
- driver (WebDriver): Selenium WebDriver
Args:
- link (str): Book preview link
Returns:
Expand All @@ -96,7 +95,7 @@ def book_preview_to_page_and_book_pages(self, link: str) -> tuple[str, int]:
def book_web_to_preview(self, link: str) -> list[str]:
"""Book website link to book preview link
Params:
Args:
- link (str): Book website link
Returns:
Expand All @@ -112,13 +111,13 @@ def book_web_to_preview(self, link: str) -> list[str]:
if preview_link is not None:
preview_links.append(preview_link)
logger.info(msg=f'Found {len(preview_links)} '
f'preview link(s) for {link}')
f'preview link(s) for \'{link}\'')
return preview_links

def get_book_files_name(self) -> list[str]:
"""Get book's files' name from the book website (Already in book website)
Params:
Args:
- None
Returns:
Expand All @@ -133,11 +132,11 @@ def get_book_files_name(self) -> list[str]:
def process_book(self, link: Link) -> Link:
"""Process book link handler
Params:
- link (Link): Current link
Args:
- link (Link): Current link object
Returns:
- Link: Processed link
- Link: Processed link object
"""
preview_links: list[str] = self.book_web_to_preview(
link=link.original_link)
Expand All @@ -156,11 +155,11 @@ def process_book(self, link: Link) -> Link:
def process_preview(self, link: Link) -> Link:
"""Process preview link handler
Params:
- link (Link): Current link
Args:
- link (Link): Current link object
Returns:
- Link: Processed link
- Link: Processed link object
"""
page_link, num_pages = self.book_preview_to_page_and_book_pages(
link=link.original_link)
Expand All @@ -171,11 +170,11 @@ def process_preview(self, link: Link) -> Link:
def process_page(self, link: Link) -> Link:
"""Process page link handler
Params:
- link (Link): Current link
Args:
- link (Link): Current link object
Returns:
- Link: Processed link
- Link: Processed link object
"""
page_link: str = Action.remove_page_query(link=link.original_link)
link.files = [LinkFile(
Expand All @@ -185,13 +184,16 @@ def process_page(self, link: Link) -> Link:
def action(self) -> list[Link]:
"""Convert all links to the page links format
Args:
- None
Returns:
- list: A list contains converted links to page links format
- list[Link]: A list processed links object
"""
converted_links: list[Link] = []
for link in self.links:
logger.info(msg=f'Processing {link.original_link} as {
link.original_type}')
logger.info(msg=f'Processing \'{link.original_link}\' '
f'as \'{link.original_type}\'')
match link.original_type:
case 'book':
converted_links.append(
Expand Down
35 changes: 28 additions & 7 deletions src/bot/browser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Setup Selenium Browser"""
"""Setup Selenium Browser
"""


from selenium import webdriver
Expand All @@ -14,7 +15,12 @@


class Browser:
"""Setup Selenium Browser"""
"""Setup Selenium Browser
Args:
- browser (str): The browser to setup
- headless (bool): Headless mode
"""

def __init__(self, browser: str, headless: bool) -> None:
self.browser: str = browser
Expand All @@ -23,7 +29,11 @@ def __init__(self, browser: str, headless: bool) -> None:
self.driver: WebDriver

def __enter__(self) -> WebDriver:
"""Setup the browser"""
"""Setup the browser when entering the context manager
Returns:
- WebDriver: Selenium WebDriver
"""
logger.info(msg='Setting up the browser...')
self.__setup_arguments()
match self.browser:
Expand All @@ -32,15 +42,18 @@ def __enter__(self) -> WebDriver:
case _:
self.driver = self.__setup_local_chrome_browser()
self.driver.implicitly_wait(30)
logger.info(msg=f'Browser {self.browser} setup complete!')
logger.info(msg=f'Browser \'{self.browser}\' setup complete!')
return self.driver

def __exit__(self, exc_type, exc_value, traceback) -> None:
"""Exit the context manager
"""
logger.info(msg='Quit the browser')
self.driver.quit()

def __setup_arguments(self) -> None:
"""Setup the browser arguments"""
"""Setup the browser arguments
"""
for argument in BROWSER_ARGUMENTS:
self.options.add_argument(argument)
if self.headless:
Expand All @@ -50,11 +63,19 @@ def __setup_arguments(self) -> None:
)

def __setup_chrome_browser(self) -> WebDriver:
"""Setup Chrome Browser"""
"""Setup Chrome Browser
Returns:
- WebDriver: Selenium WebDriver
"""
return webdriver.Chrome(
options=self.options,
service=ChromeService(ChromeDriverManager().install()))

def __setup_local_chrome_browser(self) -> WebDriver:
"""Setup Local Chrome Browser"""
"""Setup Local Chrome Browser
Returns:
- WebDriver: Selenium WebDriver
"""
return webdriver.Chrome(options=self.options, service=ChromeService(self.browser))
29 changes: 17 additions & 12 deletions src/bot/login.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Use Selenium to login to the website"""

"""Use Selenium to login to the website
"""

from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
Expand All @@ -10,7 +10,13 @@


class Login:
"""Login to the website"""
"""Login to the VNULIB website
Args:
- driver (WebDriver): Selenium WebDriver
- username (str): Username
- password (str): Password
"""

def __init__(self, driver: WebDriver,
username, password) -> None:
Expand All @@ -20,20 +26,19 @@ def __init__(self, driver: WebDriver,
self.url = LOGIN_URL

def __fill_in(self) -> None:
"""Fill in the login form"""
# username_field: WebElement = wait_element_visible(
# driver=self.driver, css_selector='.form-control[name="username"]')
# password_field: WebElement = wait_element_visible(
# driver=self.driver, css_selector='.form-control[name="password"]')
"""Fill in the login form
"""
self.driver.find_element(
By.CSS_SELECTOR, '.form-control[name="username"]').send_keys(self.username)
self.driver.find_element(
By.CSS_SELECTOR, '.form-control[name="password"]').send_keys(self.password)
# username_field.send_keys(self.username)
# password_field.send_keys(self.password)

def login(self) -> None:
"""Login to the website"""
"""Login to VNULIB website
Raises:
ConnectionError: Login failed
"""
logger.info(msg='Logging in...')
self.driver.get(self.url)
submit_button: WebElement = wait_element_clickable(
Expand All @@ -44,4 +49,4 @@ def login(self) -> None:
logger.info(msg='Logged in successfully!')
else:
logger.error(msg='Login failed!')
raise Exception('Login failed!')
raise ConnectionError('Login failed!')
Loading

0 comments on commit 7590f80

Please sign in to comment.