eD2k Book Library

Add an eD2k (eDonkey2000) links to Anna’s Archive.

  1. // ==UserScript==
  2. // @name eD2k Book Library
  3. // @description Add an eD2k (eDonkey2000) links to Anna’s Archive.
  4. // @author Schimon Jehudah, Adv.
  5. // @namespace i2p.schimon.ed2k-book-library
  6. // @homepageURL https://greasyfork.org/scripts/521451-ed2k-book-library
  7. // @supportURL https://greasyfork.org/scripts/521451-ed2k-book-library/feedback
  8. // @copyright 2024, Schimon Jehudah (http://schimon.i2p)
  9. // @license MIT; https://opensource.org/licenses/MIT
  10. // @match *://annas-archive.li/md5/*
  11. // @match *://annas-archive.org/md5/*
  12. // @match *://annas-archive.se/md5/*
  13. // @match *://libgen.bz/*
  14. // @match *://libgen.gs/*
  15. // @match *://libgen.io/*
  16. // @match *://libgen.la/*
  17. // @match *://libgen.li/*
  18. // @match *://libgen.org/*
  19. // @match *://libgen.vg/*
  20. // @version 1.0.0
  21. // ==/UserScript==
  22.  
  23. const
  24. namespace = 'i2p-schimon-ed2k-book-library';
  25.  
  26. // create button
  27. (function init() {
  28. // Properties
  29. let bookMd5sum, bookUri, bookTitle;
  30. if (location.search.startsWith('?md5=')) {
  31. url = new URL (location.href)
  32. bookMd5sum = url.searchParams.get('md5');
  33. bookTitle = 'Book ' + document.evaluate('/html/body/table/tbody/tr[2]/td[2]/table/tbody/tr[2]/td[2]/text()[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.textContent;
  34. } else {
  35. bookTitle = 'Book ' + document.title;
  36. bookMd5sum = document.documentURI.split('/')[4];
  37. }
  38. //bookFormat =
  39. bookSize = 1 // TODO Extract MB and convert to bytes: mb * 1024 * 1024
  40. // create element
  41. createButton('🫏', 90, `ed2k://|file|${bookTitle}|${bookSize}|${bookMd5sum}|/`);
  42. createButton('🧲', 20, `magnet:?dn=${bookTitle}&xt=urn:ed2k:${bookMd5sum}&xt=urn:ed2khash:${bookMd5sum}&xl=${bookSize}`);
  43. })();
  44.  
  45. function createButton(icon, pixels, uri) {
  46. btn = document.createElement('a');
  47. // set content
  48. btn.textContent = icon;
  49. btn.id = namespace;
  50. btn.href = uri
  51. //btn.style.all = 'unset';
  52. // set position
  53. btn.style.position = 'fixed';
  54. btn.style.bottom = pixels + 'px';
  55. btn.style.right = '10px';
  56. // set appearance
  57. btn.style.background = '#000';
  58. btn.style.filter = 'drop-shadow(2px 4px 6px #ff0000)';
  59. btn.style.borderRadius = '50px'
  60. btn.style.marginTop = '100px';
  61. btn.style.marginRight = '10px';
  62. btn.style.minWidth = '50px';
  63. btn.style.minHeight = '50px';
  64. btn.style.fontSize = '25px';
  65. btn.style.zIndex = 10000;
  66. // center character
  67. btn.style.justifyContent = 'center';
  68. btn.style.alignItems = 'center';
  69. btn.style.display = 'flex';
  70. btn.style.textDecoration = 'none';
  71. // disable selection marks
  72. btn.style.outline = 'none';
  73. btn.style.userSelect = 'none';
  74. btn.style.cursor = 'default';
  75. // set button behaviour
  76. btn.onclick = () => {
  77. location.href = uri
  78. };
  79. btn.onmouseover = () => {
  80. btn.style.filter = 'drop-shadow(2px 4px 6px #0000ff)';
  81. };
  82. btn.onmouseout = () => {
  83. btn.style.filter = 'drop-shadow(2px 4px 6px #ff0000)';
  84. };
  85. document.body.append(btn);
  86. }