- // ==UserScript==
- // @name Nyaa.si - Load More Thumbnail
- // @name:zh-CN Nyaa.si - 自动加载更多预览图
- // @namespace none
- // @description Load image from cover/screenshot links.
- // @description:zh-CN 从封面/截图链接加载图片并显示。
- // @icon https://www.google.com/s2/favicons?sz=64&domain=sukebei.nyaa.si
- // @version 0.9.5
- // @license MIT
- // @author York Wang
- // @match https://sukebei.nyaa.si/*
- // @match https://hentai-covers.site/*
- // @match https://www.dlsite.com/*
- // @match https://pics.dmm.co.jp/*
- // @match https://javtenshi.com/*
- // @match https://3xplanet.net/*
- // @match https://3xplanet.com/*
- // @match https://xpic.org/*
- // @match https://imgrock.pw/*
- // @match https://picrok.com/*
- // @match https://picbaron.com/*
- // @match https://imgbaron.com/*
- // @match https://kvador.com/*
- // @match https://kropic.com/*
- // @match https://imgsto.com/*
- // @match https://imgsen.com/*
- // @match https://imgstar.eu/*
- // @match https://picdollar.com/*
- // @match https://pics4you.net/*
- // @match https://silverpic.com/*
- // @match https://fotokiz.com/*
- // @match https://premalo.com/*
- // @match https://piczhq.com/*
- // @match https://trypicz.com/*
- // @match http://imglord.com/*
- // @match https://croea.com/*
- // @match https://imgtaxi.com/*
- // @match https://imgadult.com/*
- // @match https://imgdrive.net/*
- // @match https://xxxwebdlxxx.org/*
- // @match https://xxxwebdlxxx.top/*
- // @match https://uvonahaze.xyz/*
- // @match https://trans.firm.in/*
- // @match https://imgdawgknuttz.com/*
- // @match https://imagetwist.netlify.app/*
- // @match https://imagetwist.com/*
- // @match https://imagexport.com/*
- // @match https://imagenimage.com/*
- // @match https://hentai4free.net/*
- // @match https://pixhost.to/*
- // @match https://imgair.net/*
- // @match http://imgair.net/*
- // @match http://imgfrost.net/*
- // @match http://imgblaze.net/*
- // @match https://pig69.com/*
- // @match https://ai18.pics/*
- // @match https://porn4f.com/*
- // @match https://javball.com/*
- // @match https://ovabee.com/*
- // @match https://idol69.net/*
- // @match https://cnpics.org/*
- // @match https://cnxx.me/*
- // @match https://cosplay18.pics/*
- // @run-at document-end
- // @grant unsafeWindow
- // @grant GM_xmlhttpRequest
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- function Handler(pattern, process, processNyaa) {
- this.pattern = pattern
- this.process = process
- this.processNyaa = processNyaa
- }
- Handler.prototype.canHandle = function(url) {
- return this.pattern.test(url)
- }
- Handler.prototype.handle = function(url) {
- this.process(href => {
- document.location.href = href
- unsafeWindow.top.postMessage({"LMT": href, "LMT_SRC": url}, '*')
- })
- }
- Handler.prototype.handleNyaa = function(url) {
- if(this.processNyaa) {
- this.processNyaa(url, href => {
- unsafeWindow.top.postMessage({"LMT": href, "LMT_SRC": url}, '*')
- })
- } else {
- unsafeWindow.LMT_Frame.src = url
- }
- }
- const handlers = []
- const addHandler = (pattern, process, processNyaa) => handlers.push(new Handler(pattern, process, processNyaa))
-
- addHandler(/^https?:\/\/(hentai-covers\.site)\/image\/\w+/, callback => {
- return false
- }, (url, callback) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: res => {
- const src = res.responseText.match(/id="image-main" src="(.+?)"/)
- if(src.length > 1) callback(src[1])
- }
- })
- })
- addHandler(/^https?:\/\/(www\.dlsite\.com)\/maniax\/work\/=\/product_id\/RJ\d+.html/, callback => {
- return false
- }, (url, callback) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: res => {
- const src = res.responseText.match(/twitter:image:src" content="(.+?)"/)
- if(src.length > 1) callback(src[1])
- }
- })
- })
- addHandler(/^https?:\/\/pics\.dmm\.co\.jp(\/[\w]+)+\.jpg.*/, callback => {
- callback(document.location.href.match(/^https?:\/\/pics\.dmm\.co\.jp(\/[\w]+)+\.jpg/)[0])
- })
- addHandler(/^https:\/\/i\.imgur\.com\/QCqG8mw\.jpg/, callback => {
- return false
- }, (url, callback) => {
- callback(url)
- })
- addHandler(/^https?:\/\/(img169\.com|qpic\.ws|img\.blr844\.com)\/images\/\d{4}\/\d{2}\/\d{2}\/\w+\.jpg/, callback => {
- return false
- }, (url, callback) => {
- callback(url)
- })
- addHandler(/^https?:\/\/(javtenshi\.com|3xplanet\.net|3xplanet\.com)\/viewimage\/\d+\.html/, callback => {
- return false
- }, (url, callback) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: res => {
- const src = res.responseText.match(/scale\(this\);" src="(.+)/)
- if(src.length > 1) callback(src[1])
- }
- })
- })
- addHandler(/^https?:\/\/xpic\.org(\/\w+)+/, callback => {
- unsafeWindow.wuLu && unsafeWindow.wuLu()
- const img = document.querySelector('img.attachment-original.size-original')
- if(img) {
- callback(img.src)
- }
- }, (url, callback) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: res => {
- const src = res.responseText.match(/src="(.*)" class="attachment-original size-original"/)
- if(src.length > 1) callback(src[1])
- }
- })
- })
- addHandler(/^https?:\/\/(imgrock\.pw)(\/[\w\-]+)+(\.[\w\-]+)+/, callback => {
- // pause on CAPTCHA
- const iframe = document.querySelector('iframe')
- if(iframe && iframe.src.indexOf('captcha') > -1) return
-
- const img = document.querySelector('.picview')
- if(img) {
- callback(img.src)
- } else {
- const btns = document.querySelectorAll('input[name=fnext]')
- for(let i=0;i<btns.length;i++) {if(!btns[i].style.display) btns[i].click()}
- const forms = document.querySelectorAll('form')
- for(let i=0;i<forms.length;i++) {if(forms[i].hito) {forms[i].submit()}}
- }
- })
- addHandler(/^https?:\/\/(picrok\.com)(\/[\w\-]+)+\.php/, callback => {
- // pause on CAPTCHA
- const iframe = document.querySelector('iframe')
- if(iframe && iframe.src.indexOf('captcha') > -1) return
-
- const img = document.querySelector('.picview')
- if(img) {
- callback(img.src)
- } else {
- unsafeWindow.setTimeout(() => {
- const forms = document.querySelectorAll('form')
- const btns = document.querySelectorAll('form>button')
- // for(let i=0;i<btns.length;i++) {if(btns[i].style.display) forms[i-1].submit()}
- }, 5000)
- }
- })
- addHandler(/^https?:\/\/(picbaron\.com|imgbaron\.com|kvador\.com|kropic\.com|imgsto\.com|imgsen\.com|imgstar\.eu|picdollar\.com|pics4you\.net|silverpic\.com|fotokiz\.com|premalo\.com|piczhq\.com|trypicz\.com|imglord\.com)(\/.+)+(\.[\w\-]+)+/, callback => {
- const img = document.querySelector('.pic')
- if(img) {
- callback(img.src)
- } else {
- const form = document.querySelector('form')
- form && form.submit()
- }
- })
- addHandler(/^https?:\/\/(croea\.com)(\/\w+)+/, callback => {
- const img = document.querySelector('.pic')
- if(img) {
- callback(img.src)
- } else {
- const form = document.querySelector('form')
- form && form.submit()
- }
- }, (url, callback) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: res => {
- const src = res.responseText.match(/src="(.*)" class="pic img img-responsive"/)
- if(src.length > 1) {
- GM_xmlhttpRequest({
- method: 'GET',
- responseType: "blob",
- url: src[1],
- onload: res => {
- const reader = new FileReader()
- reader.onload = () => {
- callback(reader.result)
- }
- reader.readAsDataURL(res.response)
- }
- })
- }
- }
- })
- })
- addHandler(/^https?:\/\/(imgtaxi\.com|imgadult\.com|imgdrive\.net)(\/\w+)+/, callback => {
- unsafeWindow.ctipops = []
- unsafeWindow.adbctipops = []
- const img = document.querySelector('img.centred') || document.querySelector('img.centred_resized')
- if(img) {
- callback(img.src)
- } else {
- unsafeWindow.setTimeout(() => {
- const btn = document.querySelector('.overlay_ad_link')
- if(btn) {
- btn.focus()
- btn.click()
- }
- }, 1000)
- }
- }, (url, callback) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: res => {
- const src = res.responseText.match(/og:image:secure_url" content="(.*)"/)
- if(src.length > 1) callback(src[1].replace('small','big'))
- }
- })
- })
- addHandler(/^https?:\/\/(xxxwebdlxxx\.org|xxxwebdlxxx\.top)(\/\w+)+/, callback => {
- unsafeWindow.ctipops = []
- unsafeWindow.adbctipops = []
- const img = document.querySelector('img.centred') || document.querySelector('img.centred_resized')
- if(img) {
- callback(img.src)
- } else {
- unsafeWindow.setTimeout(() => {
- const btn = document.querySelector('.overlay_ad_link')
- if(btn) {
- btn.focus()
- btn.click()
- }
- }, 1000)
- }
- })
- addHandler(/^https?:\/\/(uvonahaze\.xyz|trans\.firm\.in||imgdawgknuttz\.com)(\/\w+)+/, callback => {
- const img = document.querySelector('img.centred') || document.querySelector('img.centred_resized')
- if(img) {
- callback(img.src)
- } else {
- const btn = document.querySelector('input[name=imgContinue]')
- btn && btn.click()
- }
- })
- addHandler(/^https?:\/\/(imagetwist\.netlify\.app)(\/\w+)+/, callback => {
- if(unsafeWindow.targetURL) document.location.href = unsafeWindow.targetURL
- const btn = document.querySelector('a.btn')
- btn && btn.click()
- })
- addHandler(/^https?:\/\/(imagetwist\.com|imagexport\.com|imagenimage\.com)(\/\w+)+/, callback => {
- const img = document.querySelector('.img-responsive')
- if(img) {
- callback(img.src)
- }
- })
- addHandler(/^https?:\/\/hentai4free\.net(\/\w+)+/, callback => {
- unsafeWindow.wuLu && unsafeWindow.wuLu()
- const img = document.querySelector('#image-viewer-container>img')
- if(img) {
- callback(img.src)
- }
- })
- addHandler(/^https?:\/\/pixhost\.to(\/\w+)+/, callback => {
- const img = document.querySelector('img.image-img')
- if(img) {
- callback(img.src)
- } else {
- const btn = document.querySelector('a.continue')
- btn && btn.click()
- }
- })
- addHandler(/^https?:\/\/(imgair\.net|imgfrost\.net|imgblaze\.net)(\/\w+)$/, callback => {
- unsafeWindow.wuLu && unsafeWindow.wuLu()
- const img = document.querySelector('#newImgE')
- if(img) {
- callback(img.src)
- }
- }, (url, callback) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url.replace(/^https?:\/\/(imgfrost\.net|imgblaze\.net)/, 'https://imgair.net'),
- onload: res => {
- const txt = res.responseText
- let title = txt.match(/<title>(.*)<\/title>/)
- if(!title) return false
- title = title[1].trim()
- const badChar = /[\[\(\$\^\.\]\*\\\?\+\{\}\\|\)]/gi
- const pattern = new RegExp("(http.*" + title.replace(badChar, (c) => `\\${c}`) + ")")
- const src = txt.match(pattern)
- if(src.length > 0) callback(src[0])
- }
- })
- })
- addHandler(/^https?:\/\/(pig69\.com|ai18\.pics|porn4f\.com|javball\.com|ovabee\.com|idol69\.net|cnpics\.org|cnxx\.me|cosplay18\.pics)(\/\w+)+/, callback => {
- const img = document.querySelector('#fileOriginalModal img')
- if(img) {
- callback(img.src)
- } else {
- const btn = document.querySelector('a.continue')
- btn && btn.click()
- }
- }, (url, callback) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: res => {
- const src = res.responseText.match(/"https?:\/\/((pig69\.com|ai18\.pics|porn4f\.com|javball\.com|ovabee\.com|idol69\.net|cnpics\.org|cnxx\.me|cosplay18\.pics)\/upload\/Application\/storage\/app\/public\/uploads\/users\/.*)"/)
- if(src.length > 1) callback("http://"+src[1])
- }
- })
- })
- addHandler(/^https:\/\/manko\.fun\|/, callback => {
- return false
- }, (url, callback) => {
- if(/^https:\/\/sukebei\.nyaa\.si\/(\?.*)?$/.test(href)) {
- callback(url.substr(18))
- }
- })
-
- const href = document.location.href
- if(/^https?:\/\/(sukebei\.nyaa\.si).+/g.test(href)) {
-
- let LMT_Wrap, LMT_Frame, LMT_Loading, LMT_panel
- const panelWidth = 480
- const panelHeight = 480
- function createWrap(parent) {
- parent.parentNode.insertAdjacentHTML('afterend', '<div class="panel panel-default"><div class="panel-body" id="LMT_Wrap"></div></div>')
- LMT_Wrap = document.querySelector('#LMT_Wrap')
-
- LMT_Loading = document.createElement('div')
- LMT_Loading.textContent = 'Loading Images...'
- LMT_Wrap.appendChild(LMT_Loading)
- }
- function createPanel() {
- LMT_panel = document.createElement('div')
- LMT_panel.style.position = 'fixed'
- LMT_panel.style.top = '-1000px'
- LMT_panel.style.left = '-1000px'
- LMT_panel.style.backgroundColor = '#f5f5f5'
- LMT_panel.style.backgroundSize = 'contain'
- LMT_panel.style.backgroundRepeat = 'no-repeat'
- LMT_panel.style.backgroundPosition = 'center'
- LMT_panel.style.border = '1px solid #ddd'
- LMT_panel.style.borderRadius = '6px'
- LMT_panel.style.boxShadow = '0 1px 1px rgba(0,0,0,.05)'
- LMT_panel.style.width = `${panelWidth}px`
- LMT_panel.style.height = `${panelHeight}px`
- document.body.appendChild(LMT_panel)
-
- LMT_Frame = document.createElement('iframe')
- LMT_Frame.id = 'LMT_Frame'
- LMT_Frame.sandbox = 'allow-forms allow-scripts allow-same-origin'
- LMT_Frame.style.display = 'none'
- document.body.appendChild(LMT_Frame)
- }
-
- const imgList = []
-
- function process() {
- if(imgList.length) {
- let url = imgList.shift()
- url.handler.handleNyaa(url.href)
- } else {
- if(LMT_Wrap) {
- LMT_Loading.innerText = ''
- document.body.removeChild(LMT_Frame)
-
- if(!Array.apply(null, document.querySelectorAll('#LMT_Wrap > img')).length) {
- document.querySelector('.panel:has(#LMT_Wrap)').style.display = 'none'
- }
- } else {
- LMT_Frame.src = 'about:blank'
- }
- }
- }
-
- unsafeWindow.addEventListener('message', function (e) {
- if(!e.data.LMT) return false
- if(LMT_Wrap) {
- LMT_Frame.src = ''
- const img = document.createElement('img')
- img.src = e.data.LMT
- img.style['max-width'] = '100%'
- LMT_Wrap.appendChild(img)
- }
- if(e.data.LMT_SRC) {
- const url_src = e.data.LMT_SRC
- const a = document.querySelector(`a[data-lmt-src="${decodeURI(url_src)}"]`)
- if(a && !a.dataset.lmt) {
- a.dataset.lmt = e.data.LMT
- const span = document.createElement("span");
- span.innerHTML='🖼️'
- span.dataset.lmt = e.data.LMT
- a.before(span)
-
- if(/^https?:\/\/(sukebei\.nyaa\.si\/view\/).+/g.test(a.href)) {
- const id = a.href.substr(a.href.lastIndexOf('/')+1)
- saveThumb(id, e.data.LMT)
- }
- }
- }
- process()
- })
-
- let windowWidth = unsafeWindow.innerWidth
- let windowHeight = unsafeWindow.innerHeight
- unsafeWindow.addEventListener('resize', function (e) {
- windowWidth = unsafeWindow.innerWidth
- windowHeight = unsafeWindow.innerHeight
- })
- unsafeWindow.addEventListener('mouseover', function (e) {
- const a = e.target
- if(a.dataset.lmt) {
- LMT_panel.style.backgroundImage = `url('${a.dataset.lmt}')`
- if(e.clientX + panelWidth < windowWidth) {
- LMT_panel.style.left = e.clientX+'px'
- } else {
- LMT_panel.style.left = e.clientX-panelWidth+'px'
- }
- if(e.clientY + panelHeight < windowHeight) {
- LMT_panel.style.top = e.clientY+'px'
- } else {
- LMT_panel.style.top = e.clientY-panelHeight+'px'
- }
- }
- })
- unsafeWindow.addEventListener('mouseout', function (e) {
- const a = e.target
- if(a.dataset.lmt) {
- LMT_panel.style.top = '-1000px'
- LMT_panel.style.left = '-1000px'
- }
- })
-
- const CLOUD_URL = 'https://oc1.bigsm.art'
- const getThumbs = ids => {
- return new Promise((resolve, reject) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: `${CLOUD_URL}/thumbs/?ids=${ids}`,
- onload: res => { resolve(JSON.parse(res.responseText)) },
- onError: err => { resolve([]) }
- })
- })
- }
- const saveThumb = (id, thumb) => {
- GM_xmlhttpRequest({
- method: 'POST',
- url: `${CLOUD_URL}/thumb/${id}`,
- data: `{"url": "${thumb}"}`,
- headers: {
- "Content-Type": "application/json"
- }
- })
- }
-
- if(/^https?:\/\/(sukebei\.nyaa\.si\/view\/).+/g.test(href)) {
- // Detail Page
- const desc = document.querySelector('#torrent-description')
- const links = desc.querySelectorAll('a')
- if(!desc || !links) return
-
- for(let i = 0; i < links.length; i++) {
- if(!links[i].href) continue
- links[i].dataset.lmtSrc = decodeURI(links[i].href)
- handlers.forEach(h=>{h.canHandle(links[i].href) && imgList.push({href:links[i].href,handler:h})})
- }
-
- if(!LMT_Frame) {
- createWrap(desc)
- }
- createPanel()
- process()
- } else {
- // List Page
- // try to load thumb from cloud
- const links = document.querySelectorAll('.torrent-list>tbody>tr>td:nth-child(2)>a:last-child')
- const ids = Array.apply(null, links).map(a => a.href.substr(a.href.lastIndexOf('/')+1)).join(',')
- getThumbs(ids).then(thumbs => {
- for(let i in thumbs) {
- if(!thumbs[i]) continue
- links[i].dataset.lmt = thumbs[i]
- const span = document.createElement("span");
- span.innerHTML='🖼️'
- span.dataset.lmt = thumbs[i]
- links[i].before(span)
- }
- })
-
- unsafeWindow.addEventListener('mouseover', async (e) => {
- const a = e.target
- if(!a.dataset.lmt && !a.dataset.lmtSrc && a.href) {
- const detail = await getDetail(a.href)
- let desc = detail.responseText.match(/id="torrent-description">(.*?)<\/div>/)
- if(!desc) return false
- desc = desc[1].replaceAll(' ', '\n').replaceAll(')]', ' )]').replaceAll('\*\*', ' \*\* ')
- let hrefs = desc.match(/(https?:\/\/[^\s\)]+)/g) || []
- let info = detail.responseText.match(/noopener noreferrer nofollow" href="(https?:\/\/.+?)"/)
- if(info) hrefs = [...hrefs, info[1]]
-
- let flag = false
- for (let i in hrefs) {
- let href = hrefs[i]
- // for links '[](https://manko.fun)'
- if (href.trim() === 'https://manko.fun') {
- href = desc.match(/(https?:\/\/.+?)\)\]\(https:\/\/manko\.fun\)/)
- if(href) {
- href = 'https://manko.fun|' + href[1].trim()
- } else {
- continue
- }
- }
-
- for(let j in handlers) {
- const h = handlers[j]
- if(href.indexOf('nyaa') < 0 && h.canHandle(href)) {
- a.dataset.lmtSrc = href
- imgList.push({href:href,handler:h})
- flag = true
- break
- }
- }
- if(flag) {
- process()
- break
- }
- }
- if(!flag) {
- a.dataset.lmtSrc = '#'
- }
- }
- })
- createPanel()
- const getDetail = url => {
- return new Promise((resolve, reject) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: res => { resolve(res) },
- onError: err => { reject(err) }
- })
- })
- }
- }
- } else {
- // Image Host Websites
- handlers.forEach(h=>{h.canHandle(href) && h.handle(document.location.href)})
- }
- })();