GreasyFork Search

To search scripts using Google Search

目前为 2023-09-12 提交的版本。查看 最新版本

// ==UserScript==
// @name         GreasyFork Search
// @namespace    http://tampermonkey.net/
// @version      0.5.0
// @description  To search scripts using Google Search
// @author       CY Fung
// @match        https://greasyfork.org/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    let input = document.querySelector('form input[name="q"]');
    if (!(input instanceof HTMLInputElement)) return;
    let form = input.closest('form');
    if (!(form instanceof HTMLFormElement)) return;


    let locales = [...document.querySelectorAll('select#language-selector-locale > option')].map(x => x.value)

    document.head.appendChild(document.createElement('style')).textContent = `


    @keyframes rs1tmAnimation {
        0% {
            background-position-x: 3px;
        }
        100% {
            background-position-x: 4px;
        }
    }

    form.rs1tm{
        position: fixed;
        top:-300px;
        left:-300px;
        width: 1px;
        height: 1px;
        contain: strict;
        display: flex;
        overflow: hidden;
        animation: rs1tmAnimation 1ms linear 1ms 1 normal forwards;
    }

    `
    document.addEventListener('animationstart', (evt) => {

        if (evt.animationName === 'rs1tmAnimation') {
            const target = evt.target;
            target && target.parentNode && target.remove();
        }

    }, true);

    form.addEventListener('submit', function (evt) {

      try{


        let form = evt.target;
        if (!(form instanceof HTMLFormElement)) return;
        let input = form.querySelector('input[name="q"]');
        if (!(input instanceof HTMLInputElement)) return;

        if (form.classList.contains('rs1tm')) return;

        let value = input.value;
        const lang = document.documentElement.lang || '';

        let useLang = false;


        let u = 0;
        let isGoogleSearch = false;

        let sites = [];

        const split = value.split(/\s+/);
        let forceLang = 'all';
        let reformedSplit = [];
        for (const s of split) {

            if (!isGoogleSearch && /^[a-z][a-z0-9_-]{2,}(\.[a-z][a-z0-9_-]{2,})*(\.[a-z-]{2,4})+$/.test(s)) {
                sites.push(s);
            } else if (s === 'js') {
                forceLang = 'js'; reformedSplit.push(s);
            } else if (s === 'css') {
                forceLang = 'css'; reformedSplit.push(s);
            } else if (s === 'user.js') {
                forceLang = 'js';
            } else if (s === 'user.css') {
                forceLang = 'css';
            } else if (s === '"js"') {
                reformedSplit.push('js');
            } else if (s === '"css"') {
                reformedSplit.push('css');
            } else if (u === 0 && s === 'g') {
                isGoogleSearch = true;
            } else if (locales.indexOf(s) >= 0 || s === lang) {
                useLang = s;
            } else {
                reformedSplit.push(s);
            }
            u++;
        }
      console.log(sites)

        value = reformedSplit.join(' ')

        let onlySite = '';

        if (sites.length === 1 && sites[0]) {
            onlySite = sites[0];
        }

      /*
        if (!isGoogleSearch && onlySite && /\.\w+\.\w+/.test(onlySite)) {
            alert('Greasy Fork only lists eTLD+1.');
                evt.preventDefault();
            evt.stopImmediatePropagation();
            evt.stopPropagation();
            return;
        }
        */


        if (isGoogleSearch && value) {
            let q = value.replace('g ', '');

            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%3Agreasyfork.org";



            let lr = useLang ? `&lr=lang_${useLang}` : '';
            evt.preventDefault();
            evt.stopImmediatePropagation();
            evt.stopPropagation();
            location.href = `https://www.google.com/search?q=${encodeURIComponent(q)}+${m}${lr}`

        } else if (!isGoogleSearch && (value || onlySite) ) {


            let newForm = document.createElement('form');
            newForm.className = 'rs1tm';
            const copyAttr = (x) => {
                let t = form.getAttribute(x);
                if (typeof t === 'string') newForm.setAttribute(x, t);
            }
            copyAttr('action');
            copyAttr('accept-charset');
            copyAttr('method');
            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" />`


            const nq = newForm.querySelector('input[name="q"]');
            const language = newForm.querySelector('input[name="language"]');
            const site = newForm.querySelector('input[name="site"]');
            const sort = newForm.querySelector('input[name="sort"]');

            value = value.replace(/\s+/g, ' ');
            site.value = onlySite;

            if (form.getAttribute('action') === `/${lang}/scripts` && useLang && useLang !== lang) {
                form.setAttribute('action', `/${useLang}/scripts`)
            }


            if (site.value === '') site.remove();

            nq.value = value;

            language.value = forceLang;

            if (language.value === '') language.remove();


            sort.value = 'updated';

            let sorting = document.querySelector('#script-list-sort');
          if(sorting){
            let sorts1 = {
              nil:0,
              daily_installs: 0,
              total_installs: 0,
              ratings: 0,
              created:0,
              updated:0,
              name:0
            }
            let sorts2 = {
              daily_installs: 0,
              total_installs: 0,
              ratings: 0,
              created:0,
              updated:0,
              name:0
            }
            const allOptions = sorting.querySelectorAll('.list-option');
            const sorts =  allOptions.length === 6 ?(sorts2):(sorts1);
            const keys = Object.keys(sorts)

            if(allOptions.length ===keys.length){


              for(const key of keys){
                let e = `.list-option:not(.list-current) a[href$="sort=${key}"]`
                if(key === 'nil'){
                  e = `.list-option:not(.list-current) a[href]:not([href*="sort="])`
                  e=sorting.querySelector(e)
                }else{
                  e = sorting.querySelector(e)
                }

                if(e){
                  sorts[key]=1;
                }

              }



              let p = Object.entries(sorts).filter(r=>!r[1])
              if(p.length===1){
                sort.value = p[0][0]
              }

            }

          }




            if (sort.value === '') sort.remove();

            evt.preventDefault();
            evt.stopImmediatePropagation();
            evt.stopPropagation();

            form.parentNode.insertBefore(newForm, form);
            newForm.submit();
            Promise.resolve().then(()=>{
              newForm.remove();
            })


        } else {
            evt.preventDefault();
            evt.stopImmediatePropagation();
            evt.stopPropagation();
        }

      }catch(e){
        console.log(e);

            evt.preventDefault();
            evt.stopImmediatePropagation();
            evt.stopPropagation();
      }

    })

    // Your code here...
})();