Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name nhentai
- // @namespace newsox
- // @include https://nhentai.*/g/*
- // @version 1
- // @grant none
- // ==/UserScript==
- (function(){
- //
- // Search on the local EveryThing
- //
- const search_prefix='es:';
- //
- // Search on the remote EveryThing HTTP server
- //
- // const search_prefix='http://user:password@192.168.1.8/?search=';
- const jdp="jdp";
- const jdl="jdl";
- const subfolder="subfolder=ON";
- const D=document;
- const E=(a,b=D)=>b.getElementById(a);
- const K=Object.keys;
- const S=(a,b=D)=>b.querySelector(a);
- const A=(a,b=D)=>b.querySelectorAll(a);
- const zeroPadding=(s,l)=>((s.length<l?'0'.repeat(l-s.length):'')+s);
- const stripTag = s=>s.replace(/<[^>]*>/g,'');
- const normalizeTitle=function(s)
- {
- const NT1 = {
- "!":"!","\"":"”","#":"#","$":"$","%":"%","&":"&","'":"’","~":"~","|":"|",
- "*":"*",":":":","<":"<",">":">","?":"?","/":"/","\\":"¥","`":"‘",",":",",
- " ":" ","〜":"~","♡":"","♥":"",
- "―":"-","─":"-","━":"-",
- '卷':'巻','學':'学','黑':'黒','關':'関','繪':'絵','會':'会','亞':'亜','髙':'高',
- '說':'説','说':'説' //繁体字、簡体字の"説"
- };
- const NT2={
- "×":"×","&":"&"," ":" ","%u2019;":"’"
- };
- if (!s) return s;
- const pat1 = new RegExp("["+K(NT1).join('')+"]","g");
- const pat2 = new RegExp("("+K(NT2).join('|')+")","g");
- if (String.prototype.normalize) s = s.normalize('NFKC');
- return( s
- // .replace(/\u309B/g,"\u3099")
- // .replace(/\u309C/g,"\u309A")
- .normalize('NFKC')
- .replace(pat1,m=>(m in NT1?NT1[m]:m))
- .replace(pat2,m=>(m in NT2?NT2[m]:m))
- .replace(/([\]\)])([^\s\.\)\]])/g, '$1 $2')
- .replace(/([^ ])([\[\(])/g, '$1 $2')
- .replace(/ +/g," ")
- .replace(/\.\.+/g,m=>("."))
- );
- }
- const execCopy = async (t)=>
- {
- if (!t) return;
- navigator.clipboard.writeText(t).then(()=>{});
- }
- const execShare = async (text,title='')=>
- {
- if (!text) return;
- let data = {text:text,title:title};
- try{
- await navigator.share(data);
- }
- catch(e)
- {
- }
- }
- //IN: String HTML タイトル要素
- const setTagsToTitle=function(e)
- {
- var tag_html = '';
- var tags = [];
- // 括弧、英数字、通常
- // [ 以外は末尾の数字除外
- // 数字単体除外
- const b=S('span.before',e);
- const p=S('span.pretty',e);
- const a=S('span.after' ,e);
- var tail = '';
- if (b)
- {
- const e1 = /[,、×&,、/]/;
- tag_html += b.innerHTML.replace(/\[([^<>]+?) *(?:\(([^<>]+?)\) *)?\]|\(([^<>]+?)\)/g, (m,m1,m2,m3)=>{
- if (m1)
- {
- let tmp = '';
- tags.push( ...(m1.trim().split(e1)) );
- tmp += '[' + m1.trim().split(e1).map(x=>setTagHTML(x)).join('×');
- if (m2)
- {
- tags.push( ...(m2.trim().split(e1)) );
- tmp += ' ('+m2.trim().split(e1).map(x=>setTagHTML(x)).join('×')+')';
- }
- tmp+=']';
- return tmp;
- }
- else if (m3)
- {
- tags.push( m3.trim() );
- tail = '('+setTagHTML(stripBrace(m3.trim()))+')';
- return '';
- }
- else
- {
- return m;
- }
- });
- }
- if (p)
- {
- tag_html += p.innerHTML.replace(/ *[-+] |~(.+?)~|-([^- ]+?(?:[^-]*?[^- ]+)*)-|([a-zA-Z\d\-=!?'&#$@\/,\.+;:~^|*%]+(?: +[^-+ ][a-zA-Z\d\-=!?'&#$@\/,\.+;:~^|*%]*)*|[^ (?:~.+?~)(?:\-.+?\-)]+)/g,
- (m,m1,m2,m3)=>{
- if (m1)
- {
- let x = '';
- const r = m1.match(/^(.+?)( *\d+)$/);
- if (r) m1=r[1],x=r[2];
- tags.push( m1.trim() );
- return m[0]+setTagHTML(m1)+x+m[0];
- }
- else if (m2)
- {
- tags.push( m2.trim() );
- return m[0]+setTagHTML(m2)+m[0];
- }
- else if (m3)
- {
- tags.push( m3.trim() );
- return setTagHTML(m3);
- }
- else
- {
- return m;
- }
- });
- }
- if (a)
- {
- tag_html += a.innerHTML.replace(/\[([^<>]+?)\]|\(([^<>]+?)\)|【([^<>]+?)】|~([^<>]+?)~|-([^ <>]+?[^-<>]*[^ <>]+?)-|([a-zA-Z\d\-=!?'&#$@\/,\.+;:~^|*%]+(?: +[a-zA-Z\d\-=!?'&#$@\/,\.+;:~^|*%]+)*|[^ <>]+)/g,
- (m,m1,m2,m3,m4,m5,m6)=>{
- if (m1)
- {
- tags.push( m1.trim() );
- return '['+setTagHTML(m1)+']';
- }
- else if (m2)
- {
- tags.push( m2.trim() );
- return '('+setTagHTML(m2)+')';
- }
- else if (m3)
- {
- tags.push( m3.trim() );
- return '【'+setTagHTML(m3)+'】';
- }
- else if (m4)
- {
- tags.push( m4.trim() );
- return m[0]+setTagHTML(m4)+m[0];
- }
- else if (m5)
- {
- tags.push( m5.trim() );
- return m[0]+setTagHTML(m5)+m[0];
- }
- else if (m6)
- {
- tags.push( m6.trim() );
- return setTagHTML(m6);
- }
- else
- {
- return m;
- }
- });
- }
- tag_html = tag_html.trim() + tail;
- return {html:tag_html, tag:tags};
- }
- function stripBrace(str)
- {
- return str.trim().replace(/^\(|\)$/g, '');
- }
- function setTagHTML(str)
- {
- return `<a class="tag" href="${search_prefix+str.replace(/[!?!?。。..、、,,っッ]+$/,'')}"><span class=name>${str}</span></a>`;
- }
- const getURLs = (sep='\r\n')=>
- {
- const elem_tags = E("tags");
- const elem_thumb_container = E('thumbnail-container');
- if (elem_tags === null || elem_thumb_container === null)
- return '';
- // 情報テキスト取得
- let tmp = elem_tags.textContent;
- // ページ数からファイル名の桁数取得
- var digit = 4 <= (tmp.match(/Pages:\s+(\d+)/))[1].length ? 4 : 3;
- // カテゴリ取得 Categories: doujinshi/manga/?
- let categories = (tmp.match(/Categories:\s+([a-z]+)/i))[1];
- // タイトル取得、日本語名がなければ英語名
- tmp=S("h2.title");
- if (tmp===null) tmp=S("h1.title");
- var t = stripTag(tmp.textContent.trim());
- // カテゴリ名を付与、先頭の配布イベント名は後方へやっておく
- //if (t.indexOf("(同人")==-1)
- if (!/^\(同人/.test(t))
- {
- // 先頭の括弧"(*****) ~~~~"を後方へ送る
- var limit = t.length;
- while (0 < limit)
- {
- if (tmp=t.match(/^(\([^\)\[]+\))\s*(.+?)(\s*\[[^\]\[]+\])*$/))
- {
- t=tmp[2]+" "+tmp[1];
- if (tmp[3]) t+=" "+tmp[3].trim();
- limit -= tmp[1].length;
- }
- else
- break;
- }
- // 同人誌の場合のみ
- if (categories=="doujinshi") t = "(同人誌) "+t;
- }
- // console.log('t='+t);
- var buf="";
- const r=/^https:\/\/t(\d+)(\.[^\/]+\/galleries\/)(\d+)\/(\d+)t(\.[^\/\.]+)(?:\.[^\/]+)?$/; // 拡張子重複対応
- A("img.lazyload",elem_thumb_container).forEach((g)=>
- {
- let w = g.getAttribute("data-src");
- if (w)
- buf+=w.replace(r,
- (ma,m1,m2,m3,m4,m5)=>("https://i"+m1+m2+m3+"/"+m4+m5
- +"#"+jdp+"="+encodeURIComponent(normalizeTitle(t))+"&"+jdl+"="+zeroPadding(m4,digit)+(subfolder?('&'+subfolder):'')))
- +sep;
- });
- return buf;
- }
- // already modified...
- if (E('copyURLs')) return;
- //
- // Tags for EveryThing
- //
- [S("h1.title"), S("h2.title")].forEach((h,i)=>
- {
- const h_num = i+1;
- if (!h) return;
- h.style.display='inline';
- const o = setTagsToTitle(h);
- h.innerHTML = o['html'];
- h.insertAdjacentHTML('afterend', `<a class="btn btn-primary tooltip" id="copy_title_${h_num}" style="text-align: center"><i class="fa fa-copy"></i><div class="top">Copy the title</div></a><br>`);
- E(`copy_title_${h_num}`).addEventListener('click',()=>{execCopy(S(`h${h_num}.title`).textContent.trim().replace(/ +/g,' '))});
- });
- //
- // Edit buttons
- //
- const disable_share = (navigator.canShare)?'':' btn-disabled';
- const bt_html = `<a class="btn btn-primary tooltip" id="copyURLs">
- <i class="fa fa-copy"></i> Copy<div class="top">Copy all images URLs.<i></i></div>
- </a>
- <a class="btn btn-primary tooltip${disable_share}" id="shareURLs">
- <i class="fa fa-share"></i> Share<div class="top">Share all images URLs.<i></i></div>
- </a>`;
- const e = S('div#info >div.buttons');
- if (!e) return;
- e.insertAdjacentHTML("afterbegin", bt_html);
- // Favorite, Downloadボタン修正
- A('a',e).forEach(a=>
- {
- a.style.minWidth='60px';
- if (a.textContent.indexOf('Favorite')!=-1)
- {
- const x = S('span',a);
- x.innerHTML = x.innerHTML.replace('Favorite','');
- }
- else if (a.textContent.indexOf('Download')!=-1)
- {
- a.innerHTML = a.innerHTML.replace('Download','DL');
- }
- });
- // クリックイベント設定
- E('copyURLs').addEventListener('click',()=>{execCopy(getURLs())});
- if (navigator.canShare && navigator.canShare('dummy'))
- E('shareURLs').addEventListener('click',()=>{execShare(getURLs())});
- else
- E('shareURLs').classList.add('btn-disabled')
- })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement