NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name User Info Overlay
// @namespace http://reichwald.me/
// @version 0.5
// @description Display User Information As Popover
// @author Merlin Reichwald
// @copyright 2018, Merlin-R (https://openuserjs.org//users/Merlin-R)
// @license MIT
// @match https://www.torn.com/**
// @grant none
// ==/UserScript==
(function () {
'use strict';
class UserOverlay {
constructor() {
this.id = '0';
this.position = [0, 0];
this.dimensions = [200, 183];
this.data = {};
this.apikey = localStorage.apikey;
}
setProfile(id) {
this.id = id;
}
placeAt(x, y) {
this.position = [x, y];
}
async show() {
$('.mrdProfileOverview').remove();
this.$elem = $(await this.template());
this.resetTimeout();
this.$elem.on('mouseover', () => this.resetTimeout());
this.$elem.on('mousemove', () => this.resetTimeout());
$('body').append(this.$elem);
}
hide() {
$('.mrdProfileOverview').remove();
}
resetTimeout() {
if (this.tid)
clearTimeout(this.tid);
this.tid = setTimeout(() => this.hide(), 1000);
}
getClosePos() {
let [x, y] = this.position;
let [w, h] = this.dimensions;
let cw = document.documentElement.clientWidth - 50;
let ch = document.documentElement.clientHeight - 50;
let nx, ny;
if (cw < x + w) nx = x - w;
else nx = x;
if (ch < y + h + 16) ny = y - h - 16;
else ny = y + 16;
return [nx, ny];
}
async fetchProfileData() {
if (this.data[this.id])
if (this.data[this.id].fetchedAt > Date.now() - 60000)
return this.data[this.id];
if (!this.apikey || this.apikey === 'null') this.promptApiKey();
let data = await $.get(`https://api.torn.com/user/${this.id}/?key=${this.apikey}&selections=profile,personalstats`);
data.fetchedAt = Date.now();
return this.data[this.id] = data;
}
promptApiKey() {
this.apikey = localStorage.apikey = prompt("Api Key");
}
formatMoney(money) {
if (!money || isNaN(+("" + money))) return money;
money = money.toString();
let newMoney = "";
while (money.length > 3) {
var part = money.substr(money.length - 3);
newMoney = part + '.' + newMoney;
money = money.substr(0, money.length - 3);
}
newMoney = money + (newMoney ? '.' + newMoney : '');
return newMoney;
}
async template() {
let [x, y] = this.getClosePos();
let [w, h] = this.dimensions;
let id = this.id;
let data = await this.fetchProfileData();
return `<div class="mrdProfileOverview" style="
position: absolute;
padding: 8px;
width: ${w}px;
height: ${h}px;
background: rgb(242, 242, 242);
box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 8px;
border-radius: 3px;
transition: all 0.3s ease-in-out 0s,
visibility 0.3s ease-in-out 0s;
opacity: 1;
visibility: visible;
z-index: 999999;
top: ${y}px;
left: ${x}px;">
<style>
.mrdProfileOverview a {
font-weight: 700;
text-decoration: none;
color: #333;
}
</style>
<div>
<b style="display:block">${data.name} [${id}] (${data.level})</b>
<span>${data.rank}</span>
<hr />
<span>${data.status[0]} ${data.status[1]}</span>
<hr />
<table style="border-spacing: 4px; border-collapse: separate;">
<tbody>
<tr> <td>Xanax</td> <td>${data.personalstats.xantaken || "N/A"}</td></tr>
<tr> <td>Refills</td> <td>${data.personalstats.refills || "N/A"}</td></tr>
<tr> <td>Last Active</td> <td>${data.last_action}</td></tr>
<tr> <td>Defends</td> <td>Won: ${data.personalstats.defendswon || "N/A"} | Lost: ${data.personalstats.defendslost || 0}</td></tr>
<tr> <td>Attacks</td> <td>Won: ${data.personalstats.attackswon || "N/A"} | Lost: ${data.personalstats.attackslost || 0}</td></tr>
<tr> <td>Networth</td> <td>${this.formatMoney(data.personalstats.networth || "N/A")}</td></tr>
</tbody>
</table>
<hr />
<a href="/loader2.php?sid=getInAttack&user2ID=${id}">Attack</a>
<a href="/messages.php#/p=compose&XID=${id}">Message</a>
<a onclick="window.chat.r(${id})">Chat</a>
<a href="/sendcash.php#/XID=${id}">Send Money</a>
<a href="/trade.php#step=start&userID=${id}">Trade</a>
<a href="/bounties.php#/p=add&XID=${id}">Bounty</a>
<a href="/playerreport.php?step=add&userID=${id}">Report</a>
<a href="/friendlist.php#/p=add&XID=${id}">Friend</a>
<a href="/blacklist.php#/p=add&XID=${id}">Enemy</a>
<a href="/personalstats.php?ID=${id}">Stats</a>
</div>
</div>`;
}
};
const overlay = new UserOverlay();
$(document).on('mouseover', 'a[href*="profiles.php?XID="]', e => {
console.log(e.pageX, e.pageY, e.target.href)
var target = e.target;
while(target.tagName !== 'A') {
target = target.parentElement;
}
var href = target.href;
var id = href.match(/.*\?XID=([0-9]+).*/)[1];
var off = $(target).offset();
overlay.setProfile(id);
overlay.placeAt(off.left, off.top);
overlay.show();
})
})();