Nyaa.si - Load More Thumbnail

Load image from cover/screenshot links.

2024/04/05のページです。最新版はこちら。

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
  1. // ==UserScript==
  2. // @name Nyaa.si - Load More Thumbnail
  3. // @name:zh-CN Nyaa.si - 自动加载更多预览图
  4. // @namespace none
  5. // @description Load image from cover/screenshot links.
  6. // @description:zh-CN 从封面/截图链接加载图片并显示。
  7. // @icon https://www.google.com/s2/favicons?sz=64&domain=sukebei.nyaa.si
  8. // @version 0.9.1
  9. // @license MIT
  10. // @author York Wang
  11. // @match https://sukebei.nyaa.si/*
  12. // @match https://pics.dmm.co.jp/*
  13. // @match https://img169.com/*
  14. // @match https://xpic.org/*
  15. // @match https://imgrock.pw/*
  16. // @match https://picrok.com/*
  17. // @match https://picbaron.com/*
  18. // @match https://imgbaron.com/*
  19. // @match https://kvador.com/*
  20. // @match https://kropic.com/*
  21. // @match https://imgsto.com/*
  22. // @match https://imgsen.com/*
  23. // @match https://imgstar.eu/*
  24. // @match https://picdollar.com/*
  25. // @match https://pics4you.net/*
  26. // @match https://silverpic.com/*
  27. // @match https://fotokiz.com/*
  28. // @match https://premalo.com/*
  29. // @match https://piczhq.com/*
  30. // @match https://trypicz.com/*
  31. // @match http://imglord.com/*
  32. // @match https://croea.com/*
  33. // @match https://imgtaxi.com/*
  34. // @match https://imgadult.com/*
  35. // @match https://imgdrive.net/*
  36. // @match https://xxxwebdlxxx.org/*
  37. // @match https://xxxwebdlxxx.top/*
  38. // @match https://uvonahaze.xyz/*
  39. // @match https://trans.firm.in/*
  40. // @match https://imgdawgknuttz.com/*
  41. // @match https://imagetwist.netlify.app/*
  42. // @match https://imagetwist.com/*
  43. // @match https://imagexport.com/*
  44. // @match https://hentai4free.net/*
  45. // @match https://pixhost.to/*
  46. // @match https://imgair.net/*
  47. // @match http://imgair.net/*
  48. // @match http://imgfrost.net/*
  49. // @match http://imgblaze.net/*
  50. // @match https://pig69.com/*
  51. // @match https://ai18.pics/*
  52. // @match https://porn4f.com/*
  53. // @match https://javball.com/*
  54. // @match https://ovabee.com/*
  55. // @match https://idol69.net/*
  56. // @match https://cnpics.org/*
  57. // @match https://cnxx.me/*
  58. // @match https://cosplay18.pics/*
  59. // @run-at document-end
  60. // @grant unsafeWindow
  61. // @grant GM_xmlhttpRequest
  62. // ==/UserScript==
  63.  
  64. (function() {
  65. 'use strict';
  66.  
  67. function Handler(pattern, process, processNyaa) {
  68. this.pattern = pattern
  69. this.process = process
  70. this.processNyaa = processNyaa
  71. }
  72. Handler.prototype.canHandle = function(url) {
  73. return this.pattern.test(url)
  74. }
  75. Handler.prototype.handle = function(url) {
  76. this.process(href => {
  77. document.location.href = href
  78. unsafeWindow.top.postMessage({"LMT": href, "LMT_SRC": url}, '*')
  79. })
  80. }
  81. Handler.prototype.handleNyaa = function(url) {
  82. if(this.processNyaa) {
  83. this.processNyaa(url, href => {
  84. unsafeWindow.top.postMessage({"LMT": href, "LMT_SRC": url}, '*')
  85. })
  86. } else {
  87. unsafeWindow.LMT_Frame.src = url
  88. }
  89. }
  90. const handlers = []
  91. const addHandler = (pattern, process, processNyaa) => handlers.push(new Handler(pattern, process, processNyaa))
  92.  
  93. addHandler(/^https?:\/\/pics\.dmm\.co\.jp(\/[\w]+)+\.jpg.*/, callback => {
  94. callback(document.location.href.match(/^https?:\/\/pics\.dmm\.co\.jp(\/[\w]+)+\.jpg/)[0])
  95. })
  96. addHandler(/^https?:\/\/img169\.com\/images\/\d{4}\/\d{2}\/\d{2}\/\w+\.jpg/, callback => {
  97. return false
  98. }, (url, callback) => {
  99. callback(url)
  100. })
  101. addHandler(/^https?:\/\/xpic\.org(\/\w+)+/, callback => {
  102. unsafeWindow.wuLu && unsafeWindow.wuLu()
  103. const img = document.querySelector('img.attachment-original.size-original')
  104. if(img) {
  105. callback(img.src)
  106. }
  107. }, (url, callback) => {
  108. GM_xmlhttpRequest({
  109. method: 'GET',
  110. url: url,
  111. onload: res => {
  112. const src = res.responseText.match(/src="(.*)" class="attachment-original size-original"/)
  113. if(src.length > 1) callback(src[1])
  114. }
  115. })
  116. })
  117. addHandler(/^https?:\/\/(imgrock\.pw)(\/[\w\-]+)+(\.[\w\-]+)+/, callback => {
  118. // pause on CAPTCHA
  119. const iframe = document.querySelector('iframe')
  120. if(iframe && iframe.src.indexOf('captcha') > -1) return
  121.  
  122. const img = document.querySelector('.picview')
  123. if(img) {
  124. callback(img.src)
  125. } else {
  126. const btns = document.querySelectorAll('input[name=fnext]')
  127. for(let i=0;i<btns.length;i++) {if(!btns[i].style.display) btns[i].click()}
  128. const forms = document.querySelectorAll('form')
  129. for(let i=0;i<forms.length;i++) {if(forms[i].hito) {forms[i].submit()}}
  130. }
  131. })
  132. addHandler(/^https?:\/\/(picrok\.com)(\/[\w\-]+)+\.php/, callback => {
  133. // pause on CAPTCHA
  134. const iframe = document.querySelector('iframe')
  135. if(iframe && iframe.src.indexOf('captcha') > -1) return
  136.  
  137. const img = document.querySelector('.picview')
  138. if(img) {
  139. callback(img.src)
  140. } else {
  141. unsafeWindow.setTimeout(() => {
  142. const forms = document.querySelectorAll('form')
  143. const btns = document.querySelectorAll('form>button')
  144. // for(let i=0;i<btns.length;i++) {if(btns[i].style.display) forms[i-1].submit()}
  145. }, 5000)
  146. }
  147. })
  148. 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 => {
  149. const img = document.querySelector('.pic')
  150. if(img) {
  151. callback(img.src)
  152. } else {
  153. const form = document.querySelector('form')
  154. form && form.submit()
  155. }
  156. })
  157. addHandler(/^https?:\/\/(croea\.com)(\/\w+)+/, callback => {
  158. const img = document.querySelector('.pic')
  159. if(img) {
  160. callback(img.src)
  161. } else {
  162. const form = document.querySelector('form')
  163. form && form.submit()
  164. }
  165. }, (url, callback) => {
  166. GM_xmlhttpRequest({
  167. method: 'GET',
  168. url: url,
  169. onload: res => {
  170. const src = res.responseText.match(/src="(.*)" class="pic img img-responsive"/)
  171. if(src.length > 1) {
  172. GM_xmlhttpRequest({
  173. method: 'GET',
  174. responseType: "blob",
  175. url: src[1],
  176. onload: res => {
  177. const reader = new FileReader()
  178. reader.onload = () => {
  179. callback(reader.result)
  180. }
  181. reader.readAsDataURL(res.response)
  182. }
  183. })
  184. }
  185. }
  186. })
  187. })
  188. addHandler(/^https?:\/\/(imgtaxi\.com|imgadult\.com|imgdrive\.net)(\/\w+)+/, callback => {
  189. unsafeWindow.ctipops = []
  190. unsafeWindow.adbctipops = []
  191. const img = document.querySelector('img.centred') || document.querySelector('img.centred_resized')
  192. if(img) {
  193. callback(img.src)
  194. } else {
  195. unsafeWindow.setTimeout(() => {
  196. const btn = document.querySelector('.overlay_ad_link')
  197. if(btn) {
  198. btn.focus()
  199. btn.click()
  200. }
  201. }, 1000)
  202. }
  203. }, (url, callback) => {
  204. GM_xmlhttpRequest({
  205. method: 'GET',
  206. url: url,
  207. onload: res => {
  208. const src = res.responseText.match(/og:image:secure_url" content="(.*)"/)
  209. if(src.length > 1) callback(src[1].replace('small','big'))
  210. }
  211. })
  212. })
  213. addHandler(/^https?:\/\/(xxxwebdlxxx\.org|xxxwebdlxxx\.top)(\/\w+)+/, callback => {
  214. unsafeWindow.ctipops = []
  215. unsafeWindow.adbctipops = []
  216. const img = document.querySelector('img.centred') || document.querySelector('img.centred_resized')
  217. if(img) {
  218. callback(img.src)
  219. } else {
  220. unsafeWindow.setTimeout(() => {
  221. const btn = document.querySelector('.overlay_ad_link')
  222. if(btn) {
  223. btn.focus()
  224. btn.click()
  225. }
  226. }, 1000)
  227. }
  228. })
  229. addHandler(/^https?:\/\/(uvonahaze\.xyz|trans\.firm\.in||imgdawgknuttz\.com)(\/\w+)+/, callback => {
  230. const img = document.querySelector('img.centred') || document.querySelector('img.centred_resized')
  231. if(img) {
  232. callback(img.src)
  233. } else {
  234. const btn = document.querySelector('input[name=imgContinue]')
  235. btn && btn.click()
  236. }
  237. })
  238. addHandler(/^https?:\/\/(imagetwist\.netlify\.app)(\/\w+)+/, callback => {
  239. if(unsafeWindow.targetURL) document.location.href = unsafeWindow.targetURL
  240. const btn = document.querySelector('a.btn')
  241. btn && btn.click()
  242. })
  243. addHandler(/^https?:\/\/(imagetwist\.com|imagexport\.com)(\/\w+)+/, callback => {
  244. const img = document.querySelector('.img-responsive')
  245. if(img) {
  246. callback(img.src)
  247. }
  248. })
  249. addHandler(/^https?:\/\/hentai4free\.net(\/\w+)+/, callback => {
  250. unsafeWindow.wuLu && unsafeWindow.wuLu()
  251. const img = document.querySelector('#image-viewer-container>img')
  252. if(img) {
  253. callback(img.src)
  254. }
  255. })
  256. addHandler(/^https?:\/\/pixhost\.to(\/\w+)+/, callback => {
  257. const img = document.querySelector('img.image-img')
  258. if(img) {
  259. callback(img.src)
  260. } else {
  261. const btn = document.querySelector('a.continue')
  262. btn && btn.click()
  263. }
  264. })
  265. addHandler(/^https?:\/\/(imgair\.net|imgfrost\.net|imgblaze\.net)(\/\w+)+/, callback => {
  266. unsafeWindow.wuLu && unsafeWindow.wuLu()
  267. const img = document.querySelector('#newImgE')
  268. if(img) {
  269. callback(img.src)
  270. }
  271. }, (url, callback) => {
  272. GM_xmlhttpRequest({
  273. method: 'GET',
  274. url: url.replace(/^https?:\/\/(imgfrost\.net|imgblaze\.net)/, 'https://imgair.net'),
  275. onload: res => {
  276. const txt = res.responseText
  277. const title = res.responseText.match(/<title>(.*)<\/title>/)[1].trim()
  278. const badChar = /[\[\(\$\^\.\]\*\\\?\+\{\}\\|\)]/gi
  279. const pattern = new RegExp("(http.*" + title.replace(badChar, (c) => `\\${c}`) + ")")
  280. const src = res.responseText.match(pattern)
  281. if(src.length > 0) callback(src[0])
  282. }
  283. })
  284. })
  285. addHandler(/^https?:\/\/(pig69\.com|ai18\.pics|porn4f\.com|javball\.com|ovabee\.com|idol69\.net|cnpics\.org|cnxx\.me|cosplay18\.pics)(\/\w+)+/, callback => {
  286. const img = document.querySelector('#fileOriginalModal img')
  287. if(img) {
  288. callback(img.src)
  289. } else {
  290. const btn = document.querySelector('a.continue')
  291. btn && btn.click()
  292. }
  293. }, (url, callback) => {
  294. GM_xmlhttpRequest({
  295. method: 'GET',
  296. url: url,
  297. onload: res => {
  298. 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\/.*)"/)
  299. if(src.length > 1) callback("http://"+src[1])
  300. }
  301. })
  302. })
  303.  
  304. const href = document.location.href
  305. if(/^https?:\/\/(sukebei\.nyaa\.si).+/g.test(href)) {
  306. if(document.title === '502 Bad Gateway') {
  307. document.location.href = document.location.href
  308. return
  309. }
  310. if(/^https?:\/\/(sukebei\.nyaa\.si\/view\/).+/g.test(href)) {
  311. const desc = document.querySelector('#torrent-description')
  312. const links = desc.querySelectorAll('a')
  313. if(!desc || !links) return
  314.  
  315. const list = []
  316. for(let i in links) {
  317. if(!links[i].href) continue
  318. handlers.forEach(h=>{h.canHandle(links[i].href) && list.push({href:links[i].href,handler:h})})
  319. }
  320.  
  321. let LMT_Wrap, LMT_Frame, LMT_Loading, LMT_panel
  322. const panelWidth = 480
  323. const panelHeight = 480
  324. function createWrap() {
  325. desc.parentNode.insertAdjacentHTML('afterend', '<div class="panel panel-default"><div class="panel-body" id="LMT_Wrap"></div></div>')
  326. LMT_Wrap = document.querySelector('#LMT_Wrap')
  327.  
  328. LMT_Loading = document.createElement('div')
  329. LMT_Loading.textContent = 'Loading Images...'
  330. LMT_Wrap.appendChild(LMT_Loading)
  331.  
  332. LMT_Frame = document.createElement('iframe')
  333. LMT_Frame.id = 'LMT_Frame'
  334. LMT_Frame.sandbox = 'allow-forms allow-scripts allow-same-origin'
  335. LMT_Frame.style.display = 'none'
  336. LMT_Wrap.appendChild(LMT_Frame)
  337.  
  338. LMT_panel = document.createElement('div')
  339. LMT_panel.style.position = 'fixed'
  340. LMT_panel.style.top = '-1000px'
  341. LMT_panel.style.left = '-1000px'
  342. LMT_panel.style.backgroundColor = '#f5f5f5'
  343. LMT_panel.style.backgroundSize = 'contain'
  344. LMT_panel.style.backgroundRepeat = 'no-repeat'
  345. LMT_panel.style.backgroundPosition = 'center'
  346. LMT_panel.style.border = '1px solid #ddd'
  347. LMT_panel.style.borderRadius = '6px'
  348. LMT_panel.style.boxShadow = '0 1px 1px rgba(0,0,0,.05)'
  349. LMT_panel.style.width = `${panelWidth}px`
  350. LMT_panel.style.height = `${panelHeight}px`
  351. document.body.appendChild(LMT_panel)
  352. }
  353.  
  354. function process() {
  355. if(list.length) {
  356. if(!LMT_Frame) createWrap()
  357. let url = list.shift()
  358. url.handler.handleNyaa(url.href)
  359. } else {
  360. if(LMT_Frame) {
  361. LMT_Wrap.removeChild(LMT_Frame)
  362. LMT_Wrap.removeChild(LMT_Loading)
  363. }
  364. }
  365. }
  366.  
  367. unsafeWindow.addEventListener('message', function (e) {
  368. if(e.data.LMT) {
  369. LMT_Frame.src = ''
  370. const img = document.createElement('img')
  371. img.src = e.data.LMT
  372. img.style['max-width'] = '100%'
  373. LMT_Wrap.appendChild(img)
  374. if(e.data.LMT_SRC) {
  375. const url_src = e.data.LMT_SRC
  376. const a = document.querySelector(`a[href="${url_src}"]`)
  377. a.dataset.lmt = img.src
  378. const span = document.createElement("span");
  379. span.innerHTML='✅'
  380. span.dataset.lmt = img.src
  381. a.after(span)
  382. }
  383. process()
  384. }
  385. })
  386.  
  387. process()
  388.  
  389. let windowWidth = unsafeWindow.innerWidth
  390. let windowHeight = unsafeWindow.innerHeight
  391. unsafeWindow.addEventListener('resize', function (e) {
  392. windowWidth = unsafeWindow.innerWidth
  393. windowHeight = unsafeWindow.innerHeight
  394. })
  395. unsafeWindow.addEventListener('mouseover', function (e) {
  396. const a = e.target
  397. if(a.dataset.lmt) {
  398. LMT_panel.style.backgroundImage = `url('${a.dataset.lmt}')`
  399. if(e.clientX + panelWidth < windowWidth) {
  400. LMT_panel.style.left = e.clientX+'px'
  401. } else {
  402. LMT_panel.style.left = e.clientX-panelWidth+'px'
  403. }
  404. if(e.clientY + panelHeight < windowHeight) {
  405. LMT_panel.style.top = e.clientY+'px'
  406. } else {
  407. LMT_panel.style.top = e.clientY-panelHeight+'px'
  408. }
  409. }
  410. })
  411. unsafeWindow.addEventListener('mouseout', function (e) {
  412. const a = e.target
  413. if(a.dataset.lmt) {
  414. LMT_panel.style.top = '-1000px'
  415. LMT_panel.style.left = '-1000px'
  416. }
  417. })
  418. }
  419. } else {
  420. handlers.forEach(h=>{h.canHandle(href) && h.handle(document.location.href)})
  421. }
  422. })();