// ==UserScript==
// @name Bundle Stars Keys Retrieve
// @namespace http://tampermonkey.net/
// @version 1.2.0
// @description Retrieve keys from Bundle Stars
// @icon https://cdn.bundlestars.com/production/brand/apple-touch-icon-180x180.png
// @author Bisumaruko
// @include http*://*bundlestars.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
var $ = selector => document.querySelector(selector),
$$ = selector => Array.from(document.querySelectorAll(selector));
function getAnchor() {
var anchor = $('h2');
return anchor && anchor.textContent.trim() === 'Order Keys' ? anchor : null;
}
function setup() {
var anchor = getAnchor();
if (!anchor) return;
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = `
.BSRetrive {
width: 100%;
height: 200px;
display: flex;
flex-direction: column;
box-sizing: border-box;
border: 1px solid #424242;
color: #999999;
}
.BSRetrive > textarea {
width: 100%;
height: 150px;
border: none;
background-color: #303030;
color: #DDD;
box-sizing: border-box;
resize: none;
}
.BSRetrive > div {
width: 100%;
padding-top: 5px;
box-sizing: border-box;
}
.BSRetrive > div > button, .BSRetrive select {
height: 34px;
margin-right: 10px;
padding: 6px 12px;
border: 1px solid transparent;
background-color: #262626;
color: #dedede;
box-sizing: border-box;
outline: none;
cursor: pointer;
}
.BSRetrive > div > button:hover, .BSRetrive select:hover {
color: #A8A8A8;
}
.BSRetrive > div > label {
margin-right: 10px;
color: #dedede;
}
.BSRetrive select, .BSRetrive span {
margin-right: 0;
margin-left: 10px;
float: right;
}
.BSRetrive span {
margin-top: 5px;
}
`;
document.head.appendChild(style);
var qsAll = function (selector) {
let doms = [],
from = parseInt(BSSelectFrom.value),
to = parseInt(BSSelectTo.value);
if (isNaN(from) || isNaN(to)) {
msg.alert('An error occured, please refresh the page');
return null;
}
if (from === 0 && to > 0) from = 1;
if (from > 0 && to === 0) to = pool.length - 1;
for (var index = Math.min(from, to); index <= Math.max(from, to); index++) {
let node = pool[index],
_doms = !node || Array.from(node.querySelectorAll(selector));
if (_doms) doms = doms.concat(_doms);
}
return doms;
};
var BSRetrive = document.createElement('div'),
BSTextarea = document.createElement('textarea'),
BSDiv = document.createElement('div'),
BSBtnReveal = document.createElement('button'),
BSBtnRetrieve = document.createElement('button'),
BSBtnCopy = document.createElement('button'),
BSBtnReset = document.createElement('button'),
BSCheckTitle = document.createElement('label'),
BSCheckJoin = document.createElement('label'),
BSSelectFrom = document.createElement('select'),
BSSelectTo;
BSRetrive.className = 'BSRetrive';
BSBtnReveal.textContent = 'Reveal';
BSBtnRetrieve.textContent = 'Retrieve';
BSBtnCopy.textContent = 'Copy';
BSBtnReset.textContent = 'Reset';
BSCheckTitle.innerHTML = '<input type="checkbox" class="BSCheckTitle">Include Game Title';
BSCheckJoin.innerHTML = '<input type="checkbox" class="BSCheckJoin">Join Keys';
BSBtnReveal.addEventListener('click', () => {
let keys = qsAll('.key-container a[ng-click^="redeemSerial"]');
if (!keys) {
msg.alert('Empty search, please select the correct options');
return;
}
for (let key of keys) {
if (!key.closest('.ng-hide')) key.click();
}
});
BSBtnRetrieve.addEventListener('click', () => {
let keys = [],
containers = qsAll('.key-container'),
separator = $('.BSCheckJoin').checked ? ',' : "\n";
if (!containers) {
msg.alert('Empty search, please select the correct options');
return;
}
for (let container of containers) {
let key = container.querySelector('input'),
title = container.previousElementSibling;
if (!key) continue;
key = key.value.trim();
if (title && $('.BSCheckTitle').checked) key = title.textContent.trim() + ', ' + key;
keys.push(key);
}
BSTextarea.textContent = keys.join(separator);
});
BSBtnCopy.addEventListener('click', () => {
BSTextarea.select();
document.execCommand('copy');
});
BSBtnReset.addEventListener('click', () => {
BSTextarea.textContent = '';
});
let pool = [document];
setTimeout(() => {
let blocks = $$('hr ~ div > div:not(.ng-hide)');
BSSelectFrom.appendChild(new Option('All', 0));
for (let block of blocks) {
let option,
bundle = block.querySelector('h3'),
tiers = Array.from(block.querySelectorAll('h4'));
if (tiers.length > 1) { //bundles (multiple tiers)
let title = bundle.textContent;
for (let tier of tiers) {
option = new Option(title + ' ' + tier.textContent, pool.push(tier.parentNode) - 1);
BSSelectFrom.appendChild(option);
}
} else if (bundle) { //bundles (single tier)
option = new Option(bundle.textContent, pool.push(bundle.nextElementSibling ) - 1);
BSSelectFrom.appendChild(option);
} else { //individual games
option = new Option(block.querySelector('.title').textContent, pool.push(block) - 1);
BSSelectFrom.appendChild(option);
}
}
BSSelectTo = BSSelectFrom.cloneNode(true);
let span = document.createElement('span');
span.textContent = 'to';
BSDiv.appendChild(BSSelectTo);
BSDiv.appendChild(span);
BSDiv.appendChild(BSSelectFrom);
}, 1000);
BSDiv.appendChild(BSBtnReveal);
BSDiv.appendChild(BSBtnRetrieve);
BSDiv.appendChild(BSBtnCopy);
BSDiv.appendChild(BSBtnReset);
BSDiv.appendChild(BSCheckTitle);
BSDiv.appendChild(BSCheckJoin);
BSRetrive.appendChild(BSTextarea);
BSRetrive.appendChild(BSDiv);
anchor.parentNode.insertBefore(BSRetrive, anchor);
}
function observeOrderDetails(target) {
new MutationObserver(mutations => {
for (let mutation of mutations) {
if (!mutation.addedNodes.length) continue;
if (mutation.addedNodes[0].classList.contains('ng-scope')) setup();
}
}).observe(target, {childList: true});
}
var anchor = getAnchor();
if (anchor) {
setup();
observeOrderDetails(anchor.closest('body > div.ng-scope'));
} else {
var bodyObserver = new MutationObserver(mutations => {
for (let mutation of mutations) {
if (!mutation.addedNodes.length) continue;
if (mutation.addedNodes[0].classList.contains('ng-scope')) {
observeOrderDetails(mutation.addedNodes[0]);
bodyObserver.disconnect();
}
}
});
bodyObserver.observe(document.body, {childList: true});
}
var msg = {
box: null,
init() {
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = `
.BSRetrive_msg {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 10px 20px;
border: 1px solid #424242;
background-color: rgb(32, 32, 32);
color: #FFF;
font-size: larger;
}
.BSRetrive_msg-show {
display: block;
}
`;
document.head.appendChild(style);
var BSRetrive_msg = document.createElement('div');
BSRetrive_msg.classList.add('BSRetrive_msg');
document.body.appendChild(BSRetrive_msg);
this.box = BSRetrive_msg;
},
alert(text) {
this.box.textContent = text;
this.box.classList.add('BSRetrive_msg-show');
setTimeout(this.hide.bind(this), 3000);
},
hide() {
this.box.classList.remove('BSRetrive_msg-show');
}
};
msg.init();
})();