CH Plaintext HIT Export

Export HIT information in multi-line plain text format.

Versión del día 3/6/2015. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name          CH Plaintext HIT Export
// @description   Export HIT information in multi-line plain text format.
// @version       1.6c
// @include       https://www.mturk.com/mturk/findhits*
// @include       https://www.mturk.com/mturk/viewhits*
// @include       https://www.mturk.com/mturk/sorthits*
// @include       https://www.mturk.com/mturk/searchbar*selectedSearchType=hitgroups*
// @include       https://www.mturk.com/mturk/viewsearchbar*selectedSearchType=hitgroups*
// @include       https://www.mturk.com/mturk/sortsearchbar*HITGroup*
// @include       https://www.mturk.com/mturk/preview*
// @grant         GM_setClipboard
// @author        Cristo + clickhappier
// @namespace     mturkgrind
// ==/UserScript==


// based on 'IRC Export (reformatted output mod)': https://greasyfork.org/en/scripts/6254-irc-export-reformatted-output-mod


var caps = document.getElementsByClassName('capsulelink');
for (var c = 0; c < caps.length/2; c++){
    button = document.createElement('button');
    button.setAttribute("place",c);
    button.textContent = 'TXT';
    button.style.height = '14px';
    button.style.width = '30px';
    button.style.fontSize = '8px';
    button.style.border = '1px solid';
    button.style.padding = '0px';
    button.style.backgroundColor = 'transparent';
    button.title = 'Click to save Hit information to your clipboard';
    button.addEventListener("click", display, false);
    document.getElementById('capsule'+c+'-0').parentNode.appendChild(button);
}

function getTO(f){
    var toComp = [];
    var toUrl = 'https://mturk-api.istrack.in/multi-attrs.php?ids='+f;
    var toUrl2 = 'https://turkopticon.ucsd.edu/api/multi-attrs.php?ids='+f;
    requestTO = new XMLHttpRequest();
    try{   // first try Miku's TO mirror server (istrack.in)
        requestTO.onreadystatechange = function () {
            if ((requestTO.readyState ===4) && (requestTO.status ===200)) {
                if (requestTO.responseText.split(':').length > 2) {
                    var toInfo = requestTO.responseText.split('{')[3].split('}')[0].split(',');
                    for (var t = 0; t < 4; t++) {
                        var arrTo = toInfo[t].split(':');
                        toComp.push(arrTo[1].substring(1,4));
                    }
                } 
                else { toComp = ['-','-','-','-']; }
            }
        };
        requestTO.open('GET', toUrl, false);
        requestTO.send(null);
        return toComp;
    }
    catch(err){   // if mirror unavailable, try main TO server
        try{
            requestTO.onreadystatechange = function () {
                if ((requestTO.readyState ===4) && (requestTO.status ===200)) {
                    if (requestTO.responseText.split(':').length > 2) {
                        var toInfo = requestTO.responseText.split('{')[3].split('}')[0].split(',');
                        for (var t = 0; t < 4; t++) {
                            var arrTo = toInfo[t].split(':');
                            toComp.push(arrTo[1].substring(1,4));
                        }
                    } 
                    else { toComp = ['-','-','-','-']; }
                }
            };
            requestTO.open('GET', toUrl2, false);
            requestTO.send(null);
            return toComp;
        }
        catch(err){   // if both unavailable, return 'na's
            toComp = ['na','na','na','na'];
            return toComp;
        }
    }
}

// output display box
var txtexportdiv = document.createElement('div');
var txtexporttextarea = document.createElement('textarea');
txtexportdiv.style.position = 'fixed';
txtexportdiv.style.width = '500px';
txtexportdiv.style.height = '255px';
txtexportdiv.style.left = '50%';
txtexportdiv.style.right = '50%';
txtexportdiv.style.margin = '-250px 0px 0px -250px';
txtexportdiv.style.top = '300px';
txtexportdiv.style.padding = '5px';
txtexportdiv.style.border = '2px';
txtexportdiv.style.backgroundColor = 'black';
txtexportdiv.style.color = 'white';
txtexportdiv.style.zIndex = '100';
txtexportdiv.setAttribute('id','txtexport_div');
txtexportdiv.style.display = 'none';
txtexporttextarea.style.padding = '2px';
txtexporttextarea.style.width = '500px';
txtexporttextarea.style.height = '230px';
txtexporttextarea.title = 'Plaintext Export Output';
txtexporttextarea.setAttribute('id','txtexport_text');
txtexportdiv.textContent = 'Plaintext Export: Press Ctrl+C to (re-)copy to clipboard. Click textarea to close.';
txtexportdiv.style.fontSize = '12px';
txtexportdiv.appendChild(txtexporttextarea);
document.body.insertBefore(txtexportdiv, document.body.firstChild);
txtexporttextarea.addEventListener("click", function(){ txtexportdiv.style.display = 'none'; }, false);


