include README.md
include requirements.txt
-include nhentai/viewer/index.html
-include nhentai/viewer/styles.css
-include nhentai/viewer/scripts.js
-include nhentai/viewer/main.html
-include nhentai/viewer/main.css
-include nhentai/viewer/main.js
-include nhentai/viewer/logo.png
+include nhentai/viewer/*
+include nhentai/viewer/default/*
\ No newline at end of file
-__version__ = '0.4.6'
+__version__ = '0.4.7'
__author__ = 'RicterZ'
__email__ = 'ricterzheng@gmail.com'
default=False, help='save downloaded doujinshis, whose will be skipped if you re-download them')
parser.add_option('--clean-download-history', action='store_true', default=False, dest='clean_download_history',
help='clean download history')
+ parser.add_option('--template', dest='viewer_template', action='store',
+ help='set viewer template', default='')
try:
sys.argv = [unicode(i.decode(sys.stdin.encoding)) for i in sys.argv]
logger.info('Proxy now set to \'{0}\'.'.format(args.proxy))
write_config()
exit(0)
+
+ if args.viewer_template:
+ if not args.viewer_template:
+ args.viewer_template = 'default'
+
+ if not os.path.exists(os.path.join(os.path.dirname(__file__),
+ 'viewer/{}/index.html'.format(args.viewer_template))):
+ logger.error('Template \'{}\' does not exists'.format(args.viewer_template))
+ exit(1)
+ else:
+ constant.CONFIG['template'] = args.viewer_template
+ write_config()
+
# --- end set config ---
if args.favorites:
from nhentai.doujinshi import Doujinshi
from nhentai.downloader import Downloader
from nhentai.logger import logger
-from nhentai.constant import NHENTAI_CONFIG_FILE, BASE_URL
+from nhentai.constant import BASE_URL
from nhentai.utils import generate_html, generate_cbz, generate_main_html, generate_pdf, \
paging, check_cookie, signal_handler, DB
logger.info('Using mirror: {0}'.format(BASE_URL))
# CONFIG['proxy'] will be changed after cmd_parser()
- if constant.CONFIG['proxy']:
- logger.info('Using proxy: {0}'.format(constant.CONFIG['proxy']))
+ if constant.CONFIG['proxy']['http']:
+ logger.info('Using proxy: {0}'.format(constant.CONFIG['proxy']['http']))
+
+ if constant.CONFIG['template']:
+ logger.info('Using viewer template "{}"'.format(constant.CONFIG['template']))
# check your cookie
check_cookie()
db.add_one(doujinshi.id)
if not options.is_nohtml and not options.is_cbz and not options.is_pdf:
- generate_html(options.output_dir, doujinshi)
+ generate_html(options.output_dir, doujinshi, template=constant.CONFIG['template'])
elif options.is_cbz:
generate_cbz(options.output_dir, doujinshi, options.rm_origin_dir)
elif options.is_pdf:
'proxy': {},
'cookie': '',
'language': '',
+ 'template': '',
}
return file.read()
-def generate_html(output_dir='.', doujinshi_obj=None):
+def generate_html(output_dir='.', doujinshi_obj=None, template='default'):
image_html = ''
if doujinshi_obj is not None:
image_html += '<img src="{0}" class="image-item"/>\n'\
.format(image)
- html = readfile('viewer/index.html')
- css = readfile('viewer/styles.css')
- js = readfile('viewer/scripts.js')
+ html = readfile('viewer/{}/index.html'.format(template))
+ css = readfile('viewer/{}/styles.css'.format(template))
+ js = readfile('viewer/{}/scripts.js'.format(template))
if doujinshi_obj is not None:
serialize_json(doujinshi_obj, doujinshi_dir)
--- /dev/null
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+ <meta charset="UTF-8">\r
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover" />\r
+ <title>{TITLE}</title>\r
+ <style>\r
+{STYLES}\r
+ </style>\r
+</head>\r
+<body>\r
+\r
+<nav id="list">\r
+{IMAGES}</nav>\r
+\r
+<div id="image-container">\r
+ <span id="page-num"></span>\r
+ <div id="dest"></div>\r
+</div>\r
+\r
+<script>\r
+{SCRIPTS}\r
+</script>\r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+const pages = Array.from(document.querySelectorAll('img.image-item'));
+let currentPage = 0;
+
+function changePage(pageNum) {
+ const previous = pages[currentPage];
+ const current = pages[pageNum];
+
+ if (current == null) {
+ return;
+ }
+
+ previous.classList.remove('current');
+ current.classList.add('current');
+
+ currentPage = pageNum;
+
+ const display = document.getElementById('dest');
+ display.style.backgroundImage = `url("${current.src}")`;
+
+ scroll(0,0)
+
+ document.getElementById('page-num')
+ .innerText = [
+ (pageNum + 1).toLocaleString(),
+ pages.length.toLocaleString()
+ ].join('\u200a/\u200a');
+}
+
+changePage(0);
+
+document.getElementById('list').onclick = event => {
+ if (pages.includes(event.target)) {
+ changePage(pages.indexOf(event.target));
+ }
+};
+
+document.getElementById('image-container').onclick = event => {
+ const width = document.getElementById('image-container').clientWidth;
+ const clickPos = event.clientX / width;
+
+ if (clickPos < 0.5) {
+ changePage(currentPage - 1);
+ } else {
+ changePage(currentPage + 1);
+ }
+};
+
+document.onkeypress = event => {
+ switch (event.key.toLowerCase()) {
+ // Previous Image
+ case 'w':
+ scrollBy(0, -40);
+ break;
+ case 'a':
+ changePage(currentPage - 1);
+ break;
+ // Return to previous page
+ case 'q':
+ window.history.go(-1);
+ break;
+ // Next Image
+ case ' ':
+ case 's':
+ scrollBy(0, 40);
+ break;
+ case 'd':
+ changePage(currentPage + 1);
+ break;
+ }// remove arrow cause it won't work
+};
+
+document.onkeydown = event =>{
+ switch (event.keyCode) {
+ case 37: //left
+ changePage(currentPage - 1);
+ break;
+ case 38: //up
+ break;
+ case 39: //right
+ changePage(currentPage + 1);
+ break;
+ case 40: //down
+ break;
+ }
+};
\ No newline at end of file
--- /dev/null
+
+*, *::after, *::before {
+ box-sizing: border-box;
+}
+
+img {
+ vertical-align: middle;
+}
+
+html, body {
+ display: flex;
+ background-color: #e8e6e6;
+ height: 100%;
+ width: 100%;
+ padding: 0;
+ margin: 0;
+ font-family: sans-serif;
+}
+
+#list {
+ height: 2000px;
+ overflow: scroll;
+ width: 260px;
+ text-align: center;
+}
+
+#list img {
+ width: 200px;
+ padding: 10px;
+ border-radius: 10px;
+ margin: 15px 0;
+ cursor: pointer;
+}
+
+#list img.current {
+ background: #0003;
+}
+
+#image-container {
+ flex: auto;
+ height: 2000px;
+ background: #222;
+ color: #fff;
+ text-align: center;
+ cursor: pointer;
+ -webkit-user-select: none;
+ user-select: none;
+ position: relative;
+}
+
+#image-container #dest {
+ height: 2000px;
+ width: 100%;
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-position: top;
+}
+
+#image-container #page-num {
+ position: static;
+ font-size: 14pt;
+ left: 10px;
+ bottom: 5px;
+ font-weight: bold;
+ opacity: 0.75;
+ text-shadow: /* Duplicate the same shadow to make it very strong */
+ 0 0 2px #222,
+ 0 0 2px #222,
+ 0 0 2px #222;
+}
\ No newline at end of file
+++ /dev/null
-<!DOCTYPE html>\r
-<html>\r
-<head>\r
- <meta charset="UTF-8">\r
- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover" />\r
- <title>{TITLE}</title>\r
- <style>\r
-{STYLES}\r
- </style>\r
-</head>\r
-<body>\r
-\r
-<nav id="list">\r
-{IMAGES}</nav>\r
-\r
-<div id="image-container">\r
- <span id="page-num"></span>\r
- <div id="dest"></div>\r
-</div>\r
-\r
-<script>\r
-{SCRIPTS}\r
-</script>\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-const pages = Array.from(document.querySelectorAll('img.image-item'));
-let currentPage = 0;
-
-function changePage(pageNum) {
- const previous = pages[currentPage];
- const current = pages[pageNum];
-
- if (current == null) {
- return;
- }
-
- previous.classList.remove('current');
- current.classList.add('current');
-
- currentPage = pageNum;
-
- const display = document.getElementById('dest');
- display.style.backgroundImage = `url("${current.src}")`;
-
- scroll(0,0)
-
- document.getElementById('page-num')
- .innerText = [
- (pageNum + 1).toLocaleString(),
- pages.length.toLocaleString()
- ].join('\u200a/\u200a');
-}
-
-changePage(0);
-
-document.getElementById('list').onclick = event => {
- if (pages.includes(event.target)) {
- changePage(pages.indexOf(event.target));
- }
-};
-
-document.getElementById('image-container').onclick = event => {
- const width = document.getElementById('image-container').clientWidth;
- const clickPos = event.clientX / width;
-
- if (clickPos < 0.5) {
- changePage(currentPage - 1);
- } else {
- changePage(currentPage + 1);
- }
-};
-
-document.onkeypress = event => {
- switch (event.key.toLowerCase()) {
- // Previous Image
- case 'w':
- scrollBy(0, -40);
- break;
- case 'a':
- changePage(currentPage - 1);
- break;
- // Return to previous page
- case 'q':
- window.history.go(-1);
- break;
- // Next Image
- case ' ':
- case 's':
- scrollBy(0, 40);
- break;
- case 'd':
- changePage(currentPage + 1);
- break;
- }// remove arrow cause it won't work
-};
-
-document.onkeydown = event =>{
- switch (event.keyCode) {
- case 37: //left
- changePage(currentPage - 1);
- break;
- case 38: //up
- break;
- case 39: //right
- changePage(currentPage + 1);
- break;
- case 40: //down
- break;
- }
-};
\ No newline at end of file
+++ /dev/null
-
-*, *::after, *::before {
- box-sizing: border-box;
-}
-
-img {
- vertical-align: middle;
-}
-
-html, body {
- display: flex;
- background-color: #e8e6e6;
- height: 100%;
- width: 100%;
- padding: 0;
- margin: 0;
- font-family: sans-serif;
-}
-
-#list {
- height: 2000px;
- overflow: scroll;
- width: 260px;
- text-align: center;
-}
-
-#list img {
- width: 200px;
- padding: 10px;
- border-radius: 10px;
- margin: 15px 0;
- cursor: pointer;
-}
-
-#list img.current {
- background: #0003;
-}
-
-#image-container {
- flex: auto;
- height: 2000px;
- background: #222;
- color: #fff;
- text-align: center;
- cursor: pointer;
- -webkit-user-select: none;
- user-select: none;
- position: relative;
-}
-
-#image-container #dest {
- height: 2000px;
- width: 100%;
- background-size: contain;
- background-repeat: no-repeat;
- background-position: top;
-}
-
-#image-container #page-num {
- position: static;
- font-size: 14pt;
- left: 10px;
- bottom: 5px;
- font-weight: bold;
- opacity: 0.75;
- text-shadow: /* Duplicate the same shadow to make it very strong */
- 0 0 2px #222,
- 0 0 2px #222,
- 0 0 2px #222;
-}
\ No newline at end of file