main page filter(1/2)

This commit is contained in:
Alocks 2019-12-04 00:45:14 -03:00
parent 0abcb048b4
commit bd8bb42ecd
5 changed files with 347 additions and 65 deletions

View File

@ -1,24 +1,77 @@
# coding: utf-8 # coding: utf-8
import json
import os
def serialize(doujinshi, dir):
def serialize(doujinshi): metadata = {'title' : doujinshi.name,
metadata = {'Title' : doujinshi.name, 'subtitle' : doujinshi.info.subtitle}
'Subtitle' : doujinshi.info.subtitle}
if doujinshi.info.date: if doujinshi.info.date:
metadata['Upload_Date'] = doujinshi.info.date metadata['upload_date'] = doujinshi.info.date
if doujinshi.info.parodies: if doujinshi.info.parodies:
metadata['Parodies'] = [i.strip() for i in doujinshi.info.parodies.split(',')] metadata['parody'] = [i.strip() for i in doujinshi.info.parodies.split(',')]
if doujinshi.info.characters: if doujinshi.info.characters:
metadata['Characters'] = [i.strip() for i in doujinshi.info.characters.split(',')] metadata['character'] = [i.strip() for i in doujinshi.info.characters.split(',')]
if doujinshi.info.tags: if doujinshi.info.tags:
metadata['Tags'] = [i.strip() for i in doujinshi.info.tags.split(',')] metadata['tag'] = [i.strip() for i in doujinshi.info.tags.split(',')]
if doujinshi.info.artists: if doujinshi.info.artists:
metadata['Artists'] = [i.strip() for i in doujinshi.info.artists.split(',')] metadata['artist'] = [i.strip() for i in doujinshi.info.artists.split(',')]
if doujinshi.info.groups: if doujinshi.info.groups:
metadata['Groups'] = [i.strip() for i in doujinshi.info.groups.split(',')] metadata['group'] = [i.strip() for i in doujinshi.info.groups.split(',')]
if doujinshi.info.languages: if doujinshi.info.languages:
metadata['Languages'] = [i.strip() for i in doujinshi.info.languages.split(',')] metadata['language'] = [i.strip() for i in doujinshi.info.languages.split(',')]
metadata['Categories'] = doujinshi.info.categories metadata['category'] = doujinshi.info.categories
metadata['URL'] = doujinshi.url metadata['URL'] = doujinshi.url
metadata['Pages'] = doujinshi.pages metadata['Pages'] = doujinshi.pages
return metadata with open(os.path.join(dir, 'metadata.json'), 'w') as f:
json.dump(metadata, f, separators=','':')
def merge_json():
lst = []
output_dir = "./"
os.chdir(output_dir)
doujinshi_dirs = next(os.walk('.'))[1]
for folder in doujinshi_dirs:
folder_json = ',"Folder":"' + folder + '"}'
files = os.listdir(folder)
if 'metadata.json' not in files:
continue
data_folder = output_dir + folder + '/' + 'metadata.json'
json_file = open(data_folder, encoding='raw_unicode_escape').read()[:-2]+folder_json
lst.append(json.loads(json_file.encode('raw_unicode_escape').decode()))
return lst
def serialize_unique(lst):
dictionary = {}
parody = []
character = []
tag = []
artist = []
group = []
for dic in lst:
if dic['parody']:
parody.extend([i for i in dic['parody']])
if dic['character']:
character.extend([i for i in dic['character']])
if dic['tag']:
tag.extend([i for i in dic['tag']])
if dic['artist']:
artist.extend([i for i in dic['artist']])
if dic['group']:
group.extend([i for i in dic['group']])
dictionary['parody'] = list(set(parody))
dictionary['character'] = list(set(character))
dictionary['tag'] = list(set(tag))
dictionary['artist'] = list(set(artist))
dictionary['group'] = list(set(group))
return dictionary
def set_js_database():
with open('data.js', 'w') as f:
indexed_json = merge_json()
unique_json = json.dumps(serialize_unique(indexed_json), separators=','':')
indexed_json = json.dumps(indexed_json, separators=','':')
f.write('var data = '+indexed_json)
f.write(';\nvar tags = '+unique_json)

View File

@ -4,7 +4,6 @@ from __future__ import unicode_literals, print_function
import sys import sys
import re import re
import os import os
import json
import string import string
import zipfile import zipfile
import shutil import shutil
@ -12,7 +11,7 @@ import requests
from nhentai import constant from nhentai import constant
from nhentai.logger import logger from nhentai.logger import logger
from nhentai.serializer import serialize from nhentai.serializer import serialize, set_js_database
def request(method, url, **kwargs): def request(method, url, **kwargs):
@ -81,22 +80,19 @@ def generate_html(output_dir='.', doujinshi_obj=None):
image_html += '<img src="{0}" class="image-item"/>\n'\ image_html += '<img src="{0}" class="image-item"/>\n'\
.format(image) .format(image)
html = readfile('viewer/index.html') html = readfile('viewer/index.html')
css = readfile('viewer/styles.css') css = readfile('viewer/styles.css')
js = readfile('viewer/scripts.js') js = readfile('viewer/scripts.js')
if doujinshi_obj is not None: if doujinshi_obj is not None:
metadata = serialize(doujinshi_obj) serialize(doujinshi_obj, doujinshi_dir)
name = doujinshi_obj.name
if sys.version_info < (3, 0): if sys.version_info < (3, 0):
metadata['Title'] = doujinshi_obj.name.encode('utf-8') name = doujinshi_obj.name.encode('utf-8')
metadata['Subtitle'] = doujinshi_obj.info.subtitle.encode('utf-8')
with open(os.path.join(doujinshi_dir, 'metadata.json'), 'w') as f:
json.dump(metadata, f, separators=','':')
else: else:
metadata = {'Title': 'nHentai HTML Viewer'} name = {'title': 'nHentai HTML Viewer'}
data = html.format(TITLE=metadata['Title'], IMAGES=image_html, SCRIPTS=js, STYLES=css) data = html.format(TITLE=name, IMAGES=image_html, SCRIPTS=js, STYLES=css)
try: try:
if sys.version_info < (3, 0): if sys.version_info < (3, 0):
with open(os.path.join(doujinshi_dir, 'index.html'), 'w') as f: with open(os.path.join(doujinshi_dir, 'index.html'), 'w') as f:
@ -118,6 +114,7 @@ def generate_main_html(output_dir='./'):
""" """
image_html = '' image_html = ''
main = readfile('viewer/main.html') main = readfile('viewer/main.html')
css = readfile('viewer/main.css') css = readfile('viewer/main.css')
js = readfile('viewer/main.js') js = readfile('viewer/main.js')
@ -134,11 +131,8 @@ def generate_main_html(output_dir='./'):
os.chdir(output_dir) os.chdir(output_dir)
doujinshi_dirs = next(os.walk('.'))[1] doujinshi_dirs = next(os.walk('.'))[1]
database = open('data.js', 'w')
database.write("var data = JSON.parse('[")
for folder in doujinshi_dirs: for folder in doujinshi_dirs:
folder_json = ',"Folder":"'+folder+'"}'
files = os.listdir(folder) files = os.listdir(folder)
files.sort() files.sort()
@ -147,11 +141,6 @@ def generate_main_html(output_dir='./'):
else: else:
continue continue
database.write(open(output_dir + folder + '/' + files[-1], 'r').read()[:-2]+folder_json)
if folder != doujinshi_dirs[-1]:
database.write(",'+\n'")
else:
database.write("]')")
image = files[0] # 001.jpg or 001.png image = files[0] # 001.jpg or 001.png
if folder is not None: if folder is not None:
title = folder.replace('_', ' ') title = folder.replace('_', ' ')
@ -159,8 +148,6 @@ def generate_main_html(output_dir='./'):
title = 'nHentai HTML Viewer' title = 'nHentai HTML Viewer'
image_html += element.format(FOLDER=folder, IMAGE=image, TITLE=title) image_html += element.format(FOLDER=folder, IMAGE=image, TITLE=title)
database.close()
if image_html == '': if image_html == '':
logger.warning('None index.html found, --gen-main paused.') logger.warning('None index.html found, --gen-main paused.')
return return
@ -172,6 +159,8 @@ def generate_main_html(output_dir='./'):
else: else:
with open('./main.html', 'wb') as f: with open('./main.html', 'wb') as f:
f.write(data.encode('utf-8')) f.write(data.encode('utf-8'))
shutil.copy(os.path.dirname(__file__)+'/viewer/logo.png', './')
set_js_database()
logger.log( logger.log(
15, 'Main Viewer has been write to \'{0}main.html\''.format(output_dir)) 15, 'Main Viewer has been write to \'{0}main.html\''.format(output_dir))
except Exception as e: except Exception as e:
@ -225,5 +214,3 @@ an invalid filename.
def signal_handler(signal, frame): def signal_handler(signal, frame):
logger.error('Ctrl-C signal received. Stopping...') logger.error('Ctrl-C signal received. Stopping...')
exit(1) exit(1)

