Greasy Fork is available in English.

Script Finder

Script Finder allows you to find userscripts from greasyfork on any website.

  1. // ==UserScript==
  2. // @name Script Finder
  3. // @name:zh-CN Script Finder 油猴脚本查找
  4. // @namespace http://tampermonkey.net/
  5. // @version 0.1.6
  6. // @description Script Finder allows you to find userscripts from greasyfork on any website.
  7. // @description:zh-CN Script Finder 在任何网站上找到适用于该网站的greasyfork油猴脚本
  8. // @author shiquda
  9. // @namespace https://github.com/shiquda/shiquda_UserScript
  10. // @supportURL https://github.com/shiquda/shiquda_UserScript/issues
  11. // @match *://*/*
  12. // @connect greatest.deepsurf.us
  13. // @icon data:image/jpeg;base64,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
  14. // @grant GM_xmlhttpRequest
  15. // @grant GM_addStyle
  16. // @license AGPL-3.0
  17. // ==/UserScript==
  18.  
  19. (function () {
  20. const domainParts = window.location.hostname.split('.').slice(-2);
  21. const domain = domainParts.join('.');
  22. const errorMessage = "Failed to retrieve script information or there are no available scripts for this domain.";
  23. let neverLoadedScripts = true
  24. let collapsed = true
  25. let loadedPages = 0
  26.  
  27. function getScriptsInfo(domain, page = 1) {
  28. var url = `https://greatest.deepsurf.us/scripts/by-site/${domain}?filter_locale=0&page=${page}`;
  29. GM_xmlhttpRequest({
  30. method: "GET",
  31. url: url,
  32. onload: (response) => {
  33. // 解析结果
  34. const parser = new DOMParser();
  35. const doc = parser.parseFromString(response.responseText, "text/html");
  36. const scripts = doc.querySelector("#browse-script-list")?.querySelectorAll('[data-script-id]');
  37. let scriptsInfo = [];
  38. if (!scripts) {
  39. scriptsInfo = errorMessage
  40. } else {
  41. for (var i = 0; i < scripts.length; i++) {
  42. scriptsInfo.push(parseScriptInfo(scripts[i]));
  43. }
  44. }
  45.  
  46. // 处理对象
  47. const loadMoreButton = document.querySelector('.load-more')
  48. console.log(doc.querySelector('.next_page'))
  49. if (doc.querySelector('.next_page') == null || doc.querySelector('.next_page')?.getAttribute('aria-disabled') === 'true') {
  50. loadedPages = 'max'
  51. loadMoreButton.disabled = true
  52. loadMoreButton.textContent = 'All scripts loaded'
  53. } else {
  54. loadMoreButton.disabled = false
  55. loadMoreButton.textContent = 'Load more'
  56. }
  57. // console.log(scriptsInfo);
  58. document.querySelector('.wait-loading').style.display = 'none'
  59. loadMoreButton.style.display = 'block'
  60. appendScriptsInfo(scriptsInfo);
  61. updateMatches()
  62.  
  63. typeof (loadedPages) === 'number' ? loadedPages += 1 : loadedPages = loadedPages
  64. // console.log(loadedPages)
  65. },
  66. onerror: () => {
  67. console.log("Some error occurred!");
  68. if (loadedPages === 0) {
  69. appendScriptsInfo(scriptsInfo)
  70. }
  71. const scriptsInfo = errorMessage
  72. document.querySelector('.wait-loading').style.display = 'none'
  73. }
  74. });
  75. }
  76.  
  77. // 解析脚本信息
  78. function parseScriptInfo(script) {
  79. return {
  80. id: script.getAttribute('data-script-id'),
  81. name: script.getAttribute('data-script-name'),
  82. author: script.querySelector("dd.script-list-author").textContent,
  83. description: script.querySelector(".script-description").textContent,
  84. version: script.getAttribute('data-script-version'),
  85. url: 'https://greatest.deepsurf.us/scripts/' + script.getAttribute('data-script-id'),
  86. createDate: script.getAttribute('data-script-created-date'),
  87. updateDate: script.getAttribute('data-script-updated-date'),
  88. installs: script.getAttribute('data-script-total-installs'),
  89. dailyInstalls: script.getAttribute('data-script-daily-installs'),
  90. ratingScore: script.getAttribute('data-script-rating-score')
  91. };
  92. }
  93.  
  94. // 插入脚本
  95. function appendScriptsInfo(scriptsInfo) {
  96. const infoList = document.querySelector('.info-list');
  97. if (scriptsInfo === errorMessage) {
  98. infoList.innerHTML = errorMessage;
  99. } else {
  100. for (var i = 0; i < scriptsInfo.length; i++) {
  101. var script = scriptsInfo[i];
  102. var listItem = document.createElement('li');
  103. listItem.className = 'info-item';
  104.  
  105. var scriptContainer = document.createElement('div');
  106. scriptContainer.className = 'script-container';
  107.  
  108. var nameElement = document.createElement('a');
  109. nameElement.className = 'script-link';
  110. nameElement.innerText = script.name;
  111. nameElement.href = script.url;
  112. nameElement.target = '_blank';
  113.  
  114. var descriptionElement = document.createElement('p');
  115. descriptionElement.className = 'script-description';
  116. descriptionElement.innerHTML = script.description;
  117.  
  118. var detailsContainer = document.createElement('div');
  119. detailsContainer.className = 'details-container';
  120.  
  121. // 创建一键安装按钮
  122. var installButton = document.createElement('a');
  123. installButton.className = 'install-button';
  124. installButton.innerText = `Install ${script.version}`;
  125. installButton.href = `https://greatest.deepsurf.us/scripts/${script.id}/code/script.user.js`;
  126.  
  127. const details = [
  128. { key: 'Author', value: script.author },
  129. { key: 'Installs', value: script.installs },
  130. { key: 'Daily Installs', value: script.dailyInstalls },
  131. { key: 'Created', value: script.createDate },
  132. { key: 'Updated', value: script.updateDate },
  133. { key: 'Rating', value: script.ratingScore }
  134. ];
  135.  
  136. for (let i = 0; i < details.length; i++) {
  137. const spanElement = document.createElement('span');
  138. spanElement.className = 'script-details';
  139. spanElement.innerText = `${details[i].key}:\n${details[i].value}`;
  140. detailsContainer.appendChild(spanElement);
  141. }
  142.  
  143. scriptContainer.appendChild(nameElement);
  144. scriptContainer.appendChild(descriptionElement);
  145. scriptContainer.appendChild(detailsContainer);
  146. scriptContainer.appendChild(installButton);
  147.  
  148. listItem.appendChild(scriptContainer);
  149. listItem.scriptId = script.id;
  150. infoList.appendChild(listItem);
  151. }
  152. }
  153. }
  154.  
  155. function setupUI() {
  156. GM_addStyle(`
  157. button.script-button {
  158. position: fixed;
  159. bottom: 50%;
  160. right: -50px;
  161. transform: translateY(50%);
  162. padding: 10px;
  163. font-size: 16px;
  164. border: none;
  165. border-radius: 4px;
  166. background-color: #1e90ff;
  167. color: #ffffff;
  168. cursor: pointer;
  169. transition: right 0.3s;
  170. z-index: 9999999999999999; /* 设置一个较高的 z-index 值 */
  171. }
  172. div.info-container {
  173. display: none;
  174. position: fixed;
  175. top: 10%;
  176. right: 100px;
  177. width: 650px;
  178. padding: 12px;
  179. background-color: #ffffff;
  180. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
  181. border-radius: 4px;
  182. opacity: 0;
  183. transition: opacity 0.3s;
  184. z-index: 9999;
  185. max-height: 80vh;
  186. overflow-y: auto;
  187. }
  188. ul.info-list {
  189. list-style: none;
  190. margin: 0;
  191. padding: 0;
  192. }
  193. li.info-item {
  194. margin-bottom: 15px;
  195. padding: 12px;
  196. padding-bottom: 22px;
  197. display: flex;
  198. flex-direction: column;
  199. border: 1px solid #1e90ff;
  200. border-radius: 5px;
  201. }
  202. .div.script-container {
  203. display: flex;
  204. flex-direction: column;
  205. }
  206. a.script-link {
  207. font-size: 18px !important;
  208. font-weight: bold !important;
  209. margin-bottom: 5px !important;
  210. color: #1e90ff !important;
  211. }
  212. p.script-description {
  213. color: black !important;
  214. margin-top: 2px;
  215. margin-bottom: 5px;
  216. font-size: 16px;
  217. }
  218. div.details-container {
  219. font-size: 15px;
  220. font-weight: bold;
  221. display: flex;
  222. justify-content: space-between;
  223. margin-bottom: 15px;
  224. }
  225. span.script-details {
  226. font: !important
  227. color: black !important;
  228. flex-grow: 1 !important;
  229. text-align: center !important;
  230. border: 1px solid #1e90ff !important;
  231. border-radius: 5px !important;
  232. margin: 4px !important;
  233. }
  234. div.table-header {
  235. color: #1e90ff !important;
  236. font-size: 25px;
  237. font-weight: bold;
  238. }
  239. input.script-search-input {
  240. width: 96% !important;
  241. padding: 10px !important;
  242. font-size: 18px !important;
  243. border: 1px solid #1e90ff !important;
  244. border-radius: 4px !important;
  245. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3) !important;
  246. margin-bottom: 15px !important;
  247. margin-top: 20px !important;
  248. }
  249. a.install-button {
  250. font-size: 20px;
  251. background-color: green;
  252. color: white;
  253. padding: 12px;
  254. }
  255. button.to-greasyfork {
  256. position: absolute;
  257. top: 12px;
  258. right: 12px;
  259. border-radius: 4px;
  260. padding: 8px;
  261. font-size: 16px;
  262. border: none;
  263. background-color: #1e90ff;
  264. color: #ffffff;
  265. cursor: pointer;
  266. }
  267. span.match-count {
  268. background-color: #1e90ff;
  269. font-size: 25px;
  270. font-weight: bold;
  271. color: white;
  272. padding: 6px;
  273. position: absolute;
  274. right: 50%;
  275. border-radius: 12px;
  276. top: 10px;
  277. }
  278. div.wait-loading {
  279. font-size: 20px;
  280. font-weight: bold;
  281. color: #1e90ff;
  282. animation: blink 1s infinite;
  283. }
  284. @keyframes fadeInOut {
  285. 0% {
  286. opacity: 0;
  287. }
  288. 50% {
  289. opacity: 1;
  290. }
  291. 100% {
  292. opacity: 0;
  293. }
  294. }
  295. @keyframes blink {
  296. 0%, 100% {
  297. opacity: 0;
  298. }
  299. 50% {
  300. opacity: 1;
  301. }
  302. }
  303. button.load-more {
  304. border-radius: 4px;
  305. padding: 8px;
  306. font-size: 16px;
  307. border: none;
  308. background-color: #1e90ff;
  309. color: #ffffff;
  310. cursor: pointer;
  311. position: relative;
  312. bottom: 5px;
  313. left: 50%;
  314. transform: translateX(-50%);
  315. }
  316. button.load-more:disabled {
  317. background-color: #cccccc;
  318. cursor: not-allowed;
  319. }
  320. `);
  321.  
  322.  
  323. // 创建打开列表按钮
  324. var button = document.createElement('button');
  325. button.className = 'script-button';
  326. button.innerText = 'Scripts';
  327.  
  328. // 创建脚本容器
  329. var infoContainer = document.createElement('div');
  330. infoContainer.className = 'info-container';
  331.  
  332. // 创建搜索框
  333. var searchInput = document.createElement('input');
  334. searchInput.type = 'text';
  335. searchInput.placeholder = 'Search scripts...';
  336. searchInput.className = 'script-search-input';
  337.  
  338. // 创建指向greasyfork的链接
  339. var toGreasyfork = document.createElement('button');
  340. toGreasyfork.className = 'to-greasyfork';
  341. toGreasyfork.innerText = 'View on Greasyfork';
  342.  
  343. // 创建计数器
  344. var matchCount = document.createElement('span');
  345. matchCount.className = 'match-count';
  346.  
  347. // 创建表头
  348. var tableHeader = document.createElement('div');
  349. tableHeader.className = 'table-header';
  350. tableHeader.appendChild(document.createTextNode('Script Finder'));
  351. tableHeader.appendChild(matchCount);
  352. tableHeader.appendChild(searchInput);
  353. tableHeader.appendChild(toGreasyfork);
  354.  
  355. // 创建脚本列表
  356. var infoList = document.createElement('ul');
  357. infoList.className = 'info-list';
  358.  
  359. // 创建等待加载
  360. var waitLoading = document.createElement('div');
  361. waitLoading.className = 'wait-loading';
  362. waitLoading.innerText = 'Loading scripts...';
  363.  
  364. // 创建加载更多
  365. var loadMore = document.createElement('button');
  366. loadMore.className = 'load-more';
  367. loadMore.innerText = 'Load more';
  368. loadMore.style.display = 'none';
  369.  
  370. infoList.appendChild(waitLoading);
  371. infoList.appendChild(loadMore);
  372.  
  373. infoContainer.appendChild(tableHeader)
  374. infoContainer.appendChild(infoList);
  375.  
  376. var timeout;
  377. button.addEventListener('mouseenter', function () {
  378. clearTimeout(timeout);
  379. button.style.right = '10px';
  380. });
  381.  
  382. button.addEventListener('mouseleave', function () {
  383. timeout = setTimeout(function () {
  384. button.style.right = '-50px';
  385. }, 500);
  386. });
  387.  
  388. button.addEventListener('click', function (event) {
  389. event.stopPropagation();
  390. if (collapsed) {
  391. infoContainer.style.display = "block"
  392. infoContainer.style.opacity = 1
  393. collapsed = false
  394. }
  395. else {
  396. infoContainer.style.display = "none"
  397. infoContainer.style.opacity = 0
  398. collapsed = true
  399. }
  400.  
  401. if (neverLoadedScripts) {
  402. getScriptsInfo(domain, 1)
  403. neverLoadedScripts = false
  404. }
  405.  
  406. });
  407.  
  408. infoContainer.addEventListener('click', function (event) {
  409. event.stopPropagation();
  410. });
  411.  
  412. searchInput.addEventListener('input', () => {
  413. searchScript()
  414. updateMatches()
  415. })
  416.  
  417. toGreasyfork.addEventListener('click', function () {
  418. window.open(`https://greatest.deepsurf.us/scripts/by-site/${domain}?q=${searchInput.value}&filter_locale=0`)
  419. })
  420.  
  421. loadMore.addEventListener('click', () => {
  422. if (loadedPages === 'max') {
  423. return
  424. }
  425. const loadMoreButton = document.querySelector('.load-more')
  426. loadMoreButton.disabled = true
  427. loadMoreButton.textContent = 'Loading...'
  428. document.querySelector('.wait-loading').style.display = 'block'
  429. getScriptsInfo(domain, loadedPages + 1)
  430. })
  431.  
  432. document.body.addEventListener('click', function () {
  433. clearTimeout(timeout);
  434. collapsed = true
  435. button.style.right = '-50px';
  436. infoContainer.style.opacity = 0
  437. infoContainer.style.display = "none"
  438. });
  439.  
  440. document.body.appendChild(button);
  441.  
  442. document.body.appendChild(infoContainer);
  443.  
  444. infoContainer.addEventListener('change', () => {
  445. updateMatches()
  446. })
  447. updateMatches()
  448. }
  449.  
  450. function searchScript() {
  451. const searchWord = document.querySelector('.script-search-input').value.toLowerCase(); // 将要匹配的文本转换为小写
  452. const scriptList = document.querySelectorAll('.info-item');
  453. for (let i = 0; i < scriptList.length; i++) {
  454. const scriptText = scriptList[i].innerText.toLowerCase(); // 将检索的文本转换为小写
  455. if (scriptText.includes(searchWord)) {
  456. scriptList[i].style.display = 'block';
  457. } else {
  458. scriptList[i].style.display = 'none';
  459. }
  460. }
  461. }
  462.  
  463. function updateMatches() {
  464. const matchCount = document.querySelectorAll('.info-item:not([style*="display: none"])').length;
  465. const allCount = document.querySelectorAll('.info-item').length;
  466. document.querySelector('.match-count').innerText = matchCount === allCount ? matchCount : `${matchCount}/${allCount}`
  467. }
  468.  
  469. function main() {
  470. if (window.self !== window.top) {
  471. // 在iframe中执行时,直接退出
  472. return;
  473. }
  474. setupUI()
  475. }
  476.  
  477. main()
  478.  
  479.  
  480. })();