GreasyFork Search

使用谷歌搜索GreasyFork和SleazyFork上的脚本

目前为 2024-09-02 提交的版本。查看 最新版本

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

QingJ © 2025

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