[HFR] SFBA descriptor

Copie la description de l'article lorsque une url appropriée est présente dans le presse papier

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         [HFR] SFBA descriptor
// @namespace    sfba.hfr
// @version      1.3
// @description  Copie la description de l'article lorsque une url appropriée est présente dans le presse papier
// @include       https://forum.hardware.fr/message.php*
// @include       https://forum.hardware.fr/forum2.php*
// @include       https://forum.hardware.fr/hfr/*
// @icon          http://reho.st/self/40f387c9f48884a57e8bbe05e108ed4bd59b72ce.png
// @connect       *
// @require            https://openuserjs.org/src/libs/sizzle/GM_config.js
// @grant         GM_info
// @grant         GM_deleteValue
// @grant         GM_getValue
// @grant         GM_listValues
// @grant         GM_setValue
// @grant         GM_getResourceText
// @grant         GM_getResourceURL
// @grant         GM_addStyle
// @grant         GM_log
// @grant         GM_openInTab
// @grant         GM_registerMenuCommand
// @grant         GM_setClipboard
// @grant         GM_xmlhttpRequest
// @require       http://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
// ==/UserScript==

function init_throbber(){
  GM_addStyle("#hiu_throbber_sfba{position:fixed;left:0;top:0;background-color:#242424;z-index:1001;" +
              "display:none;opacity:0;transition:opacity 0.7s ease 0s;}");
  GM_addStyle("#hiu_throbber_img_sfba{position:fixed;left:calc(50% - 64px);top:calc(50% - 64px);width:128px;height:128px;z-index:1002;" +
              "display:none;opacity:0;transition:opacity 0.7s ease 0s;border:0;padding:0;}");
  GM_addStyle(".hfr_apercu_nope{display:none !important;}");
  var throbber_image_url = "https://reho.st/self/30271dc1b7cac925aeabb89fa70e1e17cf5e1840.png";
  var hiu_throbber_img_sfba = new Image();
  hiu_throbber_img_sfba.src = throbber_image_url;
  hiu_throbber_img_sfba.setAttribute("id", "hiu_throbber_img_sfba");
  var hiu_throbber_sfba = document.createElement("div");
  hiu_throbber_sfba.setAttribute("id", "hiu_throbber_sfba");
  hiu_throbber_sfba.appendChild(hiu_throbber_img_sfba);
  hiu_throbber_sfba.addEventListener("transitionend", throbber_transitionend, false);
  document.body.appendChild(hiu_throbber_sfba);


}


function init_config(){
    GM_config.init(
    {
         'id': 'SFBAconfig', // The id used for this instance of GM_config
         'title': 'SFBA descriptor configuration', // Panel Title
         'fields': // Fields object
         {
             'amazon': // This is the id of the field
             {
                  'label': 'Amazon', // Appears next to field
                  'type': 'checkbox', // Makes this setting a checkbox input
                  'default': true // Default value if user doesn't change it
             },
             'aliexpress': // This is the id of the field
             {
                  'label': 'Aliexpress', // Appears next to field
                  'type': 'checkbox', // Makes this setting a checkbox input
                  'default': true // Default value if user doesn't change it
             },
             'dealabs': // This is the id of the field
             {
                  'label': 'Dealabs', // Appears next to field
                  'type': 'checkbox', // Makes this setting a checkbox input
                  'default': true // Default value if user doesn't change it
             },
             'gearbest': // This is the id of the field
             {
                  'label': 'Gearbest', // Appears next to field
                  'type': 'checkbox', // Makes this setting a checkbox input
                  'default': true // Default value if user doesn't change it
             },
             'banggood': // This is the id of the field
             {
                  'label': 'Banggood', // Appears next to field
                  'type': 'checkbox', // Makes this setting a checkbox input
                  'default': true // Default value if user doesn't change it
             },
             'thingiverse': // This is the id of the field
             {
                  'label': 'Thingiverse', // Appears next to field
                  'type': 'checkbox', // Makes this setting a checkbox input
                  'default': true // Default value if user doesn't change it
             }
         },
         css: '#SFBAconfig { background-color: #d0e0ff; }',
    });
    GM_registerMenuCommand("[HFR] SFBA descriptor -> configuration", function(){GM_config.open();});
}

