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(); }) })();