GreasyFork Search

To search scripts using Google Search

  1. // ==UserScript==
  2. // @name GreasyFork Search
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.6.5
  5. // @description To search scripts using Google Search
  6. // @author CY Fung
  7. // @match https://gf.qytechs.cn/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=gf.qytechs.cn
  9. // @require https://fastly.jsdelivr.net/npm/jstat@1.9.6/dist/jstat.min.js
  10. // @grant none
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14.  
  15.  
  16. (() => {
  17.  
  18.  
  19.  
  20. function jacobi(a) {
  21. var n = a.length;
  22. var trial = n * n * 2;
  23. var e = jStat.identity(n, n);
  24. var ev = [];
  25. var i, j, p, q, maxim, s;
  26. let vaildResult = false;
  27. outer: while (trial-- > 0) {
  28. maxim = a[0][1];
  29. p = 0;
  30. q = 1;
  31. for (i = 0; i < n; i++) {
  32. for (j = 0; j < n; j++) {
  33. if (i != j) {
  34. let t = Math.abs(a[i][j]);
  35. if (maxim < t) {
  36. maxim = t;
  37. p = i;
  38. q = j
  39. }
  40. }
  41. }
  42. }
  43.  
  44. s = jStat.identity(n, n);
  45.  
  46. let tanValue = 2 * a[p][q] / (a[p][p] - a[q][q]);
  47.  
  48. let cosTwoTheta = Math.sqrt(1 / (1 + tanValue * tanValue));
  49. let cosTheta = Math.sqrt(.5 * (1 + cosTwoTheta));
  50. let sinTheta = Math.sqrt(.5 * (1 - cosTwoTheta));
  51.  
  52. s[p][p] = cosTheta;
  53. s[p][q] = -sinTheta;
  54. s[q][p] = sinTheta;
  55. s[q][q] = cosTheta;
  56.  
  57. e = jStat.multiply(e, s);
  58. a = jStat.multiply(jStat.multiply(jStat.transpose(s), a), s);
  59.  
  60. for (i = 0; i < n; i++) {
  61. for (j = i + 1; j < n; j++) {
  62. if (Math.abs(a[i][j]) > .0004) {
  63. continue outer;
  64. }
  65. }
  66. }
  67.  
  68. vaildResult = true;
  69. break;
  70. }
  71. if (!vaildResult) {
  72. console.warn("The matrix is not symmetric.")
  73. return null;
  74. }
  75. for (i = 0; i < n; i++) ev.push(a[i][i]);
  76. //returns both the eigenvalue and eigenmatrix
  77. return [e, ev];
  78. }
  79.  
  80.  
  81.  
  82. function getVN(A) {
  83. // normalized the matrix values such that det(A) will be a finite value close to 1.0
  84. // vn = sqrt( ( column_vector_1 ^2 + column_vector_2 ^2 + ... + column_vector_n ^2 ) / n )
  85. let vn = 0;
  86. const AT = jStat.transpose(A);
  87. let N = AT.length;
  88. for (let i = 0; i < N; i++) {
  89. vn += jStat.dot(AT[i], AT[i]);
  90. }
  91. vn = Math.sqrt(vn / N);
  92. return vn;
  93. }
  94.  
  95. function subtractLambdaFromDiagonal(matrix, lambda) {
  96. // A - lambda I
  97. return matrix.map((row, rowIndex) => row.map((val, colIndex) => rowIndex === colIndex ? val - lambda : val));
  98. }
  99.  
  100.  
  101. function eigenvalueNewton(A, lambda0) {
  102. const N = A.length;
  103. const epsilon = 1e-5; // epsilon is applied on the normalized scale of lambda
  104. const maxTrial = 8;
  105.  
  106. function f(lambda) {
  107. return jStat.det(subtractLambdaFromDiagonal(A, lambda));
  108. }
  109.  
  110. function fPrime(lambda) {
  111. return (f(lambda + epsilon) - f(lambda)) / epsilon;
  112. }
  113.  
  114. let x_k = lambda0;
  115. let positiveSign = 0;
  116. let negativeSign = 0;
  117. for (let i = 0; i < maxTrial; i++) {
  118. const fx = f(x_k);
  119. const fxPrime = fPrime(x_k);
  120. const diff = fx / fxPrime;
  121. if (isNaN(diff)) return x_k; // ignore f/f'
  122. const x_k1 = x_k - diff;
  123. if ((diff > 0 ? diff : -diff) < epsilon) {
  124. return x_k1;
  125. }
  126. x_k = x_k1;
  127. if (fx > 0) positiveSign = 1;
  128. else if (fx < 0) negativeSign = 1;
  129. }
  130. return positiveSign && negativeSign ? x_k : lambda0; // avoid diverging iterations
  131. }
  132.  
  133. function vectorNorm(v) {
  134. // Math.sqrt(v dot v), same as jStat.norm(jStat.transpose(v))
  135. let s = 0;
  136. for (const k of v) s += k[0] * k[0];
  137. return Math.sqrt(s);
  138. }
  139.  
  140. function isUnitVector(v, tol = 0.01) {
  141. // Check if it is likely a unit vector
  142. let s = 0;
  143. for (const k of v) {
  144. s += k[0] * k[0];
  145. if (s > 1 + tol) return false;
  146. }
  147. return s > 1 - tol;
  148. }
  149.  
  150. jStat.jacobiOri = jStat.jacobi;
  151. // https://www.statskingdom.com/pca-calculator.html
  152. jStat.jacobi = function (C) {
  153.  
  154. const vn = getVN(C);
  155. C = jStat.multiply(C, 1 / vn);
  156. let r1 = jacobi(C);
  157. // let r0 = JSON.parse(JSON.stringify(r1))
  158. // r0[1] = r0[1].map(v => vn * v);
  159. let A = C;
  160. let eigenvectors = r1[0];
  161. let eigenvalues = r1[1];
  162. const iterationCount = 4;
  163.  
  164. for (let i = 0; i < eigenvalues.length; i++) {
  165. let q, m;
  166. q = jStat.transpose(eigenvectors[i]);
  167. if (!isUnitVector(q)) break;
  168. eigenvalues[i] = eigenvalueNewton(A, eigenvalues[i]); // refine eigenvalues obtained in jacobiOri
  169.  
  170. // inverse power method (A-lambda I) y_k = b_{k-1}
  171. // b_k = y_k / norm(y_k)
  172. let M = subtractLambdaFromDiagonal(A, eigenvalues[i]);
  173. for (let j = 0; j < iterationCount; j++) {
  174. m = jStat.transpose(jStat.gauss_elimination(M, q));
  175. m = jStat.multiply(m, 1 / vectorNorm(m))
  176. if (!isUnitVector(m)) break; // avoid Inf / NaN error
  177. q = m;
  178. }
  179. eigenvectors[i] = jStat.transpose(q);
  180.  
  181. }
  182. r1[1] = r1[1].map(v => vn * v);
  183. return r1;
  184. };
  185.  
  186.  
  187.  
  188. })();
  189.  
  190.  
  191. jStat.PCA = function PCA(X) {
  192. var m = X.length;
  193. var n = X[0].length;
  194. var i = 0;
  195. var j, temp1;
  196. var u = [];
  197. var D = [];
  198. var result = [];
  199. var temp2 = [];
  200. var Y = [];
  201. var Bt = [];
  202. var B = [];
  203. var C = [];
  204. var V = [];
  205. var Vt = [];
  206. for (i = 0; i < m; i++) {
  207. u[i] = jStat.sum(X[i]) / n;
  208. }
  209. for (i = 0; i < n; i++) {
  210. B[i] = [];
  211. for (j = 0; j < m; j++) {
  212. B[i][j] = X[j][i] - u[j];
  213. }
  214. }
  215. B = jStat.transpose(B);
  216. for (i = 0; i < m; i++) {
  217. C[i] = [];
  218. for (j = 0; j < m; j++) {
  219. C[i][j] = (jStat.dot([B[i]], [B[j]])) / (n - 1);
  220. }
  221. }
  222. result = jStat.jacobi(C);
  223. V = result[0];
  224. D = result[1];
  225.  
  226. Vt = jStat.transpose(V);
  227.  
  228.  
  229. let vd = [];
  230. for (i = 0; i < D.length; i++) {
  231. vd[i] = {
  232. Vt: Vt[i],
  233. D: D[i],
  234. k: D[i] * D[i]
  235. };
  236. }
  237.  
  238. vd.sort((a, b) => {
  239. return b.k - a.k
  240. })
  241.  
  242. Vt = vd.map(e => e.Vt);
  243. D = vd.map(e => e.D);
  244.  
  245.  
  246.  
  247. V = null;
  248.  
  249.  
  250. Bt = jStat.transpose(B);
  251.  
  252. let pcs_11 = [];
  253. let pt_11 = [1, 1];
  254. for (i = 0; i < m; i++) {
  255.  
  256.  
  257. pcs_11[i] = jStat.dot([Vt[i]], [pt_11]);
  258. if (pcs_11[i] < 0) Vt[i] = jStat.multiply(Vt[i], -1);
  259. pcs_11[i] = jStat.dot([Vt[i]], [pt_11]);
  260. }
  261.  
  262.  
  263.  
  264.  
  265.  
  266. for (i = 0; i < m; i++) {
  267. Y[i] = [];
  268. for (j = 0; j < Bt.length; j++) {
  269. Y[i][j] = jStat.dot([Vt[i]], [Bt[j]]);
  270. }
  271. }
  272. return [X, D, Vt, Y];
  273. };
  274.  
  275. (function () {
  276. 'use strict';
  277.  
  278. let input = document.querySelector('form input[name="q"]');
  279. if (!(input instanceof HTMLInputElement)) return;
  280. let form = input.closest('form');
  281. if (!(form instanceof HTMLFormElement)) return;
  282.  
  283.  
  284. let locales = [...document.querySelectorAll('select#language-selector-locale > option')].map(x => x.value)
  285.  
  286. document.head.appendChild(document.createElement('style')).textContent = `
  287.  
  288.  
  289. @keyframes rs1tmAnimation {
  290. 0% {
  291. background-position-x: 3px;
  292. }
  293. 100% {
  294. background-position-x: 4px;
  295. }
  296. }
  297.  
  298. form.rs1tm{
  299. position: fixed;
  300. top:-300px;
  301. left:-300px;
  302. width: 1px;
  303. height: 1px;
  304. contain: strict;
  305. display: flex;
  306. overflow: hidden;
  307. animation: rs1tmAnimation 1ms linear 1ms 1 normal forwards;
  308. }
  309.  
  310. `
  311. document.addEventListener('animationstart', (evt) => {
  312.  
  313. if (evt.animationName === 'rs1tmAnimation') {
  314. const target = evt.target;
  315. target && target.parentNode && target.remove();
  316. }
  317.  
  318. }, true);
  319.  
  320. window.callback947 = function (rainijpolynomialRegressionJs) {
  321. if (!rainijpolynomialRegressionJs) return;
  322. const { PolynomialFeatures, PolynomialRegressor, RegressionError } = rainijpolynomialRegressionJs;
  323. if (!PolynomialFeatures || !PolynomialRegressor || !RegressionError) return;
  324.  
  325. console.log(rainijpolynomialRegressionJs)
  326. }
  327.  
  328. form.addEventListener('submit', function (evt) {
  329.  
  330. try {
  331.  
  332.  
  333. let form = evt.target;
  334. if (!(form instanceof HTMLFormElement)) return;
  335. let input = form.querySelector('input[name="q"]');
  336. if (!(input instanceof HTMLInputElement)) return;
  337.  
  338. if (form.classList.contains('rs1tm')) return;
  339.  
  340. let value = input.value;
  341. const lang = document.documentElement.lang || '';
  342.  
  343. let useLang = false;
  344.  
  345.  
  346. let u = 0;
  347. let isGoogleSearch = false;
  348.  
  349. let sites = [];
  350.  
  351. const split = value.split(/\s+/);
  352. let forceLang = 'all';
  353. let reformedSplit = [];
  354. for (const s of split) {
  355.  
  356. if (!isGoogleSearch && /^[a-z][a-z0-9_-]{2,}(\.[a-z][a-z0-9_-]{2,})*(\.[a-z-]{2,4})+$/.test(s)) {
  357. if (/\.(js|css|html|htm|xml|img|svg|txt|php|cgi|xhtml|ini|vue|xhr|ajax)$/.test(s)) {
  358. reformedSplit.push(s);
  359. } else {
  360. sites.push(s);
  361. }
  362. } else if (s === 'js') {
  363. forceLang = 'js'; reformedSplit.push(s);
  364. } else if (s === 'css') {
  365. forceLang = 'css'; reformedSplit.push(s);
  366. } else if (s === 'user.js') {
  367. forceLang = 'js';
  368. } else if (s === 'user.css') {
  369. forceLang = 'css';
  370. } else if (s === '"js"') {
  371. reformedSplit.push('js');
  372. } else if (s === '"css"') {
  373. reformedSplit.push('css');
  374. } else if (u === 0 && s === 'g') {
  375. isGoogleSearch = true;
  376. } else if (locales.indexOf(s) >= 0 || s === lang) {
  377. useLang = s;
  378. } else {
  379. reformedSplit.push(s);
  380. }
  381. u++;
  382. }
  383. console.log(sites)
  384.  
  385. value = reformedSplit.join(' ')
  386.  
  387. let onlySite = '';
  388.  
  389. if (sites.length === 1 && sites[0]) {
  390. onlySite = sites[0];
  391. }
  392.  
  393. /*
  394. if (!isGoogleSearch && onlySite && /\.\w+\.\w+/.test(onlySite)) {
  395. alert('Greasy Fork镜像 only lists eTLD+1.');
  396. evt.preventDefault();
  397. evt.stopImmediatePropagation();
  398. evt.stopPropagation();
  399. return;
  400. }
  401. */
  402.  
  403.  
  404. if (isGoogleSearch && value) {
  405. let q = value.replace('g ', '');
  406.  
  407. let m = "-inurl%3A%22%2Fusers%2F%22+-inurl%3A%22%2Fdiscussions%22-inurl%3A%22%2Fstats%22+-inurl%3A%22%2Ffeedback%22+-inurl%3A%22%2Fcode%22+-inurl%3A%22q%3D%22+-inurl%3A%22%2Fby-site%2F%22+inurl%3A%22%2Fscripts%2F%22+site%3Agf.qytechs.cn";
  408.  
  409.  
  410.  
  411. let lr = useLang ? `&lr=lang_${useLang}` : '';
  412. evt.preventDefault();
  413. evt.stopImmediatePropagation();
  414. evt.stopPropagation();
  415. location.href = `https://www.google.com/search?q=${encodeURIComponent(q)}+${m}${lr}`
  416.  
  417. } else if (!isGoogleSearch && (value || onlySite)) {
  418.  
  419.  
  420. let newForm = document.createElement('form');
  421. newForm.className = 'rs1tm';
  422. const copyAttr = (x) => {
  423. let t = form.getAttribute(x);
  424. if (typeof t === 'string') newForm.setAttribute(x, t);
  425. }
  426. copyAttr('action');
  427. copyAttr('accept-charset');
  428. copyAttr('method');
  429. newForm.innerHTML = `<input name="q" type="hidden" value="" /><input name="site" type="hidden" /><input name="language" type="hidden" value="all" /><input name="sort" type="hidden" /><input name="vl" type="hidden" value="">`
  430.  
  431.  
  432. const nq = newForm.querySelector('input[name="q"]');
  433. const language = newForm.querySelector('input[name="language"]');
  434. const site = newForm.querySelector('input[name="site"]');
  435. const sort = newForm.querySelector('input[name="sort"]');
  436.  
  437. value = value.replace(/\s+/g, ' ');
  438. site.value = onlySite;
  439.  
  440. if (form.getAttribute('action') === `/${lang}/scripts` && useLang && useLang !== lang) {
  441. form.setAttribute('action', `/${useLang}/scripts`)
  442. }
  443.  
  444.  
  445. if (site.value === '') site.remove();
  446.  
  447. nq.value = value;
  448.  
  449. language.value = forceLang;
  450.  
  451. if (language.value === '') language.remove();
  452.  
  453.  
  454. sort.value = 'updated';
  455.  
  456. let sorting = document.querySelector('#script-list-sort');
  457. if (sorting) {
  458. let sorts1 = {
  459. nil: 0,
  460. daily_installs: 0,
  461. total_installs: 0,
  462. ratings: 0,
  463. created: 0,
  464. updated: 0,
  465. name: 0
  466. }
  467. let sorts2 = {
  468. daily_installs: 0,
  469. total_installs: 0,
  470. ratings: 0,
  471. created: 0,
  472. updated: 0,
  473. name: 0
  474. }
  475. const allOptions = sorting.querySelectorAll('.list-option');
  476. const sorts = allOptions.length === 6 ? (sorts2) : (sorts1);
  477. const keys = Object.keys(sorts)
  478.  
  479. if (allOptions.length === keys.length) {
  480.  
  481.  
  482. for (const key of keys) {
  483. let e = `.list-option:not(.list-current) a[href$="sort=${key}"]`
  484. if (key === 'nil') {
  485. e = `.list-option:not(.list-current) a[href]:not([href*="sort="])`
  486. e = sorting.querySelector(e)
  487. } else {
  488. e = sorting.querySelector(e)
  489. }
  490.  
  491. if (e) {
  492. sorts[key] = 1;
  493. }
  494.  
  495. }
  496.  
  497.  
  498.  
  499. let p = Object.entries(sorts).filter(r => !r[1])
  500. if (p.length === 1) {
  501. sort.value = p[0][0]
  502. }
  503.  
  504. }
  505.  
  506. }
  507.  
  508.  
  509.  
  510.  
  511. if (sort.value === '') sort.remove();
  512.  
  513. evt.preventDefault();
  514. evt.stopImmediatePropagation();
  515. evt.stopPropagation();
  516.  
  517. form.parentNode.insertBefore(newForm, form);
  518. newForm.submit();
  519. Promise.resolve().then(() => {
  520. newForm.remove();
  521. })
  522.  
  523.  
  524. } else {
  525. evt.preventDefault();
  526. evt.stopImmediatePropagation();
  527. evt.stopPropagation();
  528. }
  529.  
  530. } catch (e) {
  531. console.log(e);
  532.  
  533. evt.preventDefault();
  534. evt.stopImmediatePropagation();
  535. evt.stopPropagation();
  536. }
  537.  
  538. })
  539.  
  540. // Your code here...
  541. })();
  542.  
  543. (() => {
  544.  
  545. function prettyMatrix(A) {
  546. let w = '';
  547. for (let i = 0; i < A.length; i++) {
  548. for (let j = 0; j < A[i].length; j++) {
  549. w += A[i][j].toFixed(4) + '\t'
  550. }
  551. w += '\n\t';
  552. }
  553. return '[\n\t' + w.trim() + '\n]';
  554. }
  555.  
  556.  
  557. requestAnimationFrame(() => {
  558.  
  559. setTimeout(() => {
  560.  
  561. if ((location.search.includes('sort=updated') || location.search.includes('sort=created')) && location.pathname.endsWith('/scripts')) { } else return;
  562. if (!/[?&]vl=/.test(location.search)) return;
  563. let items = document.querySelectorAll('[data-script-id][data-script-daily-installs][data-script-total-installs]');
  564.  
  565. let data = [...items].map(e => ({
  566. id: parseInt(e.getAttribute('data-script-id')),
  567. daily: parseInt(e.getAttribute('data-script-daily-installs')),
  568. total: parseInt(e.getAttribute('data-script-total-installs'))
  569. })).filter(e => e.id && !isNaN(e.daily) && !isNaN(e.total));
  570.  
  571. const daily = data.map(d => d.daily);
  572. const total = data.map(d => d.total);
  573. dailyMean = jStat.mean(daily);
  574. dailySD = jStat.stdev(daily, true);
  575. totalMean = jStat.mean(total);
  576. totalSD = jStat.stdev(total, true);
  577.  
  578. const uDaily = jStat.multiply(jStat.subtract(daily, dailyMean), 1 / dailySD);
  579. const uTotal = jStat.multiply(jStat.subtract(total, totalMean), 1 / totalSD);
  580.  
  581. let dataA = data.map((d, i) => [uDaily[i], uTotal[i]]);
  582.  
  583. // dataA = dataA.slice(0, 4)
  584. // console.log(dataA)
  585.  
  586. let matrixA = jStat.transpose(dataA)
  587.  
  588.  
  589. const result = jStat.PCA(matrixA);
  590. const [X, D, Vt, Y] = result;
  591.  
  592.  
  593.  
  594. let q = null;
  595. let qSet = null;
  596. if (location.search.includes('q=')) {
  597. q = new URLSearchParams(location.search)
  598. q = q.get('q')
  599.  
  600. }
  601.  
  602. function makeQA(q) {
  603. let qSet = new Set();
  604. q.replace(/_-/g, ' ').replace(/\b\S+\b/g, (_) => {
  605. qSet.add(_.toLowerCase())
  606. });
  607. return qSet;
  608. }
  609.  
  610. if (q) {
  611. qSet = makeQA(q);
  612. }
  613.  
  614. let mr = new Map();
  615. let u = 0;
  616. for (const d of data) {
  617. d.pcaScore = Y[0][u++];
  618. let elm = document.querySelector(`[data-script-id="${d.id}"]`);
  619. if (elm) {
  620.  
  621. let order = 0;
  622. order -= Math.floor(d.pcaScore * 1000);
  623.  
  624. let u1 = 0, u2 = 0;
  625.  
  626. if (qSet) {
  627.  
  628. const pSet = qSet;
  629.  
  630. let elp = elm.querySelector('.script-link')
  631. if (elp) {
  632. let t = elp.textContent
  633.  
  634. t.replace(/_-/g, ' ').replace(/\b\S+\b/g, (_) => {
  635. if (pSet.has(_.toLowerCase())) u1++;
  636. });
  637.  
  638.  
  639. }
  640.  
  641.  
  642.  
  643. let elq = elm.querySelector('.script-description')
  644.  
  645. if (elq) {
  646. let t = elq.textContent
  647.  
  648. t.replace(/_-/g, ' ').replace(/\b\S+\b/g, (_) => {
  649. if (pSet.has(_.toLowerCase())) u2++;
  650. });
  651.  
  652.  
  653. }
  654.  
  655.  
  656. }
  657.  
  658.  
  659. if (u1 && u2) order -= 30000
  660. else if (u1) order -= 20000
  661. else if (u2) order -= 10000
  662.  
  663.  
  664. mr.set(d.id, order);
  665. // elm.style.order = order;
  666. // elm.parentNode.style.display = 'flex';
  667.  
  668.  
  669. // elm.parentNode.style.flexDirection = 'column';
  670.  
  671.  
  672. }
  673. }
  674.  
  675.  
  676. let lists = [...new Set([...document.querySelectorAll(`[data-script-id]`)].map(p => p.parentNode))];
  677. for (const list of lists) {
  678.  
  679. let m = [...list.childNodes].map(e => ({
  680. element: e,
  681. order: mr.get(e instanceof HTMLElement ? (+e.getAttribute('data-script-id') || '') : '') || 0
  682. }));
  683.  
  684. m.sort((a, b) => {
  685. return Math.round(a.order - b.order)
  686. });
  687. let newNodes = m.map(e => e.element);
  688.  
  689. list.replaceChildren(...newNodes);
  690. }
  691.  
  692.  
  693. // console.log(prettyMatrix(X))
  694.  
  695. // console.log(prettyMatrix(Y))
  696.  
  697.  
  698.  
  699.  
  700.  
  701. }, 300);
  702.  
  703. });
  704.  
  705.  
  706.  
  707. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址