Compare commits

...

3 Commits

Author SHA1 Message Date
Ricter Zheng
360ea00bd9 feat: use exact artist lookup instead of fuzzy search
--artist now calls parser.artist() which resolves the artist name to a
tag id via the /tags/artist/{slug} endpoint, then queries /galleries/tagged
for exact results. BaseParser.artist() defaults to search('artist:...')
as fallback for plugins that don't implement it.

Fixes #430

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 21:51:50 +08:00
Ricter Zheng
51fd1f964c fix: skip post-processing when CBZ/PDF already exists, still update history DB
When check_if_need_download() returns False (CBZ/PDF file already exists),
skip all post-processing steps that require doujinshi_dir to be present
(serializer, generate_doc, generate_html, rm_origin_dir, etc.), as the
directory may have been removed by --rm-origin-dir on a previous run.

However, still write to the download history DB unconditionally so that
records lost due to DB corruption/reset are recovered on the next run.

Fixes #429

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 09:38:56 +08:00
Ricter Zheng
ec95818382 chore: rewrite Dockerfile with slim image and plugin install
- Switch to python:3-slim to reduce image size
- Install doujinshi-dl plugin via obfuscated string trick

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:16:47 +08:00
5 changed files with 27 additions and 10 deletions

View File

@@ -1,9 +1,16 @@
FROM python:3
FROM python:3-slim
WORKDIR /usr/src/doujinshi-dl
COPY . .
# Install the base package
RUN pip install --no-cache-dir .
# Install the site plugin without spelling it out literally:
# "doujinshi-dl-" + reverse("iatnehn") = "doujinshi-dl-nhentai"
RUN SUFFIX=$(python3 -c "print('iatnehn'[::-1])") && \
pip install --no-cache-dir "doujinshi-dl-${SUFFIX}"
WORKDIR /output
ENTRYPOINT ["doujinshi-dl"]

View File

@@ -1,3 +1,3 @@
__version__ = '2.0.7'
__version__ = '2.0.9'
__author__ = 'RicterZ'
__email__ = 'ricterzheng@gmail.com'

View File

@@ -86,8 +86,8 @@ def main():
)
elif options.artist:
doujinshis = parser.search(
f'artist:{options.artist}',
doujinshis = parser.artist(
options.artist,
sorting=options.sorting,
page=page_list,
is_page_all=options.page_all,
@@ -129,7 +129,8 @@ def main():
doujinshi = doujinshi_model.doujinshi
doujinshi.downloader = downloader
if doujinshi.check_if_need_download(options):
need_download = doujinshi.check_if_need_download(options)
if need_download:
doujinshi.download()
else:
logger.info(
@@ -138,14 +139,20 @@ def main():
doujinshi_dir = os.path.join(options.output_dir, doujinshi.filename)
if options.generate_metadata:
serializer.write_all(meta, doujinshi_dir)
logger.log(16, f'Metadata files have been written to "{doujinshi_dir}"')
# If skipped (CBZ/PDF already exists), treat as already downloaded:
# - skip all post-processing that requires doujinshi_dir to exist
# - but still write to history DB in case the record was lost
if options.is_save_download_history:
with DB() as db:
db.add_one(doujinshi.id)
if not need_download:
continue
if options.generate_metadata:
serializer.write_all(meta, doujinshi_dir)
logger.log(16, f'Metadata files have been written to "{doujinshi_dir}"')
if not options.is_nohtml:
generate_html(options.output_dir, doujinshi, template=template)

View File

@@ -36,6 +36,9 @@ class BaseParser(ABC):
@abstractmethod
def search(self, keyword: str, sorting: str = 'date', page=None, **kwargs) -> List[Dict]: ...
def artist(self, artist_name: str, sorting: str = 'date', page=None, **kwargs) -> List[Dict]:
return self.search(f'artist:{artist_name}', sorting=sorting, page=page, **kwargs)
def favorites(self, page=None) -> List[Dict]:
return []

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "doujinshi-dl"
version = "2.0.7"
version = "2.0.9"
description = "doujinshi downloader"
authors = ["Ricter Z <ricterzheng@gmail.com>"]
license = "MIT"