function display(e){
    var theButton = e.target;
    theButton.style.backgroundColor = '#CC0000';
    
    var capHand = document.getElementById('capsule'+theButton.getAttribute("place")+'-0');
    var tBodies = capHand.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
    
    var capReq = tBodies.getElementsByClassName('requesterIdentity')[0].textContent;
    var capReqId = tBodies.getElementsByClassName('requesterIdentity')[0].parentNode.href.split('requesterId=')[1];
    // if on certain types of searches when logged out, more infernal Amazon-meddling may add a useless &state= value to the end of the requester link
    if ( capReqId.indexOf('&state=') > -1 )
    {
        capReqId = capReqId.split('&state')[1];
    }
    
    var capTitle = capHand.textContent.trim();
    capTitle = capTitle.replace(/<(\w+)[^>]*>.*<\/\1>/gi, "").trim();  // addition to strip html tags and their contents, appearing inside the title link (re 10-20-2014 appearance of "<span class="tags"></span>")

    var capGId = 'unavailable';  // handle logged-out export requests for HITs with no preview/notqualified links
    // if hit has a preview or notqualified link
    if ( capHand.parentNode.parentNode.getElementsByClassName('capsulelink')[1].firstChild.nextSibling.href !== '' )  
    {
        // if this is a preview link
        if ( capHand.parentNode.parentNode.getElementsByClassName('capsulelink')[1].firstChild.nextSibling.href.indexOf('preview') > -1 )
        {
            capGId = capHand.parentNode.parentNode.getElementsByClassName('capsulelink')[1].firstChild.nextSibling.href.split('=')[1];
        }
        // if this is a notqualified link
        else if ( capHand.parentNode.parentNode.getElementsByClassName('capsulelink')[1].firstChild.nextSibling.href.indexOf('notqualified') > -1 )
        {
            capGId = capHand.parentNode.parentNode.getElementsByClassName('capsulelink')[1].firstChild.nextSibling.href.split('=')[1];
            // Amazon messed up the notqualified links, now looking like https://www.mturk.com/mturk/notqualified?hitGroupId=3ID43DSF4IQ1X8LO308D15ZSD5J5GX&hitId=3ID43DSF4IQ1X8LO308D15ZSD5J5GX ; this and the above split happening on = instead of a specific value address that
            capGId = capGId.replace("&hitId", "").replace("&hitGroupId", "");  // added a removal of hitGroupId too since Amazon flipped the order of these on 6/2/15
        }
        // if this is a requestqualification link we shouldn't be on, but are anyway because of stuff Amazon screwed with on 6/2/15
        else if ( capHand.parentNode.parentNode.getElementsByClassName('capsulelink')[1].firstChild.nextSibling.href.indexOf('requestqualification') > -1 )
        {
            // go to the next link, the "(why?)" notqualified link instead
            capGId = capHand.parentNode.parentNode.getElementsByClassName('capsulelink')[1].firstChild.nextSibling.nextElementSibling.href.split('=')[1];
            // Amazon messed up the notqualified links, now looking like https://www.mturk.com/mturk/notqualified?hitGroupId=3ID43DSF4IQ1X8LO308D15ZSD5J5GX&hitId=3ID43DSF4IQ1X8LO308D15ZSD5J5GX ; this and the above split happening on = instead of a specific value address that
            capGId = capGId.replace("&hitId", "").replace("&hitGroupId", "");  // added a removal of hitGroupId too since Amazon flipped the order of these on 6/2/15
        }
    }
    
    var capRew = tBodies.getElementsByClassName('reward')[0].textContent;

    var capTime = tBodies.getElementsByClassName('capsule_field_text')[2].textContent;

    var capAvailable = tBodies.getElementsByClassName('capsule_field_text')[4].textContent;

    var qualList = document.getElementById('capsule'+theButton.getAttribute("place")+'target').getElementsByTagName('tbody')[2];
    if ( document.location.href.indexOf('?last_hits_previewed') > -1 ) { qualList = document.getElementById('capsule'+theButton.getAttribute("place")+'target').getElementsByTagName('tbody')[1]; }
    var qualColl = qualList.getElementsByTagName('td');
    var qualStart = 3;
    if ( document.getElementById('lnkWorkerSignin') ) { qualStart = 1; }  // handle logged-out export requests - difference in qual table coding
    if ( document.location.href.indexOf('?last_hits_previewed') > -1 ) { qualStart = 2; }
    var masterStat = '';
    for ( var m = qualStart; m < qualColl.length; m++ ) {
        if ( qualColl[m].textContent.indexOf('Masters') > -1 ) {
            masterStat = 'MASTERS ';
        }
    }
    
    var capUrl = 'https://www.mturk.com/mturk/preview?groupId='+capGId;
    var capReqUrl = 'https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&requesterId='+capReqId;
    var hitLinkUnav = '';
    if ( capGId == 'unavailable' ) { capUrl = capReqUrl; hitLinkUnav = " (preview link unavailable)"; }  // handle logged-out export requests for HITs with no preview/notqualified links
    var toLink = 'http://turkopticon.ucsd.edu/'+capReqId;
    var capToStats = getTO(capReqId);


    // additions for plaintext export:
    
    function DST() {    // check if daylight savings time should be adjusted for, from http://www.mresoftware.com/simpleDST.htm
        var today = new Date();
        var yr = today.getFullYear();
        var dst_start = new Date("March 14, "+yr+" 02:00:00"); // 2nd Sunday in March can't occur after the 14th 
        var dst_end = new Date("November 07, "+yr+" 02:00:00"); // 1st Sunday in November can't occur after the 7th
        var day = dst_start.getDay(); // day of week of 14th
        dst_start.setDate(14-day); // Calculate 2nd Sunday in March of this year
        day = dst_end.getDay(); // day of the week of 7th
        dst_end.setDate(7-day); // Calculate first Sunday in November of this year
        if (today >= dst_start && today < dst_end) { //does today fall inside of DST period?
            return true; //if so then return true
        }
        return false; //if not then return false
    }

    var currentDate = new Date();
    var utc = currentDate.getTime() + (currentDate.getTimezoneOffset() * 60000);   // http://www.techrepublic.com/article/convert-the-local-time-to-another-time-zone-with-this-javascript/
    var offset = '';
    if ( DST() == true ) { offset = "-7"; } else { offset = "-8"; }   // adjust Pacific Time's UTC offset for daylight savings time - http://stackoverflow.com/questions/8207655/how-to-get-time-of-specific-timezone-using-javascript/8207708#8207708
    var amazonDate = new Date(utc + (3600000*offset));
    var month = amazonDate.getMonth() + 1;
    var day = amazonDate.getDate();
    var year = amazonDate.getFullYear();
    var hours = amazonDate.getHours();
    if (hours < 10) { hours = '0' + hours; }   // http://stackoverflow.com/questions/6838197/get-local-date-string-and-time-string/6838658#6838658
    var minutes = amazonDate.getMinutes();
    if (minutes < 10) { minutes = '0' + minutes; }
    var dateStr = month + "/" + day + "/" + year + " " + hours + ":" + minutes + " PT";
    
    var capDesc = '"' + tBodies.getElementsByClassName('capsule_field_text')[5].textContent.trim().replace(/(\t)+/g,' ').replace(/(\n)+/g,' ').replace(/(\r)+/g,' ').replace(/(  )+/g,' ').replace(/(\s)+/g,' ') + '"';
    if (capDesc == '""') { capDesc = "none"; }

    var capKeywords = "";
    if ( document.location.href.indexOf('?last_hits_previewed') > -1 ) { capKeywords = "unavailable (exported from Last HITs Previewed)"; }
    else { capKeywords = '"' + tBodies.getElementsByClassName('capsule_field_text')[6].textContent.trim().replace(/(\t)+/g,' ').replace(/(\n)+/g,' ').replace(/(\r)+/g,' ').replace(/(  )+/g,' ').replace(/(\s)+/g,' ') + '"'; }
    if (capKeywords == '""' || capKeywords == '') { capKeywords = "none"; }

    var qualStr = "";
    for ( var q = qualStart; q < qualColl.length; q++ ) {
        if ( ( (qualColl[q].textContent.indexOf('is') > -1) || (qualColl[q].textContent.indexOf('has') > -1) ) && (qualColl[q].textContent.indexOf('You meet this') < 0) && (qualColl[q].textContent.indexOf('Contact the Requester') < 0) ) {
            if (qualStr != "") { qualStr += '   '; }
            qualStr += qualColl[q].textContent.trim().replace(/(\t)+/g,' ').replace(/(\n)+/g,' ').replace(/(\r)+/g,' ').replace(/(  )+/g,' ').replace(/(\s)+/g,' ') + '  \r\n';
        }
    }
    if (qualStr == "") { qualStr = "none  \r\n"; }


    var exString = dateStr + '  \r\n'
                 + masterStat + 'HIT: ' + capTitle + '   - ' + capUrl + hitLinkUnav + '  \r\n'
                 + 'Requester: ' + capReq + '   - ' + capReqUrl + '  \r\n'
                 + 'TO Ratings: ' + 'Pay='+capToStats[1] + ' Fair='+capToStats[2] + ' Comm='+capToStats[0] + ' Speed='+capToStats[3] + '   - ' + toLink + '  \r\n'
                 + 'Time Allotted: ' + capTime + '  \r\n'
                 + 'Reward: ' + capRew + '  \r\n'
                 + 'HITs Available: ' + capAvailable + '  \r\n'
                 + 'Description: ' + capDesc + '  \r\n'
                 + 'Keywords: ' + capKeywords + '  \r\n'
                 + 'Qualifications: ' + qualStr + '  \r\n' ;
    if (GM_setClipboard) { GM_setClipboard(exString); }
    window.setTimeout(function(){ theButton.style.backgroundColor = 'transparent'; }, 500);
    txtexporttextarea.textContent = exString;
    txtexportdiv.style.display = 'block';
    txtexporttextarea.select();
}