diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..9022f28 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,44 @@ +name: Docker + +on: + workflow_dispatch: + push: + branches: + - "main" + tags: + - "v*" + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: build + strategy: + fail-fast: false + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: kevinnitro/vnulib-downloader + + - name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 40156f9..ab622d4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,6 +6,10 @@ on: - src/constants.py workflow_dispatch: +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + jobs: prepare: name: prepare diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..999a471 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM python:3.12.3-alpine + +LABEL authors="KevinNitro " +LABEL name="VNULIB Downloader" +LABEL repository="https://github.com/KevinNitroG/VNULIB-Downloader" +LABEL latest=true + +WORKDIR /app + +COPY requirements/requirements.txt /app/ +RUN pip install --no-cache-dir -r requirements.txt + +COPY assets/images/error_page.jpg /app/assets/images/ +COPY assets/utils/ascii_banner.txt /app/assets/utils/ +COPY config-docker.yml /app/config.yml + +COPY main.py /app/ +COPY src/ /app/src/ + +RUN apk update +RUN apk add chromium +RUN apk add chromium-chromedriver + +CMD ["python", "main.py"] diff --git a/config-docker.yml b/config-docker.yml new file mode 100644 index 0000000..f78fcc5 --- /dev/null +++ b/config-docker.yml @@ -0,0 +1,17 @@ +# CONFIG FILE FOR RUNNING DOCKER + +USERNAME: + +PASSWORD: + +LINKS: + +TIMEOUT: + +BROWSER: /usr/bin/chromedriver + +HEADLESS: true + +CREATE_PDF: + +CLEAN_IMG: diff --git a/config-sample.yml b/config-sample.yml index 59f288f..e3840be 100644 --- a/config-sample.yml +++ b/config-sample.yml @@ -24,7 +24,7 @@ LINKS: TIMEOUT: # Browser you are using (to use Selenium webdriver) -# Options: "chrome", "path/to/local/google_chromedriver" (google chromedriver only) +# Options: "chrome", "chromium", "path/to/local/google_chromedriver" (google chromedriver only) # Ex: BROSWER: chrome BROWSER: diff --git a/docs/README.md b/docs/README.md index a81e47e..164625f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -64,6 +64,7 @@ Python CLI tool download sách từ VNULIB - [⚙️ NÂNG CAO](#️-nâng-cao) - [🗃️ Pre-config](#️-pre-config) - [⛏️ Command line arguments](#️-command-line-arguments) + - [📦 Docker](#-docker) - [🤐 Python](#-python) - [🤔 NOTES](#-notes) - [Giải thích thuật ngữ](#giải-thích-thuật-ngữ) @@ -110,7 +111,7 @@ Python CLI tool download sách từ VNULIB > [!IMPORTANT] > -> Cần cài đặt trình duyệt [Chrome](https://www.google.com/chrome/) _(cần cho Selenium Webdriver)_ +> Cần cài đặt trình duyệt [Chrome](https://www.google.com/chrome/) hoặc Chromium _(cần cho Selenium Webdriver)_ 1. Mở tool 2. Input @@ -153,11 +154,6 @@ Python CLI tool download sách từ VNULIB ## ⚙️ NÂNG CAO -- Có thể chạy tool theo các cách: - - [Pre config](#️-pre-config) - - [Command line arguments](#️-command-line-arguments) - - [Python](#-python) - > [!NOTE] > > Thứ tự ưu tiên giá trị biến: `arguments` > `config.yml` > `user input` @@ -188,9 +184,22 @@ Python CLI tool download sách từ VNULIB ``` - Ví dụ _(Windows)_: ```.ps1 - .\VNULIB-Downloader-windows.exe --link "link1" "link2" --username "1500023520000" --password "examplePass" --browser "~/chrome_driver.exe" --headless --create-pdf --clean-imgs + .\VNULIB-Downloader-windows.exe --link "link1" "link2" --username "1500023520000" --password "examplePass" --browser "./chrome_driver.exe" --headless --create-pdf --clean-imgs + ``` + +### 📦 Docker + +- Có thể tải và sử dụng thông qua docker image _(chỉ chạy theo kiểu `user input`)_ + ```sh + docker run -it --rm -v "$(pwd)/Downloads/:/app/Downloads/" kevinnitro/vnulib-downloader ``` +> [!NOTE] +> +> - Tải chạy docker image [`kevinnitro/vnulib-donwloader`](https://hub.docker.com/r/kevinnitro/vnulib-downloader) từ dockerhub +> - File tải về sẽ được lưu ở `./Downloads/` +> - Tự động xoá image sau khi chạy + ### 🤐 Python 1. Install [Python](https://www.python.org/downloads/) @@ -278,6 +287,7 @@ Python CLI tool download sách từ VNULIB ## 📓 TODO +- [ ] Docker version, auto build and push - [ ] Support more browsers _(inherited from which class?)_ - [ ] Options to enable Multithreading, Multiprocessing - [ ] Update tool option using command line arguments diff --git a/src/bot/browser.py b/src/bot/browser.py index 84b5357..2a9818d 100644 --- a/src/bot/browser.py +++ b/src/bot/browser.py @@ -8,6 +8,7 @@ from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.webdriver import WebDriver from webdriver_manager.chrome import ChromeDriverManager +from webdriver_manager.core.os_manager import ChromeType from src.constants import BROWSER_ARGUMENTS @@ -42,6 +43,8 @@ def __enter__(self) -> WebDriver: match self._browser.strip(): case "chrome" | "": self.driver = self._setup_chrome_browser() + case "chromium": + self.driver = self._setup_chromium_browser() case _: self.driver = self._setup_local_chrome_browser() self.driver.implicitly_wait(self._timeout) @@ -69,6 +72,14 @@ def _setup_chrome_browser(self) -> WebDriver: """ return webdriver.Chrome(options=self._options, service=Service(ChromeDriverManager().install())) + def _setup_chromium_browser(self) -> WebDriver: + """Setup Chromium Browser. + + Returns: + WebDriver: Selenium WebDriver. + """ + return webdriver.Chrome(options=self._options, service=Service(ChromeDriverManager(chrome_type=ChromeType.CHROMIUM).install())) + def _setup_local_chrome_browser(self) -> WebDriver: """Setup Local Chrome Browser. diff --git a/src/constants.py b/src/constants.py index 5dc1d58..81cdc54 100644 --- a/src/constants.py +++ b/src/constants.py @@ -10,7 +10,7 @@ BUNDLE_DIR = "" -VERSION: str = "1.17.1" +VERSION: str = "v1.17.2" AUTHORS: str = "KevinNitroG & NTGNguyen" BANNER_FILE: str = f"{BUNDLE_DIR}assets/utils/ascii_banner.txt" with open(BANNER_FILE, encoding="utf-8") as banner_content: diff --git a/src/modules/user_options.py b/src/modules/user_options.py index 2d00bc6..6675b7b 100644 --- a/src/modules/user_options.py +++ b/src/modules/user_options.py @@ -175,7 +175,7 @@ def _setup_browser(self) -> str: self._log_set_by_config("browser") return self._config["BROWSER"].lower() self._log_set_by_user_input("browser") - return input("Enter browser you are using [CHROME, path/to/chrome_driver]: ").strip().lower() + return input('Enter browser you are using ["CHROME", "CHROMIUM", "path/to/chrome_driver"]: ').strip().lower() def _setup_headless(self) -> bool: """Setup headless mode. @@ -220,7 +220,7 @@ def _setup_clean_img(self) -> bool: self._log_set_by_config("clean_img") return self._config["CLEAN_IMG"] self._log_set_by_user_input("clean_img") - return input("Create images of book(s) after being merged into PDF [y/N]: ").strip().upper() in USER_INPUT_NO + return input("Clean images of book(s) after being merged into PDF [y/N]: ").strip().upper() in USER_INPUT_NO @staticmethod def _log_set_by_argparse(var: str) -> None: