Advertisement
Guest User

Untitled

a guest
Apr 24th, 2019
512
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 90.46 KB | None | 0 0
  1. // ==UserScript==
  2. // @name HIT Doubleforker (Cached, Realtime Feed Tweaks, Style Tweaks)
  3. // @version 1.1.1
  4. // @description Disable or uninstall Hit Forker when using this.
  5. // @author ThisPoorGuy (forked by Cuyler Stuwe aka salembeats)
  6. // @icon https://i.imgur.com/RaPUMRP.png
  7. // @include https://worker.mturk.com/?finder_beta_test
  8. // @include https://worker.mturk.com/?hit_forker
  9. // @grant GM_log
  10. // @grant GM_setClipboard
  11. // @grant GM_xmlhttpRequest
  12. // @connect turkerview.com
  13. // @require https://code.jquery.com/jquery-3.1.0.min.js
  14. // @require https://cdnjs.cloudflare.com/ajax/libs/dompurify/1.0.8/purify.min.js
  15.  
  16. // @namespace https://greasyfork.org/users/163167
  17. // ==/UserScript==
  18.  
  19. // Acknowledgements
  20. // The core of this script was forked/stolen/adapted from Kadauchi's Hit Finder Beta script. Coding assistance in spots
  21. // provided by Salem Beats and ChrisTurk. TurkerView was created by ChrisTurk. This script hooks into JR Panda Crazy
  22. // Slothbear provided the code for text to speech, thanks!
  23.  
  24. // Changelog
  25. // 1.1.1 = Fixed an issue with the TV API where it will stop if it encounters an error
  26. // 1.1 - Added new TurkerView API code
  27. // 1.0.6.1 - Further input sanatization improvements
  28. // 1.0.5 - Minor update to change the soundjay links to https to stop mixed content complaining.
  29. // 1.0.4 - Added an I button to the HIT log/HIT list so you can just click once to add something to the include list.
  30. // 1.0.3 - Further work on input sanitization
  31. // 1.0.2 - Fixed the issue where some asshat decided to inject code into a HIT name. THIS IS WHY WE CAN'T HAVE NICE THINGS.
  32. // 1.0.1 - Fixed IRC Export function. You're welcome one guy using IRC exports.
  33. // 1.0.0 - Added Text to speech for include list hits. There's a TTS checkbox in the show config section, this will override any sounds set up on your include list with a
  34. // text to speech notification. In order for the alert to trigger you need an include list entry with play sound enabled. Which sound you pick won't matter as this
  35. // will ignore that setting and use a vocal alert. Thanks to slothbear for the code.
  36. // 0.8.1.2 - Fixed an issue exporting HITS that have quotes in the title.
  37. // 0.8.1.1 - Added a limit to the number of characters you can stick into the fields on adding something to the block list to prevent accidental pasting of a block list import into the wrong spot.
  38. // 0.8.1 - Fixed a couple of export formatting bugs.
  39. // 0.8.0 - Added the ability to press a button to launch a qualification test if you don't qualify for something and a test is availible.
  40. // Working on adding requesting for auto-grant quals, but that's...trickier.
  41. // 0.7.6 - Fixed issue with the search qualified check box not working.
  42. // 0.7.5 - Added abilible hits to the Log display. Note this only shows the data from the time when the HIT was first seen, not any subsequent scans of it.
  43. // 0.7.4 - Removed column for masters, it wasn't used for anything and was broken anyway. Also removed hide masters because it worked off of that code, which wasn't working anyway
  44. // 0.7.3 - Returned a semi-colon to it's rightful position, even though it wasn't missed
  45. // 0.7.2 - Made it so that the Panda button sets pandas without once=true set. Whoops.
  46. // 0.7.0 - Big under the hood changes with how TV and TO review scores are gathered.
  47. // 0.6.5 - Further modifications to prevent availibility of external sites causing HF to stop randomly.
  48. // 0.6.4 - Send RequesterID over to PandaCrazy along with the other info.
  49. // 0.6.3 - Bringing PC functionality in house
  50. // 0.6.1 - Fixed panda button shading
  51. // 0.6.0 - Re-jiggered panda crazy integration code to use Salem's PC library. Now detects if panda crazy is actually running when you click.
  52. // 0.5.3 - Slight modifications to break integration with JR Panda Crazy, due to a memory leak issue. Will reach out to dev to see if we can clear it up and be happy together...
  53. // 0.5.2 - Code cleanup.
  54. // 0.5.1 - Fixed the panda buttons on the Found hits table.
  55. // 0.5.0 - Hitting the panda button now sends full HIT name, pay and requester name info to panda crazy too. Have you noticed these version number leaps are pretty arbitratry?
  56. // - Fixed a stupid typo in a variable name.
  57. // 0.4.3 - Switched TO request from a .get call to a .ajax call with a timeout to prevent the entire thing from exploding when TO's servers do.
  58. // 0.4.2 - Link to TV Requester profile in export.
  59. // 0.4.1 - Show/Hide HITs and Logged Hits settings are now saved across sessions
  60. // 0.4.0 - Blocking a HIT or a Requester will now remove that Hit or all hits from said requester from display in the Hit Log
  61. // 0.3.5 - Added a button to hide the new HITS table. Moved the button to hide the logged hits for consistancy.
  62. // 0.3.2 - Modified icon for desktop notifications. Added Requester TV score to hit export
  63. // 0.3.1 - Fix for amazon screwing with things. Thanks ChrisTurk!
  64. // 0.3.0 - Under the hood changes, removed code for running on www, added new launch URL, old ?finder_beta will be phased out eventually
  65. // 0.2.9 - Now acceptable to people with red/green color blindness!
  66. // 0.2.6 - Fixed a minor error which caused colors to not work properly.
  67. // 0.2.5 - Changed Coloration to respect TV reviews FIRST and then fall back on TO Values. Also changed colors.
  68. // 0.2.0 - Added TurkerView Hourly ratings to HIT results, fixed export links.
  69. // 0.1.5 - Some minor UI tweaks
  70. // 0.1.4 - Added some indication that you have already clicked a button to send HIT to PC. Only works in log currently.
  71. // 0.1.3 - Fixed issue with the Panda buttons in the HIT log not having the right GID
  72. // 0.1.2 - Fixed an issue with HITs that have double quotes in the title not working with the ignore hit by title button. I think.
  73. // 0.1.1 - Cleaned up the header, removed unused audio files
  74. // 0.1.0 - Made modifications to launch links with worker website. Added buttons to send information to PandaCrazy directly instead of copying link
  75. // TODO:
  76. // Remove www code
  77. // Clean up interface
  78. // Delete the above todos because they're already done.ey_key
  79.  
  80. const fakeTurkerViewAPIKey = "#".repeat(40);
  81. localStorage.setItem('turkerview_api_key', fakeTurkerViewAPIKey);
  82.  
  83. const ver = GM_info.scriptMetaStr.match(/version.*?(\d+.*)/)[1];
  84. var worker = true;
  85.  
  86. var _config = JSON.parse(localStorage.getItem('_finder')) || {};
  87. _config.tv_api_key = localStorage.getItem('turkerview_api_key') || '';
  88. var blocklist = JSON.parse(localStorage.getItem('_finder_bl')) || {};
  89. var includelist = JSON.parse(localStorage.getItem('_finder_il')) || {};
  90.  
  91. // Compatability check
  92. if (_config.version !== '1.1') { _config = {}; }
  93.  
  94. var config = {
  95. version : _config.version || '1.1',
  96. delay : _config.delay || '3',
  97. type : _config.type || 'LastUpdatedTime%3A1&pageSize=',
  98. size : _config.size || '25',
  99. rew : _config.rew || '0.00',
  100. avail : _config.avail || '0',
  101. mto : _config.mto || '0.00',
  102. alert : _config.alert || '0',
  103. qual : _config.hasOwnProperty('qual') ? _config.qual : true,
  104. new : _config.hasOwnProperty('new') ? _config.new : true,
  105. newaudio : _config.newaudio || 'beep',
  106. pb : _config.hasOwnProperty('pb') ? _config.pb : false,
  107. to : _config.hasOwnProperty('to') ? _config.to : true, // We have a faster TO than the standard TO, so we can use it by default.
  108. tv : _config.hasOwnProperty('tv') ? _config.tv : true,
  109. nl : _config.hasOwnProperty('nl') ? _config.nl : false,
  110. bl : _config.hasOwnProperty('bl') ? _config.bl : false,
  111. m : _config.hasOwnProperty('m') ? _config.m : false,
  112. tts : _config.hasOwnProperty('tts') ? _config.tts : false,
  113. push : _config.push || 'access_token_na',
  114. tv_api_key : _config.tv_api_key || fakeTurkerViewAPIKey,
  115. theme : _config.theme || 'light',
  116. custom : _config.custom || {main: 'FFFFFF', primary: 'CCCCCC', secondary: '111111', text: '000000', link: '000000', visited: '000000', prop : false},
  117. to_theme : _config.to_theme || '1',
  118. h_hidden : _config.h_hidden || '0',
  119. l_hidden : _config.l_hidden || '0'
  120. };
  121. console.log(config);
  122. console.log(config.tv_api_key);
  123. var themes = {
  124. 'default' : {main: 'FFFFFF', primary: 'CCCCCC', secondary: '111111', menu: '373b44', menutext: 'FFFFFF', text: '000000', link: '0000EE', visited: '551A8B', prop : true},
  125. 'light' : {main: 'FFFFFF', primary: 'CCCCCC', secondary: '111111', menu: '373b44', menutext: 'FFFFFF', text: '000000', link: '000000', visited: '000000', prop : true},
  126. 'dark' : {main: '404040', primary: '666666', secondary: 'FFFFFF', menu: '202020', menutext: 'FFFFFF', text: 'FFFFFF', link: 'FFFFFF', visited: 'B3B3B3', prop : true},
  127. 'darker' : {main: '000000', primary: '262626', secondary: 'FFFFFF', menu: '373b44', menutext: 'FFFFFF', text: 'FFFFFF', link: 'FFFFFF', visited: 'B3B3B3', prop : true},
  128. 'custom' : config.custom
  129. };
  130.  
  131. var turkerview = { };
  132. var turkerview_update = 0;
  133. var requesters = [ ];
  134. var tvTimeoutCache = [ ];
  135.  
  136. var searches = 0,
  137. logged = 0,
  138. hitlog = {},
  139. noti_delay = [],
  140. push_delay = [];
  141.  
  142. const ViewHeaders = new Headers([
  143. ['X-VIEW-KEY', config.tv_api_key],
  144. ['X-APP-KEY', 'HIT Forker'],
  145. ['X-APP-VER', ver] //SemVer
  146. ]);
  147.  
  148. function clearHitlog() {
  149. if(!confirm("Clear this session's log of seen HITs?")) {return;}
  150. [...document.querySelectorAll("#logged_hits .cont")].forEach(hlRow => hlRow.remove());
  151. logged = 0;
  152. document.getElementById("logged_hits_data").innerHTML = `<span style="float: right;">0</span>`;
  153. hitlog = {};
  154. }
  155.  
  156. // General Configuration variables
  157. var url, upd, num, rew, minrew, searchqual, pandaurl;
  158.  
  159. url = 'https://worker.mturk.com/?';
  160. pandaurl = 'https://worker.mturk.com';
  161. upd = '&sort=updated_desc&page_size=';
  162. num = '&sort=num_hits_desc&page_size=';
  163. rew = '&sort=reward_desc&page_size=';
  164. minrew = '&filters%5Bmin_reward%5D=';
  165. searchqual = '&filters%5Bqualified=';
  166.  
  167. var PandaCrazy = (function createPandaCrazy() {
  168. let _self = this;
  169.  
  170. let _lastSentPingTime;
  171. let _lastReceivedPongTime;
  172.  
  173. let _onlineSinceLastPing;
  174.  
  175. let _pcListener;
  176.  
  177. const MAX_WAIT_FOR_PANDA_CRAZY_RESPONSE_MS = 1000;
  178.  
  179. function ping() {
  180. _lastSentPingTime = Date.now();
  181. localStorage.setItem("JR_message_ping_pandacrazy", `{"theTarget": "${Math.random()}"}`);
  182. }
  183.  
  184. function hasIndicatedOnlineSinceLastPing() {
  185. if(_lastSentPingTime !== undefined && _lastReceivedPongTime !== undefined) {
  186. return _lastReceivedPongTime >= _lastSentPingTime;
  187. }
  188. else {
  189. return undefined;
  190. }
  191. }
  192.  
  193. function online() {
  194.  
  195. function respondToStorage(resolve, reject, e) {
  196. if(e.key.includes("JR_message_pong") && Boolean(e.newValue)) {
  197.  
  198. _lastReceivedPongTime = Date.now();
  199.  
  200. let pongData = JSON.parse(e.newValue);
  201.  
  202. let lag = Number(pongData.time) - Number(_lastReceivedPongTime);
  203.  
  204. if(hasIndicatedOnlineSinceLastPing()) {
  205. resolve("online");
  206. }
  207. }
  208. }
  209.  
  210. let isOnlinePromise = new Promise((resolve, reject) => {
  211.  
  212. setTimeout(() => {reject("timeout");}, MAX_WAIT_FOR_PANDA_CRAZY_RESPONSE_MS);
  213.  
  214. if(_pcListener) {window.removeEventListener("storage", _pcListener);}
  215.  
  216. _pcListener = respondToStorage.bind(window, resolve, reject);
  217.  
  218. window.addEventListener("storage", _pcListener);
  219.  
  220. /*
  221. window.addEventListener("storage", e => {
  222.  
  223. // console.log("Storage Event", e);
  224.  
  225. if(e.key.includes("JR_message_pong") && Boolean(e.newValue)) {
  226.  
  227. _lastReceivedPongTime = Date.now();
  228.  
  229. let pongData = JSON.parse(e.newValue);
  230.  
  231. let lag = Number(pongData.time) - Number(_lastReceivedPongTime);
  232.  
  233. if(hasIndicatedOnlineSinceLastPing()) {
  234. resolve("online");
  235. }
  236. }
  237. });
  238. */
  239. });
  240.  
  241. ping();
  242.  
  243. return isOnlinePromise;
  244. }
  245.  
  246. function addJob(gid, once, metadata) {
  247. let commandString = once ? "addOnceJob" : "addJob";
  248.  
  249. localStorage.setItem("JR_message_pandacrazy", JSON.stringify({
  250. time: Date.now(),
  251. command: commandString,
  252. data: {
  253. groupId: gid,
  254. title: (metadata ? metadata.hitTitle || metadata.title : undefined),
  255. requesterName: (metadata ? metadata.requesterName : undefined),
  256. requesterId: (metadata ? metadata.requesterID || metadata.requesterId || metadata.rid : undefined),
  257. pay: (metadata ? metadata.hitValue || metadata.pay : undefined),
  258. duration: (metadata ? metadata.duration : undefined),
  259. hitsAvailable: (metadata ? metadata.hitsAvailable : undefined)
  260. }
  261. }));
  262. }
  263.  
  264. function startJob(gid) {
  265. localStorage.setItem("JR_message_pandacrazy", JSON.stringify({
  266. time: Date.now(),
  267. command: "startcollect",
  268. data: {
  269. groupId: gid
  270. }
  271. }));
  272. }
  273.  
  274. return {
  275. addJob,
  276. startJob,
  277. ping,
  278. online
  279. };
  280. })();
  281.  
  282. const SPEECH_VOICE = 3; //0 - 21ish
  283. const SPEECH_RATE = 0.9; //1 - 10 (default is 1)
  284. const SPEECH_VOLUME = 1; //0 - 1 (default is 1)
  285. const SPEECH_LANG = 'en-US'; //(default is 'en')
  286.  
  287.  
  288.  
  289. //this is what does it all!
  290. unsafeWindow.slothbearsTTS = function(obj) {
  291. let phrase = "Hit Found!" + obj.name;
  292. var speech = new Speech();
  293. if (speech.supported()) {
  294. speech.speak(phrase);
  295. }
  296. };
  297.  
  298.  
  299.  
  300. var Speech = function() {
  301. };
  302.  
  303. Speech.voices = null;
  304.  
  305. (function() {
  306. if ('speechSynthesis' in window) {
  307. // First call to getVoices may be null...later an event indicates when it is loaded
  308. Speech.voices = window.speechSynthesis.getVoices();
  309.  
  310. // Save voices when loaded after first call
  311. window.speechSynthesis.onvoiceschanged = function() {
  312. Speech.voices = window.speechSynthesis.getVoices();
  313. };
  314. }
  315. })();
  316.  
  317. Speech.prototype.supported = function() {
  318. return Speech.voices !== null;
  319. };
  320.  
  321. Speech.prototype.speak = function(text) {
  322. if (Speech.voices !== null) {
  323. var speech = new SpeechSynthesisUtterance(text);
  324.  
  325. speech.rate = SPEECH_RATE;
  326. speech.voice = speechSynthesis.getVoices()[SPEECH_VOICE];
  327. speech.lang = SPEECH_LANG;
  328. speech.volume = SPEECH_VOLUME;
  329. window.speechSynthesis.speak(speech);
  330. }
  331. };
  332.  
  333. $('head').html(
  334. '<title>HIT Forker</title>' +
  335. '<link rel="icon" type="image/jpg" href="http://nopurpose.org/stuff/avatars/Lj21396.gif">' +
  336. '<base target="_blank">' +
  337.  
  338. '<audio id="audio_1"><source src="https://www.soundjay.com/button/sounds/button-1.mp3" type="audio/mpeg"></audio>' +
  339. '<audio id="audio_2"><source src="https://www.soundjay.com/button/sounds/button-3.mp3" type="audio/mpeg"></audio>' +
  340. '<audio id="audio_3"><source src="https://www.soundjay.com/button/sounds/button-4.mp3" type="audio/mpeg"></audio>' +
  341. '<audio id="audio_4"><source src="https://www.soundjay.com/button/sounds/button-5.mp3" type="audio/mpeg"></audio>' +
  342. '<audio id="audio_beep"><source src="https://www.soundjay.com/button/sounds/beep-21.mp3" type="audio/mpeg"></audio>' +
  343. '<audio id="audio_beepbeep"><source src="https://www.soundjay.com/button/sounds/beep-24.mp3" type="audio/mpeg"></audio>' +
  344. '<audio id="audio_click"><source src="https://www.soundjay.com/button/sounds/button-20.mp3" type="audio/mpeg"></audio>' +
  345.  
  346. '<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">' +
  347. '<style id="css" type="text/css">'
  348. );
  349.  
  350. $('body').on('click', '.closeTvAlert', function(){
  351. $(this).parent().parent().hide();
  352. });
  353.  
  354. $('body').html(
  355. // Main
  356. '<style type="text/css"> a {color: #000000; text-decoration: none;} </style>' +
  357. '<div style="margin-bottom: 5px; text-align:right;" id="menubar">' +
  358. '<div style="position: absolute; top: 32px width: 100px; font-size: 14pt; font-weight: bold;" id="menu_title">HIT Forker</div>'+
  359. '<div style="line-height: 30px; margin-right:5px;">'+
  360. '<button id="scan_button" style="margin-right: 5px;">Start</button>' +
  361. '<button id="bloc_button" style="margin-right: 5px;">Block List</button>' +
  362. '<button id="incl_button" style="margin-right: 5px;">Include List</button>' +
  363. '<button id="sett_button" style="margin-right: 5px;">Advanced Settings</button>' +
  364. '<button id="conf_button" style="margin-right: 5px;">Show Config</button>' +
  365.  
  366. '</div></div>' +
  367.  
  368. // Config
  369. '<div id="config" style="position: absolute; top: 37px; right: 5px; margin-bottom: 5px;" class="hidden">' +
  370.  
  371. '<div style="margin-bottom: 5px;">' +
  372. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Delay in seconds between searches.">Search Delay: ' +
  373. '<input id="delay" style="width: 50px;" type="number" step="1" min="1" value="' + config.delay + '">' +
  374. '</label>' +
  375.  
  376. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Filter HITs by minimum reward.">Min Reward: ' +
  377. '<input id="min_rew" style="width: 50px;" type="number" step="0.01" min="0" value="' + config.rew + '">' +
  378. '</label>' +
  379.  
  380. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Filter HITs by minimum available.">Min Avail: ' +
  381. '<input id="min_avail" style="width: 50px;" type="number" step="1" min="0" value="' + config.avail + '">' +
  382. '</label>' +
  383.  
  384. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Filter HITs by minimum TO pay.">Min TO: ' +
  385. '<input id="min_to" style="width: 50px;" type="number" step="0.1" min="0" max="5" value="' + config.mto + '">' +
  386. '</label>' +
  387.  
  388. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Search for this many HITs.">Size: ' +
  389. '<input id="size" style="width: 50px;" type="number" step="1" min="1" max="100" value="' + config.size + '">' +
  390. '</label>' +
  391.  
  392. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Sort HITs by (Latest / Most Available / Highest Reward)">Sort by: ' +
  393. '<select id="type" value="' + config.type + '">' +
  394. '<option value="' + upd + '">Latest</option>' +
  395. '<option value="' + num + '">Most Available</option>' +
  396. '<option value="' + rew + '">Reward (Most)</option>' +
  397. '</select>' +
  398. '</label>' +
  399.  
  400. '<label style="margin-right: 0px; display: inline-block; border-bottom: 1px solid;" title="Only show HITs that you are for.">Qualified' +
  401. '<input id="qual" type="checkbox" ' + (config.qual ? 'checked' : '') + '>' +
  402. '</label>' +
  403. '</div>' +
  404.  
  405. '<div style="margin-bottom: 5px;">' +
  406. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Delay in seconds between desktop notifications and sound alerts for an include list match.">Alert Delay: ' +
  407. '<input id="alert_delay" style="width: 50px;" type="number" step="1" min="0" value="' + config.alert + '">' +
  408. '</label>' +
  409.  
  410. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Make a sound when a new HIT is found.">Sound On New HIT ' +
  411. '<input id="new_sound" type="checkbox" ' + (config.new ? 'checked' : '') + '>' +
  412. '<select id="new_audio" value="' + config.newaudio + '">' +
  413. //'<option value="default">Default</option>' +
  414. '<option value="beep">Beep</option>' +
  415. '<option value="beepbeep">Beep Beep</option>' +
  416. //'<option value="ding">Ding</option>' +
  417. //'<option value="squee">Squee</option>' +
  418. '<option value="click">Click</option>' +
  419. '</select>' +
  420. '</label>' +
  421.  
  422. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Allow include list to send a TTS notification when matched">TTS ' +
  423. '<input id="tts" type="checkbox" ' + (config.tts ? 'checked' : '') + '>' +
  424. '</label>' +
  425.  
  426. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Allow inludelist matches to send Pushbullet notifications if enabled for that match.">Pushbullet ' +
  427. '<input id="pb" type="checkbox" ' + (config.pb ? 'checked' : '') + '>' +
  428. '</label>' +
  429.  
  430. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Use turkopticon.">Enable TO ' +
  431. '<input id="to" type="checkbox" ' + (config.to ? 'checked' : '') + '>' +
  432. '</label>' +
  433.  
  434. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Hide all HITs that do not match your include list.">Hide Non Include List ' +
  435. '<input id="nl_hide" type="checkbox" ' + (config.nl ? 'checked' : '') + '>' +
  436. '</label>' +
  437.  
  438. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;" title="Hide HITs that match your block list.">Hide Block List ' +
  439. '<input id="bl_hide" type="checkbox" ' + (config.bl ? 'checked' : '') + '>' +
  440. '</label>' +
  441.  
  442. '</div>' +
  443.  
  444. '</div>' +
  445.  
  446. '<div id="TVAlert" style="background-color: #dff0d8; border-color: #d0e9c6;' + ((config.tv_api_key == '' || config.tv_api_key.length != 40) ? `` : ` display: none; `) +' color: #3c763d; padding: 15px; margin-bottom: 1rem; border: 1px solid transparent; border-radius: 2px; margin: auto; width: 60%; padding-top: 10px; padding-bottom: 10px;">' +
  447. '<h4 style="font-size: 0.857rem; margin-bottom: 0.5rem; margin-top: 0.5rem;">TurkerView API Changes (<span class="closeTvAlert" style="cursor: pointer;">Dismiss</span>)</h4>' +
  448.  
  449. `<small>
  450. <p>Sorry for the intrusion, but we're expanding our services & infrastructure and making huge improvements to the way we deliver information & data to Turkers in 2019!</p>
  451. <p>HIT Forker has been updated to function with TurkerView's new View API [<a href="https://forum.turkerview.com/threads/hit-forker-update.2025/" target="_blank">details here</a>]
  452. <p>TVJS 10 is out! You can read change details <a href="https://forum.turkerview.com/threads/turkerviewjs-10.2010/" target="_blank">here</a> - including improvements to approval (AA) time tracking! You can find more information about the full API changes <a href="https://forum.turkerview.com/threads/view-api-details.2012/" target="_blank" style="text-decoration: underline;">on our announcement here</a>.</p>
  453. <p>Make sure to register & get your new access keys to our upgraded API by <a href="https://turkerview.com/account/api/" target="_blank" style="text-decoration: underline;">visiting your account dashboard</a>. We'll stop displaying this as soon as you do, but the script wont be able to retrieve TV data after February 1st without an API Key.</p>
  454. </small><form action="saveForkerApiForm" onsubmit="return false;">
  455. <input type="text" class="form-control" style="max-width: 50%; margin-top: 5px; margin-bottom: 5px;">
  456. <button type="submit" class="btn btn-primary">Save API Key</button>
  457. </form>
  458. <script>
  459. $('form[action*=saveForkerApiForm]').submit(function(e){
  460. e.preventDefault();
  461. let api_key = $(this).find('input[type=text]').val().trim();
  462. console.log(api_key);
  463. if (api_key.length == 40){
  464. localStorage.setItem('turkerview_api_key', api_key);
  465. alert('Awesome, we saved your API key for future use! HIT Forker will reload now.');
  466. window.location.reload();
  467. } else {
  468. alert("We cannot save the provided key as it isn't valid.");
  469. }
  470. });
  471. </script>` +
  472.  
  473. '</div>'+
  474.  
  475. '<div id="TVErrorMessage" style="display: none; background-color: #f2dede; border-color: #ebcccc; color: #a94442; padding: 15px; margin-bottom: 1rem; border: 1px solid transparent; border-radius: 2px; margin: auto; width: 60%; padding-top: 10px; padding-bottom: 10px;">' +
  476. '<h4 style="font-size: 0.857rem; margin-bottom: 0.5rem; margin-top: 0.5rem;">TurkerView API Error (<span class="closeTvAlert" style="cursor: pointer;">Dismiss</span>)</h4>' +
  477. '<p style="margin-bottom: 0.5rem; margin-top: 0.5rem;">Error Message.</p>' +
  478. '</div>'+
  479. // HITs
  480. '<div id="latest_hits">' +
  481. '<div style="border-bottom: 3px solid; margin-bottom: 5px;">' +
  482. '<span style="font-size: 20px; font-weight: bold;">HITs</span>' +
  483. '<span id="hits_data" style="font-size: 11px;"></span>' +
  484. '<span id="hits_controls" style="float: right"><button id="hits_button" style="margin-right: 5px;">Hide New HITs</button></span>' +
  485. '</div>' +
  486. '<div id="hits_hidden" style="text-align: center; display: none;">--- HITS HIDDEN ---</div>' +
  487. '<div id="hits_table">' +
  488. '<div>' +
  489. '<div style="overflow: hidden; white-space: nowrap;">' +
  490. '<div style="float: left; width: calc(100% - 200px);">' +
  491. '<span style="width: 34%; float: left; display:inline-block; overflow: hidden;">&nbsp;</span>' +
  492. '<span style="width: 64%; float: right; display:inline-block; overflow: hidden;">&nbsp;</span>' +
  493. '</div>' +
  494.  
  495. '<div style="float: right;">' +
  496. '<span style="width: 40px; display:inline-block; text-align: center;">Size</span>' +
  497. '<span style="width: 60px; display:inline-block; text-align: center;">TV</span>' +
  498. '<span style="width: 60px; display:inline-block; text-align: center;">TO</span>' +
  499. '<span style="width: 25px; display:inline-block; text-align: center;">$/¢</span>' +
  500. '<span style="width: 60px; display:inline-block; text-align: center;">PANDA</span>' +
  501. '</div>' +
  502. '</div>' +
  503. '</div>' +
  504. '<div id="new_hits_"></div>' +
  505. '</div>' +
  506. '</div>' +
  507.  
  508. '<br>' +
  509.  
  510. //Logged HITs
  511. '<div id="logged_hits">' +
  512. '<div style="border-bottom: 3px solid; margin-bottom: 5px;">' +
  513. '<span style="font-size: 20px; font-weight: bold;">Logged HITs</span>' +
  514. '<span id="logged_hits_data" style="font-size: 11px;"></span>' +
  515. '<span id="log_controls" style="float: right"><button id="logg_button" style="margin-right: 0px;">Hide Logged HITs</button> <button id="clearHitlog">Clear Log</button></span>' +
  516. '</div>' +
  517. '<div id="log_hidden" style="text-align: center; display: none;">--- LOGGED HITS HIDDEN ---</div>' +
  518. '<div id="log_table">' +
  519. '<div>' +
  520. '<div style="overflow: hidden; white-space: nowrap;">' +
  521.  
  522. '<div style="float: left;">' +
  523. '<span style="width: 80px; display:inline-block;">Time</span>' +
  524. '</div>' +
  525.  
  526. '<div style="float: left; width: calc(100% - 3500px);">' +
  527. '<span style="width: 25%; float: left; display:inline-block; overflow: hidden;">Requester</span>' +
  528. '<span style="width: 75%; float: right; display:inline-block; overflow: hidden;">Project</span>' +
  529.  
  530. '</div>' +
  531.  
  532. '<div style="float: right;">' +
  533. '<span style="width: 60px; display:inline-block; text-align: center;">Avail</span>' +
  534. '<span style="width: 60px; display:inline-block; text-align: center;">Accept</span>' +
  535. '<span style="width: 60px; display:inline-block; text-align: center;">TV</span>' +
  536. '<span style="width: 60px; display:inline-block; text-align: center;">TO</span>' +
  537. '<span style="width: 60px; display:inline-block; text-align: center;">PANDA</span>' +
  538. '</div>' +
  539. '</div>' +
  540. '</div>' +
  541. '<div id="log_hits_"></div>' +
  542. '</div>' +
  543. '</div>' +
  544.  
  545. // Block List
  546. '<div id="bl_div" style="z-index: 99; position: fixed; width: 80%; height: 80%; left: 10%; top: 300px; margin-top: -250px; display: none;">' +
  547. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Block List</div>' +
  548. '<div id="bl_items"></div>' +
  549. '<div style="text-align: center;">' +
  550. '<button id="bl_add" style="margin-right: 5px;">Add</button>' +
  551. '<button id="bl_close" style="margin-right: 5px;">Close</button>' +
  552. '<button id="bl_import" style="margin-right: 5px;">Import</button>' +
  553. '<button id="bl_export" style="margin-right: 0px;">Export</button>' +
  554. '</div>' +
  555. '</div>' +
  556.  
  557. // Add Block List Popup
  558. '<div id="bl" class="add" style="z-index: 100; position: fixed; width: 520px; top: 300px; left: 50%; margin: -250px; padding: 5px; text-align: center; display: none;">' +
  559. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Add To Block List</div>' +
  560.  
  561. '<div>' +
  562. '<p><label>Term: </label><input id="bl_term" value="" maxlength="300"></p>' +
  563. '<p><label>Name: </label><input id="bl_name" value="" maxlength="300"></p>' +
  564. '<input id="bl_gid" value="0" type="hidden">' +
  565. '</div>' +
  566.  
  567. '<div>' +
  568. '<button id="bl_add_save" style="margin-right: 5px;">Save</button>' +
  569. '<button id="bl_add_cancel" style="margin-right: 0px;">Cancel</button>' +
  570. '</div>' +
  571. '</div>' +
  572.  
  573. // Edit Block List Popup
  574. '<div id="edit_bl" class="add" class="add" style="z-index: 100; position: fixed; width: 520px; top: 300px; left: 50%; margin: -250px; padding: 5px; text-align: center; display: none;">' +
  575. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Edit Block List Item</div>' +
  576.  
  577. '<div>' +
  578. '<p><label>Term: </label><input id="edit_bl_term" value=""disabled></p>' +
  579. '<p><label>Name: </label><input id="edit_bl_name" value=""></p>' +
  580. '</div>' +
  581.  
  582. '<div>' +
  583. '<button id="edit_bl_save" style="margin-right: 5px;">Save</button>' +
  584. '<button id="edit_bl_delete" style="margin-right: 5px;">Delete</button>' +
  585. '<button id="edit_bl_cancel" style="margin-right: 0px;">Cancel</button>' +
  586. '</div>' +
  587. '</div>' +
  588.  
  589. // Include List
  590. '<div id="il_div" style="z-index: 99; position: fixed; width: 80%; height: 80%; left: 10%; top: 300px; margin-top: -250px; display: none;">' +
  591. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Include List</div>' +
  592. '<div id="il_items"></div>' +
  593. '<div style="text-align: center;">' +
  594. '<button id="il_add" style="margin-right: 5px;">Add</button>' +
  595. '<button id="il_close" style="margin-right: 5px;">Close</button>' +
  596. '<button id="il_import" style="margin-right: 5px;">Import</button>' +
  597. '<button id="il_export" style="margin-right: 0px;">Export</button>' +
  598. '</div>' +
  599. '</div>' +
  600.  
  601. // Add Include List Popup
  602. '<div id="il" class="add" style="z-index: 100; position: fixed; width: 520px; top: 300px; left: 50%; margin: -250px; padding: 5px; text-align: center; display: none;">' +
  603. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Add To Include List</div>' +
  604.  
  605. '<div>' +
  606. '<p><label>Term: </label><input id="il_term" value=""></p>' +
  607. '<p><label>Name: </label><input id="il_name" value=""></p>' +
  608. '</div>' +
  609.  
  610. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Alerts</div>' +
  611.  
  612. '<p>' +
  613. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;">Sound: ' +
  614. '<select id="il_sound">' +
  615. '<option value="1">Sound 1</option>' +
  616. '<option value="2">Sound 2</option>' +
  617. '<option value="3">Sound 3</option>' +
  618. '<option value="4">Sound 4</option>' +
  619. '</select>' +
  620. '</label>' +
  621.  
  622. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;">Desktop Notifications' +
  623. '<input id="il_noti_cb" type="checkbox">' +
  624. '</label>' +
  625.  
  626. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;">Play Sound' +
  627. '<input id="il_sound_cb" type="checkbox">' +
  628. '</label>' +
  629.  
  630. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;">Send Pushbullet' +
  631. '<input id="il_push_cb" type="checkbox">' +
  632. '</label>' +
  633. '</p>' +
  634.  
  635. '<div>' +
  636. '<button id="il_add_save" style="margin-right: 5px;">Save</button>' +
  637. '<button id="il_add_cancel" style="margin-right: 0px;">Cancel</button>' +
  638. '</div>' +
  639. '</div>' +
  640.  
  641. // Edit Include List Popup
  642. '<div id="edit_il" class="add" style="z-index: 100; position: fixed; width: 520px; top: 300px; left: 50%; margin: -250px; padding: 5px; text-align: center; display: none;">' +
  643. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Edit Include List Item</div>' +
  644.  
  645. '<div>' +
  646. '<p><label>Term: </label><input id="edit_il_term" value="" disabled></p>' +
  647. '<p><label>Name: </label><input id="edit_il_name" value=""></p>' +
  648. '</div>' +
  649.  
  650. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;"">Alerts</div>' +
  651.  
  652. '<p>' +
  653. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;">Sound: ' +
  654. '<select id="edit_il_sound">' +
  655. '<option value="1">Sound 1</option>' +
  656. '<option value="2">Sound 2</option>' +
  657. '<option value="3">Sound 3</option>' +
  658. '<option value="4">Sound 4</option>' +
  659. '</select>' +
  660. '</label>' +
  661.  
  662. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;">Desktop Notifications' +
  663. '<input id="edit_il_noti_cb" type="checkbox">' +
  664. '</label>' +
  665.  
  666. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;">Play Sound' +
  667. '<input id="edit_il_sound_cb" type="checkbox">' +
  668. '</label>' +
  669.  
  670. '<label style="margin-right: 0px; display: inline-block; border-bottom: 1px solid;">Send Pushbullet' +
  671. '<input id="edit_il_push_cb" type="checkbox">' +
  672. '</label>' +
  673. '</p>' +
  674.  
  675. '<div>' +
  676. '<button id="edit_il_save" style="margin-right: 5px;">Save</button>' +
  677. '<button id="edit_il_delete" style="margin-right: 5px;">Delete</button>' +
  678. '<button id="edit_il_cancel" style="margin-right: 0px;">Cancel</button>' +
  679. '</div>' +
  680. '</div>' +
  681.  
  682. // Advanced Settings
  683. '<div id="sett" class="add" style="z-index: 100; position: fixed; width: 520px; top: 300px; left: 50%; margin: -250px; padding: 5px; text-align: center; display: none;">' +
  684. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Advanced Settings</div>' +
  685.  
  686. '<div>' +
  687. '<p><label>Pushbullet Token: </label><input id="push" value="' + config.push + '"></p>' +
  688. '</div>' +
  689. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">TurkerView</div>' +
  690. '<div><p><label>TurkerView API Key: </label><input id="tv_api_key" value="' + ((config.tv_api_key == null || config.tv_api_key.length != 40) ? '' : config.tv_api_key) + '"></p></div>' +
  691.  
  692. '<div style="position: relative; width: 80%; left: 10%; border-bottom: 3px solid; padding: 2px; text-align: center;">Theme</div>' +
  693.  
  694. '<p>' +
  695. '<label style="margin-right: 5px; display: inline-block; border-bottom: 1px solid;">Theme: ' +
  696. '<select id="adv_theme" value="' + config.theme + '">' +
  697. '<option value="default">Default (Light)</option>' +
  698. '<option value="light">Pastel</option>' +
  699. '<option value="dark">Dark</option>' +
  700. '<option value="darker">Darker</option>' +
  701. '<option value="custom">Custom</option>' +
  702. '</select>' +
  703. '</label>' +
  704.  
  705. '<label style="margin-right: 0px; display: inline-block; border-bottom: 1px solid;">TO Theme: ' +
  706. '<select id="to_theme" value="' + config.to_theme + '">' +
  707. '<option value="1">Default</option>' +
  708. '<option value="2">Column Only</option>' +
  709. '<option value="3">Text Only</option>' +
  710. '</select>' +
  711. '</label>' +
  712. '</p>' +
  713.  
  714. '<p>' +
  715. '<label style="width: 150px; margin-right: 5px; display: inline-block; border-bottom: 1px solid; text-align: left;">Main: #' +
  716. '<input id="theme_main" style="width: 55px; float: right;" maxlength="6">' +
  717. '</label>' +
  718.  
  719. '<label style="width: 150px; margin-right: 5px; display: inline-block; border-bottom: 1px solid; text-align: left;">Primary: #' +
  720. '<input id="theme_primary" style="width: 55px; float: right;" maxlength="6">' +
  721. '</label>' +
  722.  
  723. '<label style="width: 150px; margin-right: 0px; display: inline-block; border-bottom: 1px solid; text-align: left;">Secondary: #' +
  724. '<input id="theme_secondary" style="width: 55px; float: right;" maxlength="6">' +
  725. '</label>' +
  726. '</p>' +
  727.  
  728. '<p>' +
  729. '<label style="width: 150px; margin-right: 5px; display: inline-block; border-bottom: 1px solid; text-align: left;">Text: #' +
  730. '<input id="theme_text" style="width: 55px; float: right;" maxlength="6">' +
  731. '</label>' +
  732.  
  733. '<label style="width: 150px; margin-right: 5px; display: inline-block; border-bottom: 1px solid; text-align: left;">Link: #' +
  734. '<input id="theme_link" style="width: 55px; float: right;" maxlength="6">' +
  735. '</label>' +
  736.  
  737. '<label style="width: 150px; margin-right: 0px; display: inline-block; border-bottom: 1px solid; text-align: left;">Visited: #' +
  738. '<input id="theme_visited" style="width: 55px; float: right;" maxlength="6">' +
  739. '</label>' +
  740. '</p>' +
  741.  
  742. '<div>' +
  743. '<button id="sett_save" style="margin-right: 5px;">Save</button>' +
  744. '<button id="sett_close" style="margin-right: 0px;">Close</button>' +
  745. '</div>' +
  746. '</div>'
  747. );
  748.  
  749. document.getElementById("clearHitlog").addEventListener("click", clearHitlog);
  750.  
  751. // Click functions
  752. $('#scan_button').click(function () {
  753. if ($(this).text() === 'Start') {
  754. $(this).text('Stop');
  755. _scan();
  756. }
  757. else {
  758. $(this).text('Start');
  759. }
  760. });
  761.  
  762. $('#sett_button').click(function () {
  763. $('#sett').toggle();
  764. });
  765.  
  766. $('#conf_button').click(function () {
  767. if ($(this).text() === 'Hide Config') {
  768. $(this).text('Show Config');
  769. }
  770. else {
  771. $(this).text('Hide Config');
  772. }
  773. $('#config').toggleClass('hidden');
  774. });
  775.  
  776. $('#logg_button').click(function () {
  777. _hide_log_list( $(this).text() === 'Hide Logged HITs' ? true : false );
  778. });
  779.  
  780. $('#hits_button').click(function () {
  781. _hide_hit_list( $(this).text() === 'Hide New HITs' ? true : false );
  782. });
  783.  
  784. $('#bloc_button').click(function () {
  785. $('#bl_div').toggle();
  786. });
  787.  
  788. $('#bl_add').click(function () {
  789. $('#bl').show();
  790. });
  791.  
  792. $('#bl_close').click(function () {
  793. $('#bl_div').hide();
  794. });
  795.  
  796. $('#bl_import').click(function () {
  797. _import_block();
  798. });
  799.  
  800. $('#bl_export').click(function () {
  801. _export_block();
  802. });
  803.  
  804. $('#bl_add_save').click(function () {
  805. var obj = {
  806. term : $('#bl_term').val(),
  807. name : $('#bl_name').val() === '' ? $('#bl_term').val() : $('#bl_name').val(),
  808. gid : $('#bl_gid').val() === '' ? 'X' : $('#bl_gid').val()
  809. };
  810.  
  811. _add_block(obj);
  812.  
  813. if ( obj.gid != 'X' ) {
  814. $('.loggid_' + obj.gid ).remove();
  815. }
  816. else {
  817. $('.logreqid_' + obj.term ).remove();
  818. }
  819.  
  820. $('#bl_term, #bl_name').val('');
  821. $('#bl').hide();
  822. });
  823.  
  824. $('#bl_add_cancel').click(function () {
  825. $('#bl_term, #bl_name').val('');
  826. $('#bl').hide();
  827. });
  828.  
  829. $('#edit_bl_save').click(function () {
  830. _update_block($(this).val());
  831. $('#edit_bl_term, #edit_bl_name').val('');
  832. $('#edit_bl').hide();
  833. });
  834.  
  835. $('#edit_bl_delete').click(function () {
  836. _delete_block($(this).val());
  837. $('#edit_bl_term, #edit_bl_name').val('');
  838. $('#edit_bl').hide();
  839. });
  840.  
  841. $('#edit_bl_cancel').click(function () {
  842. $('#edit_bl_term, #edit_bl_name').val('');
  843. $('#edit_bl').hide();
  844. });
  845.  
  846. $('#incl_button').click(function () {
  847. $('#il_div').toggle();
  848. });
  849.  
  850. $('#il_add').click(function () {
  851. $('#il').show();
  852. });
  853.  
  854. $('#il_close').click(function () {
  855. $('#il_div').hide();
  856. });
  857.  
  858. $('#il_import').click(function () {
  859. _import_include();
  860. });
  861.  
  862. $('#il_export').click(function () {
  863. _export_include();
  864. });
  865.  
  866. $('#il_add_save').click(function () {
  867. var obj = {
  868. term : $('#il_term').val().trim(),
  869. name : $('#il_name').val().trim() === '' ? $('#il_term').val().trim() : $('#il_name').val().trim(),
  870. sound : $('#il_sound').val(),
  871. noti_cb : $('#il_noti_cb').prop('checked'),
  872. sound_cb : $('#il_sound_cb').prop('checked'),
  873. push_cb : $('#il_push_cb').prop('checked')
  874. };
  875.  
  876. _add_include(obj);
  877.  
  878. $('#il_term, #il_name').val('');
  879. $('#il').hide();
  880. });
  881.  
  882. $('#il_add_cancel').click(function () {
  883. $('#il_term, #il_name').val('');
  884. $('#il').hide();
  885. });
  886.  
  887. $('#edit_il_save').click(function () {
  888. _update_include($(this).val());
  889. $('#edit_il_term, #edit_il_name, #edit_il_sound').val('');
  890. $('#edit_il_noti_cb, #edit_il_sound_cb, #edit_il_push_cb').prop('checked', false);
  891. $('#edit_il').hide();
  892. });
  893.  
  894. $('#edit_il_delete').click(function () {
  895. _delete_include($(this).val());
  896. $('#edit_il_term, #edit_il_name, #edit_il_sound').val('');
  897. $('#edit_il_noti_cb, #edit_il_sound_cb, #edit_il_push_cb').prop('checked', false);
  898. $('#edit_il').hide();
  899. });
  900.  
  901. $('#edit_il_cancel').click(function () {
  902. $('#edit_il_term, #edit_il_name, #edit_il_sound').val('');
  903. $('#edit_il_noti_cb, #edit_il_sound_cb, #edit_il_push_cb').prop('checked', false);
  904. $('#edit_il').hide();
  905. });
  906.  
  907. $('.on, .off').click(function () {
  908. $(this).toggleClass('on off');
  909. _save();
  910. });
  911.  
  912. $('#sett_save').click(function () {
  913.  
  914. let original_key = config.tv_api_key;
  915. let new_key = $('#tv_api_key').val();
  916. _save('custom');
  917. _theme();
  918. if (original_key != new_key) {
  919. $('#sett').prepend(`<p class="saved-settings-alert">Settings Saved! We'll reload Forker shortly.</p>`);
  920. setTimeout(function() {
  921. window.location.reload();
  922. }, 1000)
  923. } else $('#sett').prepend(`<p class="saved-settings-alert">Settings Saved!</p>`);
  924. });
  925.  
  926. $('#sett_close').click(function () {
  927. $('#sett').find('.saved-settings-alert').remove();
  928. $('#sett').hide();
  929. });
  930.  
  931. $('#time').click(function () {
  932. $('.new').removeClass('new');
  933. });
  934.  
  935. // Delegated click functions
  936. $('body').on('click', '.blockit', function () {
  937. _edit_block($(this).val());
  938. });
  939.  
  940. $('body').on('click', '.includeit', function () {
  941. _edit_include($(this).val());
  942. });
  943.  
  944. $('body').on('click', '.rt', function () {
  945. _block($(this).data('term'), $(this).data('name'), $(this).attr('id'));
  946. });
  947.  
  948. $('body').on('click', '.it', function () {
  949. _includerid($(this).data('term'), $(this).data('name'), $(this).attr('id'));
  950. });
  951.  
  952. $('body').on('click', '.pc', function () {
  953. _panda($(this).data('term'), $(this).data('reqname'), $(this).data('reqid'), $(this).data('title'), $(this).data('value'), $(this).data('name'), $(this))
  954. });
  955.  
  956. $('body').on('click', '.vb', function () {
  957. _export_vb($(this).val());
  958. });
  959.  
  960. $('body').on('click', '.irc', function () {
  961. _export_irc($(this).val());
  962. });
  963.  
  964. $('body').on('click', '.details', function () {
  965. $(this).toggleClass('fa-plus-circle fa-minus-circle');
  966. $('.info[value="' + $(this).val() + '"]').toggle();
  967. });
  968.  
  969. // Delegated mouseover functions
  970. $('body').on('mouseover', '.new', function () {
  971. $(this).removeClass('new');
  972. });
  973.  
  974. // On change events
  975. $('#new_audio').change(function () {
  976. _save();
  977. _sound('new');
  978. });
  979.  
  980. $('#il_sound').change(function () {
  981. _sound('il');
  982. });
  983.  
  984. $('#edit_il_sound').change(function () {
  985. _sound('il_edit');
  986. });
  987.  
  988. $('#type, #size, #adv_theme, #to_theme, #c_theme, :checkbox').change(function () {
  989. _save();
  990. });
  991.  
  992. $('#adv_theme, #to_theme, #c_theme').change(function () {
  993. _theme();
  994. });
  995.  
  996. // On input events
  997. $('#delay, #min_rew, #min_avail, #min_to, #alert_delay').on('input', function () {
  998. _save();
  999. });
  1000.  
  1001. function sanitize(strings, ...values) {
  1002. console.log( strings );
  1003. const dirty = strings.reduce((prev, next, i) => `${prev}${next}${values[i]} || ''}`, '');
  1004. return DomPurify.sanitize(dirty);
  1005. }
  1006.  
  1007. function extend(obj, src) {
  1008. for (var key in src) {
  1009. if (src.hasOwnProperty(key)) obj[key] = src[key];
  1010. }
  1011. return obj;
  1012. }
  1013.  
  1014. function _scan () {
  1015. var searchqualvar
  1016. searchqualvar = (config.qual ? 'true' : 'false');
  1017.  
  1018.  
  1019. if ($('#scan_button').text() === 'Stop') {
  1020. var _url = url + $('#type').val() + $('#size').val() + minrew + $('#min_rew').val() + searchqual + searchqualvar;
  1021. //console.log( _url );
  1022. var _scanurl = _url + '&format=json';
  1023.  
  1024. var date = new Date(), h = date.getHours(), m = date.getMinutes(), s = date.getSeconds(), ampm = h >= 12 ? 'pm' : 'am';
  1025. h = h % 12; h = h ? h : 12; m = m < 10 ? '0' + m : m; s = s < 10 ? '0' + s : s;
  1026. var timeis = [h, m, s, ampm];
  1027. console.log( _scanurl );
  1028. $.get(_scanurl, function (data) {
  1029. _scrape_new(data, timeis);
  1030. }).fail(function () {
  1031. setTimeout(function () { _scan(); }, 2500);
  1032. });
  1033. }
  1034. }
  1035.  
  1036. function _scrape_new (data, timeis) {
  1037. var keys = [], log_keys = [], to = [], logged_in = true;
  1038. var new_requesters = [];
  1039. var hits = data.results;
  1040. //Set config for allowed tags
  1041. var config = {
  1042. ALLOWED_TAGS: ['p', '#text']
  1043. };
  1044.  
  1045. for (var i = 0; i < hits.length; i ++) {
  1046. var hit = hits[i],
  1047. req_name = DOMPurify.sanitize(hit.requester_name,config).replace(/"/g, "&quot;" ),
  1048. req_id = DOMPurify.sanitize(hit.requester_id,config),
  1049. req_link = DOMPurify.sanitize(hit.requester_url.replace(/\.json/, ''),config),
  1050. //req_link = 'https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&requesterId=' + hit.requester_id,
  1051. con_link = DOMPurify.sanitize('https://www.mturk.com/mturk/contact?requesterId=' + hit.requester_id, config),
  1052. group_id = DOMPurify.sanitize(hit.hit_set_id,config),
  1053. prev_link = DOMPurify.sanitize(hit.project_tasks_url.replace(/\.json/, ''),config),
  1054. //prev_link = 'https://www.mturk.com/mturk/preview?groupId=' + hit.hit_set_id,
  1055. pand_link = DOMPurify.sanitize(hit.accept_project_task_url.replace(/\.json/, ''),config),
  1056. //pand_link = 'https://www.mturk.com/mturk/previewandaccept?groupId=' + hit.hit_set_id,
  1057. title = DOMPurify.sanitize(hit.title,config),
  1058. safetitle = title.replace(/"/g, "&quot;" ),
  1059. desc = DOMPurify.sanitize(hit.description.replace(/"/g, "&quot;" ),config),
  1060. time = _convert_seconds(hit.assignment_duration_in_seconds),
  1061. reward = DOMPurify.sanitize('$' + hit.monetary_reward.amount_in_dollars.toFixed(2),config),
  1062. avail = DOMPurify.sanitize(hit.assignable_hits_count,config);
  1063.  
  1064. var key = req_id + title + reward + group_id;
  1065. keys.push(key);
  1066.  
  1067. var qualif = 'None';
  1068. var quals = hit.project_requirements;
  1069.  
  1070.  
  1071. if (quals.length) {
  1072.  
  1073. qualif = '';
  1074. for (var j = 0; j < quals.length; j ++) {
  1075. var q_comp = quals[j].comparator + ' ';
  1076. var q_name = quals[j].qualification_type.name + ' ';
  1077.  
  1078. var q_valu = quals[j].qualification_values;
  1079. var q_values = '';
  1080. for (var k = 0; k < quals.length; k ++) {
  1081. if (quals[j].qualification_values[k]) {
  1082. q_values += quals[j].qualification_values[k];
  1083. q_values += k === quals.length ? ', ' : '';
  1084. }
  1085. }
  1086. if ( typeof quals[j].qualification_request_url !== 'undefined' ) {
  1087. q_values += '~!~' + quals[j].qualification_request_url;
  1088. }
  1089. qualif += (q_name + q_comp + q_values).trim() + '; ';
  1090. }
  1091. qualif = qualif.trim();
  1092. }
  1093.  
  1094. qualif = DOMPurify.sanitize(qualif,config);
  1095.  
  1096. if (!hitlog[key]) {
  1097. hitlog[key] = {
  1098. reqname : req_name,
  1099. reqid : req_id,
  1100. reqlink : req_link,
  1101. conlink : con_link,
  1102. groupid : group_id,
  1103. prevlink : prev_link,
  1104. pandlink : pand_link,
  1105. title : title,
  1106. safetitle: safetitle,
  1107. desc : desc,
  1108. time : time,
  1109. reward : reward,
  1110. avail : avail,
  1111. quals : qualif,
  1112. key : key,
  1113. tolink : 'https://turkopticon.ucsd.edu/' + req_id,
  1114. to : { comm : 'N/A', fair : 'N/A', fast : 'N/A', pay : 'N/A' },
  1115. tvlink : 'https://turkerview.com/requesters/' + req_id,
  1116. tv : 'N/A'
  1117. };
  1118.  
  1119. if ( $.inArray( req_id, requesters ) == -1 ) {
  1120. new_requesters.push( req_id );
  1121. }
  1122.  
  1123. to.push([key, req_id]);
  1124. log_keys.push(key);
  1125. }
  1126. else {
  1127. hitlog[key].avail = avail;
  1128. }
  1129. }
  1130.  
  1131. var tvPromise = _getTVReviews( new_requesters );
  1132. var toPromise = _to(keys, log_keys, logged_in, to, timeis);
  1133.  
  1134. $.when( tvPromise, toPromise).done( function( v1, v2 ) {
  1135. _build(keys, log_keys, timeis);
  1136. }
  1137. );
  1138. }
  1139.  
  1140. let stopTV = false;
  1141. let tv_fail_rate = 0;
  1142. function _getTVReviews( reqlist ) {
  1143. var def = $.Deferred();
  1144. if ( reqlist.length > 0 && config.tv && !stopTV){
  1145.  
  1146.  
  1147. fetch(`https://www.cuylerstuwe.com:13377/?requester_ids=${reqlist.join()}`, {
  1148. method: 'GET',
  1149. cache: 'no-cache',
  1150. headers: ViewHeaders
  1151. }).then(response => {
  1152. if (!response.ok) throw response;
  1153.  
  1154. return response.json();
  1155. }).then(json => {
  1156.  
  1157. newreviews = json.requesters;
  1158. $.merge( requesters, reqlist );
  1159. turkerview = extend( turkerview, newreviews);
  1160. def.resolve(json);
  1161.  
  1162. }).catch(ex => {
  1163.  
  1164.  
  1165. tv_fail_rate++;
  1166. if (ex.statusText == 'invalidUserAuthKey') {
  1167. stopTV = true;
  1168. $('#TVErrorMessage').find('p').html(`<span>Your TurkerView API Key is invalid. If you haven't added it yet check the "Advanced Settings" options tab!</span><p style="margin-bottom: 0.5rem; margin-top: 0.5rem;">You can claim your free API key (or support the site with a subscription!) from your <a href="https://turkerview.com/account/api/" target="_blank">TurkerView account API dashboard.</a></p>`);
  1169. $('#TVErrorMessage').show();
  1170. }
  1171. else if (ex.statusText == 'dailyLimitExceeded') {
  1172. stopTV = true;
  1173. $('#TVErrorMessage').find('p').html(`<span>Your TurkerView API Key has hit its daily quota limit, please upgrade from your <a href="https://turkerview.com/account/api/" target="_blank">TurkerView account API dashboard.</a> or leave a review to increase quota.</span>`);
  1174. $('#TVErrorMessage').show();
  1175. }
  1176.  
  1177.  
  1178. def.resolve( 'Empty');
  1179. });
  1180.  
  1181. /*
  1182. var tvurl = 'https://api.turkerview.com/api/v1/requesters/?ids=' + reqlist.join() + '&from=tpg';
  1183. var newreviews;
  1184. GM_xmlhttpRequest ({
  1185. method: "GET",
  1186. url: tvurl,
  1187. timeout: 4000,
  1188. onload: function(response) {
  1189. newreviews = JSON.parse(response.responseText);
  1190. $.merge( requesters, reqlist );
  1191. turkerview = extend( turkerview, newreviews);
  1192. def.resolve( response );
  1193. },
  1194. ontimeout: function (response) {
  1195. def.resolve('Timeout');
  1196. },
  1197. onerror: function (response) {
  1198. def.resolve('Error');
  1199. }
  1200. });
  1201. */
  1202. }
  1203. else {
  1204. def.resolve( 'Empty');
  1205. }
  1206.  
  1207. return def.promise();
  1208. }
  1209.  
  1210. function _getTVHourly( reqid ) {
  1211. var tvHourly;
  1212. if( reqid in turkerview ) {
  1213. tvHourly = '$' + turkerview[reqid]['wages']['average']['wage'] + "/hr";
  1214. }
  1215. else {
  1216. tvHourly = '-';
  1217. }
  1218.  
  1219. return tvHourly;
  1220. }
  1221.  
  1222. function _to (keys, log_keys, logged_in, to, timeis) {
  1223. var def = $.Deferred();
  1224.  
  1225. var ids = [];
  1226.  
  1227. if (logged_in && to.length && config.to) {
  1228. for (var i = 0; i < to.length; i++) {
  1229. ids.push(to[i][1]);
  1230. }
  1231.  
  1232. $.ajax( {
  1233. url: 'https://www.cuylerstuwe.com:13379/?ids=' + ids + "&fastTrack=500",
  1234. success: function (data) {
  1235. var to_data = JSON.parse(data);
  1236.  
  1237. for (i = 0; i < to.length; i++) {
  1238. if (!to_data[to[i][1]].length && typeof to_data[to[i][1]].attrs != 'undefined') {
  1239. hitlog[to[i][0]].to = to_data[to[i][1]].attrs;
  1240. }
  1241. }
  1242. },
  1243. timeout: 1000
  1244. }).always(function () {
  1245. def.resolve( 'Done' );
  1246. });
  1247. }
  1248. else {
  1249. def.resolve( 'TO Off' );
  1250. }
  1251. return def.promise();
  1252.  
  1253. }
  1254.  
  1255. function _build (keys, log_keys, timeis) {
  1256. var hit_html = '', log_html = '';
  1257.  
  1258. for (var i = 0; i < keys.length; i++) {
  1259. var hit = hitlog[keys[i]], blocked = _check_block(hit), included = _check_include(hit), remove = false, classes, tvHourly, tvScore = false;
  1260.  
  1261. hit.tv = _getTVHourly( hit.reqid );
  1262.  
  1263. if ( hit.tv.substring(0,3) == 'N/A' || hit.tv.substring(0,3) == '<sp' ) {
  1264. tvScore = false;
  1265. }
  1266. else {
  1267. tvScore = true;
  1268. }
  1269.  
  1270. rowcolor = tvScore == true ? _color_tv(hit) : 'toNone';
  1271.  
  1272. classes = rowcolor;
  1273.  
  1274. if (Number(config.avail) > Number(hit.avail) || Number(config.mto) > Number(hit.to.pay)) {
  1275. classes += ' hidden';
  1276. remove = true;
  1277. }
  1278.  
  1279. if (blocked) {
  1280. classes += config.bl ? ' bl_hidden' : ' bl';
  1281. remove = true;
  1282. }
  1283.  
  1284. if (included) {
  1285. classes += ' il';
  1286. _included(included, hit);
  1287. }
  1288. else {
  1289. classes += config.nl ? ' nl_hidden' : ' nl';
  1290. }
  1291.  
  1292. hit_html +=
  1293. '<div class="cont" style="margin-bottom: 2px;">' +
  1294. '<div class="' + classes + ' " style="overflow: hidden; white-space: nowrap; margin-bottom: 2px;">' +
  1295.  
  1296. '<div style="float: left; width: calc(100% - 250px);">' +
  1297.  
  1298. '<span style="width: 20%; float: left; display:inline-block;">' +
  1299. '<button data-term="' + hit.reqid + '" data-name="' + hit.reqname + '" class="rt">R</button>' +
  1300. '<button id="'+ hit.groupid + '" data-term="' + hit.safetitle + '" data-name="' + hit.safetitle + '" class="rt">T</button>' +
  1301. '<button data-term="' + hit.reqid + '" data-name="' + hit.reqname + '" class="it">I</button>' +
  1302. '<a href="' + hit.reqlink + '">' + hit.reqname + '</a>' +
  1303. '</span>' +
  1304.  
  1305. '<span style="width: 80%; float: right; display:inline-block; text-align: right; overflow: hidden;">' +
  1306. //'<button value="' + hit.key + '" class="vb">vB</button>' +
  1307. //'<button value="' + hit.key + '" class="irc">IRC</button>' +
  1308. '<a title="' + hit.safetitle + '" href="' + hit.prevlink + '">' + (hit.safetitle.length < 50 ? hit.safetitle : hit.safetitle.substr(0,47) + "...") + '</a>' +
  1309. '</span>' +
  1310.  
  1311. '</div>' +
  1312.  
  1313. '<div style="float: right;">' +
  1314.  
  1315. '<span style="width: 40px; display:inline-block; text-align: center;">' +
  1316. "#".repeat(Math.floor(Math.log10(hit.avail)) || 0) +
  1317. '</span>' +
  1318.  
  1319. '<span class="to" style="width: 60px; display:inline-block; text-align: center;">' +
  1320. '<a href="' + hit.tvlink + '">' + "$".repeat(Math.min(Math.floor((+hit.tv.replace(/[^\d\.]/g, ""))/3), 5) || 0) + '</a>' +
  1321. '</span>' +
  1322.  
  1323. '<span class="to" style="font-size: 0.50rem; width: 60px; display:inline-block; text-align: center;">' +
  1324. '<a href="' + hit.tolink + '">' + "🌟".repeat(Math.floor(hit.to.pay)+1 || 0) + '</a>' +
  1325. '</span>' +
  1326.  
  1327. '<span style="width: 25px; display:inline-block; text-align: center;">' +
  1328. '<a href="' + hit.pandlink + '">' + (hit.reward.replace(/[^\d.]/g, "") < 1 ? "¢" : "$") + '</a>' +
  1329. '</span>' +
  1330.  
  1331. '<span style="width: 60px; display:inline-block; text-align: center;">' +
  1332. '<button data-term="' + hit.groupid + '" data-reqid="' + hit.reqid + '" data-reqname="' + hit.reqname.replace(/"/g, "&quot;" ) + '" data-title="' + hit.safetitle + '" data-value="' + hit.reward.replace(/\$/g, '') + '" data-name="panda" class="pc">P</button>' +
  1333. '<button data-term="' + hit.groupid + '" data-reqid="' + hit.reqid + '" data-reqname="' + hit.reqname.replace(/"/g, "&quot;" ) + '" data-title="' + hit.safetitle + '" data-value="' + hit.reward.replace(/\$/g, '') + '" data-name="once" class="pc">O</button>' +
  1334. '</span>' +
  1335.  
  1336. '</div>' +
  1337. '</div>' +
  1338. '</div>'
  1339. ;
  1340.  
  1341. if (remove) {
  1342. var index = log_keys.indexOf(keys[i]);
  1343.  
  1344. if (index > -1) {
  1345. log_keys.splice(index, 1);
  1346. }
  1347. }
  1348. }
  1349.  
  1350. if (log_keys.length) {
  1351. for (var j = 0; j < log_keys.length; j ++) {
  1352. var hit_log = hitlog[log_keys[j]], included_log = _check_include(hit_log), rowcolor, classes_log, tvHourly;
  1353.  
  1354. rowcolor = hit_log.tv != 'N/A' ? _color_tv(hit_log) : 'toNone';
  1355.  
  1356. classes_log = rowcolor;
  1357.  
  1358. if (included_log) {
  1359. classes_log += ' il';
  1360. }
  1361. else {
  1362. classes_log += config.nl ? ' nl_hidden' : ' nl';
  1363. }
  1364.  
  1365. var quals = hit_log.quals.split(';');
  1366. var qualif = '';
  1367.  
  1368. for (var k = 0; k < quals.length; k ++) {
  1369. if (quals[k] !== '') {
  1370. if( quals[k].indexOf('~!~') != -1 ) {
  1371. var temp = quals[k].split('~!~');
  1372. quals[k] = temp[0];
  1373. if (temp[1].indexOf('request') == -1 ) {
  1374. //Qual test
  1375. quals[k] += '<form action="' +temp[1] +'" method="get" style=" display:inline!important;"><button>Take Test</button></form>';
  1376. }
  1377. else {
  1378. //Request Qual
  1379. //quals[k] += '<form action="' +temp[1] +'" method="post"><button>Request</button></form>';
  1380. }
  1381. }
  1382. qualif += '<li style="padding: 2px;">' + quals[k] + '</li>';
  1383. }
  1384. }
  1385.  
  1386.  
  1387.  
  1388. log_html +=
  1389. '<div class="cont loggid_' + hit_log.groupid +' logreqid_' + hit_log.reqid + '" style="margin-bottom: 2px;">' +
  1390. '<div class="' + classes_log + '" style="overflow: hidden; white-space: nowrap;">' +
  1391.  
  1392. '<div style="float: left;">' +
  1393. '<span style="width: 80px; display:inline-block;">' +
  1394. '<button class="fa fa-plus-circle fa-2 details" aria-hidden="true" value="' + hit_log.key + '" style="background-color: transparent; border: 0px; padding: 1px;"></button>' +
  1395. timeis[0] + ':' + timeis[1] + timeis[3] + '</span>' +
  1396. '</div>' +
  1397.  
  1398. '<div style="float: left; width: calc(100% - 410px);">' +
  1399.  
  1400. '<span style="width: 25%; float: left; display:inline-block; overflow: hidden;">' +
  1401. '<button data-term="' + hit_log.reqid + '" data-name="' + hit_log.reqname + '" class="rt">R</button>' +
  1402. '<button id="'+ hit_log.groupid + '" data-term="' + hit_log.safetitle + '" data-name="' + hit_log.safetitle + '" class="rt">T</button>' +
  1403. '<button data-term="' + hit_log.reqid + '" data-name="' + hit_log.reqname + '" class="it">I</button>' +
  1404. '<a href="' + hit_log.reqlink + '">' + hit_log.reqname + '</a>' +
  1405. '</span>' +
  1406.  
  1407. '<span style="width: 75%; float: right; display:inline-block; overflow: hidden;">' +
  1408. '<button value="' + hit_log.key + '" class="vb">vB</button>' +
  1409. '<button value="' + hit_log.key + '" class="irc">IRC</button>' +
  1410. '<a href="' + hit_log.prevlink + '">' + hit_log.safetitle + '</a>' +
  1411. '</span>' +
  1412.  
  1413. '</div>' +
  1414.  
  1415. '<div style="float: right;">' +
  1416.  
  1417. '<span style="width: 60px; display:inline-block; text-align: center;">' +
  1418. hit_log.avail +
  1419. '</span>' +
  1420.  
  1421. '<span style="width: 60px; display: inline-block; text-align: center;">' +
  1422. '<a href="' + hit_log.pandlink + '">' + hit_log.reward + '</a>' +
  1423. '</span>' +
  1424.  
  1425. '<span class="to" style="width: 60px; display:inline-block; text-align: center;">' +
  1426. '<a href="' + hit_log.tvlink + '">' + hit_log.tv + '</a>' +
  1427. '</span>' +
  1428.  
  1429.  
  1430. '<span class="to" style="width: 60px; display:inline-block; text-align: center;">' +
  1431. '<a href="' + hit_log.tolink + '">' + hit_log.to.pay + '</a>' +
  1432. '</span>' +
  1433.  
  1434. '<span style="width: 60px; display:inline-block; text-align: center;">' +
  1435. '<button data-term="' + hit_log.groupid + '" data-reqid="' + hit_log.reqid + '" data-reqname="' + hit_log.reqname.replace(/"/g, "&quot;" ) + '" data-title="' + hit_log.safetitle + '" data-value="' + hit_log.reward.replace(/\$/g, '') + '" data-name="panda" class="pc">P</button>' +
  1436. '<button data-term="' + hit_log.groupid + '" data-reqid="' + hit_log.reqid + '" data-reqname="' + hit_log.reqname.replace(/"/g, "&quot;" ) + '" data-title="' + hit_log.safetitle + '" data-value="' + hit_log.reward.replace(/\$/g, '') + '" data-name="once" class="pc">O</button>' +
  1437. '</span>' +
  1438.  
  1439. '</div>' +
  1440. '</div>'+
  1441.  
  1442. '<div class="info ' + rowcolor + '" value="' + hit_log.key + '" style="overflow: hidden; display: none; font-size: 11px;">' +
  1443.  
  1444. '<div style="border-bottom: 1px solid #000000;"></div>' +
  1445.  
  1446. '<span style="width: 33%; float: left; display:inline-block; padding: 5px;">' +
  1447. '<span style="text-decoration: underline;">Description</span>' +
  1448. '<div style="padding: 2px;">' + hit_log.desc +'</div>' +
  1449. '<span style="text-decoration: underline;">Time</span>' +
  1450. '<div style="padding: 2px;">' + hit_log.time +'</div>' +
  1451. '</span>' +
  1452.  
  1453. '<span style="width: 33%; float: left; display:inline-block; padding: 5px;">' +
  1454. '<span style="text-decoration: underline;">Qualifications</span>' +
  1455. qualif +
  1456. '</span>' +
  1457.  
  1458. '<span style="width: calc(34% - 30px); float: right; display:inline-block; padding: 5px;">' +
  1459. '<span style="text-decoration: underline;">Turkopticon</span>' +
  1460. '<br>' +
  1461. '<span style="width: 70px; display:inline-block; padding: 2px;">Pay : ' + hit_log.to.pay +'</span>' +
  1462. '<span style="width: 70px; display:inline-block; padding: 2px;">Fair : ' + hit_log.to.fair +'</span>' +
  1463. '<br>' +
  1464. '<span style="width: 70px; display:inline-block; padding: 2px;">Comm : ' + hit_log.to.comm +'</span>' +
  1465. '<span style="width: 70px; display:inline-block; padding: 2px;">Fast : ' + hit_log.to.fast +'</span>' +
  1466. '</span>' +
  1467.  
  1468. '</div>' +
  1469. '</div>';
  1470.  
  1471. logged ++;
  1472. }
  1473. if (config.new) {
  1474. _sound('new');
  1475. }
  1476. }
  1477. $('#new_hits_').html(hit_html);
  1478. $('#log_hits_').prepend(log_html);
  1479.  
  1480. searches ++;
  1481. var hits_data = '<span> ' + timeis[0] + ':' + timeis[1] + ':' + timeis[2] + timeis[3] + ' Scanned HITs: ' + keys.length + '</span><span style="float: right;">' + tv_fail_rate + '/' + searches + '</span>';
  1482. var logged_hits_data = '<span style="float: right;">' + logged + '</span>';
  1483.  
  1484. $('#hits_data').html(hits_data);
  1485. $('#logged_hits_data').html(logged_hits_data);
  1486.  
  1487. if ($('#scan_button').text() === 'Stop') {
  1488. setTimeout(function () {
  1489. _scan();
  1490. }, $('#delay').val() * 1000);
  1491. }
  1492. }
  1493.  
  1494. function _sound (sound) {
  1495. if (sound === 'new') { $('#audio_' + config.newaudio) [0].play(); }
  1496. if (sound === 'include') { $('#audio_' + config.newaudio) [0].play(); }
  1497. if (sound === 'il') { $('#audio_' + $('#il_sound').val()) [0].play(); }
  1498. if (sound === 'il_edit') { $('#audio_' + $('#edit_il_sound').val()) [0].play(); }
  1499. }
  1500.  
  1501. function _check_block (hit) {
  1502. for (var key in blocklist) {
  1503. var obj = blocklist[key];
  1504. if (obj.term.toLowerCase() === hit.reqname.toLowerCase() || obj.term.toLowerCase() === hit.title.toLowerCase() || obj.term.toLowerCase() === hit.reqid.toLowerCase() || obj.term.toLowerCase() === hit.groupid.toLowerCase()) {
  1505. return obj;
  1506. }
  1507. }
  1508. }
  1509.  
  1510. function _check_include (hit) {
  1511. for (var key in includelist) {
  1512. var obj = includelist[key];
  1513. if (obj.term.toLowerCase() === hit.reqname.toLowerCase() || obj.term.toLowerCase() === hit.title.toLowerCase() || obj.term.toLowerCase() === hit.reqid.toLowerCase() || obj.term.toLowerCase() === hit.groupid.toLowerCase()) {
  1514. return obj;
  1515. }
  1516. }
  1517. }
  1518.  
  1519. function _included (obj, hit) {
  1520. var check = noti_delay.indexOf(hit.key) !== -1;
  1521. var pushcheck = push_delay.indexOf(hit.key) !== -1;
  1522.  
  1523. if (!check) {
  1524. noti_delay.unshift(hit.key);
  1525. setTimeout(function () { noti_delay.pop(); }, config.alert * 1000);
  1526. }
  1527. if (obj.noti_cb && !check) {
  1528. Notification.requestPermission();
  1529. var n = new Notification(hit.reqname + ' | ' + hit.reward, {
  1530. icon : 'http://nopurpose.org/stuff/avatars/Lj21396.gif',
  1531. body : hit.title,
  1532. });
  1533. setTimeout(n.close.bind(n), 5000);
  1534.  
  1535. n.onclick = function(e) {
  1536. e.preventDefault();
  1537. window.open(hit.prevlink, '_blank');
  1538. };
  1539.  
  1540. }
  1541. if (obj.sound_cb && !check) {
  1542. if ( !config.tts ) {
  1543. $('#audio_' + obj.sound)[0].play();
  1544. }
  1545. else {
  1546. //Console.log("BOOM, TTS");
  1547. slothbearsTTS(obj);
  1548. }
  1549. }
  1550. if (obj.push_cb && !pushcheck && config.pb) {
  1551. push_delay.unshift(hit.key);
  1552. setTimeout(function () { push_delay.pop(); }, 900000);
  1553.  
  1554. var push = {};
  1555.  
  1556. push['type'] = 'note';
  1557. push['title'] = 'HIT Finder';
  1558. push['body'] = '[' + hit.reqname + ']\n[' + hit.safetitle + ']\n[' + hit.reward + ']\n[' + hit.prevlink + ']';
  1559.  
  1560. $.ajax({
  1561. type : 'POST',
  1562. headers : {'Authorization': 'Bearer ' + config.push},
  1563. url : 'https://api.pushbullet.com/v2/pushes',
  1564. data : push
  1565. });
  1566.  
  1567. }
  1568. }
  1569.  
  1570. function _color_tv(hit) {
  1571. var tvHourly = hit.tv.replace(/\$/g, '').replace(/\/hr/g, '');
  1572.  
  1573. if (tvHourly == '-') return 'toNone';
  1574.  
  1575. if (config.theme == "light") {
  1576. if (tvHourly >= 10.00) { return 'tvHigh'; }
  1577. else if (tvHourly >= 7.25) { return 'tvFair'; }
  1578. else { return 'tvLow'; }
  1579. }
  1580. else {
  1581. if (tvHourly >= 10.00) { return 'toHigh'; }
  1582. else if (tvHourly >= 7.25) { return 'toAverage'; }
  1583. else { return 'toLow'; }
  1584.  
  1585. }
  1586. }
  1587.  
  1588. function _color_to (hit) {
  1589. var to = hit.to.pay;
  1590.  
  1591. if (config.theme == "light") {
  1592. if (to > 4) { return 'tvHigh'; }
  1593. else if (to > 2.5) { return 'tvFair'; }
  1594. else if (to > 0) { return 'tvLow'; }
  1595. else { return 'tvNone'; }
  1596. }
  1597. else {
  1598. if (to > 4) { return 'toHigh'; }
  1599. else if (to > 3) { return 'toGood'; }
  1600. else if (to > 2.25) { return 'toAverage'; }
  1601. else if (to > 1.25) { return 'toLow'; }
  1602. else if (to > 0) { return 'toPoor'; }
  1603. else { return 'toNone'; }
  1604.  
  1605. }
  1606. }
  1607.  
  1608. function _convert_seconds (seconds) {
  1609. seconds = Number(seconds);
  1610. var h = Math.floor(seconds / 3600);
  1611. var m = Math.floor(seconds % 3600 / 60);
  1612. var s = Math.floor(seconds % 3600 % 60);
  1613. var time = '';
  1614. if (h > 0) { time += h + ' hour(s) '; }
  1615. if (m > 0) { time += m + ' minutes(s) '; }
  1616. if (s > 0) { time += s + ' seconds(s)'; }
  1617. return time;
  1618. }
  1619.  
  1620. function _block (term, name, gid) {
  1621. $('#bl_term') .val(term);
  1622. $('#bl_name') .val(name);
  1623. $('#bl_gid').val(gid);
  1624. $('#bl') .show();
  1625. }
  1626.  
  1627. function _includerid( term, name, gid ) {
  1628. $('#il_term') .val(term);
  1629. $('#il_name') .val(name);
  1630. $('#il') .show();
  1631. }
  1632.  
  1633. function _panda(term, reqname, reqid, title, value, name, button) {
  1634. var hitData = {
  1635. hitTitle: title,
  1636. requesterName: reqname,
  1637. requesterId: reqid,
  1638. hitValue: value
  1639. }
  1640.  
  1641. var once = name == "panda" ? false : true;
  1642.  
  1643. PandaCrazy.online().then (
  1644. function(successResp) {
  1645. PandaCrazy.addJob( term, once, hitData );
  1646. button.addClass("clicked")
  1647. },
  1648. function(failedResp) {
  1649. alert( "Panda Crazy doesn't appear to be running. Please double check if it's being run on the same browser profile and try again");
  1650. }
  1651. );
  1652. //console.log ( running );
  1653. }
  1654.  
  1655.  
  1656. function _add_block (obj) {
  1657. if (!blocklist[obj.term]) {
  1658. blocklist[obj.term] = obj;
  1659. _init_lists();
  1660. }
  1661. }
  1662.  
  1663. function _edit_block (term) {
  1664. var obj = blocklist[term];
  1665. $('#edit_bl_term') .val(obj.term) .text(obj.term);
  1666. $('#edit_bl_name') .val(obj.name);
  1667. $('#edit_bl_save') .val(obj.term);
  1668. $('#edit_bl_delete') .val(obj.term);
  1669. $('#edit_bl') .show();
  1670. }
  1671.  
  1672. function _update_block (block) {
  1673. var obj = blocklist[block];
  1674. obj.name = $('#edit_bl_name').val();
  1675. _init_lists();
  1676. }
  1677.  
  1678. function _delete_block (block) {
  1679. delete blocklist[block];
  1680. _init_lists();
  1681. }
  1682.  
  1683. function _add_include (obj) {
  1684. if (!includelist[obj.term]) {
  1685. includelist[obj.term] = obj;
  1686. _init_lists();
  1687. }
  1688. }
  1689.  
  1690. function _edit_include (term) {
  1691. var obj = includelist[term];
  1692.  
  1693. $('#edit_il_term') .val(obj.term) .text(obj.term);
  1694. $('#edit_il_name') .val(obj.name);
  1695. $('#edit_il_sound') .val(obj.sound);
  1696.  
  1697. $('#edit_il_noti_cb') .prop('checked', obj.noti_cb);
  1698. $('#edit_il_sound_cb') .prop('checked', obj.sound_cb);
  1699. $('#edit_il_push_cb') .prop('checked', obj.push_cb);
  1700.  
  1701. $('#edit_il_save') .val(obj.term);
  1702. $('#edit_il_delete') .val(obj.term);
  1703.  
  1704. $('#edit_il').show();
  1705. }
  1706.  
  1707. function _update_include (term) {
  1708. var obj = includelist[term];
  1709. obj.name = $('#edit_il_name') .val().trim();
  1710. obj.sound = $('#edit_il_sound') .val().trim();
  1711. obj.noti_cb = $('#edit_il_noti_cb') .prop('checked');
  1712. obj.sound_cb = $('#edit_il_sound_cb') .prop('checked');
  1713. obj.push_cb = $('#edit_il_push_cb') .prop('checked');
  1714. _init_lists();
  1715. }
  1716.  
  1717. function _delete_include (term) {
  1718. delete includelist[term];
  1719. _init_lists();
  1720. }
  1721.  
  1722. function _hide_hit_list( hide ) {
  1723. if (hide) {
  1724. $("#hits_button").text('Show New HITs');
  1725. $('#hits_table').hide();
  1726. $('#hits_hidden').show();
  1727. config.h_hidden = '1';
  1728. }
  1729. else {
  1730. $("#hits_button").text('Hide New HITs');
  1731. $('#hits_table').show();
  1732. $('#hits_hidden').hide();
  1733. config.h_hidden = '0';
  1734. }
  1735.  
  1736. _save( 'showhide' );
  1737. }
  1738.  
  1739. function _hide_log_list( hide ) {
  1740. if (hide) {
  1741. $("#logg_button").text('Show Logged HITs');
  1742. $('#log_table').hide();
  1743. $('#log_hidden').show();
  1744. config.l_hidden = '1';
  1745. }
  1746. else {
  1747. $("#logg_button").text('Hide Logged HITs');
  1748. $('#log_table').show();
  1749. $('#log_hidden').hide();
  1750. config.l_hidden = '0';
  1751. }
  1752.  
  1753. _save( 'showhide' );
  1754. }
  1755.  
  1756. function _init_lists () {
  1757. var bl_sort = [], il_sort = [], bl_html = '', il_html = '';
  1758.  
  1759. for (var bl_key in blocklist) {
  1760. bl_sort.push([bl_key, blocklist[bl_key].name]);
  1761. }
  1762.  
  1763. bl_sort.sort(function (a, b) {
  1764. if (a[1].toLowerCase() < b[1].toLowerCase()) return -1;
  1765. if (a[1].toLowerCase() > b[1].toLowerCase()) return 1;
  1766. return 0;
  1767. });
  1768.  
  1769. for (var i = 0; i < bl_sort.length; i ++) {
  1770. var bl_obj = blocklist[bl_sort[i][0]];
  1771. bl_html += '<button class="blockit" style="margin: 2px;" value="' + bl_obj.term + '" title="' + bl_obj.term + '">' + bl_obj.name + '</button>';
  1772. }
  1773.  
  1774. for (var il_key in includelist) {
  1775. il_sort.push([il_key, includelist[il_key].name]);
  1776. }
  1777.  
  1778. il_sort.sort(function (a, b) {
  1779. if (a[1].toLowerCase() < b[1].toLowerCase()) return -1;
  1780. if (a[1].toLowerCase() > b[1].toLowerCase()) return 1;
  1781. return 0;
  1782. });
  1783.  
  1784. for (var j = 0; j < il_sort.length; j ++) {
  1785. var il_obj = includelist[il_sort[j][0]];
  1786. il_html += '<button class="includeit" style="margin: 2px;" value="' + il_obj.term + '" title="' + il_obj.term + '">' + il_obj.name + '</button>';
  1787. }
  1788.  
  1789. $('#bl_items') .html(bl_html);
  1790. $('#il_items') .html(il_html);
  1791. _save('init');
  1792. }
  1793.  
  1794. function _import_block () {
  1795. var import_bl = prompt(
  1796. 'Block List Import\n\n' +
  1797. 'You can import from HIT Finder or HIT Scraper.\n\n' +
  1798. 'This will not delete your current block list, only add to it.\n\n' +
  1799. 'Please enter your block list here.',
  1800. ''
  1801. );
  1802.  
  1803. if (import_bl) {
  1804. var json = _json_validator(import_bl);
  1805.  
  1806. if (json) {
  1807. var _bl_obj = JSON.parse(import_bl);
  1808. for (var key in _bl_obj) {
  1809. if (_bl_obj[key].hasOwnProperty('term') && _bl_obj[key].hasOwnProperty('name') && !_bl_obj[key].hasOwnProperty('sound')) {
  1810. if (!blocklist[key]) {
  1811. blocklist[key] = {
  1812. term : _bl_obj[key].term,
  1813. name : _bl_obj[key].name
  1814. };
  1815. }
  1816. }
  1817. else {
  1818. alert('An error occured while importing.\n\n Please check if you have a valid import and try again.');
  1819. break;
  1820. }
  1821. }
  1822. _init_lists();
  1823. }
  1824. else if (import_bl.match(/^/)) {
  1825. var _bl_arr = import_bl.trim().split('^');
  1826. for (var i = 0; i < _bl_arr.length; i ++) {
  1827. if (!blocklist[_bl_arr[i]]) {
  1828. blocklist[_bl_arr[i]] = {
  1829. term : _bl_arr[i],
  1830. name : _bl_arr[i]
  1831. };
  1832. }
  1833. }
  1834. _init_lists();
  1835. }
  1836. }
  1837. else {
  1838. alert('An error occured while importing.\n\n Please check if you have a valid import and try again.');
  1839. }
  1840. }
  1841.  
  1842. function _export_block () {
  1843. GM_setClipboard(localStorage.getItem('_finder_bl'));
  1844. alert('Your block list has been copied to your clipboard.');
  1845. }
  1846.  
  1847. function _import_include () {
  1848. var import_il = prompt(
  1849. 'Include List Import\n\n' +
  1850. 'You can import from HIT Finder or HIT Scraper.\n\n' +
  1851. 'This will not delete your current include list, only add to it.\n\n' +
  1852. 'Please enter your include list here.',
  1853. ''
  1854. );
  1855.  
  1856. if (import_il) {
  1857. var json = _json_validator(import_il);
  1858.  
  1859. if (json) {
  1860. var _il_obj = JSON.parse(import_il);
  1861.  
  1862. for (var key in _il_obj) {
  1863. if (_il_obj[key].hasOwnProperty('term') && _il_obj[key].hasOwnProperty('name') && _il_obj[key].hasOwnProperty('sound')) {
  1864. if (!includelist[key]) {
  1865. includelist[key] = {
  1866. term : _il_obj[key].term,
  1867. name : _il_obj[key].name,
  1868. sound : _il_obj[key].sound,
  1869. noti_cb : _il_obj[key].noti_cb,
  1870. sound_cb : _il_obj[key].sound_cb,
  1871. push_cb : _il_obj[key].push_cb
  1872. };
  1873. }
  1874. }
  1875. else {
  1876. alert('An error occured while importing.\n\n Please check that you have a valid import and try again.');
  1877. break;
  1878. }
  1879. }
  1880. _init_lists();
  1881. }
  1882. else if (import_il.match(/^/)) {
  1883. var _il_arr = import_il.split('^');
  1884.  
  1885. for (var i = 0; i < _il_arr.length; i ++) {
  1886. if (!includelist[_il_arr[i]]) {
  1887. includelist[_il_arr[i]] = {
  1888. term : _il_arr[i],
  1889. name : _il_arr[i],
  1890. sound : '1',
  1891. noti_cb : true,
  1892. sound_cb : true,
  1893. push_cb : false
  1894. };
  1895. }
  1896. }
  1897. _init_lists();
  1898. }
  1899. }
  1900. else {
  1901. alert('An error occured while importing.\n\n Please check that you have a valid import and try again.');
  1902. }
  1903. }
  1904.  
  1905. function _export_include () {
  1906. GM_setClipboard(localStorage.getItem('_finder_il'));
  1907. alert('Your include list has been copied to your clipboard.');
  1908. }
  1909.  
  1910. function _export_vb (key) {
  1911. var hit = hitlog[key];
  1912.  
  1913. var pay = hit.to.pay, _pay = '#B30000';
  1914. if (pay > 3.99) { _pay = '#00B300'; }
  1915. else if (pay > 2.99) { _pay = '#B3B300'; }
  1916. else if (pay > 1.99) { _pay = '#B37400'; }
  1917.  
  1918. var fair = hit.to.fair, _fair = '#B30000';
  1919. if (fair > 3.99) { _fair = '#00B300'; }
  1920. else if (fair > 2.99) { _fair = '#B3B300'; }
  1921. else if (fair > 1.99) { _fair = '#B37400'; }
  1922.  
  1923. var comm = hit.to.comm, _comm = '#B30000';
  1924. if (comm > 3.99) { _comm = '#00B300'; }
  1925. else if (comm > 2.99) { _comm = '#B3B300'; }
  1926. else if (comm > 1.99) { _comm = '#B37400'; }
  1927.  
  1928. var fast = hit.to.fast, _fast = '#B30000';
  1929. if (fast > 3.99) { _fast = '#00B300'; }
  1930. else if (fast > 2.99) { _fast = '#B3B300'; }
  1931. else if (fast > 1.99) { _fast = '#B37400'; }
  1932.  
  1933. var tv = hit.tv.replace(/\$/g, ''), _tvhourly = '#B30000';
  1934. if ( tv != 'N/A' ) {
  1935. if ( tv >= 10 ) { _tvhourly = '#00B300'; }
  1936. else if ( tv >= 7.25 ) { _tvhourly = '#B3B300'; }
  1937. tv = '$' + tv + '/hr';
  1938. }
  1939.  
  1940. var quals = hit.quals.split(';');
  1941. var qualif = '';
  1942.  
  1943. for (var k = 0; k < quals.length; k ++) {
  1944. if (quals[k] !== '') {
  1945. if( quals[k].indexOf('~!~') != -1 ) {
  1946. var temp = quals[k].split('~!~');
  1947. quals[k] = temp[0];
  1948. if (temp[1].indexOf('request') == -1 ) {
  1949. //Qual test
  1950. quals[k] += '[URL=' +temp[1] +']Take Test[/URL]';
  1951. }
  1952. else {
  1953. //Request Qual
  1954. //quals[k] += '<form action="' +temp[1] +'" method="post"><button>Request</button></form>';
  1955. }
  1956. }
  1957. qualif += quals[k] + ';';
  1958. }
  1959. }
  1960.  
  1961. var exportcode = '[table][tr][td]'+
  1962. '[b]Title:[/b] [URL=' + pandaurl + hit.prevlink + ']' + hit.safetitle + '[/URL] | [URL=' + pandaurl + hit.pandlink + ']PANDA[/URL]\n' +
  1963. '[b]Requester:[/b] [URL=' + pandaurl + hit.reqlink + ']' + hit.reqname + '[/URL] [' + hit.reqid + '] ([URL=' + hit.tvlink +']Req TV[/URL]): [B][COLOR=' + _tvhourly + ']' + tv + '[/COLOR][/B]\n' +
  1964. '([URL='+hit.tolink+']TO[/URL]):'+
  1965. '[b] \[Pay: [COLOR=' + _pay + ']' + pay + '[/COLOR]\][/b]'+
  1966. '[b] \[Fair: [COLOR=' + _fair + ']' + fair + '[/COLOR]\][/b]' +
  1967. '[b] \[Comm: [COLOR=' + _comm +']' + comm + '[/COLOR]\][/b]' +
  1968. '[b] \[Fast: [COLOR=' + _fast + ']' + fast + '[/COLOR]\][/b]\n' +
  1969. '[b]Description:[/b] ' + hit.desc + '\n' +
  1970. '[b]Time:[/b] ' + hit.time + '\n' +
  1971. '[b]HITs Available:[/b] ' + hit.avail + '\n' +
  1972. '[b]Reward:[/b] [COLOR=green][b] ' + hit.reward + '[/b][/COLOR]\n' +
  1973. '[b]Qualifications:[/b] ' + qualif + '\n' +
  1974. '[/td][/tr][/table]';
  1975.  
  1976. GM_setClipboard(exportcode);
  1977. alert('Forum export has been copied to your clipboard.');
  1978. }
  1979.  
  1980. function _export_irc (key) {
  1981. var hit = hitlog[key];
  1982.  
  1983. $.get('https://ns4t.net/yourls-api.php?action=bulkshortener&title=MTurk&signature=39f6cf4959&urls[]=https://worker.mturk.com' + hit.prevlink + '&urls[]=https://worker.mturk.com' + hit.pandlink, function (data) {
  1984. var urls = data.split(';'),
  1985. preview = urls[0],
  1986. panda = urls[1];
  1987.  
  1988. var exportcode = 'Req: ' + hit.reqname + ' ■ Title: ' + hit.safetitle + ' ■ Reward: ' + hit.reward;
  1989. exportcode += preview !== panda ? ' ■ Prev: ' + preview + ' ■ PandA: '+ panda : ' ■ Search: ' + preview;
  1990. exportcode += ' ■ TO: (Pay: ' + hit.to.pay + ') (Fair: ' + hit.to.fair + ') (Comm: ' + hit.to.comm + ') (Fast: ' + hit.to.fast + ')';
  1991.  
  1992. GM_setClipboard(exportcode);
  1993. alert('IRC export has been copied to your clipboard.');
  1994.  
  1995. }).fail(function () {
  1996. alert('Failed to shorten links.');
  1997. });
  1998. }
  1999.  
  2000. function _json_validator (data) {
  2001. try {
  2002. JSON.parse(data);
  2003. return true;
  2004. }
  2005. catch (e) {
  2006. return false;
  2007. }
  2008. }
  2009.  
  2010. function _save (type) {
  2011. if (type !== 'init' && type !== 'custom') {
  2012. config.delay = $('#delay') .val();
  2013. config.rew = $('#min_rew') .val();
  2014. config.avail = $('#min_avail') .val();
  2015. config.mto = $('#min_to') .val();
  2016. config.alert = $('#alert_delay') .val();
  2017. config.type = $('#type') .val();
  2018. config.size = $('#size') .val();
  2019. config.newaudio = $('#new_audio') .val();
  2020. config.theme = $('#adv_theme') .val();
  2021. config.to_theme = $('#to_theme') .val();
  2022.  
  2023. config.new = $('#new_sound') .prop('checked');
  2024. config.pb = $('#pb') .prop('checked');
  2025. config.tts = $('#tts') .prop('checked');
  2026. config.to = $('#to') .prop('checked');
  2027. config.qual = $('#qual') .prop('checked');
  2028. config.nl = $('#nl_hide') .prop('checked');
  2029. config.bl = $('#bl_hide') .prop('checked');
  2030. config.m = $('#m_hide') .prop('checked');
  2031. console.log($('#push').val());
  2032.  
  2033. }
  2034. if (type === 'custom' && $('#adv_theme').val() === 'custom') {
  2035. config.custom = {
  2036. main : $('#theme_main') .val(),
  2037. primary : $('#theme_primary') .val(),
  2038. secondary : $('#theme_secondary') .val(),
  2039. text : $('#theme_text') .val(),
  2040. link : $('#theme_link') .val(),
  2041. visited : $('#theme_visited') .val(),
  2042. prop : false
  2043. };
  2044. themes.custom = config.custom;
  2045. }
  2046. config.push = $('#push').val();
  2047. config.tv_api_key = $('#tv_api_key').val();
  2048.  
  2049. localStorage.setItem('_finder', JSON.stringify(config));
  2050. localStorage.setItem('_finder_bl', JSON.stringify(blocklist));
  2051. localStorage.setItem('_finder_il', JSON.stringify(includelist));
  2052.  
  2053. if (config.nl) { $('.nl').toggleClass('nl nl_hidden'); }
  2054. else { $('.nl_hidden').toggleClass('nl nl_hidden'); }
  2055.  
  2056. if (config.bl) { $('.bl').toggleClass('bl bl_hidden'); }
  2057. else { $('.bl_hidden').toggleClass('bl bl_hidden'); }
  2058.  
  2059. if (config.m) { $('.m').toggleClass('m m_hidden'); }
  2060. else { $('.m_hidden').toggleClass('m m_hidden'); }
  2061. }
  2062.  
  2063. function _theme () {
  2064. var theme = themes[config.theme];
  2065.  
  2066. $('#theme_main') .val(theme.main) .prop('disabled', theme.prop);
  2067. $('#theme_primary') .val(theme.primary) .prop('disabled', theme.prop);
  2068. $('#theme_secondary') .val(theme.secondary) .prop('disabled', theme.prop);
  2069. $('#theme_text') .val(theme.text) .prop('disabled', theme.prop);
  2070. $('#theme_link') .val(theme.link) .prop('disabled', theme.prop);
  2071. $('#theme_visited') .val(theme.visited) .prop('disabled', theme.prop);
  2072. _write_theme();
  2073. }
  2074.  
  2075. function _write_theme () {
  2076. var css = _to_theme(), theme = themes[config.theme];
  2077.  
  2078. css +=
  2079. 'html {color: #' + theme.text + '; background-color: #' + theme.main + '; line-height: 1.5; font-family: "Roboto", sans-serif; font-size: 15px; font-weight: normal;}' +
  2080. 'body {margin: 0px;}' +
  2081. '#menubar { background-color: #' + theme.menu + '; margin: 0px; padding: 3px; height:30px; color: #' + theme.menutext + ' }' +
  2082. '#latest_hits { margin: 5px; }' +
  2083. '#logged_hits { margin: 5px; }' +
  2084. '#config { background-color: #' + theme.primary + '; border: 2px #' + theme.text + ' solid; padding: 2px;}' +
  2085.  
  2086. '#bl_items, #il_items {background-color: #'+theme.main+'; height: calc(100% - 64px); overflow-y: scroll;}' +
  2087. '#bl_div, #il_div {background-color: #'+theme.primary+'; border: 2px solid #'+theme.secondary+';}' +
  2088.  
  2089. '.add {background-color: #'+theme.primary+'; border: 2px solid #'+theme.secondary+';}' +
  2090.  
  2091. '.bl {border: 2px solid #FF0000;}' +
  2092. '.il {border: 2px solid #009900;}' +
  2093. '.hidden, .nl_hidden, .bl_hidden, .m_hidden {display: none;}' +
  2094. 'button:focus {outline: none !important;}';
  2095.  
  2096. if (config.theme == 'light' ) {
  2097. css +=
  2098. '.tvHigh {font-weight: bold; background-color: rgba(0,128,0,0.3); }' +
  2099. '.tvFair {opacity: 0.8; background-color: rgba(255,165, 0, 0.3);}' +
  2100. '.tvLow {opacity: 0.5; background-color: rgba(255,0,0,0.3); }' +
  2101. '.tvNone {background-color: rgba(128,128,128, 0.3); }'
  2102. }
  2103.  
  2104. $('#css').html(css);
  2105. }
  2106.  
  2107. function _to_theme () {
  2108. var to, theme = themes[config.theme], color = '';
  2109. console.log(config.to_theme);
  2110. if (config.theme === 'default') {
  2111. color = 'd9d9d9';
  2112. }
  2113. else {
  2114. color = '262626';
  2115. }
  2116.  
  2117. switch (config.to_theme) {
  2118. case '1':
  2119. to =
  2120. 'td {font-weight: bold;}' +
  2121. '.cont, .hit, .details {color: #000000;}' +
  2122. '.toHigh {background-color: #cff9dc;}' +
  2123. '.toGood {background-color: #dcf9cf;}' +
  2124. '.toAverage {background-color: #f1f9cf;}' +
  2125. '.toLow {background-color: #f9e6cf;}' +
  2126. '.toPoor {background-color: #f9cfcf;}' +
  2127. '.toNone {background-color: #eeeeee;}' +
  2128. '.rt, .it, .pc {width: 20px; height: 20px; background-color: transparent; margin: 1px; border: 1px solid #000000; font-size: 80%; padding: 1px;}' +
  2129. '.vb, .irc {width: 25px; height: 20px; background-color: transparent; margin: 1px; border: 1px solid #000000; font-size: 80%; padding: 1px;}' +
  2130. '.clicked {background-color:grey;}';
  2131. ;
  2132. return to;
  2133. case '2':
  2134. to =
  2135. 'a {color: #'+theme.link+';}' +
  2136. 'a:visited {color: #'+theme.visited+';}' +
  2137. 'tbody td {color: #'+theme.text+';}' +
  2138. '.to a {color: #000000;}' +
  2139.  
  2140. '.cont, .details {color: #'+theme.text+';}' +
  2141. '.toHigh {background-color: #'+color+';}' +
  2142. '.toGood {background-color: #'+color+';}' +
  2143. '.toAverage {background-color: #'+color+';}' +
  2144. '.toLow {background-color: #'+color+';}' +
  2145. '.toPoor {background-color: #'+color+';}' +
  2146. '.toNone {background-color: #'+color+';}' +
  2147.  
  2148. '.toHigh .to {background-color: #33cc59;}' +
  2149. '.toGood .to {background-color: #a6cc33;}' +
  2150. '.toAverage .to {background-color: #cccc33;}' +
  2151. '.toLow .to {background-color: #cca633;}' +
  2152. '.toPoor .to {background-color: #cc3333;}' +
  2153. '.toNone .to {background-color: #cccccc;}' +
  2154. '.rt, .pc {width: 20px; height: 20px; color: #'+theme.text+'; background-color: transparent; margin: 1px; border: 1px solid #'+theme.text+'; font-size: 80%; padding: 1px;}' +
  2155. '.vb, .irc {width: 25px; height: 20px; color: #'+theme.text+'; background-color: transparent; margin: 1px; border: 1px solid #'+theme.text+'; font-size: 80%; padding: 1px;}' +
  2156. '.clicked {background-color:grey;}';
  2157. ;
  2158. return to;
  2159. case '3':
  2160. to =
  2161. 'a {color: #'+theme.link+';}' +
  2162. 'a:visited {color: #'+theme.visited+';}' +
  2163. 'tbody td {color: #'+theme.text+';}' +
  2164.  
  2165. '.cont, .details {color: #'+theme.text+';}' +
  2166. '.toHigh {background-color: #'+color+';}' +
  2167. '.toGood {background-color: #'+color+';}' +
  2168. '.toAverage {background-color: #'+color+';}' +
  2169. '.toLow {background-color: #'+color+';}' +
  2170. '.toPoor {background-color: #'+color+';}' +
  2171. '.toNone {background-color: #'+color+';}' +
  2172.  
  2173. '.toHigh .to a {color: #33cc59;}' +
  2174. '.toGood .to a {color: #a6cc33;}' +
  2175. '.toAverage .to a {color: #cccc33;}' +
  2176. '.toLow .to a {color: #cca633;}' +
  2177. '.toPoor .to a {color: #cc3333;}' +
  2178. '.toNone .to a {color: #cccccc;}' +
  2179. '.rt, .pc {width: 20px; height: 20px; color: #'+theme.text+'; background-color: transparent; margin: 1px; border: 1px solid #'+theme.text+'; font-size: 80%; padding: 1px;}' +
  2180. '.vb, .irc {width: 25px; height: 20px; color: #'+theme.text+'; background-color: transparent; margin: 1px; border: 1px solid #'+theme.text+'; font-size: 80%; padding: 1px;}' +
  2181. '.clicked {background-color:grey;}';
  2182. ;
  2183. return to;
  2184. }
  2185. }
  2186.  
  2187. $('#type option[value="' + config.type + '"]') .prop('selected', true);
  2188. $('#size option[value="' + config.size + '"]') .prop('selected', true);
  2189. $('#new_audio option[value="' + config.newaudio + '"]') .prop('selected', true);
  2190. $('#adv_theme option[value="' + config.theme + '"]') .prop('selected', true);
  2191. $('#to_theme option[value="' + config.to_theme + '"]') .prop('selected', true);
  2192.  
  2193. _theme();
  2194. _init_lists();
  2195. _hide_hit_list( config.h_hidden == '1' ? true : false );
  2196. _hide_log_list( config.l_hidden == '1' ? true : false );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement