Skip to content

Commit

Permalink
added automatic testing, for that Hentai.download(...) now returns PDF
Browse files Browse the repository at this point in the history
  • Loading branch information
9FS committed Sep 28, 2023
1 parent 3ed67e6 commit 1b55f5e
Show file tree
Hide file tree
Showing 8 changed files with 319 additions and 30 deletions.
38 changes: 32 additions & 6 deletions .github/workflows/on tag deploy on Github.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,12 @@ jobs:
outputs: # set step output as job output so other jobs can access
NOW: ${{steps.now.outputs.NOW}}
TODAY: ${{steps.today.outputs.TODAY}}



create_release:
name: Create Release
test:
name: Run Tests
env:
working-directory: ${{github.workspace}}
needs: datetime
runs-on: ubuntu-latest

steps:
Expand All @@ -44,7 +43,7 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: ${{env.PYTHON_VERSION}}

- name: Install Poetry
run: |
pip install poetry
Expand All @@ -61,6 +60,33 @@ jobs:
else
exit 1
fi
- name: Run Tests
run: poetry run pytest


create_release:
name: Create Release
env:
working-directory: ${{github.workspace}}
needs: [datetime, test]
runs-on: ubuntu-latest

steps:
- name: Checkout Repository
uses: actions/checkout@v4 # makes repository structure available

- name: Install Python
uses: actions/setup-python@v4
with:
python-version: ${{env.PYTHON_VERSION}}

- name: Install Poetry
run: |
pip install poetry
poetry config virtualenvs.in-project true
poetry config repositories.test-pypi https://test.pypi.org/legacy/
poetry install
- name: Create Release
env:
Expand Down Expand Up @@ -128,7 +154,7 @@ jobs:
name: Deploy on Github
env:
working-directory: ${{github.workspace}}
needs: [build, create_release, datetime]
needs: [build, create_release, datetime, test]
runs-on: ${{matrix.os}}
strategy:
matrix:
Expand Down
15 changes: 9 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
*.log
*.pyc
*.token
/doc_templates/
/hentai/
/log/
/src/test.py
/supplements/
downloadme.txt

.hypothesis/
.pytest_cache/
doc_templates/
hentai/
log/

downloadme.txt
tests/test.py
119 changes: 118 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ kfsconfig = "^1.0.0"
kfsfstr = "^1.0.0"
kfslog = "^1.0.0"
kfsmedia = "^2.1.0"
pillow = "^10.0.1"
python = "^3.11.0"

[tool.poetry.group.dev.dependencies]
hypothesis = "^6.87.0"
pytest = "^7.4.2"

[build-system]
build-backend = "poetry.core.masonry.api"
requires = ["poetry-core"]
36 changes: 20 additions & 16 deletions src/Hentai.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import json
import logging
import os
import PIL.Image
import random
import re
import requests
Expand All @@ -17,12 +18,12 @@ class Hentai:
represents an individual hentai
"""

def __init__(self, nhentai_ID: int, cookies: dict[str, str], headers: dict[str, str]):
def __init__(self, hentai_ID: int, cookies: dict[str, str], headers: dict[str, str]):
"""
Constructs hentai object. Downloads data from the nhentai API.
Arguments:
- nhentai_ID: the hentai from nhentai.net found here: https://nhentai.net/g/{nhentai_ID}
- hentai_ID: the hentai from nhentai.net found here: https://nhentai.net/g/{hentai_ID}
- cookies: cookies to send with the request to bypass bot protection
- headers: user agent to send with the request to bypass bot protection
Expand All @@ -43,14 +44,14 @@ def __init__(self, nhentai_ID: int, cookies: dict[str, str], headers: dict[str,

logging.debug(f"Creating hentai object...")

self.ID=nhentai_ID
self.ID=hentai_ID

logging.info(f"Downloading gallery from \"{NHENTAI_GALLERY_API_URL}/{self.ID}\"...")
attempt_no: int=1
while True:
try:
gallery_page=requests.get(f"{NHENTAI_GALLERY_API_URL}/{self.ID}", cookies=cookies, headers=headers, timeout=10)
except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout): # if connection error: try again
except (requests.exceptions.ConnectionError, requests.Timeout): # if connection error: try again
time.sleep(1)
if attempt_no<3: # try 3 times
continue
Expand All @@ -77,9 +78,7 @@ def __init__(self, nhentai_ID: int, cookies: dict[str, str], headers: dict[str,

self.title=self._gallery["title"]["pretty"]

self._fails=[]
for _ in range(self.page_amount): # initialise with amount of pages number of zeros
self._fails.append(0)
self._fails=[0 for _ in range(self.page_amount)] # initialise with amount of pages number of zeros

logging.debug(f"\rCreated hentai object.")
logging.debug(self.__repr__())
Expand Down Expand Up @@ -117,9 +116,12 @@ def _increment_fails(self, image_list: list[str]) -> None:
return


def download(self) -> None:
def download(self) -> list[PIL.Image.Image]:
"""
Downloads the hentai and saves it at f"./{self.ID} {self.title}.pdf".
Downloads the hentai, saves it at f"./{self.ID} {self.title}.pdf", and also returns it in case needed.
Returns:
- PDF: finished PDF
Raises:
- FileExistsError: File \"{PDF_filepath}\" already exists.
Expand All @@ -136,6 +138,7 @@ def download(self) -> None:
"p": ".png",
}
pages_URL: list[str]=[] # URL to individual pages to download
PDF: list[PIL.Image.Image] # finished PDF
PDF_filepath: str # where to save downloaded result, ID title pdf, but title maximum 140 characters and without illegal filename characters
TITLE_CHARACTERS_FORBIDDEN: str="\\/:*?\"<>|\t\n" # in title forbidden characters

Expand All @@ -155,6 +158,7 @@ def download(self) -> None:
PDF_filepath=f"./hentai/{self.ID} {PDF_filepath}.pdf"
if os.path.isfile(PDF_filepath)==True: # if PDF already exists: skip download
logging.info(f"File \"{PDF_filepath}\" already exists. Skipped download.")
self.PDF_filepath=PDF_filepath # save PDF filepath
raise FileExistsError(f"File \"{PDF_filepath}\" already exists. Skipped download.") # raise exception to skip upload in main
if os.path.isdir(PDF_filepath)==True: # if PDF already exists as directory: skip download, append to failures
logging.error(f"\"{PDF_filepath}\" already exists as directory. Skipped download.")
Expand All @@ -169,14 +173,14 @@ def download(self) -> None:
continue

try:
KFSmedia.convert_images_to_PDF(images_filepath, PDF_filepath) # convert images to PDF
PDF=KFSmedia.convert_images_to_PDF(images_filepath, PDF_filepath) # convert images to PDF
except KFSmedia.ConversionError as e:
self._increment_fails(e.args[0]) # increment fails, may trigger giving up
self._increment_fails(e.args[0]) # increment fails, may trigger giving up
continue
else: # if conversion successful:
self.PDF_filepath=PDF_filepath # save PDF filepath
break # break out
else: # if giving up:
else: # if conversion successful:
self.PDF_filepath=PDF_filepath # save PDF filepath
break # break out
else: # if giving up:
logging.error(f"Tried to download and convert hentai \"{self}\" several times, but failed. Giving up.")
raise KFSmedia.DownloadError(f"Error in {self.download.__name__}{inspect.signature(self.download)}: Tried to download and convert hentai \"{self}\" several times, but failed. Giving up.")

Expand All @@ -187,4 +191,4 @@ def download(self) -> None:
except PermissionError: # may fail if another process is still using directory like dropbox
pass # don't warn because will be retried in main

return
return PDF
2 changes: 1 addition & 1 deletion src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def main():
headers=json.loads(KFSconfig.load_config("headers.json", HEADERS_DEFAULT)) # load headers to bypass bot protection
except FileNotFoundError:
return
hentai_ID_list=get_hentai_ID_list() # get desired hentai ID
hentai_ID_list=get_hentai_ID_list() # get desired hentai ID


for i, hentai_ID in enumerate(hentai_ID_list): # work through all desired hentai
Expand Down
Loading

0 comments on commit 1b55f5e

Please sign in to comment.