Alex revised this gist 4 months ago. Go to revision
No changes
Alex Thomassen revised this gist 4 months ago. Go to revision
1 file changed, 64 insertions, 6 deletions
nyaa-shit.user.js
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | // @namespace github.com/Decicus | |
| 4 | 4 | // @match https://nyaa.si/* | |
| 5 | 5 | // @grant GM_setClipboard | |
| 6 | - | // @version 1.4.1 | |
| 6 | + | // @version 1.5.0 | |
| 7 | 7 | // @author Decicus | |
| 8 | 8 | // @description Adds some extra functionality to Nyaa. | |
| 9 | 9 | // ==/UserScript== | |
| @@ -194,16 +194,21 @@ const titleReplacements = [ | |||
| 194 | 194 | search: / \"[A-z0-9-!\s]+\"$/, | |
| 195 | 195 | replacement: '', | |
| 196 | 196 | }, | |
| 197 | - | { | |
| 198 | - | comment: 'Move release group to the end', | |
| 199 | - | search: /^\[([-\w ]+)\] (.+)$/, | |
| 200 | - | replacement: '$2 [$1]', | |
| 201 | - | }, | |
| 197 | + | // { | |
| 198 | + | // comment: 'Move release group to the end', | |
| 199 | + | // search: /^\[([-\w ]+)\] (.+)$/, | |
| 200 | + | // replacement: '$2 [$1]', | |
| 201 | + | // }, | |
| 202 | 202 | { | |
| 203 | 203 | comment: 'Colon space to space dash space', | |
| 204 | 204 | search: /: /g, | |
| 205 | 205 | replacement: ' - ', | |
| 206 | 206 | }, | |
| 207 | + | { | |
| 208 | + | comment: 'Ensure seasons have two numbers', | |
| 209 | + | search: / \(Season (\d)\)/g, | |
| 210 | + | replacement: ' (Season 0$1)', | |
| 211 | + | }, | |
| 207 | 212 | { | |
| 208 | 213 | comment: 'Season naming so Sonarr doesnt get confused because its dumb', | |
| 209 | 214 | search: / \(Season (\d+)\)/g, | |
| @@ -294,6 +299,58 @@ function titleHandler() | |||
| 294 | 299 | titleParent.insertAdjacentElement('afterbegin', buttonParent); | |
| 295 | 300 | } | |
| 296 | 301 | ||
| 302 | + | /** | |
| 303 | + | * Used by `copyFilenameHandler()` to do the actual copying | |
| 304 | + | */ | |
| 305 | + | function copyFilenameTrigger(ev) | |
| 306 | + | { | |
| 307 | + | const { target } = ev; | |
| 308 | + | ||
| 309 | + | // Trust no one, not even yourself | |
| 310 | + | if (!target) { | |
| 311 | + | return; | |
| 312 | + | } | |
| 313 | + | ||
| 314 | + | // We clone it here because I want to remove the file size that's normally at the end | |
| 315 | + | // If I simply do a `remove()` on the usual element, it will actually remove it from the DOM. | |
| 316 | + | const parent = target.parentElement.cloneNode(true); | |
| 317 | + | const fileSize = parent.querySelector('.file-size'); | |
| 318 | + | ||
| 319 | + | if (fileSize) { | |
| 320 | + | fileSize.remove(); | |
| 321 | + | } | |
| 322 | + | ||
| 323 | + | const filename = parent.textContent.trim(); | |
| 324 | + | ||
| 325 | + | target.classList.remove('fa-file'); | |
| 326 | + | target.classList.add('fa-check'); | |
| 327 | + | ||
| 328 | + | GM_setClipboard(filename); | |
| 329 | + | ||
| 330 | + | setTimeout(() => { | |
| 331 | + | target.classList.remove('fa-check'); | |
| 332 | + | target.classList.add('fa-file'); | |
| 333 | + | }, 1500); | |
| 334 | + | } | |
| 335 | + | ||
| 336 | + | /** | |
| 337 | + | * Clicking the file icon in front of each file will allow you to copy the filename | |
| 338 | + | */ | |
| 339 | + | async function copyFilenameHandler() | |
| 340 | + | { | |
| 341 | + | const fileList = document.querySelector('.torrent-file-list'); | |
| 342 | + | if (!fileList) { | |
| 343 | + | return; | |
| 344 | + | } | |
| 345 | + | ||
| 346 | + | const fileIcons = fileList.querySelectorAll('.fa-file'); | |
| 347 | + | ||
| 348 | + | for (const icon of fileIcons) | |
| 349 | + | { | |
| 350 | + | icon.addEventListener('click', copyFilenameTrigger); | |
| 351 | + | } | |
| 352 | + | } | |
| 353 | + | ||
| 297 | 354 | function bbcodeConverter(html) { | |
| 298 | 355 | html = html.replace(/<pre(.*?)>(.*?)<\/pre>/gmi, "[code]$2[/code]"); | |
| 299 | 356 | html = html.replace(/<h[1-7](.*?)>(.*?)<\/h[1-7]>/, "\n[h]$2[/h]\n"); | |
| @@ -559,6 +616,7 @@ function init() { | |||
| 559 | 616 | changeToCopy(); | |
| 560 | 617 | titleHandler(); | |
| 561 | 618 | descriptionHandler(); | |
| 619 | + | copyFilenameHandler(); | |
| 562 | 620 | torrentListViewHandler(); | |
| 563 | 621 | calculateTotalSize(); | |
| 564 | 622 | widerContainers(); | |
Alex Thomassen revised this gist 1 year ago. Go to revision
1 file changed, 25 insertions, 15 deletions
nyaa-shit.user.js
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | // @namespace github.com/Decicus | |
| 4 | 4 | // @match https://nyaa.si/* | |
| 5 | 5 | // @grant GM_setClipboard | |
| 6 | - | // @version 1.4.0 | |
| 6 | + | // @version 1.4.1 | |
| 7 | 7 | // @author Decicus | |
| 8 | 8 | // @description Adds some extra functionality to Nyaa. | |
| 9 | 9 | // ==/UserScript== | |
| @@ -83,6 +83,9 @@ function calculateTotalSize() | |||
| 83 | 83 | return; | |
| 84 | 84 | } | |
| 85 | 85 | ||
| 86 | + | const sampleTorrent = "https://nyaa.si/download/222409.torrent"; | |
| 87 | + | const sampleMagnet = "magnet:?xt=urn:btih:db0ffe8174317b0b0ee4beb7b54f558bb9089746&dn=%5Beoy%5D%20dark%20dragoon%20-%2001.txt&tr=http%3A%2F%2Fnyaa.tracker.wf%3A7777%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce"; | |
| 88 | + | ||
| 86 | 89 | const html = `<tr class="default" id="all-torrents-size"> | |
| 87 | 90 | <td class="text-center"> | |
| 88 | 91 | <a href="#all-torrents-size" title="Total size"> | |
| @@ -92,7 +95,12 @@ function calculateTotalSize() | |||
| 92 | 95 | <td colspan="2"> | |
| 93 | 96 | <a href="#all-torrents-size">Total size</a> | |
| 94 | 97 | </td> | |
| 95 | - | <td class="text-center"><!-- Download --></td> | |
| 98 | + | <td class="text-center"> | |
| 99 | + | <!-- These elements purely exist to avoid any issues with extensions or userscripts that would normally expect valid torrent/magnet URIs --> | |
| 100 | + | <!-- In my case I only found an issue with NyaaBlue from SeaDex --> | |
| 101 | + | <a href="${sampleTorrent}" style="display: none;"><!-- Download torrent --></a> | |
| 102 | + | <a href="${sampleMagnet}" style="display: none;"><!-- Magnet URI --></a> | |
| 103 | + | </td> | |
| 96 | 104 | <td class="text-center">${totalSize}</td> | |
| 97 | 105 | <td class="text-center"><!-- Timestamp --></td> | |
| 98 | 106 | <td class="text-center"><!-- Seeders --></td> | |
| @@ -528,21 +536,23 @@ function torrentListViewHandler() | |||
| 528 | 536 | parentElement.insertAdjacentElement('beforebegin', amountCopyLinks); | |
| 529 | 537 | } | |
| 530 | 538 | ||
| 531 | - | function changeContainers() | |
| 539 | + | /** | |
| 540 | + | * This previously changed some `.container` classes to `.container-fluid`, | |
| 541 | + | * but since that breaks other userscripts, such as NyaaBlue from SeaDex, | |
| 542 | + | * I figured it'd be better to simply override the CSS width that .container usually applies. | |
| 543 | + | */ | |
| 544 | + | function widerContainers() | |
| 532 | 545 | { | |
| 533 | - | const selectors = ['.navbar-static-top > .container', 'body > .container']; | |
| 534 | - | for (const selector of selectors) | |
| 535 | - | { | |
| 536 | - | const element = document.querySelector(selector); | |
| 537 | - | if (!element) { | |
| 538 | - | console.error('Could not find any element with selector', selector); | |
| 539 | - | continue; | |
| 546 | + | const styleDoc = document.createElement('style'); | |
| 547 | + | styleDoc.setAttribute('type', 'text/css'); | |
| 548 | + | ||
| 549 | + | styleDoc.textContent = ` | |
| 550 | + | .container { | |
| 551 | + | width: auto !important; | |
| 540 | 552 | } | |
| 553 | + | `; | |
| 541 | 554 | ||
| 542 | - | element.classList.remove('container'); | |
| 543 | - | element.classList.add('container-fluid'); | |
| 544 | - | console.log('Element updated with container-fluid', selector, element); | |
| 545 | - | } | |
| 555 | + | document.head.insertAdjacentElement('beforeend', styleDoc); | |
| 546 | 556 | } | |
| 547 | 557 | ||
| 548 | 558 | function init() { | |
| @@ -551,7 +561,7 @@ function init() { | |||
| 551 | 561 | descriptionHandler(); | |
| 552 | 562 | torrentListViewHandler(); | |
| 553 | 563 | calculateTotalSize(); | |
| 554 | - | changeContainers(); | |
| 564 | + | widerContainers(); | |
| 555 | 565 | } | |
| 556 | 566 | ||
| 557 | 567 | init(); | |
Alex Thomassen revised this gist 2 years ago. Go to revision
1 file changed, 19 insertions, 2 deletions
nyaa-shit.user.js
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | // @namespace github.com/Decicus | |
| 4 | 4 | // @match https://nyaa.si/* | |
| 5 | 5 | // @grant GM_setClipboard | |
| 6 | - | // @version 1.3.1 | |
| 6 | + | // @version 1.4.0 | |
| 7 | 7 | // @author Decicus | |
| 8 | 8 | // @description Adds some extra functionality to Nyaa. | |
| 9 | 9 | // ==/UserScript== | |
| @@ -60,7 +60,6 @@ function calculateTotalSize() | |||
| 60 | 60 | const torrentBytes = sizeNumber * multiplier; | |
| 61 | 61 | ||
| 62 | 62 | totalBytes += torrentBytes; | |
| 63 | - | console.log(totalBytes); | |
| 64 | 63 | } | |
| 65 | 64 | ||
| 66 | 65 | const multiplierKeys = Object.keys(multipliers).reverse(); | |
| @@ -529,12 +528,30 @@ function torrentListViewHandler() | |||
| 529 | 528 | parentElement.insertAdjacentElement('beforebegin', amountCopyLinks); | |
| 530 | 529 | } | |
| 531 | 530 | ||
| 531 | + | function changeContainers() | |
| 532 | + | { | |
| 533 | + | const selectors = ['.navbar-static-top > .container', 'body > .container']; | |
| 534 | + | for (const selector of selectors) | |
| 535 | + | { | |
| 536 | + | const element = document.querySelector(selector); | |
| 537 | + | if (!element) { | |
| 538 | + | console.error('Could not find any element with selector', selector); | |
| 539 | + | continue; | |
| 540 | + | } | |
| 541 | + | ||
| 542 | + | element.classList.remove('container'); | |
| 543 | + | element.classList.add('container-fluid'); | |
| 544 | + | console.log('Element updated with container-fluid', selector, element); | |
| 545 | + | } | |
| 546 | + | } | |
| 547 | + | ||
| 532 | 548 | function init() { | |
| 533 | 549 | changeToCopy(); | |
| 534 | 550 | titleHandler(); | |
| 535 | 551 | descriptionHandler(); | |
| 536 | 552 | torrentListViewHandler(); | |
| 537 | 553 | calculateTotalSize(); | |
| 554 | + | changeContainers(); | |
| 538 | 555 | } | |
| 539 | 556 | ||
| 540 | 557 | init(); | |
Alex Thomassen revised this gist 2 years ago. Go to revision
1 file changed, 5 insertions, 1 deletion
nyaa-shit.user.js
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | // @namespace github.com/Decicus | |
| 4 | 4 | // @match https://nyaa.si/* | |
| 5 | 5 | // @grant GM_setClipboard | |
| 6 | - | // @version 1.3.0 | |
| 6 | + | // @version 1.3.1 | |
| 7 | 7 | // @author Decicus | |
| 8 | 8 | // @description Adds some extra functionality to Nyaa. | |
| 9 | 9 | // ==/UserScript== | |
| @@ -80,6 +80,10 @@ function calculateTotalSize() | |||
| 80 | 80 | } | |
| 81 | 81 | ||
| 82 | 82 | const torrentList = document.querySelector('.torrent-list tbody'); | |
| 83 | + | if (!torrentList) { | |
| 84 | + | return; | |
| 85 | + | } | |
| 86 | + | ||
| 83 | 87 | const html = `<tr class="default" id="all-torrents-size"> | |
| 84 | 88 | <td class="text-center"> | |
| 85 | 89 | <a href="#all-torrents-size" title="Total size"> | |
Alex Thomassen revised this gist 2 years ago. Go to revision
1 file changed, 68 insertions, 68 deletions
nyaa-shit.user.js
| @@ -81,21 +81,21 @@ function calculateTotalSize() | |||
| 81 | 81 | ||
| 82 | 82 | const torrentList = document.querySelector('.torrent-list tbody'); | |
| 83 | 83 | const html = `<tr class="default" id="all-torrents-size"> | |
| 84 | - | <td class="text-center"> | |
| 85 | - | <a href="#all-torrents-size" title="Total size"> | |
| 86 | - | 💽 | |
| 87 | - | </a> | |
| 88 | - | </td> | |
| 89 | - | <td colspan="2"> | |
| 84 | + | <td class="text-center"> | |
| 85 | + | <a href="#all-torrents-size" title="Total size"> | |
| 86 | + | 💽 | |
| 87 | + | </a> | |
| 88 | + | </td> | |
| 89 | + | <td colspan="2"> | |
| 90 | 90 | <a href="#all-torrents-size">Total size</a> | |
| 91 | - | </td> | |
| 92 | - | <td class="text-center"><!-- Download --></td> | |
| 93 | - | <td class="text-center">${totalSize}</td> | |
| 94 | - | <td class="text-center"><!-- Timestamp --></td> | |
| 95 | - | <td class="text-center"><!-- Seeders --></td> | |
| 96 | - | <td class="text-center"><!-- Leechers --></td> | |
| 97 | - | <td class="text-center"><!-- Completed --></td> | |
| 98 | - | </tr>`; | |
| 91 | + | </td> | |
| 92 | + | <td class="text-center"><!-- Download --></td> | |
| 93 | + | <td class="text-center">${totalSize}</td> | |
| 94 | + | <td class="text-center"><!-- Timestamp --></td> | |
| 95 | + | <td class="text-center"><!-- Seeders --></td> | |
| 96 | + | <td class="text-center"><!-- Leechers --></td> | |
| 97 | + | <td class="text-center"><!-- Completed --></td> | |
| 98 | + | </tr>`; | |
| 99 | 99 | ||
| 100 | 100 | torrentList.insertAdjacentHTML('beforeend', html); | |
| 101 | 101 | } | |
| @@ -285,63 +285,63 @@ function titleHandler() | |||
| 285 | 285 | ||
| 286 | 286 | function bbcodeConverter(html) { | |
| 287 | 287 | html = html.replace(/<pre(.*?)>(.*?)<\/pre>/gmi, "[code]$2[/code]"); | |
| 288 | - | html = html.replace(/<h[1-7](.*?)>(.*?)<\/h[1-7]>/, "\n[h]$2[/h]\n"); | |
| 289 | - | //paragraph handling: | |
| 290 | - | //- if a paragraph opens on the same line as another one closes, insert an extra blank line | |
| 291 | - | //- opening tag becomes two line breaks | |
| 292 | - | //- closing tags are just removed | |
| 293 | - | // html += html.replace(/<\/p><p/<\/p>\n<p/gi; | |
| 294 | - | // html += html.replace(/<p[^>]*>/\n\n/gi; | |
| 295 | - | // html += html.replace(/<\/p>//gi; | |
| 288 | + | html = html.replace(/<h[1-7](.*?)>(.*?)<\/h[1-7]>/, "\n[h]$2[/h]\n"); | |
| 289 | + | //paragraph handling: | |
| 290 | + | //- if a paragraph opens on the same line as another one closes, insert an extra blank line | |
| 291 | + | //- opening tag becomes two line breaks | |
| 292 | + | //- closing tags are just removed | |
| 293 | + | // html += html.replace(/<\/p><p/<\/p>\n<p/gi; | |
| 294 | + | // html += html.replace(/<p[^>]*>/\n\n/gi; | |
| 295 | + | // html += html.replace(/<\/p>//gi; | |
| 296 | 296 | ||
| 297 | 297 | html = html.replace(/<\/p>\n<p>/gi, "\n\n\n"); | |
| 298 | 298 | ||
| 299 | - | html = html.replace(/<br(.*?)>/gi, "\n"); | |
| 300 | - | html = html.replace(/<textarea(.*?)>(.*?)<\/textarea>/gmi, "\[code]$2\[\/code]"); | |
| 301 | - | html = html.replace(/<b>/gi, "[b]"); | |
| 302 | - | html = html.replace(/<i>/gi, "[i]"); | |
| 303 | - | html = html.replace(/<u>/gi, "[u]"); | |
| 304 | - | html = html.replace(/<\/b>/gi, "[/b]"); | |
| 305 | - | html = html.replace(/<\/i>/gi, "[/i]"); | |
| 306 | - | html = html.replace(/<\/u>/gi, "[/u]"); | |
| 307 | - | html = html.replace(/<em>/gi, "[b]"); | |
| 308 | - | html = html.replace(/<\/em>/gi, "[/b]"); | |
| 309 | - | html = html.replace(/<strong>/gi, "[b]"); | |
| 310 | - | html = html.replace(/<\/strong>/gi, "[/b]"); | |
| 311 | - | html = html.replace(/<cite>/gi, "[i]"); | |
| 312 | - | html = html.replace(/<\/cite>/gi, "[/i]"); | |
| 313 | - | html = html.replace(/<font color="(.*?)">(.*?)<\/font>/gmi, "[color=$1]$2[/color]"); | |
| 314 | - | html = html.replace(/<font color=(.*?)>(.*?)<\/font>/gmi, "[color=$1]$2[/color]"); | |
| 315 | - | html = html.replace(/<link(.*?)>/gi, ""); | |
| 316 | - | html = html.replace(/<li(.*?)>(.*?)<\/li>/gi, "[*]$2"); | |
| 317 | - | html = html.replace(/<ul(.*?)>/gi, "[list]"); | |
| 318 | - | html = html.replace(/<\/ul>/gi, "[/list]"); | |
| 319 | - | html = html.replace(/<div>/gi, "\n"); | |
| 320 | - | html = html.replace(/<\/div>/gi, "\n"); | |
| 321 | - | html = html.replace(/<td(.*?)>/gi, " "); | |
| 322 | - | html = html.replace(/<tr(.*?)>/gi, "\n"); | |
| 323 | - | ||
| 324 | - | html = html.replace(/<img(.*?)src="(.*?)"(.*?)>/gi, "[img]$2[/img]"); | |
| 325 | - | html = html.replace(/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/gi, "[url=$2]$4[/url]"); | |
| 326 | - | ||
| 327 | - | html = html.replace(/<head>(.*?)<\/head>/gmi, ""); | |
| 328 | - | html = html.replace(/<object>(.*?)<\/object>/gmi, ""); | |
| 329 | - | html = html.replace(/<script(.*?)>(.*?)<\/script>/gmi, ""); | |
| 330 | - | html = html.replace(/<style(.*?)>(.*?)<\/style>/gmi, ""); | |
| 331 | - | html = html.replace(/<title>(.*?)<\/title>/gmi, ""); | |
| 332 | - | html = html.replace(/<!--(.*?)-->/gmi, "\n"); | |
| 333 | - | ||
| 334 | - | html = html.replace(/\/\//gi, "/"); | |
| 335 | - | html = html.replace(/http:\//gi, "http://"); | |
| 336 | - | ||
| 337 | - | html = html.replace(/<(?:[^>'"]*|(['"]).*?\1)*>/gmi, ""); | |
| 338 | - | html = html.replace(/\r\r/gi, ""); | |
| 339 | - | html = html.replace(/\[img]\//gi, "[img]"); | |
| 340 | - | html = html.replace(/\[url=\//gi, "[url="); | |
| 341 | - | ||
| 342 | - | html = html.replace(/(\S)\n/gi, "$1 "); | |
| 343 | - | ||
| 344 | - | return html; | |
| 299 | + | html = html.replace(/<br(.*?)>/gi, "\n"); | |
| 300 | + | html = html.replace(/<textarea(.*?)>(.*?)<\/textarea>/gmi, "\[code]$2\[\/code]"); | |
| 301 | + | html = html.replace(/<b>/gi, "[b]"); | |
| 302 | + | html = html.replace(/<i>/gi, "[i]"); | |
| 303 | + | html = html.replace(/<u>/gi, "[u]"); | |
| 304 | + | html = html.replace(/<\/b>/gi, "[/b]"); | |
| 305 | + | html = html.replace(/<\/i>/gi, "[/i]"); | |
| 306 | + | html = html.replace(/<\/u>/gi, "[/u]"); | |
| 307 | + | html = html.replace(/<em>/gi, "[b]"); | |
| 308 | + | html = html.replace(/<\/em>/gi, "[/b]"); | |
| 309 | + | html = html.replace(/<strong>/gi, "[b]"); | |
| 310 | + | html = html.replace(/<\/strong>/gi, "[/b]"); | |
| 311 | + | html = html.replace(/<cite>/gi, "[i]"); | |
| 312 | + | html = html.replace(/<\/cite>/gi, "[/i]"); | |
| 313 | + | html = html.replace(/<font color="(.*?)">(.*?)<\/font>/gmi, "[color=$1]$2[/color]"); | |
| 314 | + | html = html.replace(/<font color=(.*?)>(.*?)<\/font>/gmi, "[color=$1]$2[/color]"); | |
| 315 | + | html = html.replace(/<link(.*?)>/gi, ""); | |
| 316 | + | html = html.replace(/<li(.*?)>(.*?)<\/li>/gi, "[*]$2"); | |
| 317 | + | html = html.replace(/<ul(.*?)>/gi, "[list]"); | |
| 318 | + | html = html.replace(/<\/ul>/gi, "[/list]"); | |
| 319 | + | html = html.replace(/<div>/gi, "\n"); | |
| 320 | + | html = html.replace(/<\/div>/gi, "\n"); | |
| 321 | + | html = html.replace(/<td(.*?)>/gi, " "); | |
| 322 | + | html = html.replace(/<tr(.*?)>/gi, "\n"); | |
| 323 | + | ||
| 324 | + | html = html.replace(/<img(.*?)src="(.*?)"(.*?)>/gi, "[img]$2[/img]"); | |
| 325 | + | html = html.replace(/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/gi, "[url=$2]$4[/url]"); | |
| 326 | + | ||
| 327 | + | html = html.replace(/<head>(.*?)<\/head>/gmi, ""); | |
| 328 | + | html = html.replace(/<object>(.*?)<\/object>/gmi, ""); | |
| 329 | + | html = html.replace(/<script(.*?)>(.*?)<\/script>/gmi, ""); | |
| 330 | + | html = html.replace(/<style(.*?)>(.*?)<\/style>/gmi, ""); | |
| 331 | + | html = html.replace(/<title>(.*?)<\/title>/gmi, ""); | |
| 332 | + | html = html.replace(/<!--(.*?)-->/gmi, "\n"); | |
| 333 | + | ||
| 334 | + | html = html.replace(/\/\//gi, "/"); | |
| 335 | + | html = html.replace(/http:\//gi, "http://"); | |
| 336 | + | ||
| 337 | + | html = html.replace(/<(?:[^>'"]*|(['"]).*?\1)*>/gmi, ""); | |
| 338 | + | html = html.replace(/\r\r/gi, ""); | |
| 339 | + | html = html.replace(/\[img]\//gi, "[img]"); | |
| 340 | + | html = html.replace(/\[url=\//gi, "[url="); | |
| 341 | + | ||
| 342 | + | html = html.replace(/(\S)\n/gi, "$1 "); | |
| 343 | + | ||
| 344 | + | return html; | |
| 345 | 345 | } | |
| 346 | 346 | ||
| 347 | 347 | function descriptionHandler() | |
Alex Thomassen revised this gist 2 years ago. Go to revision
1 file changed, 74 insertions, 1 deletion
nyaa-shit.user.js
| @@ -3,12 +3,21 @@ | |||
| 3 | 3 | // @namespace github.com/Decicus | |
| 4 | 4 | // @match https://nyaa.si/* | |
| 5 | 5 | // @grant GM_setClipboard | |
| 6 | - | // @version 1.2.0 | |
| 6 | + | // @version 1.3.0 | |
| 7 | 7 | // @author Decicus | |
| 8 | 8 | // @description Adds some extra functionality to Nyaa. | |
| 9 | 9 | // ==/UserScript== | |
| 10 | 10 | ||
| 11 | 11 | let copyAmount = 5; | |
| 12 | + | const multipliers = { | |
| 13 | + | Bytes: 1, | |
| 14 | + | KiB: 1024, | |
| 15 | + | MiB: 1024 * 1024, | |
| 16 | + | GiB: 1024 * 1024 * 1024, | |
| 17 | + | TiB: 1024 * 1024 * 1024 * 1024, | |
| 18 | + | }; | |
| 19 | + | ||
| 20 | + | const sizesRegex = /(Bytes|KiB|MiB|GiB|TiB)/g; | |
| 12 | 21 | ||
| 13 | 22 | function getElements(linkType = 'download') | |
| 14 | 23 | { | |
| @@ -28,6 +37,69 @@ function getMagnets() | |||
| 28 | 37 | return getElements('magnet'); | |
| 29 | 38 | } | |
| 30 | 39 | ||
| 40 | + | /** | |
| 41 | + | * Calculate the approximate total size of all torrents listed in the table and append it as an information row at the bottom of the table | |
| 42 | + | */ | |
| 43 | + | function calculateTotalSize() | |
| 44 | + | { | |
| 45 | + | const timestamps = document.querySelectorAll('.torrent-list td[data-timestamp]'); | |
| 46 | + | let totalBytes = 0; | |
| 47 | + | for (const timestamp of timestamps) | |
| 48 | + | { | |
| 49 | + | const sizeCell = timestamp.previousElementSibling; | |
| 50 | + | const size = sizeCell.textContent.trim(); | |
| 51 | + | let suffix = size.match(sizesRegex); | |
| 52 | + | if (!suffix || suffix.length < 1) { | |
| 53 | + | console.error('Could not find size in element', sizeCell); | |
| 54 | + | continue; | |
| 55 | + | } | |
| 56 | + | ||
| 57 | + | suffix = suffix[0]; | |
| 58 | + | const multiplier = multipliers[suffix]; | |
| 59 | + | const sizeNumber = parseFloat(size.replace(` ${suffix}`, '').trim()); | |
| 60 | + | const torrentBytes = sizeNumber * multiplier; | |
| 61 | + | ||
| 62 | + | totalBytes += torrentBytes; | |
| 63 | + | console.log(totalBytes); | |
| 64 | + | } | |
| 65 | + | ||
| 66 | + | const multiplierKeys = Object.keys(multipliers).reverse(); | |
| 67 | + | let totalSize = `${totalBytes} Bytes`; | |
| 68 | + | for (const key of multiplierKeys) | |
| 69 | + | { | |
| 70 | + | if (totalBytes === 0) { | |
| 71 | + | break; | |
| 72 | + | } | |
| 73 | + | ||
| 74 | + | const divideBy = multipliers[key]; | |
| 75 | + | const result = totalBytes / divideBy; | |
| 76 | + | if (result > 1) { | |
| 77 | + | totalSize = `${result.toFixed(2)} ${key}`; | |
| 78 | + | break; | |
| 79 | + | } | |
| 80 | + | } | |
| 81 | + | ||
| 82 | + | const torrentList = document.querySelector('.torrent-list tbody'); | |
| 83 | + | const html = `<tr class="default" id="all-torrents-size"> | |
| 84 | + | <td class="text-center"> | |
| 85 | + | <a href="#all-torrents-size" title="Total size"> | |
| 86 | + | 💽 | |
| 87 | + | </a> | |
| 88 | + | </td> | |
| 89 | + | <td colspan="2"> | |
| 90 | + | <a href="#all-torrents-size">Total size</a> | |
| 91 | + | </td> | |
| 92 | + | <td class="text-center"><!-- Download --></td> | |
| 93 | + | <td class="text-center">${totalSize}</td> | |
| 94 | + | <td class="text-center"><!-- Timestamp --></td> | |
| 95 | + | <td class="text-center"><!-- Seeders --></td> | |
| 96 | + | <td class="text-center"><!-- Leechers --></td> | |
| 97 | + | <td class="text-center"><!-- Completed --></td> | |
| 98 | + | </tr>`; | |
| 99 | + | ||
| 100 | + | torrentList.insertAdjacentHTML('beforeend', html); | |
| 101 | + | } | |
| 102 | + | ||
| 31 | 103 | /** | |
| 32 | 104 | * Handler for copying download links (torrents) | |
| 33 | 105 | */ | |
| @@ -458,6 +530,7 @@ function init() { | |||
| 458 | 530 | titleHandler(); | |
| 459 | 531 | descriptionHandler(); | |
| 460 | 532 | torrentListViewHandler(); | |
| 533 | + | calculateTotalSize(); | |
| 461 | 534 | } | |
| 462 | 535 | ||
| 463 | 536 | init(); | |
Alex Thomassen revised this gist 2 years ago. Go to revision
1 file changed, 463 insertions
nyaa-shit.user.js(file created)
| @@ -0,0 +1,463 @@ | |||
| 1 | + | // ==UserScript== | |
| 2 | + | // @name Nyaa - Personal Tweaks | |
| 3 | + | // @namespace github.com/Decicus | |
| 4 | + | // @match https://nyaa.si/* | |
| 5 | + | // @grant GM_setClipboard | |
| 6 | + | // @version 1.2.0 | |
| 7 | + | // @author Decicus | |
| 8 | + | // @description Adds some extra functionality to Nyaa. | |
| 9 | + | // ==/UserScript== | |
| 10 | + | ||
| 11 | + | let copyAmount = 5; | |
| 12 | + | ||
| 13 | + | function getElements(linkType = 'download') | |
| 14 | + | { | |
| 15 | + | const elements = document.querySelectorAll(`.fa-${linkType}`); | |
| 16 | + | return Array.from(elements) | |
| 17 | + | .map(x => x.parentElement.href) | |
| 18 | + | .filter(x => x && x.trim() !== ''); | |
| 19 | + | } | |
| 20 | + | ||
| 21 | + | function getLinks() | |
| 22 | + | { | |
| 23 | + | return getElements('download'); | |
| 24 | + | } | |
| 25 | + | ||
| 26 | + | function getMagnets() | |
| 27 | + | { | |
| 28 | + | return getElements('magnet'); | |
| 29 | + | } | |
| 30 | + | ||
| 31 | + | /** | |
| 32 | + | * Handler for copying download links (torrents) | |
| 33 | + | */ | |
| 34 | + | function copyLinks(amount) | |
| 35 | + | { | |
| 36 | + | let links = getLinks(); | |
| 37 | + | if (amount && typeof amount === 'number') { | |
| 38 | + | amount = amount > links.length ? links.length : amount; | |
| 39 | + | links = links.slice(0, amount); | |
| 40 | + | } | |
| 41 | + | ||
| 42 | + | const list = links.join('\n'); | |
| 43 | + | GM_setClipboard(list); | |
| 44 | + | } | |
| 45 | + | ||
| 46 | + | /** | |
| 47 | + | * Handler for copying magnets | |
| 48 | + | */ | |
| 49 | + | function copyMagnets(amount) | |
| 50 | + | { | |
| 51 | + | let magnets = getMagnets(); | |
| 52 | + | if (amount && typeof amount === 'number') { | |
| 53 | + | amount = amount > magnets.length ? magnets.length : amount; | |
| 54 | + | magnets = magnets.slice(0, amount); | |
| 55 | + | } | |
| 56 | + | ||
| 57 | + | const list = magnets.join('\n'); | |
| 58 | + | GM_setClipboard(list); | |
| 59 | + | } | |
| 60 | + | ||
| 61 | + | /** | |
| 62 | + | * Changes the download links for torrents/magnets to trigger a copy, | |
| 63 | + | * instead of default handling (download for torrents, torrent *client* for magnets). | |
| 64 | + | */ | |
| 65 | + | function copyOnClick(ev) | |
| 66 | + | { | |
| 67 | + | ev.preventDefault(); | |
| 68 | + | ||
| 69 | + | const target = ev.target; | |
| 70 | + | const isAnchor = target.nodeName === 'A'; | |
| 71 | + | const parent = isAnchor ? target : target.parentElement; | |
| 72 | + | GM_setClipboard(parent.href + '\n'); | |
| 73 | + | ||
| 74 | + | const checkIcon = 'fa-check'; | |
| 75 | + | const originalIcon = parent.href.includes('/download/') ? 'fa-download' : 'fa-magnet'; | |
| 76 | + | ||
| 77 | + | const iconElement = !target.classList.contains('fa') ? target.querySelector('.fa') : target; | |
| 78 | + | console.log(iconElement); | |
| 79 | + | ||
| 80 | + | if (iconElement) { | |
| 81 | + | iconElement.classList.replace(originalIcon, checkIcon); | |
| 82 | + | ||
| 83 | + | setTimeout( | |
| 84 | + | function() { | |
| 85 | + | iconElement.classList.replace(checkIcon, originalIcon); | |
| 86 | + | }, | |
| 87 | + | 1500 | |
| 88 | + | ); | |
| 89 | + | } | |
| 90 | + | } | |
| 91 | + | ||
| 92 | + | /** | |
| 93 | + | * Changes said magnet/torrent links to use the `copyOnClick` handler. | |
| 94 | + | */ | |
| 95 | + | function changeToCopy() | |
| 96 | + | { | |
| 97 | + | const links = document.querySelectorAll('.fa-magnet, .fa-download'); | |
| 98 | + | ||
| 99 | + | for (const link of links) | |
| 100 | + | { | |
| 101 | + | link.parentElement.addEventListener('click', copyOnClick); | |
| 102 | + | } | |
| 103 | + | } | |
| 104 | + | ||
| 105 | + | /** | |
| 106 | + | * List of regex replacements so that I can copy titles as directory names, with my personally preferred naming scheme. | |
| 107 | + | */ | |
| 108 | + | const titleReplacements = [ | |
| 109 | + | { | |
| 110 | + | comment: 'Remove quoted series/movie title from the end', | |
| 111 | + | search: / \"[A-z0-9-!\s]+\"$/, | |
| 112 | + | replacement: '', | |
| 113 | + | }, | |
| 114 | + | { | |
| 115 | + | comment: 'Move release group to the end', | |
| 116 | + | search: /^\[([-\w ]+)\] (.+)$/, | |
| 117 | + | replacement: '$2 [$1]', | |
| 118 | + | }, | |
| 119 | + | { | |
| 120 | + | comment: 'Colon space to space dash space', | |
| 121 | + | search: /: /g, | |
| 122 | + | replacement: ' - ', | |
| 123 | + | }, | |
| 124 | + | { | |
| 125 | + | comment: 'Season naming so Sonarr doesnt get confused because its dumb', | |
| 126 | + | search: / \(Season (\d+)\)/g, | |
| 127 | + | replacement: ' - S$1', | |
| 128 | + | }, | |
| 129 | + | { | |
| 130 | + | comment: 'No slashes, please', | |
| 131 | + | search: /\//g, | |
| 132 | + | replacement: '-', | |
| 133 | + | }, | |
| 134 | + | { | |
| 135 | + | comment: 'Closing => Opening bracket spacing between each "tag"', | |
| 136 | + | search: /\]\[/g, | |
| 137 | + | replacement: '] [', | |
| 138 | + | }, | |
| 139 | + | { | |
| 140 | + | comment: 'Final replacement: Replace 2+ spaces with one space', | |
| 141 | + | search: /\s{2,}/g, | |
| 142 | + | replacement: ' ', | |
| 143 | + | }, | |
| 144 | + | ]; | |
| 145 | + | ||
| 146 | + | /** | |
| 147 | + | * Uses `titleReplacements` to "fix" torrent name when "Copy torrent name" button is clicked. | |
| 148 | + | */ | |
| 149 | + | function fixTitle(input) | |
| 150 | + | { | |
| 151 | + | let finalString = input.trim(); | |
| 152 | + | for (const replace of titleReplacements) | |
| 153 | + | { | |
| 154 | + | const { comment, search, replacement } = replace; | |
| 155 | + | ||
| 156 | + | const match = finalString.match(search); | |
| 157 | + | if (match === null) { | |
| 158 | + | continue; | |
| 159 | + | } | |
| 160 | + | ||
| 161 | + | console.log(`\nFound: ${search}\nComment: ${comment}\nMatches:\n- ${match.join('\n- ')}`); | |
| 162 | + | finalString = finalString.replace(search, replacement || ''); | |
| 163 | + | } | |
| 164 | + | ||
| 165 | + | // Deal with any excess whitespace | |
| 166 | + | finalString = finalString.trim(); | |
| 167 | + | console.log(`Original input: ${input}\nFinal string: ${finalString}`); | |
| 168 | + | ||
| 169 | + | return finalString; | |
| 170 | + | } | |
| 171 | + | ||
| 172 | + | /** | |
| 173 | + | * Adds copy button for torrent titles on torrent pages | |
| 174 | + | * Implements `fixTitle()` | |
| 175 | + | */ | |
| 176 | + | function titleHandler() | |
| 177 | + | { | |
| 178 | + | const title = document.querySelector('h3.panel-title'); | |
| 179 | + | ||
| 180 | + | if (!title) { | |
| 181 | + | return; | |
| 182 | + | } | |
| 183 | + | ||
| 184 | + | const titleParent = title.parentElement; | |
| 185 | + | ||
| 186 | + | const buttonParent = document.createElement('div'); | |
| 187 | + | buttonParent.setAttribute('class', 'btn-group pull-right'); | |
| 188 | + | ||
| 189 | + | const button = document.createElement('button'); | |
| 190 | + | button.textContent = '📋'; | |
| 191 | + | button.setAttribute('class', 'btn btn-primary btn-sm'); | |
| 192 | + | button.addEventListener('click', function() { | |
| 193 | + | const origText = button.textContent; | |
| 194 | + | ||
| 195 | + | button.textContent = '✔'; | |
| 196 | + | button.setAttribute('disabled', '1'); | |
| 197 | + | ||
| 198 | + | const fixedTitle = fixTitle(title.textContent.trim()); | |
| 199 | + | GM_setClipboard(fixedTitle); | |
| 200 | + | ||
| 201 | + | setTimeout( | |
| 202 | + | () => { | |
| 203 | + | button.textContent = origText; | |
| 204 | + | button.removeAttribute('disabled'); | |
| 205 | + | }, 1500 | |
| 206 | + | ); | |
| 207 | + | }); | |
| 208 | + | ||
| 209 | + | titleParent.classList.add('clearfix'); | |
| 210 | + | buttonParent.insertAdjacentElement('afterbegin', button); | |
| 211 | + | titleParent.insertAdjacentElement('afterbegin', buttonParent); | |
| 212 | + | } | |
| 213 | + | ||
| 214 | + | function bbcodeConverter(html) { | |
| 215 | + | html = html.replace(/<pre(.*?)>(.*?)<\/pre>/gmi, "[code]$2[/code]"); | |
| 216 | + | html = html.replace(/<h[1-7](.*?)>(.*?)<\/h[1-7]>/, "\n[h]$2[/h]\n"); | |
| 217 | + | //paragraph handling: | |
| 218 | + | //- if a paragraph opens on the same line as another one closes, insert an extra blank line | |
| 219 | + | //- opening tag becomes two line breaks | |
| 220 | + | //- closing tags are just removed | |
| 221 | + | // html += html.replace(/<\/p><p/<\/p>\n<p/gi; | |
| 222 | + | // html += html.replace(/<p[^>]*>/\n\n/gi; | |
| 223 | + | // html += html.replace(/<\/p>//gi; | |
| 224 | + | ||
| 225 | + | html = html.replace(/<\/p>\n<p>/gi, "\n\n\n"); | |
| 226 | + | ||
| 227 | + | html = html.replace(/<br(.*?)>/gi, "\n"); | |
| 228 | + | html = html.replace(/<textarea(.*?)>(.*?)<\/textarea>/gmi, "\[code]$2\[\/code]"); | |
| 229 | + | html = html.replace(/<b>/gi, "[b]"); | |
| 230 | + | html = html.replace(/<i>/gi, "[i]"); | |
| 231 | + | html = html.replace(/<u>/gi, "[u]"); | |
| 232 | + | html = html.replace(/<\/b>/gi, "[/b]"); | |
| 233 | + | html = html.replace(/<\/i>/gi, "[/i]"); | |
| 234 | + | html = html.replace(/<\/u>/gi, "[/u]"); | |
| 235 | + | html = html.replace(/<em>/gi, "[b]"); | |
| 236 | + | html = html.replace(/<\/em>/gi, "[/b]"); | |
| 237 | + | html = html.replace(/<strong>/gi, "[b]"); | |
| 238 | + | html = html.replace(/<\/strong>/gi, "[/b]"); | |
| 239 | + | html = html.replace(/<cite>/gi, "[i]"); | |
| 240 | + | html = html.replace(/<\/cite>/gi, "[/i]"); | |
| 241 | + | html = html.replace(/<font color="(.*?)">(.*?)<\/font>/gmi, "[color=$1]$2[/color]"); | |
| 242 | + | html = html.replace(/<font color=(.*?)>(.*?)<\/font>/gmi, "[color=$1]$2[/color]"); | |
| 243 | + | html = html.replace(/<link(.*?)>/gi, ""); | |
| 244 | + | html = html.replace(/<li(.*?)>(.*?)<\/li>/gi, "[*]$2"); | |
| 245 | + | html = html.replace(/<ul(.*?)>/gi, "[list]"); | |
| 246 | + | html = html.replace(/<\/ul>/gi, "[/list]"); | |
| 247 | + | html = html.replace(/<div>/gi, "\n"); | |
| 248 | + | html = html.replace(/<\/div>/gi, "\n"); | |
| 249 | + | html = html.replace(/<td(.*?)>/gi, " "); | |
| 250 | + | html = html.replace(/<tr(.*?)>/gi, "\n"); | |
| 251 | + | ||
| 252 | + | html = html.replace(/<img(.*?)src="(.*?)"(.*?)>/gi, "[img]$2[/img]"); | |
| 253 | + | html = html.replace(/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/gi, "[url=$2]$4[/url]"); | |
| 254 | + | ||
| 255 | + | html = html.replace(/<head>(.*?)<\/head>/gmi, ""); | |
| 256 | + | html = html.replace(/<object>(.*?)<\/object>/gmi, ""); | |
| 257 | + | html = html.replace(/<script(.*?)>(.*?)<\/script>/gmi, ""); | |
| 258 | + | html = html.replace(/<style(.*?)>(.*?)<\/style>/gmi, ""); | |
| 259 | + | html = html.replace(/<title>(.*?)<\/title>/gmi, ""); | |
| 260 | + | html = html.replace(/<!--(.*?)-->/gmi, "\n"); | |
| 261 | + | ||
| 262 | + | html = html.replace(/\/\//gi, "/"); | |
| 263 | + | html = html.replace(/http:\//gi, "http://"); | |
| 264 | + | ||
| 265 | + | html = html.replace(/<(?:[^>'"]*|(['"]).*?\1)*>/gmi, ""); | |
| 266 | + | html = html.replace(/\r\r/gi, ""); | |
| 267 | + | html = html.replace(/\[img]\//gi, "[img]"); | |
| 268 | + | html = html.replace(/\[url=\//gi, "[url="); | |
| 269 | + | ||
| 270 | + | html = html.replace(/(\S)\n/gi, "$1 "); | |
| 271 | + | ||
| 272 | + | return html; | |
| 273 | + | } | |
| 274 | + | ||
| 275 | + | function descriptionHandler() | |
| 276 | + | { | |
| 277 | + | const descriptionElem = document.querySelector('#torrent-description'); | |
| 278 | + | if (!descriptionElem) { | |
| 279 | + | return; | |
| 280 | + | } | |
| 281 | + | ||
| 282 | + | console.log(bbcodeConverter(descriptionElem.innerHTML)); | |
| 283 | + | ||
| 284 | + | const button = document.createElement('button'); | |
| 285 | + | button.textContent = '📋 Copy description as BBCode'; | |
| 286 | + | button.setAttribute('class', 'btn btn-primary'); | |
| 287 | + | button.addEventListener('click', function() { | |
| 288 | + | const origText = button.textContent; | |
| 289 | + | ||
| 290 | + | button.textContent = '✔ Copied!'; | |
| 291 | + | button.setAttribute('disabled', '1'); | |
| 292 | + | ||
| 293 | + | const descriptionBBcode = bbcodeConverter(descriptionElem.innerHTML).trim(); | |
| 294 | + | GM_setClipboard(descriptionBBcode); | |
| 295 | + | ||
| 296 | + | setTimeout( | |
| 297 | + | () => { | |
| 298 | + | button.textContent = origText; | |
| 299 | + | button.removeAttribute('disabled'); | |
| 300 | + | }, 1500 | |
| 301 | + | ); | |
| 302 | + | }); | |
| 303 | + | ||
| 304 | + | const panelHeading = document.createElement('div'); | |
| 305 | + | panelHeading.setAttribute('class', 'panel-heading'); | |
| 306 | + | panelHeading.insertAdjacentElement('beforeend', button); | |
| 307 | + | ||
| 308 | + | descriptionElem.insertAdjacentElement('beforebegin', panelHeading); | |
| 309 | + | } | |
| 310 | + | ||
| 311 | + | /** | |
| 312 | + | * Adds a clipboard icon (using Font Awesome 4) to each row that is marked for "mass copy". | |
| 313 | + | */ | |
| 314 | + | function addClipboardIconToRow() | |
| 315 | + | { | |
| 316 | + | const rows = document.querySelectorAll('.torrent-list > tbody > tr > td[colspan="2"]'); | |
| 317 | + | ||
| 318 | + | let currentAmount = 0; | |
| 319 | + | ||
| 320 | + | for (const row of rows) | |
| 321 | + | { | |
| 322 | + | currentAmount++; | |
| 323 | + | const iconExists = row.querySelector('a.clipboard-icon'); | |
| 324 | + | if (iconExists) { | |
| 325 | + | iconExists.remove(); | |
| 326 | + | } | |
| 327 | + | ||
| 328 | + | // Check if this row is past the point of "don't receive icon" | |
| 329 | + | if (currentAmount > copyAmount) { | |
| 330 | + | // `continue`, not `break` - If we break, then when we lower `copyAmount`, there will be extra rows with clipboard icon. | |
| 331 | + | continue; | |
| 332 | + | } | |
| 333 | + | ||
| 334 | + | row.insertAdjacentHTML('afterbegin', '<a href="#" class="comments clipboard-icon" style="margin-left: 0.5em;"><i class="fa fa-clipboard"></i></a>'); | |
| 335 | + | } | |
| 336 | + | } | |
| 337 | + | ||
| 338 | + | /** | |
| 339 | + | * Adds buttons and number input fields above torrent table, for "mass copying" links/magnets. | |
| 340 | + | */ | |
| 341 | + | function torrentListViewHandler() | |
| 342 | + | { | |
| 343 | + | const parentElement = document.querySelector('.table-responsive'); | |
| 344 | + | ||
| 345 | + | if (!parentElement) { | |
| 346 | + | return; | |
| 347 | + | } | |
| 348 | + | ||
| 349 | + | addClipboardIconToRow(); | |
| 350 | + | ||
| 351 | + | /** | |
| 352 | + | * Start: Copy all links/magnets | |
| 353 | + | */ | |
| 354 | + | const element = document.createElement('button'); | |
| 355 | + | element.innerHTML = '📋 Copy all download links <i class="fa fa-fw fa-download"></i>'; | |
| 356 | + | element.setAttribute('class', 'btn btn-default'); | |
| 357 | + | element.addEventListener('click', function() { | |
| 358 | + | const origText = element.innerHTML; | |
| 359 | + | ||
| 360 | + | element.innerHTML = '✔'; | |
| 361 | + | element.setAttribute('disabled', '1'); | |
| 362 | + | copyLinks(); | |
| 363 | + | ||
| 364 | + | setTimeout(() => { | |
| 365 | + | element.innerHTML = origText; | |
| 366 | + | element.removeAttribute('disabled'); | |
| 367 | + | }, 1500); | |
| 368 | + | }); | |
| 369 | + | ||
| 370 | + | const magnetCopy = document.createElement('button'); | |
| 371 | + | magnetCopy.innerHTML = '📋 Copy all magnets <i class="fa fa-fw fa-magnet"></i>'; | |
| 372 | + | magnetCopy.setAttribute('class', 'btn btn-default'); | |
| 373 | + | magnetCopy.addEventListener('click', function() { | |
| 374 | + | const origText = magnetCopy.innerHTML; | |
| 375 | + | ||
| 376 | + | magnetCopy.innerHTML = '✔'; | |
| 377 | + | magnetCopy.setAttribute('disabled', '1'); | |
| 378 | + | copyMagnets(); | |
| 379 | + | ||
| 380 | + | setTimeout(() => { | |
| 381 | + | magnetCopy.innerHTML = origText; | |
| 382 | + | magnetCopy.removeAttribute('disabled'); | |
| 383 | + | }, 1500); | |
| 384 | + | }); | |
| 385 | + | ||
| 386 | + | /** | |
| 387 | + | * End: Copy all links/magnets | |
| 388 | + | */ | |
| 389 | + | ||
| 390 | + | /** | |
| 391 | + | * Start: Copy X links/magnets | |
| 392 | + | */ | |
| 393 | + | const linkAmount = (getLinks()).length; | |
| 394 | + | copyAmount = linkAmount < 5 ? linkAmount : 5; | |
| 395 | + | const amountSelect = document.createElement('input'); | |
| 396 | + | amountSelect.setAttribute('type', 'number'); | |
| 397 | + | amountSelect.setAttribute('min', '2'); | |
| 398 | + | amountSelect.setAttribute('max', linkAmount); | |
| 399 | + | amountSelect.setAttribute('value', copyAmount); | |
| 400 | + | amountSelect.setAttribute('class', 'pull-right'); | |
| 401 | + | ||
| 402 | + | const amountCopyLinks = document.createElement('button'); | |
| 403 | + | amountCopyLinks.innerHTML = `📋 Copy ${copyAmount} download links <i class="fa fa-fw fa-download"></i>`; | |
| 404 | + | amountCopyLinks.setAttribute('class', 'btn btn-default pull-right'); | |
| 405 | + | amountCopyLinks.addEventListener('click', function() { | |
| 406 | + | const origText = amountCopyLinks.innerHTML; | |
| 407 | + | ||
| 408 | + | amountCopyLinks.innerHTML = '✔'; | |
| 409 | + | amountCopyLinks.setAttribute('disabled', '1'); | |
| 410 | + | copyLinks(copyAmount); | |
| 411 | + | ||
| 412 | + | setTimeout(() => { | |
| 413 | + | amountCopyLinks.innerHTML = origText; | |
| 414 | + | amountCopyLinks.removeAttribute('disabled'); | |
| 415 | + | }, 1500); | |
| 416 | + | }); | |
| 417 | + | ||
| 418 | + | const amountCopyMagnets = document.createElement('button'); | |
| 419 | + | amountCopyMagnets.innerHTML = `📋 Copy ${copyAmount} magnets <i class="fa fa-fw fa-magnet"></i>`; | |
| 420 | + | amountCopyMagnets.setAttribute('class', 'btn btn-default pull-right'); | |
| 421 | + | amountCopyMagnets.addEventListener('click', function() { | |
| 422 | + | const origText = amountCopyMagnets.innerHTML; | |
| 423 | + | ||
| 424 | + | amountCopyMagnets.innerHTML = '✔'; | |
| 425 | + | amountCopyMagnets.setAttribute('disabled', '1'); | |
| 426 | + | copyMagnets(copyAmount); | |
| 427 | + | ||
| 428 | + | setTimeout(() => { | |
| 429 | + | amountCopyMagnets.innerHTML = origText; | |
| 430 | + | amountCopyMagnets.removeAttribute('disabled'); | |
| 431 | + | }, 1500); | |
| 432 | + | }); | |
| 433 | + | ||
| 434 | + | amountSelect.addEventListener('change', function() { | |
| 435 | + | copyAmount = parseInt(amountSelect.value, 10); | |
| 436 | + | amountCopyLinks.innerHTML = `📋 Copy ${copyAmount} download links <i class="fa fa-fw fa-download"></i>`; | |
| 437 | + | amountCopyMagnets.innerHTML = `📋 Copy ${copyAmount} magnets <i class="fa fa-fw fa-magnet"></i>`; | |
| 438 | + | ||
| 439 | + | addClipboardIconToRow(); | |
| 440 | + | }); | |
| 441 | + | /** | |
| 442 | + | * End: Copy X links/magnets | |
| 443 | + | */ | |
| 444 | + | ||
| 445 | + | /** | |
| 446 | + | * Append all these buttons and inputs to the DOM. | |
| 447 | + | */ | |
| 448 | + | parentElement.insertAdjacentElement('beforebegin', element); | |
| 449 | + | parentElement.insertAdjacentElement('beforebegin', magnetCopy); | |
| 450 | + | ||
| 451 | + | parentElement.insertAdjacentElement('beforebegin', amountSelect); | |
| 452 | + | parentElement.insertAdjacentElement('beforebegin', amountCopyMagnets); | |
| 453 | + | parentElement.insertAdjacentElement('beforebegin', amountCopyLinks); | |
| 454 | + | } | |
| 455 | + | ||
| 456 | + | function init() { | |
| 457 | + | changeToCopy(); | |
| 458 | + | titleHandler(); | |
| 459 | + | descriptionHandler(); | |
| 460 | + | torrentListViewHandler(); | |
| 461 | + | } | |
| 462 | + | ||
| 463 | + | init(); | |