Sleazy Fork is available in English.

Save NHentai images to Eagle

go to the manga selection page and then just right click and then save. Happy fapping! (VPN required)

  1. // ==UserScript==
  2. // @name Save NHentai images to Eagle
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description go to the manga selection page and then just right click and then save. Happy fapping! (VPN required)
  6. // @author GreasyWeebs
  7. // @match *://*/*
  8. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  9. // @run-at context-menu
  10. // @require https://code.jquery.com/jquery-3.5.1.min.js
  11. // @grant GM_xmlhttpRequest
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. const EAGLE_SERVER_URL = "http://localhost:41595";
  18. const EAGLE_IMPORT_API_URL = `${EAGLE_SERVER_URL}/api/item/addFromURL`;
  19. const EAGLE_CREATE_FOLDER_API_URL = `${EAGLE_SERVER_URL}/api/folder/create`;
  20.  
  21. const SELECTOR_IMAGE = ".gallery a";
  22. const SELECTOR_HIGHRES = ".thumb-container noscript img";
  23. var imgElements = Array.from(document.querySelectorAll(SELECTOR_IMAGE));
  24. var galleryElements = Array.from(document.querySelectorAll('.gallery'));
  25. var galleryCount = galleryElements.length;
  26. var count = 0;
  27.  
  28. var createFolder = function(folderName, callback) {
  29. GM_xmlhttpRequest({
  30. url: EAGLE_CREATE_FOLDER_API_URL,
  31. method: "POST",
  32. data: JSON.stringify({ folderName: folderName }),
  33. onload: function(response) {
  34. try {
  35. var result = JSON.parse(response.response);
  36. if (result.status === "success" && result.data && result.data.id) {
  37. callback(undefined, result.data);
  38. } else {
  39. callback(true);
  40. }
  41. } catch (err) {
  42. callback(true);
  43. }
  44. }
  45. });
  46. };
  47.  
  48. function addImageToEagle(data) {
  49. GM_xmlhttpRequest({
  50. url: EAGLE_IMPORT_API_URL,
  51. method: "POST",
  52. data: JSON.stringify(data),
  53. onload: function (response) {
  54. }
  55. });
  56. }
  57.  
  58. function saveImages(folder, title, imgCount, hiresImgID, tagsData, imgLinkSource){
  59. for(var i=0;i<imgCount;i++){
  60. var saveData = {
  61. "url": "https://i.nhentai.net/galleries/"+hiresImgID+"/"+(i+1)+".jpg",
  62. "name": 'page '+(i+1),
  63. "website": imgLinkSource,
  64. "folderId": folder.id,
  65. "tags": tagsData,
  66. "headers": {
  67. "referer": "nhentai.net"
  68. }
  69. };
  70. addImageToEagle(saveData);
  71. }
  72. }
  73.  
  74. var fetchImg = setInterval(function(){
  75. $.get(imgElements[count].href, function (html) {
  76. var parser = new DOMParser();
  77. var doc = parser.parseFromString(html, "text/html");
  78. var preloadData = Array.from(doc.querySelectorAll('.thumb-container'));
  79. var imgCount = preloadData.length;
  80. var titleRaw = Array.from(doc.querySelectorAll('.title'));
  81. var title = titleRaw[0].querySelector('.title .before').innerHTML+" "+titleRaw[0].querySelector('.title .pretty').innerHTML+" "+titleRaw[0].querySelector('.title .after').innerHTML;
  82. var hiresImg = Array.from(doc.querySelectorAll(SELECTOR_HIGHRES));
  83. var hiresImgSplit1 = hiresImg[0].src.split("https://t.nhentai.net/galleries/");
  84. var hiresImgSplit2 = hiresImgSplit1[1].split("/1t");
  85. var hiresImgID = hiresImgSplit2[0];
  86. var tags = Array.from(doc.querySelectorAll('.tag-container .tags a .name'));
  87. var imgLinkSource = imgElements[count].href;
  88. var tagsData = [];
  89. for(var i=0;i<tags.length-1;i++){
  90. tagsData[i] = tags[i].innerHTML;
  91. }
  92. createFolder(title, function (err, folder) {
  93. if (folder) {
  94. saveImages(folder, title, imgCount, hiresImgID, tagsData, imgLinkSource);
  95. } else {
  96. alert("folder is not exist");
  97. }
  98. });
  99. });
  100. count++;
  101. if(count==galleryCount){
  102. clearInterval(fetchImg);
  103. }
  104. }, 1000);
  105. })();