Advertisement
Guest User

Untitled

a guest
Sep 23rd, 2017
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name        Torn Helper
  3. // @namespace   Jebster.Torn
  4. // @author      Jeggy
  5. // @description Adds extra information to different pages all around Torn.
  6. // @include     *.torn.com/profiles.php?XID=*
  7. // @version     0.3.2
  8. // @require     http://code.jquery.com/jquery-2.2.4.min.js
  9. // @require     http://code.jquery.com/ui/1.12.1/jquery-ui.min.js
  10. // ==/UserScript==
  11. // debugger;
  12.  
  13. //GM_addStyle(GM_getResourceText('jquery-base'));
  14. //GM_addStyle(GM_getResourceText('jquery-ui'));
  15.  
  16. String.prototype.format = function() {
  17.     var formatted = this;
  18.     for (var i = 0; i < arguments.length; i++) {
  19.         var regexp = new RegExp('\\{'+i+'\\}', 'gi');
  20.         formatted = formatted.replace(regexp, arguments[i]);
  21.     }
  22.     return formatted;
  23. };
  24.  
  25. var data = {};
  26.  
  27. (function() {
  28.     'use strict';
  29.  
  30.     $('head').append('<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">');
  31.     // http://jquerymodal.com/
  32.     $('head').append('<link rel="stylesheet" href="https://jebster.net/lib/jquery.modal.min.css">');
  33.     $('head').append('<script src="https://jebster.net/lib/jquery.modal.min.js" type="text/javascript"></script>');
  34.  
  35.     var site = window.location.pathname;
  36.  
  37.     loadData();
  38.     saveOwnData();
  39.  
  40.     loadAttackLog();
  41.  
  42.     if(site.indexOf('profiles.php') > 0) profileView();
  43.  
  44. })();
  45.  
  46. function loadAttackLog(){
  47.     var selections = '';
  48.     var now = new Date().getTime();
  49.  
  50.     if('attackLogLoad' in data){
  51.         if(data.attackLogLoad < now - (12*60*60*1000)) // More than 12 hours ago
  52.             selections = 'attacksfull';
  53.         else if(data.attackLogLoad < now - (2*60*1000)) // More than 2 minutes ago
  54.             selection = 'attacks';
  55.     }else // First time
  56.         selections = 'attacksfull';
  57.  
  58.     var url = 'https://api.torn.com/user/'+data.me.id+'?selections='+selections+'&key='+data.apikey;
  59.     if(selections !== ''){
  60.         data.attackLogLoad = now;
  61.  
  62.         apiCall(url, function(d) {
  63.             if(d.error) getApiKey();
  64.             else{
  65.                 for(var p in d.attacks){
  66.                     if (d.attacks.hasOwnProperty(p)) {
  67.                         var attack = d.attacks[p];
  68.                         var defender_id = attack.defender_id;
  69.                         if(!(defender_id in data)) data[defender_id] = {};
  70.  
  71.                         if(attack.attacker_id == data.me.id){
  72.                             // My attack
  73.                             if(!('attacks' in data[defender_id])) data[defender_id].attacks = {};
  74.                             data[defender_id].attacks[p] = attack;
  75.                         }else if('attacker_id' in attack && attack.attacker_id in data){
  76.                             // I'm being attacked
  77.                             if(!('defends' in data[attack.attacker_id])) data[attack.attacker_id].defends = {};
  78.                             data[attack.attacker_id].defends[p] = attack;
  79.                         }
  80.                     }
  81.                 }
  82.  
  83.                 save();
  84.             }
  85.         });
  86.     }
  87. }
  88.  
  89. function profileView(){
  90.     var userid = getParameterByName('XID');
  91.     var userData = data[userid];
  92.     var content = '';
  93.     content += profileViewSelectionPopUp();
  94.     content += '<div id="compareStats">';
  95.     content += 'Loading...';
  96.     content += '<br />';
  97.     content += '</div>';
  98.  
  99.     var acrdHtml = accordion('Torn Helper', content);
  100.  
  101.     var afterWait = function () {
  102.         $(acrdHtml).insertAfter($('.profile-wrapper + .m-top10')[0]);
  103.         var compareFunc = function(){
  104.             $('#compareStats').replaceWith(compareTemplate(userid, data.me.userid));
  105.         };
  106.         apiUserStats(userid, compareFunc);
  107.         apiUserStats(data.me.userid, compareFunc);
  108.     };
  109.     var wait = function () {
  110.         var loaded = $('.profile-wrapper + .medals-wrapper + .m-top10').length > 0;
  111.  
  112.         if (loaded) afterWait();
  113.         else setTimeout(wait, 5);
  114.     };
  115.  
  116.     wait();
  117. }
  118.  
  119. // Only supports one accordion on the page at the moment.
  120. function accordion(title, block){
  121.     var css = '<style>'+
  122.         'button.Jaccordion {'+
  123.         'cursor: pointer;'+
  124.         'padding: 18px;'+
  125.         'width: 100%;'+
  126.         'text-align: left;'+
  127.         'transition: 0.4s;'+
  128.         '}'+
  129.         'div.Jpanel {'+
  130.         'position:relative;'+
  131.         'max-height: 0;'+
  132.         'overflow: hidden;'+
  133.         'transition: 0.8s ease-in-out;'+
  134.         'opacity: 0;'+
  135.         '}'+
  136.         'div.Jshow {'+
  137.         'opacity: 1;'+
  138.         'max-height: 1000px;'+
  139.         'width: auto;'+
  140.         '}'+
  141.         'div.JAccordionIconShow {'+
  142.         'opacity: 1;'+
  143.         'max-height: 30px;'+
  144.         'width: auto;'+
  145.         '}'+
  146.         '.JProfileViewAccordion{'+
  147.         'width: 0;'+
  148.         'float: right;'+
  149.         'max-height: 0;'+
  150.         'overflow: hidden;'+
  151.         'opacity: 0;'+
  152.         'padding-right: 7px;'+
  153.         '}'+
  154.         '.JAccordionIcon{'+
  155.         'padding: 6px 5px 6px 25px;'+
  156.         'cursor: pointer;'+
  157.         '}'+
  158.         '</style>';
  159.  
  160.     var script = '<script>$(".JAccordionIcon").click(function() {'+
  161.         '$(".Jpanel").toggleClass("Jshow");'+
  162.         '$(".JProfileViewAccordion").toggleClass("JshJAccordionIconShowow");'+
  163.         '$(".JProfileViewAccordion").toggleClass("JAccordionIconShow");'+
  164.         '});</script>';
  165.  
  166.     var show = data.profileview.show;
  167.  
  168.     var html = '<div class="Jaccordion profile-wrapper medals-wrapper m-top10">'+
  169.         '<div class="menu-header">'+title+
  170.         '<div class="JProfileViewAccordion '+(show ? '' : 'JAccordionIconShow')+'"><i class="fa fa-plus-square JAccordionIcon" aria-hidden="true" /></div>'+
  171.         '<div class="JProfileViewAccordion '+(show ? 'JAccordionIconShow' : '')+'"><i class="fa fa-minus-square JAccordionIcon" aria-hidden="true" /></div>'+
  172.         '</div>'+
  173.         '<div class="Jpanel '+(show ? 'Jshow' : '')+'">'+
  174.         block+
  175.         '</div>'+
  176.         '</div>';
  177.  
  178.     $(document).on('click','.JAccordionIcon', function(){
  179.         data.profileview.show = !data.profileview.show;
  180.         save();
  181.     });
  182.  
  183.     return css+script+html;
  184. }
  185.  
  186. function profileViewSelectionPopUp(){
  187.     var possibilities = possibleStats();
  188.     var settings = allSettings();
  189.  
  190.     var popupHtml = '<div>';
  191.     var categories = {};
  192.     for(var p in possibilities){
  193.         var o = possibilities[p];
  194.         var checked = inArray(p, data.profileview.display) ? 'checked' : '';
  195.  
  196.         if(o.category){
  197.             if(!categories[o.category]) categories[o.category] = {display: o.category, html: ''};
  198.         }else{
  199.             if(!categories.others) categories.others = {display: 'Others', html: ''};
  200.         }
  201.  
  202.         var cat = o.category ? o.category : 'others';
  203.  
  204.         var html = '<div style="';
  205.         // TODO: Extract this css into a css rule
  206.         html += 'border-radius: 2px; border: 1px solid gray; background-color: lightgray; margin: 3px;';
  207.         html += 'padding: 3px 10px 3px 5px; display: inline-block; cursor: pointer;';
  208.         html += '">';
  209.         html += '<input type="checkbox" name="view'+p+'" id="view'+p+'" '+checked+'>';
  210.         html += '<label id="JC'+p+'" for="view'+p+'">'+o.display+'</label>';
  211.         html += '</div>';
  212.         categories[cat].html += html;
  213.     }
  214.  
  215.     popupHtml += '<fieldset style="border:1px solid black; padding: 10px; margin: 10px 0;">';
  216.     popupHtml += '<legend><b>Settings</b></legend>';
  217.     for(var setting in settings){
  218.         if(!settings.hasOwnProperty(setting)) continue;
  219.         popupHtml += '<label for="setting'+setting+'">'+settings[setting].display+'</label>: ';
  220.         switch(settings[setting].type){
  221.             case 'checkbox':
  222.                 popupHtml += '<input type="'+settings[setting].type+'" name="setting'+setting+'" id="setting'+setting+'" '+(data.settings && data.settings.versusMine ? 'checked' : '')+'>';
  223.                 break;
  224.             default:
  225.                 // TODO: Implement text!!!!
  226.         }
  227.         popupHtml += '<br>';
  228.     }
  229.     popupHtml += '</fieldset>';
  230.  
  231.     for(var category in categories){
  232.         if (categories.hasOwnProperty(category)) {
  233.             popupHtml += '<fieldset style="border:1px solid black; padding: 10px; margin: 10px 0;">';
  234.             popupHtml += '<legend onclick=\'document.getElementById("JC'+category+'").style.display = document.getElementById("JC'+category+'").style.display == "none" ? "block" : "none";\'';
  235.             popupHtml += '><b>'+categories[category].display+'</b></legend>';
  236.             popupHtml += categories[category].html;
  237.             popupHtml += '</fieldset>';
  238.         }
  239.     }
  240.  
  241.     popupHtml += '</div>';
  242.     var popup = popupWindow(
  243.         {
  244.             element: '#editProfileView',
  245.             title: 'Edit Profile view',
  246.             width: 640
  247.         },
  248.         popupHtml,
  249.         [
  250.             {
  251.                 'display': 'Close',
  252.                 'close': true
  253.             },
  254.             {
  255.                 'display': 'Save',
  256.                 'callback': function(){
  257.                     var selected = [];
  258.                     for(var p in possibleStats()){
  259.                         var checked = $("#view"+p).is(':checked');
  260.                         if(checked) selected.push(p);
  261.                     }
  262.                     var settings = {};
  263.                     var all = allSettings();
  264.                     for(var setting in all){
  265.                         switch(all[setting].type){
  266.                             case 'checkbox':
  267.                                 settings[setting] = $('#setting'+setting).is(':checked');
  268.                                 break;
  269.                             default:
  270.                                 settings[setting] = $('#setting'+setting).val();
  271.                         }
  272.                     }
  273.  
  274.                     data.profileview.display = selected;
  275.                     data.settings = settings;
  276.                     save();
  277.                     location.reload();
  278.                 }
  279.             }
  280.         ]
  281.     );
  282.  
  283.     var button = '<div style="float:right;right:0;position:absolute;">';
  284.     button += '<a href="#ex1" rel="modal:open" style="';
  285.     button += 'background-color: #282828;';
  286.     button += 'border: none;';
  287.     button += 'border-radius: 5px;';
  288.     button += 'color: white;';
  289.     button += 'padding: 5px 5px 5px 7px;';
  290.     button += 'text-align: center;';
  291.     button += 'text-decoration: none;';
  292.     button += 'display: inline-block;';
  293.     button += 'font-size: 16px;';
  294.     button += 'margin: 4px 2px;';
  295.     button += 'cursor: pointer;';
  296.     button += 'text-decoration: none;';
  297.     button += '"><i class="fa fa-pencil-square-o" aria-hidden="true" /></a></div>';
  298.  
  299.     return button+popup;
  300. }
  301.  
  302. /**
  303. * Example usage:
  304. * popupWindow(
  305. * { 'element': '#myDialogButton', 'title': 'Hello World' },
  306. * '<h3>Something</h3><input type="text" id="myfield" />',
  307. * [{'display': 'Save',
  308. * 'close': false, // default: true
  309. * callback: function(){var something = $("#myfield").val();}
  310. * }]);
  311. */
  312. function popupWindow(e, content, buttons){
  313.     var script = '<script>';
  314.     var btns = '<div id="JModalButtons">';
  315.     for (var i = 0; i < buttons.length; i++) {
  316.         btns += '<button id="JModalBtn'+i+'">'+buttons[i].display+'</button>';
  317.         $(document).on('click', '#JModalBtn'+i, e => {
  318.             console.log(e.target.id);
  319.             var pressed = e.target.id.substr(e.target.id.length -1);
  320.             if (buttons[pressed].callback) buttons[pressed].callback();
  321.             if(buttons[pressed].close) console.log('CLOSE THE MODAL!');
  322.         });
  323.     }
  324.     btns += '</div>';
  325.     var popup = '<div id="ex1" style="display:none;">';
  326.     // Header
  327.     popup += '<div>';
  328.     popup += 'HEADERBAR';
  329.     popup += '<hr />';
  330.     popup += '</div>';
  331.  
  332.     // Content
  333.     popup += '<div style="padding: 0 5px; overflow-y: auto; overflow-x: hidden; max-height: 420px;">';
  334.     popup += content;
  335.     popup += '</div>';
  336.  
  337.     // Footer
  338.     popup += '<div>';
  339.     popup += '<hr />';
  340.     popup += btns;
  341.     popup += '</div>';
  342.  
  343.     popup += '</div>';
  344.     script += '$("ex1").modal({fadeDuration:100});';
  345.     script += '</script>';
  346.     return popup+script;
  347. }
  348.  
  349. function inArray(c, a){
  350.     // Somehow $.inArray is not working? 😕
  351.     for(var i = 0; i < a.length; i++){
  352.         if(c == a[i]) return true;
  353.     }
  354.     return false;
  355. }
  356.  
  357. function getUserValue(userid, property){
  358.     var user = data[userid];
  359.     if(user){
  360.         if($.isArray(property)){
  361.             for(var i = 0; i < property.length; i++){
  362.                 user = user[property[i]];
  363.             }
  364.             return user;
  365.         }else{
  366.             var userData = user[property];
  367.             if(userData){
  368.                 return userData;
  369.             }
  370.         }
  371.     }
  372.     return -1;
  373. }
  374.  
  375. function setUserValue(userid, property, value){
  376.     if(data[userid] === undefined) data[userid] = {};
  377.     data[userid][property] = value;
  378. }
  379.  
  380. function save(){
  381.     localStorage.setItem('jebster.torn', JSON.stringify(data));
  382. }
  383.  
  384. function saveOwnData(){
  385.     if(!('me' in data) || !('id' in data.me) || data.me.id < 1){
  386.         var url = 'https://api.torn.com/user/'+data.me.id+'?selections=basic&key='+data.apikey;
  387.         apiCall(url, function(d) {
  388.             id = d.player_id;
  389.             data.me = {'id': id};
  390.             save();
  391.         });
  392.     }
  393. }
  394.  
  395. function loadData(){
  396.     data = localStorage.getItem('jebster.torn');
  397.     if(data === undefined || data === null){
  398.         // Default settings
  399.         data = {
  400.             profileview:{
  401.                 show: true,
  402.                 display: ['xantaken','logins','refills','useractivity']
  403.             }
  404.         };
  405.     }else{
  406.         data = JSON.parse(data);
  407.     }
  408.  
  409.     if(data.apikey === undefined || data.apikey === ''){
  410.         getApiKey();
  411.     }
  412. }
  413.  
  414. var asked = false;
  415. function getApiKey(){
  416.     if(asked) return; asked = true;
  417.  
  418.  
  419.     var button = '<button id="JApiKeyBtn" style="';
  420.     button += 'background-color: #282828;';
  421.     button += 'border: none;';
  422.     button += 'border-radius: 0 8px 8px 0;';
  423.     button += 'color: white;';
  424.     button += 'padding: 5px 5px 5px 6px;';
  425.     button += 'text-align: center;';
  426.     button += 'text-decoration: none;';
  427.     button += 'display: inline-block;';
  428.     button += 'font-size: 16px;';
  429.     button += 'margin: 4px 0px;';
  430.     button += 'cursor: pointer;';
  431.     button += '"><i class="fa fa-floppy-o" aria-hidden="true"></i></button>';
  432.  
  433.     var input = '<input type="text" id="JApiKeyInput" style="';
  434.     input += 'border-radius: 8px 0 0 8px;';
  435.     input += 'margin: 4px 0px;';
  436.     input += 'padding: 5px;';
  437.     input += 'font-size: 16px;';
  438.     input += '" placeholder="ApiKey"></input>';
  439.  
  440.     var block = '<div class="profile-wrapper medals-wrapper m-top10">';
  441.     block += '<div class="menu-header">Torn Helper</div>';
  442.     block += '<div class="profile-container"><div class="profile-container-description">';
  443.     block += 'In order to use this script you need to enter your Torn Api Key, which you can '+
  444.         'get on your <a href="http://www.torn.com/preferences.php">preferences page</a> and under the \'API Key\' tab.<br />';
  445.     block += input;
  446.     block += button;
  447.     block += '</div></div></div>';
  448.  
  449.     $(block).insertAfter('.content-title');
  450.  
  451.     $('#JApiKeyBtn').click(function(){
  452.         var key = $("#JApiKeyInput").val();
  453.         if(!('me' in data)) data.me = {};
  454.         data.apikey = key;
  455.         save();
  456.         location.reload();
  457.     });
  458.  
  459. }
  460.  
  461. function apiUserStats(userid, cb){
  462.     var lastRequest = getUserValue(userid, 'lastRequest');
  463.     var now = new Date();
  464.     if(lastRequest === 0 || lastRequest < now.getTime() - (2*60*60*1000)){ // Every 2hours
  465.         var selections = 'personalstats,basic,crimes';
  466.         var url = 'https://api.torn.com/user/'+userid+'?selections='+selections+'&key='+data.apikey;
  467.         apiCall(url, function(data) {
  468.             if(data.error) getApiKey();
  469.             else{
  470.                 setUserValue(userid, 'stats', data.personalstats);
  471.                 setUserValue(userid, 'lastRequest', now.getTime());
  472.                 setUserValue(userid, 'username', data.name);
  473.                 setUserValue(userid, 'gender', data.gender);
  474.                 setUserValue(userid, 'crimes', data.criminalrecord);
  475.                 save();
  476.                 cb(data);
  477.             }
  478.         });
  479.     }else{
  480.         cb(data[userid].stats);
  481.     }
  482. }
  483.  
  484. function compareTemplate(user1Id, user2Id){
  485.     var versusMe = data.settings && data.settings.versusMine;
  486.  
  487.     var css = '<style>'+
  488.         '.tornHelper{' +
  489.         'min-width:200px;' +
  490.         '}' +
  491.         '</style>';
  492.  
  493.     var html = css+'<div class="profile-container basic-info"><ul class="basic-list">';
  494.     html += '<li>';
  495.     html += '<div class="user-information-section left"><span class="bold"></span></div>';
  496.     html += '<div class="'+(versusMe ? 'user-information-section left' : '')+' tornHelper"><span class="bold">'+getUserValue(user1Id, 'username')+'</span></div>';
  497.     html += versusMe ? '<div class="tornHelper"><span class="bold">'+getUserValue(user2Id, 'username')+' (You)</span></div>' : '';
  498.     html += '</li>';
  499.  
  500.     var stats = possibleStats();
  501.     for(var i = 0; i < data.profileview.display.length; i++){
  502.         var display = stats[data.profileview.display[i]];
  503.         if(stats[data.profileview.display[i]]){
  504.             var user1Value = 0, user2Value = 0;
  505.             if(display.apiname){
  506.                 user1Value = getUserValue(user1Id, display.apiname);
  507.                 user2Value = getUserValue(user2Id, display.apiname);
  508.             }else if(display.total){
  509.                 for(var j = 0; j < display.total.length; j++){
  510.                     user1Value += getUserValue(user1Id, display.total[j]);
  511.                     user2Value += getUserValue(user2Id, display.total[j]);
  512.                 }
  513.             }else if(display.custom){
  514.                 user1Value = display.custom(user1Id);
  515.                 user2Value = display.custom(user2Id);
  516.             }
  517.             user1Value = user1Value ? user1Value : 0;
  518.             user2Value = user2Value ? user2Value : 0;
  519.  
  520.             if(display.format){
  521.                 user1Value = display.format(user1Value);
  522.                 user2Value = display.format(user2Value);
  523.             }else{
  524.                 user1Value = formatNumber(user1Value);
  525.                 user2Value = formatNumber(user2Value);
  526.             }
  527.  
  528.             html += '<li>';
  529.             html += '<div class="user-information-section left"><span class="bold">';
  530.             html += display.display;
  531.             if(display.tooltip){
  532.                 html += ' <i class="fa fa-question-circle" aria-hidden="true" title="'+display.tooltip+'" style="cursor: pointer;" />';
  533.             }
  534.             html += '</span></div>';
  535.             html += '<div class="'+(versusMe ? 'user-information-section left' : '')+' tornHelper">';
  536.             html += user1Value +'</div>';
  537.             html += versusMe ? '<div class="tornHelper">'+user2Value+'</div>' : '';
  538.             html += '</li>';
  539.         }
  540.     }
  541.     html += '</ul><hr />';
  542.  
  543.     var f = function(type, id){
  544.         var attacks = {hosp: {display: 'Hosped', times: 0, other: 0}, mug: {display: 'Mugged', times: 0},
  545.                        left: {display: 'Left', times: 0}, lost: {display: 'Lost', times: 0}};
  546.         if(type in data[id]){
  547.             for(var p in data[id][type]){
  548.                 var attack = data[id][type][p];
  549.                 switch(attack.result){
  550.                     case 'Mug':
  551.                         attacks.mug.times++;
  552.                         break;
  553.                     case 'Hospitalize':
  554.                         attacks.hosp.times++;
  555.                         break;
  556.                     case 'Leave':
  557.                         attacks.left.times++;
  558.                         break;
  559.                     case 'Lose':
  560.                         attacks.lost.times++;
  561.                         break;
  562.                 }
  563.             }
  564.         }
  565.         return attacks;
  566.     };
  567.     var attacks = f('attacks', user1Id);
  568.     var defends = f('defends', user1Id);
  569.  
  570.     var ahtml = '<ul class="basic-list">';
  571.     var lis = '';
  572.     var anyAttacks = false;
  573.     for(var type in attacks){
  574.         if(attacks[type].times > 0 || (defends[type].times > 0 && versusMe)){
  575.             lis += '<li>';
  576.             lis += '<div class="user-information-section left width112"><span class="bold">'+attacks[type].display+'</span></div>';
  577.             lis += versusMe ? '<div class="user-information-section left tornHelper">'+defends[type].times+'</div>' : '';
  578.             lis += '<div class="tornHelper">'+attacks[type].times+'</div>';
  579.             lis += '</li>';
  580.             anyAttacks = true;
  581.         }
  582.     }
  583.     if(anyAttacks){
  584.         var g = getUserValue(user1Id, 'gender');
  585.         var gender = g == 'Male' ? 'him' : g == 'Female' ? 'her' : 'them';
  586.         ahtml += '<li>';
  587.         ahtml += '<div class="user-information-section left"><span class="bold">Attacks</span></div>';
  588.         ahtml += versusMe ? '<div class="user-information-section left tornHelper"><span class="bold">Towards you</span></div>' : '';
  589.         ahtml += '<div class="tornHelper"><span class="bold">'+(versusMe ? 'Towards '+gender : 'You made') +'</span></div>';
  590.         ahtml += '</li>';
  591.     }
  592.     ahtml += lis;
  593.     ahtml += '</ul></div>';
  594.  
  595.     html += !anyAttacks ? 'You haven\'t attacked '+getUserValue(user1Id, 'username')+' before.' : '';
  596.     html += ahtml;
  597.     return html;
  598. }
  599.  
  600. function possibleStats(){
  601.     return {
  602.         attackswon:{apiname:['stats','attackswon'], display: 'Attacks won', category: 'Attacking'},
  603.         attackslost:{apiname:['stats','attackslost'], display: 'Attacks lost', category: 'Attacking'},
  604.         attacksdraw:{apiname:['stats','attacksdraw'], display: 'Attacks Draw', category: 'Attacking'},
  605.         attacksassisted:{apiname:['stats','attacksassisted'], display: 'Attacks assisted', category: 'Attacking'},
  606.         totalattacks:{total:[['stats','attackswon'],['stats','attackslost'],['stats','attacksdraw'],['stats','attacksassisted'],['stats','yourunaway']], display: 'Total attacks', category: 'Attacking', format:formatNumber},
  607.         defendswon:{apiname:['stats','defendswon'], display: 'Defends won', category: 'Attacking'},
  608.         defendslost:{apiname:['stats','defendslost'], display: 'Defends lost', category: 'Attacking'},
  609.         defendsstalemated:{apiname:['stats','defendsstalemated'], display: 'Defends stalemated', category: 'Attacking'},
  610.         yourunaway:{apiname:['stats','yourunaway'], display: 'Run Aways', category: 'Attacking'},
  611.         theyrunaway:{apiname:['stats','theyrunaway'], display: 'Other Ran Away', category: 'Attacking'},
  612.         bestkillstreak:{apiname:['stats','bestkillstreak'], display: 'Best Kill Streak', category: 'Attacking'},
  613.         attackcriticalhits:{apiname:['stats','attackcriticalhits'], display: 'Attack Critical Hits', category: 'Attacking'},
  614.         attackhits:{apiname:['stats','attackhits'], display: 'Attack Hits', category: 'Attacking'},
  615.         attackmisses:{apiname:['stats','attackmisses'], display: 'Attack Misses', category: 'Attacking'},
  616.         roundsfired:{apiname:['stats','roundsfired'], display: 'Rounds Fired', category: 'Attacking'},
  617.         attacksstealthed:{apiname:['stats','attacksstealthed'], display: 'Attacks Stealthed', category: 'Attacking'},
  618.         moneymugged:{apiname:['stats','moneymugged'], display: 'Money Mugged', category: 'Attacking', format: formatMoney},
  619.         largestmug:{apiname:['stats','largestmug'], display: 'Largest Mug', category: 'Attacking', format: formatMoney},
  620.         highestbeaten:{apiname:['stats','highestbeaten'], display: 'Highest Level Beaten', category: 'Attacking'},
  621.         respectforfaction:{apiname:['stats','respectforfaction'], display: 'Respect For Faction', category: 'Attacking'},
  622.  
  623.         itemsbought:{apiname:['stats','itemsbought'], display: 'Items Bought', category: 'Trading'},
  624.         auctionswon:{apiname:['stats','auctionswon'], display: 'Auctions Won', category: 'Trading'},
  625.         auctionsells:{apiname:['stats','auctionsells'], display: 'Auction Sells', category: 'Trading'},
  626.         itemssent:{apiname:['stats','itemssent'], display: 'Items Sent', category: 'Trading'},
  627.         trades:{apiname:['stats','trades'], display: 'Trades', category: 'Trading'},
  628.         weaponsbought:{apiname:['stats','weaponsbought'], display: 'Weapons Bought', category: 'Trading'},
  629.         pointssold:{apiname:['stats','pointssold'], display: 'Points Sold', category: 'Trading'},
  630.         pointsbought:{apiname:['stats','pointsbought'], display: 'Points Bought', category: 'Trading'},
  631.         bazaarcustomers:{apiname:['stats','bazaarcustomers'], display: 'Bazaar Customers', category: 'Trading'},
  632.         bazaarsales:{apiname:['stats','bazaarsales'], display: 'Bazaar Sales', category: 'Trading'},
  633.         bazaarprofit:{apiname:['stats','bazaarprofit'], display: 'Bazaar Profit', category: 'Trading', format: formatMoney},
  634.         jailed:{apiname:['stats','jailed'], display: 'Jailed', category: 'Jail'},
  635.         peoplebusted:{apiname:['stats','peoplebusted'], display: 'People Busted', category: 'Jail'},
  636.         failedbusts:{apiname:['stats','failedbusts'], display: 'Failed Busts', category: 'Jail'},
  637.         peoplebought:{apiname:['stats','peoplebought'], display: 'People Bought out of Jail', category: 'Jail'},
  638.         peopleboughtspent:{apiname:['stats','peopleboughtspent'], display: 'Money Spent on buying people out of jail', category: 'Jail', format: formatMoney}, // TODO: Some shorter display text
  639.         hospital:{apiname:['stats','hospital'], display: 'Hospital', category: 'Hospital'}, // TODO:
  640.         medicalitemsused:{apiname:['stats','medicalitemsused'], display: 'Medical Items Used', category: 'Hospital'},
  641.         bloodwithdrawn:{apiname:['stats','bloodwithdrawn'], display: 'Blood Withdrawn', category: 'Hospital'},
  642.         revives:{apiname:['stats','revives'], display: 'Revives', category: 'Hospital'},
  643.         revivesreceived:{apiname:['stats','revivesreceived'], display: 'Revives Received', category: 'Hospital'},
  644.         medstolen:{apiname:['stats','medstolen'], display: 'Medical Items Stolen', category: 'Hospital'},
  645.         heahits:{apiname:['stats','heahits'], display: 'Heavy artillery', category: 'Finishing Hits'},
  646.         machits:{apiname:['stats','machits'], display: 'Machine guns', category: 'Finishing Hits'},
  647.         rifhits:{apiname:['stats','rifhits'], display: 'Rifles', category: 'Finishing Hits'},
  648.         smghits:{apiname:['stats','smghits'], display: 'Sub machine guns', category: 'Finishing Hits'},
  649.         shohits:{apiname:['stats','shohits'], display: 'Shotguns', category: 'Finishing Hits'},
  650.         pishits:{apiname:['stats','pishits'], display: 'Pistols', category: 'Finishing Hits'},
  651.         grehits:{apiname:['stats','grehits'], display: 'Temporary weapons', category: 'Finishing Hits'},
  652.         piehits:{apiname:['stats','piehits'], display: 'Piercing weapons', category: 'Finishing Hits'},
  653.         slahits:{apiname:['stats','slahits'], display: 'Slashing weapons', category: 'Finishing Hits'},
  654.         axehits:{apiname:['stats','axehits'], display: 'Clubbed weapons', category: 'Finishing Hits'},
  655.         chahits:{apiname:['stats','chahits'], display: 'Mechanical weapons', category: 'Finishing Hits'},
  656.         mailssent:{apiname:['stats','mailssent'], display: 'Mail Sent', category: 'Communication'},
  657.         friendmailssent:{apiname:['stats','friendmailssent'], display: 'Friend Mail Sent', category: 'Communication'},
  658.         factionmailssent:{apiname:['stats','factionmailssent'], display: 'Faction Mail Sent', category: 'Communication'},
  659.         companymailssent:{apiname:['stats','companymailssent'], display: 'Company Mail Sent', category: 'Communication'},
  660.         spousemailssent:{apiname:['stats','spousemailssent'], display: 'Spouse Mail Sent', category: 'Communication'},
  661.         classifiedadsplaced:{apiname:['stats','classifiedadsplaced'], display: 'Classified Newspaper Ads Placed', category: 'Communication'},
  662.         personalsplaced:{apiname:['stats','personalsplaced'], display: 'Personal Placed', category: 'Communication'},
  663.         bountiesplaced:{apiname:['stats','bountiesplaced'], display: 'Bounties Placed', category: 'Bounties'},
  664.         totalbountyspent:{apiname:['stats','totalbountyspent'], display: 'Total Bounty Money Spent', category: 'Bounties', format: formatMoney},
  665.         bountiescollected:{apiname:['stats','bountiescollected'], display: 'Bounties Collected', category: 'Bounties'},
  666.         totalbountyreward:{apiname:['stats','totalbountyreward'], display: 'Total Bounty Money Gained', category: 'Bounties', format: formatMoney},
  667.         bountiesreceived:{apiname:['stats','bountiesreceived'], display: 'Bounties Received', category: 'Bounties'},
  668.         cityfinds:{apiname:['stats','cityfinds'], display: 'City Finds', category: 'Items'},
  669.         itemsdumped:{apiname:['stats','itemsdumped'], display: 'Items Dumped', category: 'Items'},
  670.         dumpsearches:{apiname:['stats','dumpsearches'], display: 'Dump Searches', category: 'Items'},
  671.         dumpfinds:{apiname:['stats','dumpfinds'], display: 'Dump Finds', category: 'Items'},
  672.         traveltimes:{apiname:['stats','traveltimes'], display: 'Travel Times', category: 'Travel'},
  673.         itemsboughtabroad:{apiname:['stats','itemsboughtabroad'], display: 'Items Bought Abroad', category: 'Travel'},
  674.         argtravel:{apiname:['stats','argtravel'], display: 'Argentina Traveled', category: 'Travel'},
  675.         mextravel:{apiname:['stats','mextravel'], display: 'Mexico Traveled', category: 'Travel'},
  676.         dubtravel:{apiname:['stats','dubtravel'], display: 'Dubai Traveled', category: 'Travel'},
  677.         hawtravel:{apiname:['stats','hawtravel'], display: 'Hawaii Traveled', category: 'Travel'},
  678.         japtravel:{apiname:['stats','japtravel'], display: 'Japan Traveled', category: 'Travel'},
  679.         lontravel:{apiname:['stats','lontravel'], display: 'London Traveled', category: 'Travel'},
  680.         soutravel:{apiname:['stats','soutravel'], display: 'South Africa Traveled', category: 'Travel'},
  681.         switravel:{apiname:['stats','switravel'], display: 'Switzerland Traveled', category: 'Travel'},
  682.         chitravel:{apiname:['stats','chitravel'], display: 'China Traveled', category: 'Travel'},
  683.         cantravel:{apiname:['stats','cantravel'], display: 'Canada Traveled', category: 'Travel'},
  684.         caytravel:{apiname:['stats','caytravel'], display: 'Cayman Islands Traveled', category: 'Travel'},
  685.         drugsused:{apiname:['stats','drugsused'], display: 'Drug Used', category: 'Drugs'},
  686.         overdosed:{apiname:['stats','overdosed'], display: 'Drug Overses', category: 'Drugs'},
  687.         cantaken:{apiname:['stats','cantaken'], display: 'Canabis Taken', category: 'Drugs'},
  688.         exttaken:{apiname:['stats','exttaken'], display: 'Ecstasy Taken', category: 'Drugs'},
  689.         kettaken:{apiname:['stats','kettaken'], display: 'Ketamine Taken', category: 'Drugs'},
  690.         lsdtaken:{apiname:['stats','lsdtaken'], display: 'LSD Taken', category: 'Drugs'},
  691.         opitaken:{apiname:['stats','opitaken'], display: 'Opium Taken', category: 'Drugs'},
  692.         shrtaken:{apiname:['stats','shrtaken'], display: 'Shrooms Taken', category: 'Drugs'},
  693.         spetaken:{apiname:['stats','spetaken'], display: 'Speed Taken', category: 'Drugs'},
  694.         pcptaken:{apiname:['stats','pcptaken'], display: 'PCP Taken', category: 'Drugs'},
  695.         xantaken:{apiname:['stats','xantaken'], display: 'Xanax Taken', category: 'Drugs'},
  696.         victaken:{apiname:['stats','victaken'], display: 'Vicodin Taken', category: 'Drugs'},
  697.         networth:{apiname:['stats','networth'], display: 'Networth', format: formatMoney},
  698.         logins:{apiname:['stats','logins'], display: 'Logins'},
  699.         useractivity:{apiname:['stats','useractivity'], display: 'Time Played', format: formatSeconds},
  700.         meritsbought:{apiname:['stats','meritsbought'], display: 'Merits Bought'},
  701.         refills:{apiname:['stats','refills'], display: 'Refills'},
  702.         trainsreceived:{apiname:['stats','trainsreceived'], display: 'Trains Received'},
  703.         spydone:{apiname:['stats','spydone'], display: 'Spies Done'},
  704.         statenhancersused:{apiname:['stats','statenhancersused'], display: 'Stat Enhancers Used'},
  705.         virusescoded:{apiname:['stats','virusescoded'], display: 'Viruses Coded'},
  706.         daysbeendonator:{apiname:['stats','daysbeendonator'], display: 'Days Been Donator'},
  707.         missionscompleted:{apiname:['stats','missionscompleted'], display: 'Missions Completed', category: 'Missions'},
  708.         contractscompleted:{apiname:['stats','contractscompleted'], display: 'Contracts Completed', category: 'Missions'},
  709.         dukecontractscompleted:{apiname:['stats','dukecontractscompleted'], display: 'Duke Contracts Completed', category: 'Missions'},
  710.         missioncreditsearned:{apiname:['stats','missioncreditsearned'], display: 'Mission Credits Earned', category: 'Missions'},
  711.         sellingillegalproducts:{apiname:['crimes','selling_illegal_products'], display: 'Illegal Products Sold', category: 'Crimes'},
  712.         theft:{apiname:['crimes','theft'], display: 'Theft', category: 'Crimes'},
  713.         auto_theft:{apiname:['crimes','auto_theft'], display: 'Auto Theft', category: 'Crimes'},
  714.         drug_deals:{apiname:['crimes','drug_deals'], display: 'Drug Deals', category: 'Crimes'},
  715.         computer_crimes:{apiname:['crimes','computer_crimes'], display: 'Computer Crimes', category: 'Crimes'},
  716.         murder:{apiname:['crimes','murder'], display: 'Murder', category: 'Crimes'},
  717.         fraud_crimes:{apiname:['crimes','fraud_crimes'], display: 'Fraud Crimes', category: 'Crimes'},
  718.         other:{apiname:['crimes','other'], display: 'Other Crimes', category: 'Crimes'},
  719.         total:{apiname:['crimes','total'], display: 'Total Crimes', category: 'Crimes'},
  720.         awards:{display: 'Awards', custom: function(id){return getAwards(id);}, tooltip: 'Your award count only updates when you visit your own profile.'},
  721.         point:{display:'Point', custom: function(id){
  722.             var x = getUserValue(id, ['stats', 'attackswon'])+getUserValue(id,['stats','attackslost']);
  723.             x += getUserValue(id,['stats','attacksdraw'])+getUserValue(id,['stats','yourunaway']);
  724.             var y = getUserValue(id, ['stats','xantaken']);
  725.             return (y*250) - (x*25);
  726.         }, category: 'Requests'},
  727.     };
  728. }
  729.  
  730. function allSettings(){
  731.     return {
  732.         versusMine: {display: 'Show my stats', type:'checkbox'}
  733.     };
  734. }
  735.  
  736. function apiCall(url, cb){
  737.     console.log('Torn helper: making request \''+url+'\'');
  738.     $.ajax({
  739.         url: url,
  740.         type: 'GET',
  741.         success: function(data) {
  742.             cb(data);
  743.         }
  744.     });
  745. }
  746.  
  747. function getAwards(id){
  748.     var element = $(".profile-container.basic-info.bottom-round ul:nth-child(2) li:nth-child(8)");
  749.     var content = element.first().contents().filter(function(){
  750.         return this.nodeType == 3;
  751.     });
  752.     var value = parseInt(content.text().trim());
  753.  
  754.     if(!id){
  755.         if(data.me.awards)
  756.             return data.me.awards;
  757.         return -1;
  758.     }
  759.     if(id == data.me.id){
  760.         data.me.awards = value;
  761.         save();
  762.     }
  763.     return value;
  764. }
  765.  
  766. function removeFirstAndLastLine(text){
  767.     var lines = text.split('\n');
  768.     lines.splice(0,1);
  769.     lines.splice(-1,1);
  770.     var newtext = lines.join('\n');
  771. }
  772.  
  773. function formatSeconds(s){
  774.     var minutes = Math.floor(s/60)%60;
  775.     var hours = Math.floor(s/(60*60))%24;
  776.     var days = Math.floor(s/(60*60*24));
  777.     var seconds = s%60;
  778.  
  779.     return '{0}d {1}h {2}m {3}s'.format(days, hours, minutes, seconds);
  780. }
  781.  
  782. function formatNumber(n){
  783.     return n.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
  784. }
  785.  
  786. function formatMoney(m){
  787.     return '$'+formatNumber(m);
  788. }
  789.  
  790. // Taken from: http://stackoverflow.com/a/901144/1832471
  791. function getParameterByName(name, url) {
  792.     if (!url) {
  793.         url = window.location.href;
  794.     }
  795.     name = name.replace(/[\[\]]/g, "\\$&");
  796.     var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
  797.         results = regex.exec(url);
  798.     if (!results) return null;
  799.     if (!results[2]) return '';
  800.     return decodeURIComponent(results[2].replace(/\+/g, " "));
  801. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement