Greasy Fork is available in English.

Liblib tool

一键下载Liblib.art模型+配图+简介

  1. // ==UserScript==
  2. // @name Liblib tool
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.22
  5. // @description 一键下载Liblib.art模型+配图+简介
  6. // @author 宇泽同学
  7. // @license MIT
  8. // @match https://www.liblib.art/*
  9. // @grant GM_download
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // 添加按钮和选择器的样式
  16. var style = document.createElement('style');
  17. style.type = 'text/css';
  18. style.innerHTML = `
  19. .custom-button {
  20. background: linear-gradient(to right, #23caff,#56e5a9); /* 渐变色 */
  21. color: white;
  22. width: 100px;
  23. height: 35px;
  24. padding: 5px 15px;
  25. text-align: center;
  26. text-decoration: none;
  27. display: inline-block;
  28. font-size: 16px;
  29. margin: 5px 2px;
  30. cursor: pointer;
  31. border: none;
  32. border-radius: 20px;
  33. }
  34. .image-count-selector {
  35. width: 65px; /* 边框宽度 */
  36. height: 35px;
  37. padding: 5px;
  38. border: 1px solid #4CAF50; /* Green border */
  39. border-radius: 20px;
  40. margin-left: 5px;
  41. display: inline-block;
  42. border-width:1.5px 1.5px 1.5px 1.5px
  43. }
  44. `;
  45. document.head.appendChild(style);
  46.  
  47. // 检查并添加按钮的函数
  48. function checkAndAddButtons() {
  49. const generateButton = document.querySelector('.ModelActionCard_runPic__0I9wi');
  50. if (generateButton && !document.querySelector('.one-click-download')) {
  51. // 创建"下载全部"按钮
  52. const downloadButton = document.createElement('button');
  53. downloadButton.innerHTML = '下载全部';
  54. downloadButton.className = 'custom-button one-click-download';
  55. downloadButton.onclick = autoDownload;
  56.  
  57. // 创建"下载图片"按钮
  58. const downloadImageButton = document.createElement('button');
  59. downloadImageButton.innerHTML = '下载图片';
  60. downloadImageButton.className = 'custom-button download-images-only';
  61. downloadImageButton.onclick = function() {
  62. const modelName = getModelName();
  63. const imageCount = document.querySelector('.image-count-selector').value;
  64. downloadImages(modelName, imageCount);
  65. };
  66.  
  67. // 创建图片数量选择器
  68. const imageCountSelector = document.createElement('input');
  69. imageCountSelector.type = 'number';
  70. imageCountSelector.min = '1';
  71. imageCountSelector.value = '1'; // 默认值为1
  72. imageCountSelector.className = 'image-count-selector';
  73.  
  74. // 将"下载图片"按钮和图片数量选择器添加到页面上
  75. generateButton.parentNode.insertBefore(downloadButton, generateButton.nextSibling);
  76. generateButton.parentNode.insertBefore(downloadImageButton, downloadButton.nextSibling);
  77. generateButton.parentNode.insertBefore(imageCountSelector, downloadImageButton.nextSibling);
  78.  
  79. // 创建"下载简介"按钮
  80. const downloadDocButton = document.createElement('button');
  81. downloadDocButton.innerHTML = '下载简介';
  82. downloadDocButton.className = 'custom-button download-doc-only';
  83. downloadDocButton.onclick = function() {
  84. const modelName = getModelName();
  85. saveAsPlainText(modelName);
  86. };
  87.  
  88. generateButton.parentNode.insertBefore(downloadDocButton, imageCountSelector.nextSibling);
  89. }
  90. }
  91.  
  92. // 建立MutationObserver以监视DOM变化
  93. const observer = new MutationObserver(function(mutations) {
  94. mutations.forEach(function(mutation) {
  95. if (mutation.type === 'childList') {
  96. checkAndAddButtons();
  97. }
  98. });
  99. });
  100.  
  101. // 在DOMContentLoaded事件中初始化按钮和观察者
  102. document.addEventListener('DOMContentLoaded', function() {
  103. checkAndAddButtons();
  104. observer.observe(document.body, { childList: true, subtree: true });
  105. });
  106.  
  107. // 获取选中的Tab名称
  108. function getSelectedTabName() {
  109. //...保留原有的getSelectedTabName函数...
  110. // 获取所有的tab
  111. var tabs = document.querySelectorAll('.ant-tabs-tab');
  112.  
  113. // 遍历所有的tab
  114. for (var i = 0; i < tabs.length; i++) {
  115. // 获取aria-selected属性
  116. var isSelected = tabs[i].querySelector('.ant-tabs-tab-btn').getAttribute('aria-selected');
  117.  
  118. // 检查tab是否被选中
  119. if (isSelected === 'true') {
  120. // 获取tab的标题
  121. var title = tabs[i].textContent;
  122. return title; // 返回标题
  123. }
  124. }
  125.  
  126. }
  127.  
  128. // 获取模型名称
  129. function getModelName() {
  130. var version = getSelectedTabName();
  131. var modelName = document.querySelector('.ModelInfoHead_title__p5txd').innerText;
  132. modelName += "_" + version;
  133. return modelName;
  134. }
  135.  
  136. // 自动下载函数
  137. function autoDownload() {
  138. var modelName = getModelName();
  139. downloadModel();
  140. saveAsPlainText(modelName);
  141.  
  142. var imageCount = document.querySelector('.image-count-selector').value;
  143. downloadImages(modelName, imageCount);
  144. }
  145.  
  146. // 下载模型函数
  147. function downloadModel() {
  148. var downloadButton = document.querySelector('.ModelActionCard_inner__XBdzk');
  149. if (downloadButton) {
  150. downloadButton.click();
  151. }
  152. }
  153. // 选择简介函数
  154. function selectReadme() {
  155. var mainElement = document.querySelector('.mantine-AppShell-main');
  156. return mainElement.querySelector('[class^="ModelDescription_desc"]');
  157. }
  158.  
  159. // 记录URL函数
  160. function recordURL(modelName) {
  161. var url = window.location.href;
  162. var blob = new Blob([url], { type: 'text/plain' });
  163. var urlObject = window.URL.createObjectURL(blob);
  164. var downloadLink = document.createElement('a');
  165. downloadLink.href = urlObject;
  166. downloadLink.download = modelName + '_URL.txt';
  167. downloadLink.click();
  168. window.URL.revokeObjectURL(urlObject);
  169. }
  170.  
  171. function saveAsHTML(modelName) {
  172. var descriptionElement = selectReadme();
  173. if (descriptionElement) {
  174. var htmlText = descriptionElement.innerHTML;
  175. var blob = new Blob([htmlText], { type: 'text/html' });
  176. var url = window.URL.createObjectURL(blob);
  177. var link = document.createElement('a');
  178. link.href = url;
  179. link.download = modelName + '.html';
  180. link.style.display = 'none';
  181. document.body.appendChild(link);
  182. console.log('Attempting to download HTML file:', link.download);
  183. link.click();
  184. document.body.removeChild(link);
  185. } else {
  186. console.log('Description element not found.');
  187. }
  188. }
  189.  
  190.  
  191.  
  192. function saveAsPlainText(modelName) {
  193. var descriptionElement = selectReadme();
  194. if (descriptionElement) {
  195. var plainText = descriptionElement.innerText;
  196. // Append the model URL and empty lines
  197. plainText += "\n\n☑️本模型地址:" + window.location.href + "\n\n";
  198. var blob = new Blob([plainText], { type: 'text/plain' });
  199. var url = window.URL.createObjectURL(blob);
  200. var link = document.createElement('a');
  201. link.href = url;
  202. link.download = modelName + '.txt';
  203. link.style.display = 'none';
  204. document.body.appendChild(link);
  205. console.log('Attempting to download text file:', link.download);
  206. link.click();
  207. document.body.removeChild(link);
  208. } else {
  209. console.log('Description element not found.');
  210. }
  211. }
  212.  
  213. async function downloadImages(modelName, maxImages) {
  214. var images = document.querySelectorAll('img');
  215. var count = 0;
  216. if (images.length > 0) {
  217. for (var i = 0; i < images.length && count < maxImages; i++) {
  218. // 检查图片地址是否符合预期的格式
  219. if (images[i].src.startsWith('https://liblibai-online.vibrou.com/img/') ||
  220. images[i].src.startsWith('https://liblibai-online.vibrou.com/web/image/')) {
  221. var url = new URL(images[i].src);
  222. var pathSegments = url.pathname.split('/').filter(Boolean); // 分割路径并过滤空值
  223. // 拼接出清洁的URL,移除任何额外的查询参数或片段
  224. var cleanUrl = url.protocol + '//' + url.host + '/' + pathSegments.join('/');
  225.  
  226. // 如果 count 为 0,不添加后缀,如果 count 大于 0,后缀从 _2 开始
  227. var fileNameSuffix = count > 0 ? '_' + (count + 1) : '';
  228. GM_download({
  229. url: cleanUrl,
  230. name: modelName + fileNameSuffix + '.png', // 添加 fileNameSuffix 以区分下载的图片
  231. saveAs: true
  232. });
  233. count++; // 增加 count
  234. await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒钟以避免服务器过载
  235. }
  236. }
  237. }
  238. }
  239.  
  240. //...保留其他必要的代码和函数...
  241.  
  242. })();