function display_throbber(){
  if(document.querySelector("div#apercu_reponse")){
    document.querySelector("div#apercu_reponse").classList.add("hfr_apercu_nope");
  }
  hiu_throbber_img_sfba.style.display = "block";
  hiu_throbber_sfba.style.display = "block";
  hiu_throbber_sfba.style.width = document.documentElement.scrollWidth + "px";
  hiu_throbber_sfba.style.height = document.documentElement.scrollHeight + "px";
  hiu_throbber_img_sfba.style.opacity = "1";
  hiu_throbber_sfba.style.opacity = "0.8";
}

function throbber_transitionend() {
  if(hiu_throbber_sfba.style.opacity === "0") {
    hiu_throbber_img_sfba.style.display = "none";
    hiu_throbber_sfba.style.display = "none";
    if(document.querySelector("div#apercu_reponse")){
      document.querySelector("div#apercu_reponse").classList.remove("hfr_apercu_nope");
    }
  }
}

function hide_throbber(){
  hiu_throbber_img_sfba.style.opacity = "0";
  hiu_throbber_sfba.style.opacity = "0";
}

function insert_text_at_cursor (textarea, text) {
	var start = textarea.selectionStart;
	var end = textarea.selectionEnd;
	textarea.value = textarea.value.substr (0, start) + text + textarea.value.substr (end);
	textarea.setSelectionRange (start + text.length, start + text.length);
}

function isUrlValid(url) {
    var valid = /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url.href);

    var parsable = false;
    
    if (valid)
    {
        if ( (url.host.indexOf("amazon") !== -1) && (GM_config.get('amazon')))
        {
            parsable = true;
        }
        else if ( (url.host.indexOf("aliexpress") !== -1)  && (GM_config.get('aliexpress')))
        {
            parsable = true;
        }
        else if ( (url.host.indexOf("dealabs") !== -1) && (GM_config.get('dealabs')))
        {
            parsable = true;
        }
        else if ( (url.host.indexOf("gearbest") !== -1) && (GM_config.get('gearbest')))
        {
            parsable = true;
        }
        else if ( (url.host.indexOf("banggood") !== -1) && (GM_config.get('banggood')))
        {
            parsable = true;
        }
        else if ( (url.host.indexOf("thingiverse") !== -1) && (GM_config.get('thingiverse')))
        {
            parsable = true;
        }
    }
    
    return (valid & parsable);
}

function extractHostname(url) {
    var hostname;
    //find & remove protocol (http, ftp, etc.) and get hostname

    if (url.indexOf("://") > -1) {
        hostname = url.split('/')[2];
    }
    else {
        hostname = url.split('/')[0];
    }

    //find & remove port number
    hostname = hostname.split(':')[0];
    //find & remove "?"
    hostname = hostname.split('?')[0];

    return hostname;
}

function parseAmazon(doc, raw = false)
{
    var img = "";
    var title = doc.find("#productTitle").text().trim();    
    var imgJson = doc.find("#imgTagWrapperId").children().attr('data-a-dynamic-image');
    if (imgJson)
        img = Object.keys(JSON.parse(imgJson))[0];
    var price = doc.find(".a-size-medium.a-color-price").eq(0).text();
    if (price)
        price = price.trim();

    if (title && img && price)
    {
        if (raw)
        {
            return [img, title + " - " + price];
        }
        else
        {
            return title + " - " + price + "[/url]\n[img]http://reho.st/preview/" + img + "[/img]";
        }
    }
    else
        return "";
}

function parseAli(doc, raw = false)
{
    var title = doc.find(".product-name").text().trim();
    var img = doc.find(".ui-image-viewer-thumb-frame").children().attr('src');
    var price = doc.find("#j-sku-discount-price").text().trim() + doc.find(".p-symbol").text()[0];
    if (price)
        price = price.trim();

    if (title && img && price)
    {
        if (raw)
        {
            return [img, title + " - " + price];
        }
        else
        {
            return title + " - " + price + "[/url]\n[img]http://reho.st/preview/" + img + "[/img]";
        }
    }
    else
        return "";
}

