mirror of
https://github.com/RicterZ/nhentai.git
synced 2026-04-08 18:50:21 +02:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51fd1f964c | ||
|
|
ec95818382 | ||
|
|
b28dbc6d86 | ||
|
|
1131df0b94 | ||
|
|
f2abc7b79f | ||
|
|
ed7361a777 |
@@ -1,9 +1,16 @@
|
|||||||
FROM python:3
|
FROM python:3-slim
|
||||||
|
|
||||||
WORKDIR /usr/src/doujinshi-dl
|
WORKDIR /usr/src/doujinshi-dl
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
# Install the base package
|
||||||
RUN pip install --no-cache-dir .
|
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
|
WORKDIR /output
|
||||||
ENTRYPOINT ["doujinshi-dl"]
|
ENTRYPOINT ["doujinshi-dl"]
|
||||||
|
|||||||
35
README.rst
35
README.rst
@@ -52,26 +52,11 @@ For a self-contained installation, use `pipx <https://github.com/pipxproject/pip
|
|||||||
=====
|
=====
|
||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
**⚠️IMPORTANT⚠️**: To bypass Cloudflare, you should use ``--cookie`` and ``--useragent`` options to store your cookie and user-agent.
|
**⚠️IMPORTANT⚠️**: Authentication is required. Get your API token from your account settings page and save it:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
doujinshi-dl --useragent "USER AGENT of YOUR BROWSER"
|
doujinshi-dl --token "YOUR_API_TOKEN"
|
||||||
doujinshi-dl --cookie "YOUR COOKIE"
|
|
||||||
|
|
||||||
**NOTE:**
|
|
||||||
|
|
||||||
- The format of the cookie is ``"csrftoken=TOKEN; sessionid=ID; cf_clearance=CLOUDFLARE"``
|
|
||||||
- ``cf_clearance`` cookie and useragent must be set if you encounter "blocked by cloudflare captcha" error. Make sure you use the same IP and useragent as when you got it
|
|
||||||
|
|
||||||
| To get csrftoken and sessionid, first login to your account in a web browser, then:
|
|
||||||
| (Chrome) |ve| |ld| More tools |ld| Developer tools |ld| Application |ld| Storage |ld| Cookies |ld| your mirror URL
|
|
||||||
| (Firefox) |hv| |ld| Web Developer |ld| Web Developer Tools |ld| Storage |ld| Cookies |ld| your mirror URL
|
|
||||||
|
|
|
||||||
|
|
||||||
.. |hv| unicode:: U+2630 .. https://www.compart.com/en/unicode/U+2630
|
|
||||||
.. |ve| unicode:: U+22EE .. https://www.compart.com/en/unicode/U+22EE
|
|
||||||
.. |ld| unicode:: U+2014 .. https://www.compart.com/en/unicode/U+2014
|
|
||||||
|
|
||||||
*The default download folder will be the path where you run the command (%cd% or $PWD).*
|
*The default download folder will be the path where you run the command (%cd% or $PWD).*
|
||||||
|
|
||||||
@@ -185,9 +170,7 @@ Other options:
|
|||||||
folder when generated CBZ or PDF file
|
folder when generated CBZ or PDF file
|
||||||
--regenerate regenerate the cbz or pdf file if exists
|
--regenerate regenerate the cbz or pdf file if exists
|
||||||
--zip package into a single zip file
|
--zip package into a single zip file
|
||||||
--cookie COOKIE set cookie to bypass Cloudflare captcha
|
--token TOKEN set API token for authentication
|
||||||
--useragent, --user-agent USERAGENT
|
|
||||||
set useragent to bypass Cloudflare captcha
|
|
||||||
--language LANGUAGE set default language to parse doujinshis
|
--language LANGUAGE set default language to parse doujinshis
|
||||||
--clean-language set DEFAULT as language to parse doujinshis
|
--clean-language set DEFAULT as language to parse doujinshis
|
||||||
--save-download-history
|
--save-download-history
|
||||||
@@ -197,7 +180,6 @@ Other options:
|
|||||||
clean download history
|
clean download history
|
||||||
--template VIEWER_TEMPLATE
|
--template VIEWER_TEMPLATE
|
||||||
set viewer template
|
set viewer template
|
||||||
--legacy use legacy searching method
|
|
||||||
|
|
||||||
======
|
======
|
||||||
Mirror
|
Mirror
|
||||||
@@ -208,17 +190,6 @@ To use a mirror, set the ``DOUJINSHI_DL_URL`` environment variable to your mirro
|
|||||||
|
|
||||||
DOUJINSHI_DL_URL=https://your-mirror.example.com doujinshi-dl --id 123456
|
DOUJINSHI_DL_URL=https://your-mirror.example.com doujinshi-dl --id 123456
|
||||||
|
|
||||||
.. image:: https://github.com/RicterZ/doujinshi-dl/raw/master/images/search.png
|
|
||||||
:alt: search
|
|
||||||
:align: center
|
|
||||||
.. image:: https://github.com/RicterZ/doujinshi-dl/raw/master/images/download.png
|
|
||||||
:alt: download
|
|
||||||
:align: center
|
|
||||||
.. image:: https://github.com/RicterZ/doujinshi-dl/raw/master/images/viewer.png
|
|
||||||
:alt: viewer
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
|
|
||||||
.. |license| image:: https://img.shields.io/github/license/ricterz/nhentai.svg
|
.. |license| image:: https://img.shields.io/github/license/ricterz/nhentai.svg
|
||||||
:target: https://github.com/RicterZ/nhentai/blob/master/LICENSE
|
:target: https://github.com/RicterZ/nhentai/blob/master/LICENSE
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
__version__ = '2.0.5'
|
__version__ = '2.0.8'
|
||||||
__author__ = 'RicterZ'
|
__author__ = 'RicterZ'
|
||||||
__email__ = 'ricterzheng@gmail.com'
|
__email__ = 'ricterzheng@gmail.com'
|
||||||
|
|||||||
@@ -162,10 +162,8 @@ def cmd_parser():
|
|||||||
parser.add_argument('--zip', action='store_true', help='Package into a single zip file')
|
parser.add_argument('--zip', action='store_true', help='Package into a single zip file')
|
||||||
|
|
||||||
# site options
|
# site options
|
||||||
parser.add_argument('--cookie', type=str, dest='cookie',
|
parser.add_argument('--token', type=str, dest='token',
|
||||||
help='set cookie to bypass Cloudflare captcha')
|
help='set API token for authentication')
|
||||||
parser.add_argument('--useragent', '--user-agent', type=str, dest='useragent',
|
|
||||||
help='set useragent to bypass Cloudflare captcha')
|
|
||||||
parser.add_argument('--language', type=str, dest='language',
|
parser.add_argument('--language', type=str, dest='language',
|
||||||
help='set default language to parse doujinshis')
|
help='set default language to parse doujinshis')
|
||||||
parser.add_argument('--clean-language', dest='clean_language', action='store_true', default=False,
|
parser.add_argument('--clean-language', dest='clean_language', action='store_true', default=False,
|
||||||
@@ -176,8 +174,7 @@ def cmd_parser():
|
|||||||
help='clean download history')
|
help='clean download history')
|
||||||
parser.add_argument('--template', dest='viewer_template', type=str, default='',
|
parser.add_argument('--template', dest='viewer_template', type=str, default='',
|
||||||
help='set viewer template')
|
help='set viewer template')
|
||||||
parser.add_argument('--legacy', dest='legacy', action='store_true', default=False,
|
|
||||||
help='use legacy searching method')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -216,15 +213,10 @@ def cmd_parser():
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# --- set config ---
|
# --- set config ---
|
||||||
if args.cookie is not None:
|
if args.token is not None:
|
||||||
c.CONFIG['cookie'] = args.cookie.strip()
|
c.CONFIG['token'] = args.token.strip()
|
||||||
write_config()
|
write_config()
|
||||||
logger.info('Cookie saved.')
|
logger.info('Token saved.')
|
||||||
|
|
||||||
if args.useragent is not None:
|
|
||||||
c.CONFIG['useragent'] = args.useragent.strip()
|
|
||||||
write_config()
|
|
||||||
logger.info('User-Agent saved.')
|
|
||||||
|
|
||||||
if args.language is not None:
|
if args.language is not None:
|
||||||
c.CONFIG['language'] = args.language
|
c.CONFIG['language'] = args.language
|
||||||
@@ -232,7 +224,7 @@ def cmd_parser():
|
|||||||
logger.info(f'Default language now set to "{args.language}"')
|
logger.info(f'Default language now set to "{args.language}"')
|
||||||
# TODO: search without language
|
# TODO: search without language
|
||||||
|
|
||||||
if any([args.cookie, args.useragent, args.language]):
|
if any([args.token, args.language]):
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if args.proxy is not None:
|
if args.proxy is not None:
|
||||||
@@ -262,8 +254,8 @@ def cmd_parser():
|
|||||||
# --- end set config ---
|
# --- end set config ---
|
||||||
|
|
||||||
if args.favorites:
|
if args.favorites:
|
||||||
if not c.CONFIG['cookie']:
|
if not c.CONFIG.get('cookie') and not c.CONFIG.get('token'):
|
||||||
logger.warning('Cookie has not been set, please use `doujinshi-dl --cookie \'COOKIE\'` to set it.')
|
logger.warning('Token has not been set, please use `doujinshi-dl --token \'TOKEN\'` to set it.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if args.file:
|
if args.file:
|
||||||
|
|||||||
@@ -82,17 +82,15 @@ def main():
|
|||||||
options.keyword,
|
options.keyword,
|
||||||
sorting=options.sorting,
|
sorting=options.sorting,
|
||||||
page=page_list,
|
page=page_list,
|
||||||
legacy=options.legacy,
|
|
||||||
is_page_all=options.page_all,
|
is_page_all=options.page_all,
|
||||||
)
|
)
|
||||||
|
|
||||||
elif options.artist:
|
elif options.artist:
|
||||||
doujinshis = parser.search(
|
doujinshis = parser.search(
|
||||||
options.artist,
|
f'artist:{options.artist}',
|
||||||
sorting=options.sorting,
|
sorting=options.sorting,
|
||||||
page=page_list,
|
page=page_list,
|
||||||
is_page_all=options.page_all,
|
is_page_all=options.page_all,
|
||||||
type_='ARTIST',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
elif not doujinshi_ids:
|
elif not doujinshi_ids:
|
||||||
@@ -131,7 +129,8 @@ def main():
|
|||||||
doujinshi = doujinshi_model.doujinshi
|
doujinshi = doujinshi_model.doujinshi
|
||||||
doujinshi.downloader = downloader
|
doujinshi.downloader = downloader
|
||||||
|
|
||||||
if doujinshi.check_if_need_download(options):
|
need_download = doujinshi.check_if_need_download(options)
|
||||||
|
if need_download:
|
||||||
doujinshi.download()
|
doujinshi.download()
|
||||||
else:
|
else:
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -140,14 +139,20 @@ def main():
|
|||||||
|
|
||||||
doujinshi_dir = os.path.join(options.output_dir, doujinshi.filename)
|
doujinshi_dir = os.path.join(options.output_dir, doujinshi.filename)
|
||||||
|
|
||||||
if options.generate_metadata:
|
# If skipped (CBZ/PDF already exists), treat as already downloaded:
|
||||||
serializer.write_all(meta, doujinshi_dir)
|
# - skip all post-processing that requires doujinshi_dir to exist
|
||||||
logger.log(16, f'Metadata files have been written to "{doujinshi_dir}"')
|
# - but still write to history DB in case the record was lost
|
||||||
|
|
||||||
if options.is_save_download_history:
|
if options.is_save_download_history:
|
||||||
with DB() as db:
|
with DB() as db:
|
||||||
db.add_one(doujinshi.id)
|
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:
|
if not options.is_nohtml:
|
||||||
generate_html(options.output_dir, doujinshi, template=template)
|
generate_html(options.output_dir, doujinshi, template=template)
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 991 KiB |
BIN
images/usage.png
BIN
images/usage.png
Binary file not shown.
|
Before Width: | Height: | Size: 679 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 MiB |
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "doujinshi-dl"
|
name = "doujinshi-dl"
|
||||||
version = "2.0.5"
|
version = "2.0.8"
|
||||||
description = "doujinshi downloader"
|
description = "doujinshi downloader"
|
||||||
authors = ["Ricter Z <ricterzheng@gmail.com>"]
|
authors = ["Ricter Z <ricterzheng@gmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
Reference in New Issue
Block a user