(async function( $, mw ) {
'use strict';
if ((mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').user && mw.config.get('wgTitle') === 'GeneralNotability/SpurLookup') &&
mw.config.get('wgAction') === 'view') {
await mw.loader.load(['mediawiki.util', 'mediawiki.user']);
const contentdiv = document.getElementById('spur-content');
contentdiv.textContent = ''; // clear children
const noScriptDiv = document.getElementById('spur-noscript');
noScriptDiv.textContent = ''; // nuke the "you don't have the script" warning
const ip = mw.util.getParamValue('address');
if (!ip) {
contentdiv.innerText = 'Address parameter was not specified in the URL';
return;
}
if (!mw.util.isIPAddress(ip)) {
contentdiv.innerText = `${ip} is not a valid IP address`;
return;
}
mw.config.set("wgRelevantUserName", ip);
let apiKey = mw.user.options.get('userjs-spurkey');
if (!apiKey) {
const mwapi = new mw.Api();
apiKey = prompt('Please enter your Spur API key');
if (!apiKey) {
contentdiv.innerText = 'An API key is required to use this tool';
return;
}
mw.user.options.set('userjs-spurkey', apiKey);
await mwapi.saveOption('userjs-spurkey', apiKey);
}
// Actually send the query
const apiUrl = `https://api.spur.us/v1/context/${ip}`;
let apiResponse;
try {
apiResponse = $.ajax({
async: false,
url: apiUrl,
headers: {'Token': apiKey},
dataType: 'json'
});
} catch (err) {
contentdiv.innerText = `Failed to query the Spur API: ${err}`;
return;
}
console.log(apiResponse);
const responseJson = apiResponse.responseJSON;
let newHtml = '';
newHtml += `This search took ${apiResponse.getResponseHeader('x-query-cost')} queries.<p/>`;
newHtml += `You have ${apiResponse.getResponseHeader('x-balance-remaining')} queries left this month.<p/>`;
newHtml += `
<ul>
<li>IP: <a href="${mw.config.get('wgServer')}${mw.config.get('wgArticlePath').replace('$1', 'Special:Contributions/')}${responseJson.ip}">${responseJson.ip}</a></li>
<li>Suspected VPN/proxy: ${responseJson.anonymous}</li>
<li><a href="https://isprangefinder.toolforge.org/hint.php?type=asn&range=${responseJson.as.number}">AS${responseJson.as.number}</a>, belongs to ${responseJson.as.organization}</li>
`;
if (responseJson.assignment.exists) {
newHtml += ` <li>Assignment: ${responseJson.assignment}</li>\n`;
}
if (responseJson.infrastructure) {
newHtml += ` <li>Infrastructure: ${responseJson.infrastructure}</li>\n`;
}
if (responseJson.devices && responseJson.devices.estimate) {
newHtml += ` <li># devices on IP (estimated): ${responseJson.devices.estimate}</li>\n`;
}
if (responseJson.vpnOperators.exists) {
newHtml += ' <li>VPN operators:\n';
newHtml += ' <ul>';
for (const oper of responseJson.vpnOperators.operators) {
newHtml += ` <li>${oper.name}</li>\n`;
}
newHtml += ' </ul>\n </li>\n';
}
if (responseJson.geolite) {
newHtml += ` <li>GeoLite data: ${JSON.stringify(responseJson.geolite)}</li>\n`;
}
if (responseJson.deviceBehaviors.exists) {
newHtml += ' <li>Device behaviors:\n';
newHtml += ' <ul>';
for (const behavior of responseJson.deviceBehaviors.behaviors) {
newHtml += ` <li>${JSON.stringify(behavior.name)}</li>\n`;
}
newHtml += ' </ul>\n </li>\n';
}
if (responseJson.proxiedTraffic.exists) {
newHtml += ' <li>Proxy services:\n';
newHtml += ' <ul>';
for (const proxy of responseJson.proxiedTraffic.proxies) {
newHtml += ` <li>${JSON.stringify(proxy)}</li>\n`;
}
newHtml += ' </ul>\n </li>\n';
}
if (responseJson.geoPrecision.exists) {
newHtml += ` <li>Estimated user location: ${JSON.stringify(responseJson.geoPrecision)}</li>\n`;
}
if (responseJson.similarIPs.exists) {
newHtml += ' <li>Similar IPs:\n';
newHtml += ' <ul>';
for (const ip of responseJson.similarIPs.ips) {
newHtml += ` <li><a href="${mw.config.get('wgServer')}${mw.config.get('wgArticlePath').replace('$1', 'Special:Contributions/')}${ip}">${ip}</a> (<a href="https://en.wikipedia.org/wiki/User:GeneralNotability/SpurLookup?address=${ip}">query</a>)</li>\n`;
}
newHtml += ' </ul>\n </li>\n';
}
if (responseJson.wifi.exists) {
newHtml += ' <li>Associated SSIDs:\n';
newHtml += ' <ul>';
for (const wifi of responseJson.wifi.ssids) {
newHtml += ` <li>${wifi}</li>\n`;
}
newHtml += ' </ul>\n </li>\n';
}
newHtml += '</ul>';
contentdiv.innerHTML = newHtml;
}
}) (jQuery, mediaWiki );