// ==UserScript==
// @name Torn Helper
// @namespace Jebster.Torn
// @author Jeggy
// @description Adds extra information to different pages all around Torn.
// @include *.torn.com/profiles.php?XID=*
// @version 0.1.3
// @require http://code.jquery.com/jquery-2.2.4.min.js
// @require http://code.jquery.com/ui/1.12.1/jquery-ui.min.js
// @resource jquery-ui http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/black-tie/jquery-ui.min.css
// @resource jquery-base http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css
// @grant GM_addStyle
// @grant GM_getResourceText
// ==/UserScript==
// debugger;
GM_addStyle(GM_getResourceText('jquery-base'));
GM_addStyle(GM_getResourceText('jquery-ui'));
String.prototype.format = function() {
var formatted = this;
for (var i = 0; i < arguments.length; i++) {
var regexp = new RegExp('\\{'+i+'\\}', 'gi');
formatted = formatted.replace(regexp, arguments[i]);
}
return formatted;
};
var data = {};
(function() {
'use strict';
var site = window.location.pathname;
loadData();
saveOwnData();
loadAttackLog();
if(site.indexOf('profiles.php') > 0) profileView();
})();
function loadAttackLog(){
var selections = 'attacks';
if('attackLogLoad' in data)
//if(data.attackLogLoad > new Date().getTime() + (60*60*6))
logAttacks(false);
else
logAttacks(true);
}
function logAttacks(full){
var selections = 'attacks' + (full ? 'full' : '');
var url = 'https://api.torn.com/user/'+data.me.id+'?selections='+selections+'&key='+data.apikey;
var now = new Date().getTime();
if(!('attackLogLoad' in data) || data.attackLogLoad < now - (60*60*1000)){ // every one hour
data.attackLogLoad = now;
apiCall(url, function(d) {
if(d.error) getApiKey();
else{
for(var p in d.attacks){
if (d.attacks.hasOwnProperty(p)) {
var attack = d.attacks[p];
var defender_id = attack.defender_id;
if(!(defender_id in data)) data[defender_id] = {};
if(attack.attacker_id == data.me.id){
// My attack
if(!('attacks' in data[defender_id])) {console.log('Test'); data[defender_id].attacks = {};}
data[defender_id].attacks[p] = attack;
}else{
// I'm being attacked
}
}
}
save();
}
});
}
}
function profileView(){
var userid = getParameterByName('XID');
var userData = data[userid];
var content = '';
content += profileViewSelectionPopUp(); // TODO: Figoure out how to call tampermonkey function from the injected code.
content += '<div id="compareStats">';
content += 'Loading...';
content += '<br />';
content += '</div>';
// content += '<hr />';
// content += '<b>Notes</b><br />';
// content += getUserValue(userid, 'notes');
// content += '<br />';
var block = $(
'<div class="profile-wrapper medals-wrapper m-top10">' +
'<div class="menu-header">Torn Helper</div>' +
'<div class="profile-container"> ' +
'<div class="profile-container-description">'+content+'</div>' +
'</div>' +
'<div class="clear"></div></div>');
$(block).insertAfter('.tutorial-cont + .profile-wrapper');
var compareFunc = function(){
$('#compareStats').replaceWith(compareTemplate(userid, data.me.userid));
};
apiUserStats(userid, compareFunc);
apiUserStats(data.me.userid, compareFunc);
}
function profileViewSelectionPopUp(){
var possibilities = possibleStats();
var popupHtml = '<div><fieldset><legend>Select:</legend>';
for(var p in possibilities){
var o = possibilities[p];
var checked = inArray(p, data.profileview.display) ? 'checked' : '';
popupHtml += '<label for="checkbox'+p+'">'+o.display+'</label>: '+
'<input type="checkbox" name="checkbox'+p+'" id="view'+p+'" '+checked+'> <br />';
}
popupHtml += '</fieldset></div>';
var popup = popupWindow(
{
element: '#editProfileView',
title: 'Edit Profile view'
},
popupHtml,
[
{
'display': 'Save',
'callback': function(){
var selected = [];
for(var p in possibleStats()){
var checked = $("#view"+p).is(':checked');
if(checked) selected.push(p);
}
data.profileview.display = selected;
save();
location.reload();
}
}
]
);
var button = '<div style="float:right">' +
'<button id="editProfileView">Edit</button></div>';
return button+popup;
}
/**
* Example usage:
* popupWindow(
* { 'element': '#myDialogButton', 'title': 'Hello World' },
* '<h3>Something</h3><input type="text" id="myfield" />',
* [{'display': 'Save',
* 'close': false, // default: true
* callback: function(){var something = $("#myfield").val();}
* }]);
*/
function popupWindow(e, content, buttons){
var script = '<script>$("'+e.element+'").click(function(){$("#dialog-message").dialog({'+
'modal: true,'+
'draggable: true,'+
'resizable: true,'+
'position: [\'center\'],'+
'show: \'blind\','+
'hide: \'blind\','+
'width: 400,'+
'buttons: [';
var test = '';
for(var i = 0; i < buttons.length; i++){
script += '{';
script += 'text: \''+buttons[i].display+'\',';
script += 'id: \'dialogButton'+i+'\'';
script += '}';
// TODO: Fix this shit later!
$(document).on('click','#dialogButton0', function(){
buttons[0].callback();
$("a.ui-dialog-titlebar-close")[0].click();
});
// TODO: Support multiple buttons!
}
// todo: remove last char
script += ']}';
script += ');});'+test;
script += '</script>';
var html = '<div id="dialog-message" title="'+e.title+'" style="display: none;">';
html += content;
html += '</div>';
return script+html;
}
function inArray(c, a){
// Somehow $.inArray is not working? ?
for(var i = 0; i < a.length; i++){
if(c == a[i]) return true;
}
return false;
}
function getUserValue(userid, property){
var user = data[userid];
if(user){
if($.isArray(property)){
for(var i = 0; i < property.length; i++){
user = user[property[i]];
}
return user;
}else{
var userData = user[property];
if(userData){
return userData;
}
}
}
return -1;
}
function setUserValue(userid, property, value){
if(data[userid] === undefined) data[userid] = {};
data[userid][property] = value;
}
function save(){
localStorage.setItem('jebster.torn', JSON.stringify(data));
}
function saveOwnData(){
if(!('me' in data) || !('id' in data.me) || data.me.id < 1){
var url = 'https://api.torn.com/user/'+data.me.id+'?selections=basic&key='+data.apikey;
apiCall(url, function(d) {
id = d.player_id;
data.me = {'id': id};
save();
});
}
}
function loadData(){
data = localStorage.getItem('jebster.torn');
if(data === undefined || data === null){
// Default settings
data = {
profileview:{
display: ['xantaken','logins','refills','useractivity']
}
};
}else{
data = JSON.parse(data);
}
if(data.apikey === undefined || data.apikey === ''){
getApiKey();
}
}
var asked = false;
function getApiKey(){
// Add some beautiful input/popup on the page itself
if(asked) return; asked = true;
var key = prompt('You API Key', 'key');
if(!('me' in data)) data.me = {};
data.apikey = key;
save();
}
function apiUserStats(userid, cb){
var lastRequest = getUserValue(userid, 'lastRequest');
var now = new Date();
if(lastRequest === 0 || lastRequest < now.getTime() - (60*60*5*1000)){ // TODO:
var selections = 'personalstats,basic';
var url = 'https://api.torn.com/user/'+userid+'?selections='+selections+'&key='+data.apikey;
apiCall(url, function(data) {
if(data.error) getApiKey();
else{
setUserValue(userid, 'stats', data.personalstats);
setUserValue(userid, 'lastRequest', now.getTime());
setUserValue(userid, 'username', data.name);
save();
cb(data);
}
});
}else{
cb(data[userid].stats);
}
}
function compareTemplate(user1Id, user2Id){
var css = '<style>'+
'.tornHelper{' +
'min-width:200px;' +
'}' +
'</style>';
var html = css+'<div class="profile-container basic-info"><ul class="basic-list">' +
'<li>' +
'<div class="user-information-section left"><span class="bold"></span></div>' +
'<div class="user-information-section left tornHelper"><span class="bold">'+getUserValue(user1Id, 'username')+'</span></div>' +
'<div class="tornHelper"><span class="bold">'+getUserValue(user2Id, 'username')+' (You)</span></div>' +
'</li>';
var stats = possibleStats();
for(var i = 0; i < data.profileview.display.length; i++){
var display = stats[data.profileview.display[i]];
if(stats[data.profileview.display[i]]){
var user1Value = getUserValue(user1Id, display.apiname);
var user2Value = getUserValue(user2Id, display.apiname);
user1Value = user1Value ? user1Value : 0;
user2Value = user2Value ? user2Value : 0;
if(display.format){
user1Value = display.format(user1Value);
user2Value = display.format(user2Value);
}
html += '<li>' +
'<div class="user-information-section left"><span class="bold">' +
display.display +
'</span></div>' +
'<div class="user-information-section left tornHelper">' +
user1Value +'</div>' +
'<div class="tornHelper">'+user2Value+'</div>' +
'</li>';
}
}
html += '</ul><hr />';
var attacks = {hosp: {display: 'Hosped', times: 0}, mug: {display: 'Mugged', times: 0}, left: {display: 'Left', times: 0}, lost: {display: 'Lost', times: 0}};
if('attacks' in data[user1Id]){
for(var p in data[user1Id].attacks){
var attack = data[user1Id].attacks[p];
switch(attack.result){
case 'Mug':
attacks.mug.times++;
break;
case 'Hospitalize':
attacks.hosp.times++;
break;
case 'Leave':
attacks.left.times++;
break;
case 'Lose':
attacks.lost.times++;
break;
}
}
}
html += 'Attacks you made against \''+getUserValue(user1Id, 'username')+'\'';
html += '<ul class="basic-list">';
for(var type in attacks){
html += '<li>';
html += '<div class="user-information-section left width112"><span class="bold">'+attacks[type].display+'</span></div>';
html += attacks[type].times;
html += '</li>';
}
html += '</ul></div>';
return html;
}
function possibleStats(){
return {
attackswon:{apiname:['stats','attackswon'], display: 'Attacks Won'},
attackslost:{apiname:['stats','attackslost'], display: 'Attacks Lost'},
attacksdraw:{apiname:['stats','attacksdraw'], display: 'Attacks Draw'},
attacksassisted:{apiname:['stats','attacksassisted'], display: 'Attacks Assisted'},
defendswon:{apiname:['stats','defendswon'], display: 'Defends Won'},
defendslost:{apiname:['stats','defendslost'], display: 'Defends Lost'},
defendsstalemated:{apiname:['stats','defendsstalemated'], display: 'Defends Stalemated'},
yourunaway:{apiname:['stats','yourunaway'], display: 'Run Aways'},
theyrunaway:{apiname:['stats','theyrunaway'], display: 'Other Run Away'}, // TODO: Some better display text
bestkillstreak:{apiname:['stats','bestkillstreak'], display: 'Best Kill Streak'},
attackcriticalhits:{apiname:['stats','attackcriticalhits'], display: 'Attack Critical Hits'},
attackhits:{apiname:['stats','attackhits'], display: 'Attack Hits'},
attackmisses:{apiname:['stats','attackmisses'], display: 'Attack Misses'},
roundsfired:{apiname:['stats','roundsfired'], display: 'Rounds Fired'},
attacksstealthed:{apiname:['stats','attacksstealthed'], display: 'Attacks Stealthed'},
moneymugged:{apiname:['stats','moneymugged'], display: 'Money Mugged'},
largestmug:{apiname:['stats','largestmug'], display: 'Largest Mug'},
highestbeaten:{apiname:['stats','highestbeaten'], display: 'Highest Level Beaten'},
respectforfaction:{apiname:['stats','respectforfaction'], display: 'Respect For Faction'},
itemsbought:{apiname:['stats','itemsbought'], display: 'Items Bought'},
auctionswon:{apiname:['stats','auctionswon'], display: 'Auctions Won'},
auctionsells:{apiname:['stats','auctionsells'], display: 'Auction Sells'},
itemssent:{apiname:['stats','itemssent'], display: 'Items Sent'},
trades:{apiname:['stats','trades'], display: 'Trades'},
weaponsbought:{apiname:['stats','weaponsbought'], display: 'Weapons Bought'},
pointssold:{apiname:['stats','pointssold'], display: 'Points Sold'},
pointsbought:{apiname:['stats','pointsbought'], display: 'Points Bought'},
bazaarcustomers:{apiname:['stats','bazaarcustomers'], display: 'Bazaar Customers'},
bazaarsales:{apiname:['stats','bazaarsales'], display: 'Bazaar Sales'},
bazaarprofit:{apiname:['stats','bazaarprofit'], display: 'Bazaar Profit'},
jailed:{apiname:['stats','jailed'], display: 'Jailed'},
peoplebusted:{apiname:['stats','peoplebusted'], display: 'People Busted'},
failedbusts:{apiname:['stats','failedbusts'], display: 'Failed Busts'},
peoplebought:{apiname:['stats','peoplebought'], display: 'People Bought out of Jail'},
peopleboughtspent:{apiname:['stats','peopleboughtspent'], display: 'Money Spent on buying people out of jail'}, // TODO: Some shorter display text
hospital:{apiname:['stats','hospital'], display: 'Hospital'},
medicalitemsused:{apiname:['stats','medicalitemsused'], display: 'Medical Items Used'},
bloodwithdrawn:{apiname:['stats','bloodwithdrawn'], display: 'Blood Withdrawn'},
revives:{apiname:['stats','revives'], display: 'Revives'},
revivesreceived:{apiname:['stats','revivesreceived'], display: 'Revives Received'},
medstolen:{apiname:['stats','medstolen'], display: 'Medical Items Stolen'},
//heahits:{apiname:['stats','heahits'], display: ''}, // TODO:
//machits:{apiname:['stats','machits'], display: ''},
//rifhits:{apiname:['stats','rifhits'], display: ''},
//smghits:{apiname:['stats','smghits'], display: ''},
//shohits:{apiname:['stats','shohits'], display: ''},
//pishits:{apiname:['stats','pishits'], display: ''},
//grehits:{apiname:['stats','grehits'], display: ''},
//piehits:{apiname:['stats','piehits'], display: ''},
//slahits:{apiname:['stats','slahits'], display: ''},
//axehits:{apiname:['stats','axehits'], display: ''},
//chahits:{apiname:['stats','chahits'], display: ''},
mailssent:{apiname:['stats','mailssent'], display: 'Mail Sent'},
friendmailssent:{apiname:['stats','friendmailssent'], display: 'Friend Mail Sent'},
factionmailssent:{apiname:['stats','factionmailssent'], display: 'Faction Mail Sent'},
companymailssent:{apiname:['stats','companymailssent'], display: 'Company Mail Sent'},
spousemailssent:{apiname:['stats','spousemailssent'], display: 'Spouse Mail Sent'},
classifiedadsplaced:{apiname:['stats','classifiedadsplaced'], display: 'Classified Newspaper Ads Placed'},
personalsplaced:{apiname:['stats','personalsplaced'], display: 'Personal Newspaper Placed'},
bountiesplaced:{apiname:['stats','bountiesplaced'], display: 'Bounties Placed'},
totalbountyspent:{apiname:['stats','totalbountyspent'], display: 'Total Bounty Money Spent'},
bountiescollected:{apiname:['stats','bountiescollected'], display: 'Bounties Collected'},
totalbountyreward:{apiname:['stats','totalbountyreward'], display: 'Total Bounty Money Gained'},
bountiesreceived:{apiname:['stats','bountiesreceived'], display: 'Bounties Received'},
cityfinds:{apiname:['stats','cityfinds'], display: 'City Finds'},
itemsdumped:{apiname:['stats','itemsdumped'], display: 'Items Dumped'},
dumpsearches:{apiname:['stats','dumpsearches'], display: 'Dump Searches'},
dumpfinds:{apiname:['stats','dumpfinds'], display: 'Dump Finds'},
traveltimes:{apiname:['stats','traveltimes'], display: 'Travel Times'},
itemsboughtabroad:{apiname:['stats','itemsboughtabroad'], display: 'Items Bought Abroad'},
argtravel:{apiname:['stats','argtravel'], display: 'Argentina Traveled'},
mextravel:{apiname:['stats','mextravel'], display: 'Mexico Traveled'},
dubtravel:{apiname:['stats','dubtravel'], display: 'Dubai Traveled'},
hawtravel:{apiname:['stats','hawtravel'], display: 'Hawaii Traveled'},
japtravel:{apiname:['stats','japtravel'], display: 'Japan Traveled'},
lontravel:{apiname:['stats','lontravel'], display: 'London Traveled'},
soutravel:{apiname:['stats','soutravel'], display: 'South Africa Traveled'},
switravel:{apiname:['stats','switravel'], display: 'Switzerland Traveled'},
chitravel:{apiname:['stats','chitravel'], display: 'China Traveled'},
cantravel:{apiname:['stats','cantravel'], display: 'Canada Traveled'},
caytravel:{apiname:['stats','caytravel'], display: 'Cayman Islands Traveled'},
drugsused:{apiname:['stats','drugsused'], display: 'Drug Used'},
overdosed:{apiname:['stats','overdosed'], display: 'Drug Overses'},
cantaken:{apiname:['stats','cantaken'], display: 'Canabis Taken'},
exttaken:{apiname:['stats','exttaken'], display: 'Ecstasy Taken'},
kettaken:{apiname:['stats','kettaken'], display: 'Ketamine Taken'},
lsdtaken:{apiname:['stats','lsdtaken'], display: 'LSD Taken'},
opitaken:{apiname:['stats','opitaken'], display: 'Opium Taken'},
shrtaken:{apiname:['stats','shrtaken'], display: 'Shrooms Taken'},
spetaken:{apiname:['stats','spetaken'], display: 'Speed Taken'},
pcptaken:{apiname:['stats','pcptaken'], display: 'PCP Taken'},
xantaken:{apiname:['stats','xantaken'], display: 'Xanax Taken'},
victaken:{apiname:['stats','victaken'], display: 'Vicodin Taken'},
networth:{apiname:['stats','networth'], display: 'Networth', format: formatMoney},
logins:{apiname:['stats','logins'], display: 'Logins'},
useractivity:{apiname:['stats','useractivity'], display: 'Time Played', format: formatSeconds},
meritsbought:{apiname:['stats','meritsbought'], display: 'Merits Bought'},
refills:{apiname:['stats','refills'], display: 'Refills'},
trainsreceived:{apiname:['stats','trainsreceived'], display: 'Trains Received'},
spydone:{apiname:['stats','spydone'], display: 'Spies Done'},
statenhancersused:{apiname:['stats','statenhancersused'], display: 'Stat Enhancers Used'},
virusescoded:{apiname:['stats','virusescoded'], display: 'Viruses Coded'},
daysbeendonator:{apiname:['stats','daysbeendonator'], display: 'Days Been Donator'},
missionscompleted:{apiname:['stats','missionscompleted'], display: 'Missions Completed'},
contractscompleted:{apiname:['stats','contractscompleted'], display: 'Contracts Completed'},
dukecontractscompleted:{apiname:['stats','dukecontractscompleted'], display: 'Duke Contracts Completed'},
missioncreditsearned:{apiname:['stats','missioncreditsearned'], display: 'Mission Credits Earned'}
};
}
function apiCall(url, cb){
console.log(url);
$.ajax({
url: url,
type: 'GET',
success: function(data) {
cb(data);
},
//async: false
});
}
function removeFirstAndLastLine(text){
var lines = text.split('\n');
lines.splice(0,1);
lines.splice(-1,1);
var newtext = lines.join('\n');
}
function formatSeconds(s){
var minutes = Math.floor(s/60)%60;
var hours = Math.floor(s/(60*60))%24;
var days = Math.floor(s/(60*60*24));
var seconds = s%60;
return '{0}d {1}h {2}m {3}s'.format(days, hours, minutes, seconds);
}
function formatNumber(n){
return n;
}
function formatMoney(m){
return '$'+m.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}
// Taken from: http://stackoverflow.com/a/15724300/1832471
function getCookieValue(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
// Taken from: http://stackoverflow.com/a/901144/1832471
function getParameterByName(name, url) {
if (!url) {
url = window.location.href;
}
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}