Skip to content

Instantly share code, notes, and snippets.

@Sitethief
Last active June 19, 2022 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sitethief/b3c20fe1da63f58c95fec611a4f7d6a4 to your computer and use it in GitHub Desktop.
Save Sitethief/b3c20fe1da63f58c95fec611a4f7d6a4 to your computer and use it in GitHub Desktop.
Shows if configured owners own the card
// ==UserScript==
// @name NSShowCardOwners
// @namespace sitethiefs-ns-scripts
// @version 0.5.3
// @description Shows if configured owners own the card
// @author Sitethief of Vylixan
// @copyright GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
// @match https://www.nationstates.net/*page=deck/*
// @match https://www.nationstates.net/*page=deck
// @match https://www.nationstates.net/page=deck/*
// @grant GM.xmlHttpRequest
// @grant GM.getValue
// @grant GM.setValue
// @grant GM.deleteValue
// ==/UserScript==
(function () {
'use strict';
/**
* Configuration
*/
const getOwnersOnFocus = false; // Set this to true if you want a button in the topbar to request the owners manually
const placeButton = true; // Set this to true if you want a button in the topbar to request the owners when the page has focus (Won't work once focus
const ProvideAllOwners = false; // Set this to true if you want a to see a list if all owners, warning these lists are long!
const SUCPTInstalled = true; // Set this to true if you have Sitethiefs Ultimate Tweaked Card Deck (SUTCD) installed
const disablePageStyleChanges = false; // Set this to true to dsiable chabnging the page layout
let options = {
containerMethod: 'container', // set this to 'container' if you use the 'containerise (container)' type, and to 'nation' if you use 'containerise (nation)' as type.
stripOldContainer: true, // this removes any existing container parts of the current url, leave true if you're unsure
target: '_blank', // _blank for opening a new page with the card, _self for opening the card in the same page
}
/**
* These are the filter settings for region collectors
* format is as follows:
const filterRegionOwners = {
'region_name': [
'collection_nation_name_1',
'collection_nation_name_2',
'collection_nation_name_3',
'collection_nation_name_4',
],
};
*/
const filterRegionOwners = {
};
/**
* These are the filter settings for other card owners
* format is as follows:
const filterOtherOwners = {
'Giovanniland': 'Wreaths/1984 Orwell/Brazil/Chess',
'Vylixan Aphrodite': 'Flowers',
};
*/
const filterOtherOwners = {
};
/**
* List of your own puppets you migth want to check if it has the card
* format is as follows:
let puppetList = [
'Giovanniland',
'Vylixan Aphrodite',
];
*/
let puppetList = [
];
/**
* End of Configuration
*/
var getOwnersButton;
const container = document.querySelector('div.deckcard-container');
const singlCardPage = window.location.href.includes('card=');
const body = document.getElementById('loggedin');
let ownersContainer = document.getElementById('ownersContainer');
let currentNationKey = '';
if (body) {
currentNationKey = body.dataset.nname;
if (singlCardPage && container) {
const splitPath = new URL(window.location.href)
.pathname.split('/');
const regionAnchor = container.querySelectorAll('div.deckcard > figure.front > div.deckcard-stripe > div.deckcard-region > a');
let filterEntryFound = false;
let regionOwnerList = [];
if (regionAnchor[0]) {
const regionName = regionAnchor[0].getAttribute('href')
.replace('region=', '');
for (let filterRegionOwnerKey in filterRegionOwners) {
if (canonicalize(filterRegionOwnerKey) === regionName) {
regionOwnerList = filterRegionOwners[filterRegionOwnerKey];
filterEntryFound = true;
}
}
}
if (splitPath) {
const cardPart = splitPath.filter(part => part.includes('card='));
const seaonPart = splitPath.filter(part => part.includes('season='));
if (cardPart[0] && seaonPart[0]) {
const cardID = cardPart[0].replace('card=', '');
const cardSeaon = seaonPart[0].replace('season=', '');
let cardElement = document.getElementById("deck-single-card");
cardElement.style.justifyContent = 'space-between';
if (!ownersContainer) {
// Create ownersContainer
ownersContainer = document.createElement("div");
ownersContainer.id = 'ownersContainer';
} else {
// Remove all child elements
ownersContainer.replaceChildren();
}
cardElement.insertBefore(ownersContainer, container)
if (!getOwnersButton && placeButton) {
getOwnersButton = document.createElement("div");
getOwnersButton.setAttribute('class', "bel");
getOwnersButton.innerHTML = "<div class=\"belcontent\"><a href=\"#\" id=\"owners_request_button\" class=\"bellink\"><i class=\"icon-cards\"></i>CARDS</a><div class=\"notificationnumber refreshable\" style=\"background-color:red\">Owners</div></div>";
getOwnersButton.addEventListener(
"click",
async function (event) {
event.preventDefault();
await getOwners(cardID, cardSeaon, currentNationKey);
},
false
);
(document.getElementsByClassName("belspacer belspacermain")[0])
.before(getOwnersButton);
}
if (getOwnersOnFocus) {
document.addEventListener("focus", getOwners(cardID, cardSeaon, currentNationKey), true)
}
}
}
function canonicalize(name) {
return name.trim()
.toLowerCase()
.replace(/ /g, "_");
}
function getOwners(cardID, cardSeaon, nationName) {
// try to find list of owners in storage
// if present and no older the 1 hour, use that
// otherwise reset
// and retrieve new list
// if last storage action is longer then 1 hour ago, clear entire storage
GM.xmlHttpRequest({
headers: {
"User-Agent": nationName,
"Accept": "text/xml",
},
method: "GET",
url: `https://www.nationstates.net/cgi-bin/api.cgi?q=card+info+owners;cardid=${cardID};season=${cardSeaon}`,
onload: function (response) {
let cardElement = document.getElementById("deck-single-card");
let ownersContainer = document.getElementById("ownersContainer");
ownersContainer.style.marginBottom = '-200px';
ownersContainer.style.marginTop = '-150px';
ownersContainer.style.backgroundColor = 'white';
ownersContainer.style.zIndex = '10';
let ownerTitle = document.createElement("h3");
ownerTitle.innerHTML = '<h2>Card owners<h2>';
ownersContainer.appendChild(ownerTitle);
if (!disablePageStyleChanges) {
if (document.querySelector('#editcollectiontable2')) {
document.querySelector('#editcollectiontable2')
.style.marginLeft = '300px';
document.querySelector('#editcollectiontable2')
.style.maxWidth = '1400px';
document.querySelector('#editcollectiontable2')
.style.marginTop = '100px';
}
let minorInfo = document.querySelector('.minorinfo');
if (minorInfo) {
minorInfo.style.marginLeft = '300px';
}
}
//margin-left: 300px;
if (!SUCPTInstalled && !disablePageStyleChanges) {
let tipBox = document.querySelector('.deckcard-tip-box');
if (tipBox) {
tipBox.querySelector('p:first-child')
.remove();
}
if (document.querySelector('#content h1')) {
document.querySelector('#content h1')
.style.textAlign = 'center';
}
if (document.querySelector('.deckcard-season-card-list')) {
document.querySelector('.deckcard-season-card-list')
.style.textAlign = 'center';
}
let minorInfo = document.querySelector('.minorinfo');
if (minorInfo) {
minorInfo.style.float = 'right';
minorInfo.style.marginRight = '485px';
minorInfo.style.marginTop = '-75px';
minorInfo.style.width = '400px';
}
let cardStats = document.querySelector('.deckcard-card-stats');
if (cardStats) {
cardStats.style.width = 'inherit';
document.querySelector('#deck-single-card')
.style.marginBottom = '1500px';
container.parentNode.insertBefore(cardStats, container.nextSibling);
}
if (document.querySelector('.deckcard-info-section')) {
document.querySelector('.deckcard-info-section')
.style.marginLeft = '350px';
document.querySelector('.deckcard-info-section')
.style.maxWidth = '1500px';
document.querySelector('.deckcard-info-section')
.style.marginTop = '100px';
}
if (document.querySelector('.fill-content')) {
document.querySelector('.fill-content')
.style.marginLeft = '350px';
document.querySelector('.fill-content')
.style.maxWidth = '1500px';
document.querySelector('.fill-content')
.style.marginTop = '100px';
}
if (document.querySelector('.auctiongiftbox')) {
document.querySelector('.auctiongiftbox')
.style.marginLeft = '350px';
document.querySelector('.auctiongiftbox')
.style.maxWidth = '1500px';
document.querySelector('.auctiongiftbox')
.style.marginTop = '100px';
}
if (document.querySelector('#deck-single-card')) {
document.querySelector('#deck-single-card')
.style.marginBottom = '-80px';
}
let auctionBox = document.querySelector('#auctiontablebox');
if (auctionBox) {
auctionBox.style.marginTop = '90px';
}
}
let responseXML = new DOMParser()
.parseFromString(response.responseText, "text/xml");
let owners = responseXML.getElementsByTagName("OWNER");
let ownerCardsCount = owners.length;
let notOwned = [];
let ownerStatus = [];
let otherOwnerStatus = [];
let allOwners = [];
for (let key in owners) {
if (owners[key].localName === 'OWNER') {
allOwners[owners[key].innerHTML] = owners[key].innerHTML;
}
}
let ownerCount = 0;
for (let i in allOwners) {
ownerCount++;
}
let ownerCountRow = document.createElement("tr");
ownerCountRow.innerHHTML = `<td>Owners</td><td>${ownerCount}</td>`;
let statsBody = document.querySelector('.deckcard-card-stats tbody');
statsBody.appendChild(ownerCountRow);
for (let ownerKey in regionOwnerList) {
if (typeof allOwners[canonicalize(regionOwnerList[ownerKey])] !== 'undefined') {
ownerStatus[regionOwnerList[ownerKey]] = true;
} else {
ownerStatus[regionOwnerList[ownerKey]] = false;
}
}
for (let otherOwnerKey in filterOtherOwners) {
if (typeof allOwners[canonicalize(otherOwnerKey)] !== 'undefined') {
otherOwnerStatus[otherOwnerKey] = true;
} else {
otherOwnerStatus[otherOwnerKey] = false;
}
}
let puppetsFound = [];
for (let puppetOwnerKey in puppetList) {
if (typeof allOwners[canonicalize(puppetList[puppetOwnerKey])] !== 'undefined') {
puppetsFound[puppetList[puppetOwnerKey]] = puppetList[puppetOwnerKey];
}
}
//let cardCountSpan = document.createElement("span");
//cardCountSpan.innerHTML = 'Card count: ' + ownerCardsCount + '</br>';
//ownersContainer.appendChild(cardCountSpan);
//let ownerCountSpan = document.createElement("span");
//ownerCountSpan.innerHTML = 'Owner count: ' + ownerCount;
//ownersContainer.appendChild(ownerCountSpan);
// Make puppets block
if (Object.keys(puppetsFound)
.length > 0) {
let location = window.location.href;
let otherTitle = document.createElement("span");
otherTitle.innerHTML = '<h3>Own puppets</h2>';
otherTitle.style.display = 'block';
otherTitle.style.fontWeight = 'bold';
otherTitle.style.display = 'block';
otherTitle.style.margin = '5px 0 5px 0';
ownersContainer.appendChild(otherTitle);
for (let puppetStatusKey in puppetsFound) {
let cannonName = canonicalize(puppetStatusKey);
let ownerName = puppetStatusKey.replaceAll('_', ' ');
let colour = 'green';
let ownerSpan = document.createElement("span");
ownerSpan.style.color = colour;
ownerSpan.style.display = 'block';
ownerSpan.style.margin = '5px 0 0 0';
let quickmenuLink = document.createElement("a");
let newLocation = location;
// strip old container references
if (options.stripOldContainer === true) {
newLocation = newLocation.replace(options.containerMethod + '=' + currentNationKey + '/', '');
}
// Create link
newLocation = newLocation + '/' + options.containerMethod + '=' + cannonName + '/';
// Prevent double //, this is ugly
newLocation = newLocation.replace('//container', '/container');
quickmenuLink.href = newLocation;
quickmenuLink.style.display = 'block';
quickmenuLink.style.margin = '5px 0 0';
quickmenuLink.innerHTML = ownerName;
quickmenuLink.target = options.target;
ownerSpan.appendChild(quickmenuLink);
ownersContainer.appendChild(ownerSpan);
}
}
// Make Region Block
if (filterEntryFound && Object.keys(ownerStatus)
.length > 0) {
let regionTitle = document.createElement("span");
regionTitle.innerHTML = '<h3>Region Collectors</h2>';
regionTitle.style.display = 'block';
regionTitle.style.fontWeight = 'bold';
regionTitle.style.margin = '5px 0 5px 0';
ownersContainer.appendChild(regionTitle);
for (let ownerStatusKey in ownerStatus) {
let ownerName = ownerStatusKey.replaceAll('_', ' ');
let colour = 'green';
if (ownerStatus[ownerStatusKey] === false) {
ownerName += ' (Not owned)';
colour = 'red';
} else {
ownerName += ' (Owned)';
}
let ownerSpan = document.createElement("span");
ownerSpan.style.color = colour;
ownerSpan.innerHTML = ownerName;
ownerSpan.style.display = 'block';
ownerSpan.style.margin = '5px 0 0 0';
ownersContainer.appendChild(ownerSpan);
}
}
// Make other block
if (Object.keys(otherOwnerStatus)
.length > 0) {
let otherOwnerStatusFound = [];
let otherOwnerStatusNotFound = [];
for (let otherOwnerStatusKey in otherOwnerStatus) {
if (otherOwnerStatus[otherOwnerStatusKey] === false) {
otherOwnerStatusNotFound[otherOwnerStatusKey] = otherOwnerStatus[otherOwnerStatusKey];
} else {
otherOwnerStatusFound[otherOwnerStatusKey] = otherOwnerStatus[otherOwnerStatusKey];
}
}
let otherTitle = document.createElement("span");
otherTitle.innerHTML = '<h3>Other Collectors</h2>';
otherTitle.style.display = 'block';
otherTitle.style.fontWeight = 'bold';
otherTitle.style.display = 'block';
otherTitle.style.margin = '5px 0 5px 0';
ownersContainer.appendChild(otherTitle);
for (let otherOwnerStatusFoundKey in otherOwnerStatusFound) {
let ownerName = otherOwnerStatusFoundKey.replaceAll('_', ' ');
let colour = 'green';
ownerName += ` (${filterOtherOwners[otherOwnerStatusFoundKey]})`;
let ownerSpan = document.createElement("span");
ownerSpan.style.color = colour;
ownerSpan.innerHTML = ownerName;
ownerSpan.style.display = 'block';
ownerSpan.style.margin = '5px 0 0 0';
ownersContainer.appendChild(ownerSpan);
}
for (let otherOwnerStatusNotFoundKey in otherOwnerStatusNotFound) {
let ownerName = otherOwnerStatusNotFoundKey.replaceAll('_', ' ');
let colour = 'red';
ownerName += ` (${filterOtherOwners[otherOwnerStatusNotFoundKey]})`;
let ownerSpan = document.createElement("span");
ownerSpan.style.color = colour;
ownerSpan.innerHTML = ownerName;
ownerSpan.style.display = 'block';
ownerSpan.style.margin = '5px 0 0 0';
ownersContainer.appendChild(ownerSpan);
}
}
if (ProvideAllOwners && Object.keys(allOwners)
.length > 0) {
let allTitle = document.createElement("span");
allTitle.innerHTML = '<h3>All Owners</h2>';
allTitle.style.display = 'block';
allTitle.style.fontWeight = 'bold';
allTitle.style.display = 'block';
allTitle.style.margin = '5px 0 5px 0';
ownersContainer.appendChild(allTitle);
let allContainer = document.createElement("div");
allContainer.style.maxHeight = '200px';
allContainer.style.overflow = 'scroll';
for (let allOwnersKey in allOwners) {
let ownerSpan = document.createElement("span");
ownerSpan.innerHTML = allOwnersKey;
ownerSpan.style.display = 'block';
ownerSpan.style.margin = '5px 0 0 0';
allContainer.appendChild(ownerSpan);
}
ownersContainer.appendChild(allContainer);
}
}
});
}
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment