JR Mturk Panda Crazy Helper - Temp

A script add on for Panda Crazy sending commands to main script.

  1. // ==UserScript==
  2. // @name JR Mturk Panda Crazy Helper - Temp
  3. // @version 0.3.11-HN4
  4. // @namespace https://greasyfork.org/users/6406
  5. // @description A script add on for Panda Crazy sending commands to main script.
  6. // @author (JohnnyRS on mturkcrowd.com and mturkgrind.com) johnnyrs@allbyjohn.com
  7. // @include http*://worker.mturk.com/*
  8. // @include http*://*mturkcrowd.com/threads/*
  9. // @include http*://*turkerview.com/threads/*
  10. // @include http*://*mturkforum.com/showthread*
  11. // @include http*://*mturkforum.com/*threads/*
  12. // @include http*://*hitnotifier.com/*
  13. // @include http*://www.reddit.com/r/HITsWorthTurkingFor*
  14. // @exclude http*://*mturk.com/mturk/findhits?*hit_scraper*
  15. // @require http://code.jquery.com/jquery-2.1.4.min.js
  16. // @grant GM_getValue
  17. // @grant GM_setValue
  18. // @grant GM_deleteValue
  19. // ==/UserScript==
  20.  
  21. var gScriptVersion = "0.3.11";
  22. var gScriptName = "pandacrazy";
  23. var gLocation = window.location.href, gNewSite=false;
  24. var gConstantSearch = null;
  25. var gJobDataDefault = {"requesterName":"","requesterId":"","groupId":"","pay":"","title":"","duration":"0","hitsAvailable":0,"timeLeft":"","totalSeconds":0,"hitId":"",
  26. "qual":"","continueURL":"","returnURL":"","durationParsed":{},"jobNumber":"-1","friendlyRName":"","friendlyTitle":"","assignedOn":"","description":"",
  27. "keywords":"","timeData":{},"assignmentID":"","hitSetID":"","secondsOff":-1,"goHam":false};
  28.  
  29. function createMessageData(command,data) { return {"time":(new Date().getTime()),"command":command,"data":data}; }
  30. function sendCommandMessage(data) { localStorage.setItem("JR_message_" + gScriptName, JSON.stringify(data)); }
  31. function createQueueData(length) { return {"queueLength":length}; }
  32. function createProjectedData(earnings) { return {"projectedEarnings":earnings}; }
  33. function createJobData(jobData) { return {"groupId":jobData.groupId,"title":jobData.title,"requesterName":jobData.requesterName,"requesterId":jobData.requesterId,
  34. "pay":jobData.pay,"duration":jobData.duration,"hitsAvailable":jobData.hitsAvailable}; }
  35. function setAttributes(el, attrs) { for (var key in attrs) { el.setAttribute(key, attrs[key]); } }
  36. function elementInit(theElement,theClass,theText,theStyle) {
  37. if (theClass) theElement.className = theClass; if (theText) theElement.textContent = theText; if (theStyle) theElement.style = theStyle; return theElement;
  38. }
  39. function createSpan(theClass,theText,theStyle) { var span = document.createElement("span"); return elementInit(span,theClass,theText,theStyle); }
  40. function createSpanButton(toDo,theClass,theText,theBackgroundColor,theColor,theFontSize,addStyle) {
  41. var backgroundColor = (typeof theBackgroundColor != 'undefined') ? theBackgroundColor : "initial";
  42. var textColor = (typeof theColor != 'undefined') ? theColor : "initial", fontSize = (typeof theFontSize != 'undefined') ? theFontSize : "9px";
  43. var theButton = createSpan("nonselectable " + theClass,theText,"font-size:" + fontSize + "; padding:0px 2px; background-color:" + backgroundColor + "; color:" + textColor +
  44. "; border:2px groove darkgrey; cursor:default; margin:0px 1px;" + addStyle);
  45. if (toDo) theButton.addEventListener("click", function (e) { toDo(e); });
  46. return theButton;
  47. }
  48. function speakThisNow(thisText) {
  49. if('speechSynthesis' in window){
  50. var speech = new SpeechSynthesisUtterance(thisText);
  51. speech.lang = 'en-US';
  52. window.speechSynthesis.speak(speech);
  53. }
  54. }
  55. function locationForums() {
  56. if (gLocation.match(/.*(mturkcrowd|turkerview|mturkforum|reddit)\.com.*/)!==null) return true;
  57. else return false;
  58. }
  59. function getTimeLeft(theTime) {
  60. if (theTime!==null && theTime!=="") {
  61. var tempArray = (theTime.indexOf("second") != -1) ? theTime.split("second")[0].trim().split(" ") : null;
  62. var seconds = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  63. tempArray = (theTime.indexOf("minute") != -1) ? theTime.split("minute")[0].trim().split(" ") : null;
  64. var minutes = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  65. tempArray = (theTime.indexOf("hour") != -1) ? theTime.split("hour")[0].trim().split(" ") : null;
  66. var hours = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  67. tempArray = (theTime.indexOf("day") != -1) ? theTime.split("day")[0].trim().split(" ") : null;
  68. var days = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  69. tempArray = (theTime.indexOf("week") != -1) ? theTime.split("week")[0].trim().split(" ") : null;
  70. var weeks = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  71. return( {"weeks":weeks,"days":days,"hours":hours,"minutes":minutes,"seconds":seconds} );
  72. } else return null;
  73. }
  74. function formatTimeLeft(resetNow,thisDigit,timeString,lastDigit) {
  75. formatTimeLeft.timeFill = formatTimeLeft.timeFill || 0;
  76. if (resetNow) formatTimeLeft.timeFill = 0;
  77. var missingDigit = (lastDigit!="0" && thisDigit=="0") ? true : false;
  78. if (( thisDigit!="0" || missingDigit) && formatTimeLeft.timeFill<2) {
  79. formatTimeLeft.timeFill++;
  80. if (missingDigit) { return "00 " + timeString + "s"; }
  81. else {
  82. var addZero = (thisDigit<10) ? ((formatTimeLeft.timeFill==1) ? false : true) : false, plural = (thisDigit==1) ? false : true;
  83. return ((addZero) ? "0" : "") + thisDigit + " " + ((plural) ? (timeString+"s") : timeString) + " ";
  84. }
  85. } else return "";
  86. }
  87. function convertToTimeString(timeData) {
  88. var returnString = "";
  89. returnString += formatTimeLeft(true,timeData.weeks,"week",false); returnString += formatTimeLeft(false,timeData.days,"day",timeData.weeks);
  90. returnString += formatTimeLeft(false,timeData.hours,"hour",timeData.days); returnString += formatTimeLeft(false,timeData.minutes,"minute",timeData.hours);
  91. returnString += formatTimeLeft(false,timeData.seconds,"second",timeData.minutes);
  92. return returnString.trim();
  93. }
  94. function convertTimeToSeconds(timeData) {
  95. var totalSeconds = timeData.seconds + ((timeData.minutes) ? (timeData.minutes*60) : 0) + ((timeData.hours) ? (timeData.hours*3600) : 0) +
  96. ((timeData.days) ? (timeData.days*86400) : 0) + ((timeData.weeks) ? (timeData.weeks*604800) : 0);
  97. return totalSeconds;
  98. }
  99. function convertSecondsToTimeData(seconds) {
  100. var timeData = {};
  101. timeData.weeks = Math.floor(seconds/604800); seconds = seconds - (timeData.weeks*604800);
  102. timeData.days = Math.floor(seconds/86400); seconds = seconds - (timeData.days*86400);
  103. timeData.hours = Math.floor(seconds/3600); seconds = seconds - (timeData.hours*3600);
  104. timeData.minutes = Math.floor(seconds/60); seconds = seconds - (timeData.minutes*60);
  105. timeData.seconds = seconds;
  106. return timeData;
  107. }
  108. function convertToSeconds(milliseconds,fixed) { fixed = fixed || 2; var seconds = parseFloat((milliseconds/1000.0 * 100) / 100).toFixed(fixed) + ""; return seconds.replace(/\.0*$/,""); }
  109. function convertToMilliseconds(seconds) { if (seconds) return seconds*1000 + ""; else return "0"; }
  110.  
  111. function sendMessageData(command,theData) {
  112. var messageData = createMessageData(command,theData);
  113. sendCommandMessage(messageData);
  114. }
  115. function sendQueueData(queueLength) { sendMessageData("queueData",createQueueData(queueLength)); }
  116. function sendProjectedData(projectedEarnings) { sendMessageData("projectedEarnings",createProjectedData(projectedEarnings)); }
  117. function sendJobData(jobData) { sendMessageData("addJob",createJobData(jobData)); }
  118. function sendJobOnceData(jobData) { sendMessageData("addOnceJob",createJobData(jobData)); }
  119. function sendJobSearchData(jobData) { sendMessageData("addSearchJob",createJobData(jobData)); }
  120. function sendPingMessage() { localStorage.setItem("JR_message_ping_" + gScriptName, JSON.stringify({"command":"areYouThere","time":(new Date().getTime())})); }
  121.  
  122. function appendPandaButtons(element,jobData) {
  123. $(element).append($("<span>").css({"font-size":"9px"}).html("Add: ")
  124. .append($("<button>").html("Panda").css({"font-size":"10px","line-height":"10px","padding":"1px","color":"black"})
  125. .data("jobData",jobData).attr({"type":"button"})
  126. .click(function(e) { sendJobData($(e.target).data("jobData")); return false; }))
  127. .append($("<button>").html("Once").css({"font-size":"10px","line-height":"10px","padding":"1px","color":"black"})
  128. .data("jobData",jobData).attr({"type":"button"})
  129. .click(function(e) { sendJobOnceData($(e.target).data("jobData")); return false; }))
  130. .append($("<button>").html("Search").css({"font-size":"10px","line-height":"10px","padding":"1px","color":"black"})
  131. .data("jobData",jobData).attr({"type":"button"})
  132. .click(function(e) { sendJobSearchData($(e.target).data("jobData")); return false; }))
  133. );
  134. }
  135. function parseHitsInfo(reactInfo,finalUrl) {
  136. var jobData = jQuery.extend(true, {}, gJobDataDefault), projectData = ("project" in reactInfo) ? reactInfo.project : reactInfo;
  137. jobData.hitSetID = projectData.hit_set_id; jobData.hitsAvailable = projectData.assignable_hits_count;
  138. jobData.continueURL = ""; jobData.returnURL = ""; jobData.groupId = projectData.hit_set_id;
  139. jobData.requesterName = projectData.requester_name; jobData.requesterId = projectData.requester_id;
  140. jobData.totalSeconds = projectData.assignment_duration_in_seconds; jobData.timeData = convertSecondsToTimeData(jobData.totalSeconds);
  141. jobData.title = projectData.title; jobData.timeLeft = convertToTimeString(jobData.timeData);
  142. jobData.pay = parseFloat(projectData.monetary_reward.amount_in_dollars).toFixed(2);
  143. jobData.duration = jobData.timeLeft;
  144. return jobData;
  145. }
  146. function parseNewHitPageRequesters(projectDetailBar,finalUrl) {
  147. var jobData = jQuery.extend(true, {}, gJobDataDefault);
  148. var tempPrevDiv = projectDetailBar[0].getElementsByClassName("col-sm-4 col-xs-5");
  149. if (tempPrevDiv.length===0) tempPrevDiv = projectDetailBar[0].getElementsByClassName("col-md-6 col-xs-12"); // col-md-6 col-xs-12
  150. if (tempPrevDiv.length===0) tempPrevDiv = projectDetailBar[0].getElementsByClassName("col-xs-12"); // col-xs-12
  151. if (tempPrevDiv.length===0) tempPrevDiv = projectDetailBar[0].getElementsByClassName("p-l-xs");
  152. var reactInfo = (tempPrevDiv.length>0) ? tempPrevDiv[0].firstElementChild.dataset.reactProps : null;
  153. if (reactInfo) {
  154. reactInfo = JSON.parse(reactInfo).modalOptions;
  155. var contactRequesterUrl = reactInfo.contactRequesterUrl, contactVar = (contactRequesterUrl.indexOf("requester_id") != -1) ? "requester_id%5D=" : "requesterId=";
  156. jobData.hitsAvailable = reactInfo.assignableHitsCount; jobData.requesterName = reactInfo.requesterName;
  157. jobData.groupId = finalUrl.split("/projects/")[1].split("/")[0]; jobData.hitSetID = jobData.groupId;
  158. if (finalUrl.indexOf("assignment_id")!=-1) {
  159. jobData.hitId = finalUrl.split("/tasks/")[1].split("?")[0]; jobData.assignmentId = finalUrl.split("assignment_id=")[1].split("&")[0];
  160. jobData.continueURL = finalUrl;
  161. } else { jobData.hitId = ""; jobData.assignmentId = ""; jobData.continueURL = ""; }
  162. jobData.returnURL = "";
  163. var tempContact = contactRequesterUrl.split(contactVar); if (tempContact.length) jobData.requesterId = contactRequesterUrl.split(contactVar)[1].split("&")[0];
  164. jobData.totalSeconds = reactInfo.assignmentDurationInSeconds; jobData.timeData = convertSecondsToTimeData(jobData.totalSeconds); jobData.title = reactInfo.projectTitle;
  165. jobData.timeLeft = convertToTimeString(jobData.timeData); jobData.pay = parseFloat(reactInfo.monetaryReward.amountInDollars).toFixed(2);
  166. jobData.duration = jobData.timeLeft;
  167. }
  168. return jobData;
  169. }
  170. function findProjectedEarnings() {
  171. // find if Projected Earnings scripts are installed and get info.
  172. var spanEarnings = null, earnings = "";
  173. if ( ($(".me-bar").length ) ) {
  174. spanEarnings = $(".me-bar:first").find("span:contains('Earnings:'):first");
  175. if (spanEarnings) earnings = $(spanEarnings).next("a").text();
  176. sendProjectedData(earnings.replace("$",""));
  177. }
  178. }
  179. function pcContainer(thisGroupId,thisRequesterName,thisRequesterId,thisTitle,thisReward) {
  180. var thisContainer = $(createSpan("PCSpanButtons","","")).append(document.createTextNode(" [PC] Add: "))
  181. .append($(createSpanButton(function(e) { window.open("https://worker.mturk.com/requesters/PandaCrazyAdd/projects?JRGID=" + thisGroupId + "&JRRName=" +
  182. thisRequesterName + "&JRRID=" + thisRequesterId + "&JRTitle=" + thisTitle + "&JRReward=" + thisReward,
  183. "PandaCommand", "height=200,width=200"); },"","Panda", "lightgrey","red","11px")))
  184. .append($(createSpanButton(function(e) { window.open("https://worker.mturk.com/requesters/PandaCrazyOnce/projects?JRGID=" + thisGroupId + "&JRRName=" +
  185. thisRequesterName + "&JRRID=" + thisRequesterId + "&JRTitle=" + thisTitle + "&JRReward=" + thisReward,
  186. "PandaCommand", "height=200,width=200"); },"","Once", "lightgrey","red","11px")))
  187. .append($(createSpanButton(function(e) { window.open("https://worker.mturk.com/requesters/PandaCrazySearch/projects?JRGID=" + thisGroupId + "&JRRName=" +
  188. thisRequesterName + "&JRRID=" + thisRequesterId + "&JRTitle=" + thisTitle + "&JRReward=" + thisReward,
  189. "PandaCommand", "height=200,width=200"); },"","Search", "lightgrey","red","11px")));
  190. return thisContainer;
  191. }
  192. function format1(foundUrl,thisNode) {
  193. var thisGroupId="", thisRequesterName="", thisRequesterId="", thisTitle="", thisReward="";
  194. var grabbedUrl = foundUrl.attr("href"); var newWorkerSite = (grabbedUrl.indexOf("worker.mturk.com") != -1) ? true : false;
  195. if (newWorkerSite) thisGroupId = grabbedUrl.split("/projects/")[1].split("/tasks")[0];
  196. else thisGroupId = grabbedUrl.split("groupId=")[1].split("&")[0];
  197. thisRequesterName = escape($(thisNode).find("b:contains('Requester:')").next("a").text().trim());
  198. thisRequesterId = ($(thisNode).find("b:contains('Requester:')").next("a")).attr("href").split("/requesters/")[1].split("/projects")[0];
  199. thisRequesterId = thisRequesterId.split("]")[0].replace("[","").replace("]","");
  200. var bTitle = $(thisNode).find("b:contains('Title:')");
  201. thisTitle = escape($(thisNode).find("b:contains('Title:')").next("a").text().trim());
  202. thisReward = escape($(thisNode).find("b:contains('Reward:')").next("span, font").text().trim().replace("$",""));
  203. if (thisReward==="") thisReward = escape($(thisNode).find("b:contains('Reward:')").get(0).nextSibling.nodeValue.trim().replace("$",""));
  204. return {"GID":thisGroupId,"RID":thisRequesterId,"RName":thisRequesterName,"Title":thisTitle,"Reward":thisReward};
  205. }
  206. function format2(foundUrl,thisNode) {
  207. var thisGroupId="", thisRequesterName="", thisRequesterId="", thisTitle="", thisReward="";
  208. thisGroupId = $(foundUrl).attr("href").split("/projects/")[1].split("/tasks/")[0];
  209. thisRequesterName = escape($(thisNode).find("a[href*='worker.mturk']:first").text().trim());
  210. thisRequesterId = $(thisNode).find("a[href*='.mturk.com/requesters']:first").attr("href").split("/requesters/")[1].split("/projects")[0];
  211. thisRequesterId = thisRequesterId.split("]")[0].replace("[","").replace("]","");
  212. thisTitle = $(thisNode).find("i").text().trim();
  213. var rewardIndex = thisTitle.lastIndexOf("-");
  214. if (rewardIndex) thisReward = thisTitle.substr(rewardIndex+2).replace("$","").trim();
  215. if (rewardIndex) thisTitle = escape(thisTitle.substr(0, rewardIndex).trim());
  216. return {"GID":thisGroupId,"RID":thisRequesterId,"RName":thisRequesterName,"Title":thisTitle,"Reward":thisReward};
  217. }
  218. function format3(foundUrl,thisNode) {
  219. var thisGroupId="", thisRequesterName="", thisRequesterId="", thisTitle="", thisReward="";
  220. var turkerviewNode = $(thisNode).find("a[href*='/requesters/']");
  221. thisGroupId = $(foundUrl).attr("href").split("/projects/")[1].split("/tasks")[0];
  222. thisRequesterName = escape($(thisNode).find("a[href*='worker.mturk.com/requesters']").get(0).previousSibling.nodeValue.slice(0, -2).trim().replace("Requester: ",""));
  223. if (!thisRequesterName) thisRequesterName = $(turkerviewNode).text();
  224. thisRequesterId = $(turkerviewNode).attr("href").split("/requesters/")[1].split("/")[0];
  225. thisTitle = escape($(thisNode).find("a:first").text().trim());
  226. if (!thisTitle) thisTitle = escape($(thisNode).find("a:first").get(0).previousSibling.nodeValue.slice(0, -2).trim());
  227. thisReward = escape($(thisNode).find("b:contains('Reward:')").get(0).nextSibling.nodeValue.trim().replace("$",""));
  228. return {"GID":thisGroupId,"RID":thisRequesterId,"RName":thisRequesterName,"Title":thisTitle,"Reward":thisReward};
  229. }
  230. function addMessageButtons(thisMessage) {
  231. var myContainer=null, thisGroupId="", thisRequesterName="", thisRequesterId="", thisTitle="", thisReward="", jobData = null;
  232. var firstNode = $(thisMessage).find(".ctaBbcodeTableRowTransparent, table.cms_table");
  233. if (gLocation.indexOf("mturkforum.com") != -1) firstNode = $(thisMessage).find("table");
  234. if (firstNode.length) {
  235. $(firstNode).each( function() {
  236. var theAcceptUrl = $(this).find("a:contains('Accept')"), format=1, grabbedUrl = "";
  237. if (!theAcceptUrl.length) { format=2; theAcceptUrl = $(this).find("a:contains('PANDA')"); }
  238. if (theAcceptUrl.length) {
  239. jobData = (format==1) ? format1(theAcceptUrl,this) : format2(theAcceptUrl,this);
  240. myContainer = pcContainer(jobData.GID,jobData.RName,jobData.RID,jobData.Title,jobData.Reward);
  241. var newWorkerSite = ($(theAcceptUrl).attr("href").indexOf("worker.mturk.com") != -1) ? true : false;
  242. var contactLinkFound = ($(this).find("a:contains('Contact')").length) ? true : false;
  243. var requesterLinkFound = ($(this).find("a:contains('Requester')").length) ? true : false;
  244. if ($(this).find("a:contains('Req TV')").length) $(this).find("a:contains('Req TV'):first").next("b").after($(myContainer));
  245. else if ($(this).find("a[href*='turkerview.com/requesters/']").length) $(this).find("a:contains('Contact'):first").after($(myContainer));
  246. else if (requesterLinkFound) $(this).find("a:contains('Requester'):first").after($(myContainer));
  247. else if (contactLinkFound && newWorkerSite && format==1) $(this).find("a:contains('Contact'):first").after($(myContainer));
  248. else if (contactLinkFound && $(this).find("a[href*='turkopticon']").length) $(this).find("a[href*='turkopticon']:first").prev().before($(myContainer));
  249. else if ($(this).find("b:contains('TO Ratings:')").length) $(this).find("b:contains('TO Ratings:')").prev("br").before($(myContainer));
  250. }
  251. });
  252. } else if ($(thisMessage).find(".vw-div:first").length) {
  253. var vwDiv = $(thisMessage).find(".vw-div:first");
  254. if (vwDiv.length && $(thisMessage).find("a:contains('PANDA')").length) {
  255. jobData = format2($(thisMessage).find("a:contains('PANDA')"),thisMessage);
  256. myContainer = pcContainer(jobData.GID,jobData.RName,jobData.RID,jobData.Title,jobData.Reward);
  257. $(vwDiv).prev().after(myContainer);
  258. }
  259. } else if ($(thisMessage).find("a[href*='turkerview.com/requesters/']").length || $(thisMessage).find("b:contains('TurkerView:')").length) {
  260. var thisOne = $(thisMessage);
  261. if ($(thisMessage).find(".quoteContainer").length) thisOne = $(thisMessage).find(".quoteContainer");
  262. jobData = format3($(thisOne).find("a:first"),thisOne);
  263. myContainer = pcContainer(jobData.GID,jobData.RName,jobData.RID,jobData.Title,jobData.Reward);
  264. if ($(thisOne).find("a:contains('Req TV')").length) $(thisOne).find("a:contains('Req TV'):first b:first").after(myContainer);
  265. else if ($(thisOne).find("b:contains('TurkerView')").length) $(thisOne).find("b:contains('TurkerView'):first").prev().before(myContainer);
  266. else $(thisOne).find("a[href*='/requesters/']:first").prev().before(myContainer);
  267. }
  268. $(thisMessage).addClass("JRDoneButtonized");
  269. }
  270. function addPageButtons() {
  271. $("blockquote:not('.quoteContainer, .JRDoneButtonized'), .card:not('.col-10'), #hit").each( function() { addMessageButtons(this); });
  272. }
  273.  
  274. function mainListener(e) {
  275. if ( e.key == 'JR_message_pong_' + gScriptName && e.newValue && gLocation == (JSON.parse(e.newValue).url)) {
  276. window.removeEventListener("storage", mainListener, false);
  277. var noHitsError = ($("td.error_title:contains('There are currently no HITs assigned to you.')").length > 0), buttonPosition=null;
  278. var noHitsAlert = ($("#alertboxHeader:contains('There are currently no HITs assigned to you.')").length > 0);
  279. var returnedAlert = ($("#alertboxHeader:contains('The HIT has been returned.')").length > 0);
  280. if ( gLocation.indexOf("worker.mturk.com") != -1 ) {
  281. var projectDetailBar = $(".project-detail-bar"), requestersInfo={};
  282. var mturkAlertDanger = $(".mturk-alert-danger");
  283. if (mturkAlertDanger.length && $(mturkAlertDanger).find(".mturk-alert-content:contains('There are no more of these HITs available')")) {
  284. var savedGID = GM_getValue("JRHoldGID"), savedRID = GM_getValue("JRHoldRID"), savedRName = GM_getValue("JRHoldRName"),
  285. savedTitle = GM_getValue("JRHoldTitle"), savedReward = GM_getValue("JRHoldReward");
  286. if (savedGID && savedGID!=="" &&
  287. $("button:contains('Accept'), button:contains('Return'), .mturk-alert-content:contains('This HIT requires Qualifications')").length === 0) {
  288. $(mturkAlertDanger).find(".p-b-0").append($("<span>").attr({"class":"JR_PandaCrazy"}).css({"font-size":"10px","margin-left":"10px"}).html("[PC] "));
  289. var thisJobData = jQuery.extend(true, {}, gJobDataDefault);
  290. thisJobData.groupId = savedGID; thisJobData.requesterId = savedRID || ""; thisJobData.requesterName = savedRName || "";
  291. thisJobData.title = savedTitle || ""; thisJobData.pay = savedReward || "";
  292. appendPandaButtons($(mturkAlertDanger).find(".JR_PandaCrazy:first"),thisJobData);
  293. }
  294. }
  295. GM_deleteValue("JRHoldGID"); GM_deleteValue("JRHoldRID"); GM_deleteValue("JRHoldRName"); GM_deleteValue("JRHoldTitle"); GM_deleteValue("JRHoldReward");
  296. if (projectDetailBar.length) {
  297. requestersInfo = parseNewHitPageRequesters(projectDetailBar,gLocation);
  298. buttonPosition = $(".task-project-title:first").parent().parent().parent();
  299. $(buttonPosition).append($("<span>").attr({"class":"JR_PandaCrazy"}).css({"font-size":"9px","margin-left":"10px"}).html("[PC] "));
  300. appendPandaButtons($(".JR_PandaCrazy:first"),requestersInfo);
  301. } else {
  302. var projectsControls = $(".row.projects-info-header, .row.task-queue-header");
  303. if (projectsControls.length) {
  304. var tempPrevDiv = $(projectsControls[0]).next().find(".col-xs-12:first");
  305. var reactInfo = tempPrevDiv.find("div:first").data("reactProps");
  306. reactInfo = reactInfo.bodyData;
  307. $(tempPrevDiv).find(".table-row").bind("DOMSubtreeModified", function() {
  308. if ($(this).find(".expanded-row").length) {
  309. if (!$(this).data("JR-expandedDesc")) {
  310. $(this).data({"JR-expandedDesc":"true"});
  311. var reactIDString = $(this).data("reactid");
  312. var reactID = reactIDString.split("$")[1];
  313. var thisJobData=parseHitsInfo(reactInfo[reactID]);
  314. $(this).find(".p-b-md,.task-info-column").append($("<div>").attr({"class":"JR_PandaCrazy"})
  315. .css({"font-size":"10px","margin-left":"10px"}).html("[PC] "));
  316. appendPandaButtons($(this).find(".JR_PandaCrazy:first"),thisJobData);
  317. }
  318. } else { $(this).removeData("JR-expandedDesc"); }
  319. });
  320. }
  321. }
  322. setTimeout( findProjectedEarnings,900 );
  323. }
  324. }
  325. }
  326. function fixJson(theNode) { // only used to fix hitscraper.
  327. $(theNode).find("a[href*='/projects/']").each( function() {
  328. $(this).attr("href",$(this).attr("href").replace(".json",""));
  329. });
  330. }
  331. function holdGIDLinks(theNode) {
  332. document.onclick = function(event) {
  333. if (event===undefined) event= window.event;
  334. var target= 'target' in event? event.target : event.srcElement, secondPart = "", jobData = null;
  335. if (target.tagName == "A" && target.href.indexOf("/projects/")) {
  336. if ($(target).closest("td.ctaBbcodeTableCellLeft").length) jobData = format1($(target),$(target).closest("td.ctaBbcodeTableCellLeft"));
  337. else if ($(target).closest("td.cms_table_td").length) jobData = format1($(target),$(target).closest("td.cms_table_td"));
  338. else if (gLocation.indexOf("mturkforum.com") != -1) jobData = format1($(target),$(target).closest("td"));
  339. else if ($(target).closest("blockquote.messageText").length) jobData = format2($(target),$(target).closest("blockquote.messageText"));
  340. else if ($(target).closest("a[href*='turkerview.com/requesters/']").length) jobData = format3($(target),$(target).closest("a[href*='turkerview.com/requesters/']"));
  341. else if ($(target).find("b:contains('TurkerView:')").length) jobData = format3($(target),$(target).find("b:contains('TurkerView:')"));
  342. else {
  343. secondPart = target.href.split("/projects/")[1]; var thisGID = (secondPart) ? secondPart.split("/")[0] : "";
  344. jobData = {"GID":thisGID,"RID":"","RName":"","Title":"","Reward":""};
  345. }
  346. if (jobData.GID!=="") {
  347. GM_setValue("JRHoldGID",jobData.GID);
  348. GM_setValue("JRHoldRID",jobData.RID);
  349. GM_setValue("JRHoldRName",unescape(jobData.RName));
  350. GM_setValue("JRHoldTitle",unescape(jobData.Title));
  351. GM_setValue("JRHoldReward",unescape(jobData.Reward));
  352. }
  353. }
  354. };
  355. }
  356. function setUpObserver(theNode,addButtons,jsonFix) {
  357. var targetObserveNode = theNode;
  358. var config = { childList: true };
  359. var callback = function(mutations) {
  360. for (var index = 0,len=mutations.length; index < len; index++) {
  361. var thisMutationNode = mutations[index].addedNodes;
  362. for (var index2 = 0,len2=thisMutationNode.length; index2 < len2; index2++) {
  363. if (addButtons) addMessageButtons(thisMutationNode[index2]);
  364. if (jsonFix) fixJson(thisMutationNode[index2]);
  365. }
  366. }
  367. };
  368. var observer = new MutationObserver(callback);
  369. observer.observe(targetObserveNode, config);
  370. }
  371.  
  372. if (locationForums()) {
  373. setTimeout( function() {
  374. holdGIDLinks($("body"));
  375. addPageButtons();
  376. if ($("#messageList").length) { // forums
  377. setUpObserver($("#messageList")[0],true,false,false);
  378. }
  379. }, 600);
  380. } else {
  381. $(function() {
  382. if (gLocation.indexOf("worker.mturk.com") != -1) gNewSite = true;
  383. if (gLocation.indexOf("worker.mturk.com/requesters/PandaCrazy") != -1) {
  384. var sendFormat = (gLocation.indexOf("PandaCrazyAdd") != -1) ? 1 : (gLocation.indexOf("PandaCrazyOnce") != -1) ? 2 : (gLocation.indexOf("PandaCrazySearch") != -1) ? 3 : 0;
  385. if (sendFormat>0) {
  386. var jobData = jQuery.extend(true, {}, gJobDataDefault);
  387. if ( gLocation.indexOf("JRGID=") != -1) jobData.groupId = gLocation.split("JRGID=")[1].split("&")[0];
  388. if ( gLocation.indexOf("JRRID=") != -1) jobData.requesterId = gLocation.split("JRRID=")[1].split("&")[0];
  389. if ( gLocation.indexOf("JRRName=") != -1) jobData.requesterName = unescape(gLocation.split("JRRName=")[1].split("&")[0]);
  390. if ( gLocation.indexOf("JRTitle=") != -1) jobData.title = unescape(gLocation.split("JRTitle=")[1].split("&")[0]);
  391. if ( gLocation.indexOf("JRReward=") != -1) jobData.pay = unescape(gLocation.split("JRReward=")[1].split("&")[0]);
  392. if (sendFormat==1) sendJobData(jobData);
  393. else if (sendFormat==2) sendJobOnceData(jobData);
  394. else sendJobSearchData(jobData);
  395. setTimeout( function() { window.top.close(); },300);
  396. }
  397. } else if (gLocation.indexOf("mturk.com/") != -1) {
  398. holdGIDLinks($("body"));
  399. if ( !$(".navbar-sub-nav.navbar-nav:contains('Your HITs Queue')").length ) {
  400. $(".nav.navbar-nav.hidden-xs-down:not(:contains('HITs Queue'))").append('<li class="nav-item"><a class="nav-link" href="https://worker.mturk.com/tasks">HITs Queue</a></li>');
  401. }
  402. if ( gLocation.indexOf("/tasks") == -1 && $("button:contains('Return')").length ) {
  403. $(".col-xs-12.navbar-content a.navbar-brand:first").after("<div class='navbar-divider hidden-xs-down'></div><ul class='nav navbar-nav hidden-xs-down'><li class='nav-item'><a class='nav-link' style='color:white;' href='https://worker.mturk.com/tasks'>HITs Queue</a></li></ul>");
  404. }
  405. window.addEventListener("storage", mainListener, false);
  406. setTimeout( function() { sendPingMessage(); }, 500);
  407. }
  408. });
  409. }
  410.  
  411. if (gLocation.includes(`hitnotifier.com`)) {
  412. document.addEventListener(`pandaCrazy`, (event) => {
  413. const hit = event.detail;
  414. const jobData = {};
  415.  
  416. if (hit.project.hit_set_id) jobData.groupId = hit.project.hit_set_id;
  417. if (hit.project.hit_set_id) jobData.requesterId = hit.project.requester_id;
  418. if (hit.project.requester_name) jobData.requesterName = hit.project.requester_name;
  419. if (hit.project.title) jobData.title = hit.project.title;
  420. if (hit.project.monetary_reward) jobData.pay = hit.project.monetary_reward.amount_in_dollars;
  421.  
  422. const search = `?JRGID=${jobData.groupId}&JRRName=${jobData.requesterName}&JRRID=${jobData.requesterId}&JRTitle=${jobData.title}&JRReward=${jobData.pay}`
  423.  
  424. if (hit.search) window.open(`https://worker.mturk.com/requesters/PandaCrazySearch/projects${search}`);
  425. else if (hit.once) window.open(`https://worker.mturk.com/requesters/PandaCrazyOnce/projects${search}`);
  426. else window.open(`https://worker.mturk.com/requesters/PandaCrazyAdd/projects${search}`);
  427. });
  428. }