View File

@ -1,7 +1,6 @@
/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
/* Original from https://static.nhentai.net/css/main_style.9bb9b703e601.css */ /* Original from https://static.nhentai.net/css/main_style.9bb9b703e601.css */
html { html {
font-family: sans-serif;
line-height: 1.15; line-height: 1.15;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100% -webkit-text-size-adjust: 100%
@ -21,10 +20,6 @@ a {
-webkit-text-decoration-skip: objects -webkit-text-decoration-skip: objects
} }
a:active,a:hover {
outline-width: 0
}
abbr[title] { abbr[title] {
border-bottom: none; border-bottom: none;
text-decoration: underline; text-decoration: underline;
@ -104,11 +99,6 @@ a {
color: #34495e color: #34495e
} }
a:hover {
text-decoration: none;
color: #ed2553
}
a.count { a.count {
color: #999 color: #999
} }
@ -130,15 +120,15 @@ blockquote {
.container { .container {
display: block; display: block;
clear: both; clear: both;
margin-left: 200px; margin-left: 15rem;
margin-right: auto; margin-right: 0.5rem;
margin-bottom: 10px; margin-bottom: 5px;
margin-top: 10px; margin-top: 5px;
padding: 10px; padding: 4px;
border-radius: 9px; border-radius: 9px;
background-color: #ecf0f1; background-color: #ecf0f1;
width: 100% - 200px; width: 100% - 15rem;
max-width: 1200px max-width: 1500px
} }
.gallery,.gallery-favorite,.thumb-container { .gallery,.gallery-favorite,.thumb-container {
@ -156,7 +146,6 @@ blockquote {
.gallery,.gallery-favorite,.thumb-container { .gallery,.gallery-favorite,.thumb-container {
width:19%; width:19%;
margin: 3px; margin: 3px;
margin-bottom: 8px
} }
} }
@ -224,31 +213,202 @@ blockquote {
.sidenav { .sidenav {
height: 100%; height: 100%;
width: 200px; width: 15rem;
position: absolute; position: fixed;
z-index: 1; z-index: 1;
top: 0; top: 0;
left: 0; left: 0;
background-color: #111; background-color: #0d0d0d;
overflow-x: hidden; overflow: hidden;
padding-top: 20px; padding-top: 20px;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
ms-user-select: none; /* Internet Explorer/Edge */
user-select: none;
} }
.sidenav a { .sidenav a {
padding: 6px 6px 6px 32px; background-color: #eee;
padding: 5px 0px 5px 15px;
text-decoration: none; text-decoration: none;
font-size: 25px; font-size: 15px;
color: #818181; color: #0d0d0d9;
display: block; display: block;
text-align: left;
}
.sidenav img {
width:100%;
padding: 0px 5px 0px 5px;
}
.sidenav h1 {
font-size: 1.5em;
margin: 0px 0px 10px;
} }
.sidenav a:hover { .sidenav a:hover {
color: #f1f1f1; color: white;
background-color: #EC2754;
} }
@media screen and (max-height: 450px) { @media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;} .sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;} .sidenav a {font-size: 15px;}
}
.accordion {
font-weight: bold;
background-color: #eee;
color: #444;
padding: 10px 0px 5px 8px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
cursor:pointer;
}
.accordion:hover {
background-color: #ddd;
}
.accordion.active{
background-color:#ddd;
}
.nav-btn {
font-weight: bold;
background-color: #eee;
color: #444;
padding: 10px 0px 5px 8px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.nav-btn.hidden {
display:none
}
.options {
padding: 0px 0px 0px 0px;
background-color: #eee;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
cursor:pointer;
}
.search{background-color: #eee;
padding-right:45px;
white-space: nowrap;
padding-top: 5px
}
.search input{
border-top-right-radius:10px;
padding-top:0;
padding-bottom:0;
font-size:1em;
width:100%;
height:38px;
vertical-align:top;
}
.search .btn.btn-square{
border-top-left-radius:10px;
border-bottom-left-radius:0px;
}
.fa{
font:normal normal normal 14px/1 FontAwesome;
font-size:1.33333333em;
line-height:.75em;
}
.fa-search:before{
content:"\f002";
}
.btn{
font-weight:700;
padding-right:12px;
padding-left:12px;
color:#fff;
border:0;
font-size:100%;
height:38px;
line-height:40px;
outline: 0;
}
.btn.btn-primary{
background-color:#ed2553;
}
.btn.btn-primary:active,.btn.btn-primary:focus,.btn.btn-primary:hover{
color:#fff;background:#f15478;
}
#tags{
text-align:left;
display: block;
width:15rem;
display: flex;
flex-flow: row wrap;
justify-content: start;
margin: 2px 2px 2px 0px
}
.btn-2{
font-weight:700;
padding-right:10px;
padding-left:10px;
color:#fff;
border:0;
font-size:100%;
height:20px;
outline: 0;
border-radius: 3px;
cursor: pointer;
margin:2px;
}
.btn-2.parody{
background-color: red;
}
.btn-2.character{
background-color: blue;
}
.btn-2.tag{
background-color: green;
}
.btn-2.artist{
background-color: fuchsia;
}
.btn-2.group{
background-color: teal;
}
.btn-2.hover{
filter: saturate(20%)
}
input,input:focus{
border:none;
outline:0;
} }
html.theme-black,html.theme-black body { html.theme-black,html.theme-black body {
@ -281,4 +441,4 @@ html.theme-black code {
color: #ed2553; color: #ed2553;
border: none; border: none;
background-color: #292929 background-color: #292929
} }

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="theme-color" content="#1f1f1f" /> <meta name="theme-color" content="#1f1f1f" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover" />
<title>nHentai &raquo; Viewer</title> <title>nHentai Viewer</title>
<script type="text/javascript" src="data.js"></script> <script type="text/javascript" src="data.js"></script>
<!-- <link rel="stylesheet" href="./main.css"> --> <!-- <link rel="stylesheet" href="./main.css"> -->
<style> <style>
@ -15,7 +15,29 @@
<body> <body>
<div id="content"> <div id="content">
<nav class="sidenav">nHentai Viewer</nav> <nav class="sidenav">
<img src="logo.png">
<h1>nHentai Viewer</h1>
<button class="accordion">Language</button>
<div class="options" id="language">
<a>English</a>
<a>日本語</a>
<a>中国語</a>
</div>
<button class="accordion">Category</button>
<div class="options" id ="category">
<a>Doujinshi </a>
<a>Manga</a>
</div>
<button class="nav-btn hidden">Filters</button>
<div class="search">
<input type="search" name="q" value="" autocapitalize="none" required="">
<button type="submit" class="btn btn-primary btn-square">
<i class="fa fa-search"></i></button>
</div>
<div id="tags">
</div>
</nav>
<div class="container" id="favcontainer"> <div class="container" id="favcontainer">
{PICTURE} {PICTURE}

View File

@ -0,0 +1,60 @@
//------------------------------------navbar script------------------------------------
var menu = document.getElementsByClassName("accordion");
for (var i = 0; i < menu.length; i++) {
menu[i].addEventListener("click", function() {
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
this.classList.toggle("active");
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
this.classList.toggle("active");
}
});
}
var language = document.getElementById("language").children;
for (var i = 0; i < language.length; i++){
language[i].addEventListener("click", function() {
document.getElementById("language").style.maxHeight = null;
document.getElementsByClassName("accordion")[0].classList.toggle("active");
var toggler = document.getElementsByClassName("nav-btn")[0].classList;
if (toggler.contains("hidden")){
toggler.toggle("hidden");
}
});
}
var category = document.getElementById("category").children;
for (var i = 0; i < category.length; i++){
category[i].addEventListener("click", function() {
document.getElementById("category").style.maxHeight = null;
document.getElementsByClassName("accordion")[1].classList.toggle("active");
var toggler = document.getElementsByClassName("nav-btn")[0].classList;
if (toggler.contains("hidden")){
toggler.toggle("hidden");
}
});
}
//-----------------------------------------------------------------------------------
var tags = document.getElementById("tags");
for (i in data){
tag_maker(data[i])
}
function tag_maker(data){
var options = ["parody", "character", "tag", "artist", "group"];
for (i in options){
var i = options[i]
if (data[i] != null){
for (j in data[i]){
var node = document.createElement("button"); // Create a <li> node
var textnode = document.createTextNode(data[i][j]); // Create a text node
node.appendChild(textnode); // Append the text to <li>
node.classList.add("btn-2");
node.classList.add("parody");
document.getElementById(i).appendChild(node);
console.log("teste");
}
}
}
}