Greasy Fork is available in English.

Highlight OCH links

Hit escape to check whether one-click hoster links are online or offline.

目前為 2015-11-14 提交的版本,檢視 最新版本

// ==UserScript==
// @name        Highlight OCH links
// @namespace   cuzi
// @oujs:author cuzi
// @description Hit escape to check whether one-click hoster links are online or offline.
// @homepageURL https://openuserjs.org/scripts/cuzi/Highlight_OCH_links
// @icon        http://imagizer.imageshack.us/v2/150x100q90/539/zrjtcQ.png
// @include     *
// @exclude     *.yahoo.*
// @exclude     *.google.*
// @exclude     *.youtube.*
// @exclude     *.bing.com*
// @version     2
// @require     http://openuserjs.org/src/libs/cuzi/RequestQueue.js
// @require     http://openuserjs.org/src/libs/cuzi/OCH_List.js
// @grant       GM_xmlhttpRequest
// ==/UserScript==
"use strict";


const MAXTEXTNODES = 10000;
const MAXPARALLELCONNECTIONS = 10;
const MAXREQUESTS = 150;

/*
// Export
var mypatterns = [];
var mynames = [];
var myurls = [];
for(var key in OCH) {
  var o = OCH[key];
  if(o.multi.length > 0) {
    mypatterns.push(o.pattern.toString());
    mynames.push("'"+key+"'");  
    myurls.push(" - ["+o.title+"]("+o.homepage+")");
  }
}

alert(mypatterns.join(",\n"));
alert(mynames.join(",\n"));
alert(myurls.join("\n"));
*/





var links = []; // [  { hoster: "", url: "", element: DOMNode} , ...   ]
var rq = new RequestQueue(MAXPARALLELCONNECTIONS,MAXREQUESTS);


function linkOffline(link) {
  link.element.style.backgroundColor = "rgba(255, 0, 20, 0.5)";
  link.element.dataset.linkValidatedAs = "offline";
}
function linkOnline(link) {
  link.element.style.backgroundColor = "rgba(70, 255 ,0, 0.5)";
  link.element.dataset.linkValidatedAs = "online";
}
function linkWaiting(link) {
  link.element.style.backgroundColor = "rgba(255, 150, 80, 0.4)";
}

function handleResult(link,result,errorstring) {
  if(result === 1) {
    linkOnline(link);
  } else if(result === 0) {
    linkOffline(link);
  } else if(result == -1) {
    link.element.style.backgroundColor = "blue";
    link.element.title = errorstring;
    console.log(errorstring);
  } else {
    console.log("handleResult(link,result,errorstring) wrong resultcode: "+result);
  }
}

function matchHoster(str) {
  // Return name of first hoster that matches, otherwise return false
  for(var name in OCH) {
    for(var i = 0; i < OCH[name].pattern.length; i++) {
      if(OCH[name].pattern[i].test(str)) {
        return name
      }
    }
  }  
  return false;
}

function findLinks() {  
  links = [];
  
  // Normalize hoster object: Replace single patterns with arrays [RegExp]
  for(var name in OCH) {
    if(!Array.isArray(OCH[name].pattern)) {
      OCH[name].pattern = [ OCH[name].pattern ];
    }
  }  
  
  // Find all text nodes that contain "http://"
  var nodes = [];
  var walk = document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT,{ acceptNode: function(node) {
    if(node.parentNode.href || node.parentNode.parentNode.href || node.parentNode.parentNode.parentNode.href)
      return NodeFilter.FILTER_REJECT;
    if(node.parentNode.tagName == "TEXTAREA" || node.parentNode.parentNode.tagName == "TEXTAREA")
      return NodeFilter.FILTER_REJECT;
    if(node.data.match(/(\s|^)https?:\/\/\w+/))
      return NodeFilter.FILTER_ACCEPT; 
  } },false);
  var node = walk.nextNode();
  while(node) {
      nodes.push(node);
      node = walk.nextNode();
  }
  
  // For each found text nodes check whether the URL is a valid OCH URL
  for(var i = 0; i < nodes.length && i < MAXTEXTNODES; i++) {
    if("" === nodes[i].data) {
      continue;
    }
    var httpPosition = nodes[i].data.indexOf("http");
    if(httpPosition == -1) {
      continue;
    }   
    
    var urlnode;
    if(httpPosition > 0) {
      urlnode = nodes[i].splitText(httpPosition); // Split leading text
    } else {
      urlnode = nodes[i];
    }
    var stop = urlnode.data.match(/$|\s/)[0]; // Find end of URL
    if("" !== stop) { // If empty string, we found $ end of string
      var nextnode = urlnode.splitText(urlnode.data.indexOf(stop)); // Split trailing text
      if("" !== nextnode.data && nextnode.data.indexOf("http") != -1) {// The trailing text might contain another URL
        nodes.push(nextnode); 
      }
    }

    // Check whether the URL is a OCH. If so, create an <a> element
    var url = urlnode.data;
    var mh = matchHoster(url);
    if(mh !== false) {
      var a = document.createElement("a");
      a.href = url;
      a.appendChild(urlnode.parentNode.replaceChild(a, urlnode));
      links.push( {
        'hoster' : mh,
        'url' : url,
        'element' : a
      });
    }
  }

  // Find actual <a> links
  var al = document.getElementsByTagName('a');
  for(var i = 0; i < al.length; i++) {
    if(al[i].dataset.linkValidatedAs) {
      continue; // Link was already checked
    }
    var mH = matchHoster(al[i].href);
    if(mH !== false) {
      links.push( {
        'hoster' : mH,
        'url' : al[i].href,
        'element' : al[i]
      });
    }
  }

  return links.length;
}

function checkLinks() {
  // Check all links by calling the hoster's check function
  for(var i = 0; i < links.length; i++) {
    if(links[i] && OCH[links[i].hoster].check && typeof(OCH[links[i].hoster].check) === 'function') {
      linkWaiting(links[i]);
      OCH[links[i].hoster].check(links[i],handleResult);
    }
  } 
}

(function() {
  var doit = true;
  document.addEventListener('keydown',function(ev) {
      if (ev.keyCode == 27) {
        if(doit) {
          // Highlight links and check them
          var n = findLinks();
          if(n > 0 )
            checkLinks();
        } else {
          // Abort all requests
          rq.abort();
        }
        doit = !doit;
      }
  },false);
})();