User:GeneralNotability/spurlookup.js

(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. `;		newHtml += `You have ${apiResponse.getResponseHeader('x-balance-remaining')} queries left this month. `;		newHtml += `  IP: ${responseJson.ip} Suspected VPN/proxy: ${responseJson.anonymous} AS${responseJson.as.number}, belongs to ${responseJson.as.organization} `;		if (responseJson.assignment.exists) { newHtml += ` Assignment: ${responseJson.assignment}\n`; }		if (responseJson.infrastructure) { newHtml += ` Infrastructure: ${responseJson.infrastructure}\n`; }		if (responseJson.devices && responseJson.devices.estimate) { newHtml += ` # 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 );