function parseDealabs(doc, raw = false)
{
    var title = doc.find("h1.thread-title").text().trim();
    var img = doc.find("a.threadItem-imgFrame").children().attr('src');
    var price = "";
    var oldPrice = "";
    try 
    {
        price = doc.find("span.thread-price").first().text().trim();
        oldPrice = doc.find("span.text--lineThrough").text().trim();
    }
    catch(err){}
    
    if (title && img && price)
    {
        if (oldPrice)
        {
            if (raw)
            {
                return [img, title + " - " + price + oldPrice];
            }
            else
            {
                return title + "[/url]\n[img]http://reho.st/preview/" + img + "[/img]\n[b][#FF0000]" + price + "[/#FF0000][/b] [strike]" + oldPrice + "[/strike]";
            }
        }
        else
        {
            if (raw)
            {
                return [img, title + " - " + price];
            }
            else
            {
                return title + "[/url]\n[img]http://reho.st/preview/" + img + "[/img]\n[b][#FF0000]" + price + "[/#FF0000][/b]";
            }
        }
    }
    else
    {
        return "";
    }
}

function parseGearbest(doc, raw= false)
{
    var title = doc.find("h1").text().trim();
    var img = doc.find("#js-goodsNormalImg").attr('src');
    var price = doc.find(".goodsIntro_price.js-currency.js-panelIntroPrice").text();
    if (price)
        price = price.trim();
    
    if (title && img && price)
    {
        if (raw)
        {
           return [img, title + " - " + price];
        }
        else
        {
            return title + " - " + price + "[/url]\n[img]" + img + "[/img]";
        }
    }
    else
        return ""; 
}

function parseBanggood(doc, raw = false)
{
    var title = doc.find("h1").text().trim();
    var img = doc.find(".left_largerView_image_20161213").children().attr('src');
    var price = doc.find(".now").text().trim() + doc.find(".top_price_datalist_20161213").children().first().text().trim();
    if (price)
        price = price.trim();

    if (title && img && price)
    {
        if (raw)
        {
            return [img, title + " - " + price];
        }
        else
        {
            return title + " - " + price + "[/url]\n[img]" + img + "[/img]";
        }
    }
    else
        return "";
}

function parseThingiverse(doc, raw = false)
{
    var title = doc.find("h1").first().text().trim();
    var img = doc.find(".gallery-slider").children().attr('data-medium');

    if (title && img)
    {
        if (raw)
        {
            return [img, title];
        }
        else
        {
            return title + "[/url]\n[img]" + img + "[/img]";
        }
    }
}

function displayContent(link)
{
    var container;

    link.addEventListener("mouseover", function()
    {
        container = document.createElement("div");
        container.style.position = "fixed";
        container.style.background = "#dedfdf";
        container.style.width = "auto";
        container.style.padding = "5px";
        container.style.border = "1px solid black";
        container.style.top = "10px";
        container.style.right = "10px";
        container.style.maxWidth = "450px";

        document.body.appendChild(container);

        let text = document.createElement("p");
        text.style.fontFamily = "arial,sans-serif";
        text.style.fontWeight = "bold";
        text.innerHTML = "Chargement";
        container.appendChild(text);

        let img = new Image();
        img.style.display = "block";
        img.style.margin = "auto";
        img.style.maxWidth = "450px";
        img.style.maxHeight = parseInt((document.documentElement.clientHeight - 20 - 12), 10) + "px";

        getData(link.href, img, text);

        container.appendChild(img);
    });

    link.addEventListener("mouseout", function()
    {
        if(container && container.parentNode)
        {
            let elts = container.querySelectorAll("p, img");
            for(let elt of elts)
            {
                elt.parentNode.removeChild(elt);
            }
            container.parentNode.removeChild(container);
        }
    }, false);

}

function getData(url, img, txt)
{
    var content = "";

    GM_xmlhttpRequest({
		method : "GET",
		url : url,
        anonymous: true,
        context : {
			textarea : this
		},
		onabort : hide_throbber,
		onerror : hide_throbber,
		ontimeout : hide_throbber,
		onload : function (response) {
			// fin du chargement
			hide_throbber();

            if (extractHostname(url).indexOf("amazon") !== -1)
            {
                content = parseAmazon($(response.responseText), true);
            }
            else if (extractHostname(url).indexOf("aliexpress") !== -1)
            {
                content = parseAli($(response.responseText), true);
            }
            else if (extractHostname(url).indexOf("dealabs") !== -1)
            {
                content = parseDealabs($(response.responseText), true);
            }
            else if (extractHostname(url).indexOf("gearbest") !== -1)
            {
                content = parseGearbest($(response.responseText), true);
            }
            else if (extractHostname(url).indexOf("banggood") !== -1)
            {
                content = parseBanggood($(response.responseText), true);
            }
            else if (extractHostname(url).indexOf("thingiverse") !== -1)
            {
                content = parseThingiverse($(response.responseText), true);
            }
            img.src = content[0];
            txt.innerHTML = content[1];
        }
    });
}

init_throbber();
init_config();

function pasting (event) {
    var url = "";
    var bbcode = "";
	if (event.clipboardData.files.length < 1)
    {
		var str = event.clipboardData.getData("text/plain");
		if ( (str.length === 0) || (!isUrlValid(str)) )
			return;
        else
            url = str;
	}
    else
    {
        return;
    }
	
	// chargement
	display_throbber();
	
	GM_xmlhttpRequest({
		method : "GET",
		url : url,
        context : {
			textarea : this
		},
		onabort : hide_throbber,
		onerror : hide_throbber,
		ontimeout : hide_throbber,
		onload : function (response) {
			// fin du chargement
			hide_throbber();

            if (extractHostname(url).indexOf("amazon") !== -1)
            {
                bbcode = parseAmazon($(response.responseText));
            }
            else if (extractHostname(url).indexOf("aliexpress") !== -1)
            {
                bbcode = parseAli($(response.responseText));
            }
            else if (extractHostname(url).indexOf("dealabs") !== -1)
            {
                bbcode = parseDealabs($(response.responseText));
            }
            else if (extractHostname(url).indexOf("gearbest") !== -1)
            {
                bbcode = parseGearbest($(response.responseText));
            }
            else if (extractHostname(url).indexOf("banggood") !== -1)
            {
                bbcode = parseBanggood($(response.responseText));
            }
            else if (extractHostname(url).indexOf("thingiverse") !== -1)
            {
                bbcode = parseThingiverse($(response.responseText));
            }
            
            if (bbcode)
                insert_text_at_cursor(this.context.textarea, "[url=" + url + "]" + bbcode);
            else
                insert_text_at_cursor(this.context.textarea, "[url]" + url + "[/url]");
		}
	});
	return event.preventDefault();
	
}

var content_form = document.querySelector("#content_form");
if (content_form !== null)
	content_form.addEventListener('paste', pasting);




var observer=new MutationObserver(function(mutations, observer){ 
  var textareas=document.querySelectorAll("textarea[id^=\"rep_editin_\"]" ); 
  if(textareas.length){ 
    for(var textarea of textareas) { 
      textarea.removeEventListener('paste', pasting, false); 
      textarea.addEventListener('paste', pasting, false); 
    } 
  } 
}); 
observer.observe(document, {attributes: false, childList: true, characterData: false, subtree: true});

var links = document.getElementById("mesdiscussions").querySelectorAll(
  "table.messagetable td.messCase2 div[id^='para'] > span:not(.signature) a.cLink, " +
  "table.messagetable td.messCase2 div[id^='para'] > div:not(.edited) a.cLink, " +
  "table.messagetable td.messCase2 div[id^='para'] > *:not(span):not(div) a.cLink");
for(let link of links)
{
  if (isUrlValid(link))
  {
      displayContent(link);
  }
}