// ==UserScript==
// @name Gota.io Skin Gallery
// @namespace http://tampermonkey.net/
// @version 0.32
// @description Just a simple script that helps you manage your skins.
// @author Amy
// @match https://skins.gota.io/skins
// @icon https://skin-data.gota.io/e6e200b3-5e6d-406f-8ab6-0338f4ba09cf.png
// @resource IMPORTED_CSS https://raw.githubusercontent.com/Aymayy/css-files/main/style.css
// @grant GM_getResourceText
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
const my_css = GM_getResourceText("IMPORTED_CSS");
GM_addStyle(my_css);
const local__storage = window.localStorage;
const defaultSkinSize = 250;
const defaultCols = 5;
const container = document.querySelector('.grid.grid-cols-4.gap-4');
const containerOfContainer = document.querySelector('.px-8.py-3.border-t.border-gray-700');
const nrCols = document.querySelector('.grid.grid-cols-4.gap-4');
const names = container.querySelectorAll('.text-lg.font-bold');
const skins = container.querySelectorAll('.flex.flex-col');
const submit__button = document.querySelector('.button.is-primary');
const computedNames = [];
let gallery__skins = {};
let gallery__skins__data = {};
let searched__gallery__skins = {};
let skinElements = {};
let searchedSkins = {};
let galleryState = false;
let skin__code = '';
//Create and Add and Remove DOM elements
const containerHeader = document.querySelector('.flex.justify-between')
const navbar = document.querySelector('nav');
const removeElement = containerHeader.querySelector('.flex.items-center');
removeElement.remove();
const submit__button__parent = submit__button.parentElement;
submit__button__parent.classList.add('submit__button__parent');
const skinSliderString = `<div class="slider-container" style="display: flex; justify-content: space-between; align-items: center; width: 15rem;"><label>Size</label><input type="range" min="50" max="1000" value="${defaultSkinSize}" class="slider skinSlider" id="myRange"><span class="skinSpan">${defaultSkinSize}</span></div>`;
const columsSliderString = `<div class="slider-container" style="display: flex; justify-content: space-between; align-items: center; width: 15rem;"><label>Cols</label><input type="range" min="1" max="25" value="${defaultCols}" class="slider colSlider" id="myRange"><span class="colSpan">${defaultCols}</span></div>`;
const searchInputString = `<div class="form__group field"><input type="input" class="search__input form__field" autocapitalize="off" spellcheck="false" placeholder="Search" name="name" id='name' required /><label for="name" class="form__label">Search</label></div>`;
const sortButtonString = `<button class="corner-button"><span>Sort</span></button>`;
const galleryString = `<a class="gallery__icon__container flex items-center"><svg class="gallery__icon" height="30pt" viewBox="1 -47 511.999 511" width="30pt" xmlns="http://www.w3.org/2000/svg"><path d="m469.488281 84.417969h-4.390625c-2.570312-22.023438-20.292968-39.484375-42.441406-41.621094-2.542969-23.742187-22.683594-42.296875-47.085938-42.296875h-302.21875c-40.445312 0-73.351562 32.90625-73.351562 73.347656v211.902344c0 24.574219 18.804688 44.828125 42.773438 47.144531 2.515624 23.488281 22.261718 41.886719 46.3125 42.273438.0625 4.167969.714843 8.191406 1.898437 11.988281 5.386719 17.292969 21.550781 29.882812 40.59375 29.882812h337.910156c23.441407 0 42.511719-19.070312 42.511719-42.507812v-247.601562c0-23.441407-19.070312-42.511719-42.511719-42.511719zm22.511719 42.511719v163.738281l-43.5-32.859375c-11.886719-8.976563-27.960938-9.117188-40-.347656l-55.027344 40.09375-104.9375-108.1875c-12.5-12.890626-32.839844-13.683594-46.304687-1.800782l-93.160157 82.191406v-142.828124c0-12.414063 10.097657-22.511719 22.507813-22.511719h337.910156c12.414063 0 22.511719 10.097656 22.511719 22.511719zm0 247.597656c0 12.414062-10.097656 22.511718-22.507812 22.511718h-337.914063c-10.082031 0-18.640625-6.667968-21.492187-15.824218-.660157-2.113282-1.015626-4.359375-1.015626-6.683594v-78.105469l106.394532-93.863281c5.441406-4.804688 13.660156-4.484375 18.714844.726562l47.359374 48.828126c0 .003906 0 .003906.003907.003906l94.261719 97.183594c1.960937 2.023437 4.566406 3.039062 7.179687 3.039062 2.507813 0 5.019531-.9375 6.960937-2.820312 3.960938-3.847657 4.058594-10.175782.214844-14.140626l-22.625-23.328124 52.742188-38.425782c4.867187-3.546875 11.363281-3.492187 16.167968.136719l55.554688 41.964844zm-429.5-46.707032v-236.109374c0-1.003907.050781-2 .152344-2.976563 1.492187-14.675781 13.925781-26.164063 28.988281-26.164063h122.320313c5.523437 0 10-4.476562 10-10 0-5.523437-4.476563-10-10-10h-122.320313c-27.097656 0-49.140625 22.042969-49.140625 49.140626v220.976562c-12.777344-2.300781-22.5-13.503906-22.5-26.9375v-211.902344c0-29.414062 23.933594-53.347656 53.351562-53.347656h302.21875c13.273438 0 24.371094 9.503906 26.84375 22.070312h-108.453124c-5.523438 0-10 4.476563-10 10 0 5.523438 4.476562 10 10 10h118.96875.011718 5.128906c13.195313 0 24.242188 9.394532 26.800782 21.847657h-313.292969c-23.4375 0-42.507813 19.070312-42.507813 42.511719v164.976562.007812 63.253907c-14.722656-.417969-26.570312-12.523438-26.570312-27.347657zm0 0"></path><path d="m388.515625 145.117188c-23.601563 0-42.796875 19.199218-42.796875 42.792968 0 23.597656 19.199219 42.796875 42.796875 42.796875 23.59375 0 42.792969-19.199219 42.792969-42.796875 0-23.59375-19.199219-42.792968-42.792969-42.792968zm0 65.589843c-12.570313 0-22.796875-10.226562-22.796875-22.792969 0-12.570312 10.226562-22.796874 22.796875-22.796874 12.566406 0 22.792969 10.226562 22.792969 22.796874 0 12.566407-10.226563 22.792969-22.792969 22.792969zm0 0"></path><path d="m244.730469 56.398438c.25.601562.558593 1.179687.917969 1.722656.363281.546875.78125 1.058594 1.242187 1.519531.460937.457031.96875.878906 1.519531 1.25.539063.359375 1.128906.667969 1.730469.917969.597656.25 1.230469.441406 1.871094.570312.636719.128906 1.296875.191406 1.949219.191406.660156 0 1.308593-.0625 1.960937-.191406.636719-.128906 1.257813-.320312 1.867187-.570312.601563-.25 1.179688-.558594 1.722657-.917969.546875-.371094 1.058593-.792969 1.519531-1.25.46875-.460937.878906-.972656 1.25-1.519531.359375-.542969.667969-1.121094.917969-1.722656.25-.609376.441406-1.238282.570312-1.867188.128907-.652344.191407-1.3125.191407-1.960938 0-.652343-.0625-1.3125-.191407-1.949218-.128906-.640625-.320312-1.273438-.570312-1.871094-.25-.609375-.558594-1.191406-.917969-1.730469-.371094-.550781-.78125-1.058593-1.25-1.519531-.460938-.460938-.972656-.878906-1.519531-1.242188-.542969-.359374-1.121094-.667968-1.722657-.917968-.609374-.25-1.230468-.441406-1.867187-.570313-1.292969-.261719-2.621094-.261719-3.910156 0-.640625.128907-1.273438.320313-1.871094.570313-.601563.25-1.191406.558594-1.730469.917968-.550781.363282-1.058594.78125-1.519531 1.242188s-.878906.96875-1.242187 1.519531c-.359376.539063-.667969 1.121094-.917969 1.730469-.25.597656-.441407 1.230469-.570313 1.871094-.128906.636718-.199218 1.296875-.199218 1.949218 0 .648438.070312 1.308594.199218 1.960938.128906.628906.320313 1.257812.570313 1.867188zm0 0"></path></svg><h3 class="gallery__label text-lg leading-6 font-medium text-gray-200">Gallery</h3></a>`;
const empty__container__string = `<div class="gallery__container grid grid-cols-4 gap-4"></div>`;
const gallery__navbar__string = `<div class="gallery__navbar__container px-4 py-5 sm:px-6 flex justify-between "></div>`;
const add__skin__button__string = `<div class="add__skin__button__container"><a class="add__skin__button button is-primary">Add Skin By Code</a></div>`;
const skinSlider = document.createRange().createContextualFragment(skinSliderString);
const columnSlider = document.createRange().createContextualFragment(columsSliderString);
const searchInput = document.createRange().createContextualFragment(searchInputString);
const sortButton = document.createRange().createContextualFragment(sortButtonString);
const gallery = document.createRange().createContextualFragment(galleryString);
const slidersContainer = document.createElement('div');
slidersContainer.classList.add('sliders-container');
slidersContainer.style = 'display: flex; justify-content: space-around; align-items: center; width: 40%';
slidersContainer.appendChild(skinSlider);
slidersContainer.appendChild(columnSlider);
containerHeader.insertBefore(slidersContainer, containerHeader.children[0]);
containerHeader.insertBefore(searchInput, containerHeader.children[0]);
containerHeader.insertBefore(sortButton, containerHeader.children[0]);
containerHeader.insertBefore(gallery, containerHeader.children[0]);
//Initialize defaults
(function() {
const slider1 = document.querySelector('.skinSlider');
const slider2 = document.querySelector('.colSlider');
const searchInput = document.querySelector('.search__input');
updateSkins();
slider1.value = defaultSkinSize;
slider2.value = defaultCols;
const grid = document.querySelector('.grid.grid-cols-4.gap-4');
grid.style.gridTemplateColumns = `repeat(${defaultCols},minmax(0,1fr))`;
//Fix/custom some styling
skins.forEach(skin => {
const img = skin.querySelector('img');
img.style.maxWidth = 'none';
img.style.width = `${defaultSkinSize}px`;
skin.style.justifyContent = 'center'
skin.style.alignItems = 'center';
});
})();
//Event Listeners
document.querySelector('.gallery__icon__container').addEventListener('click', function (e) {
galleryState = !galleryState;
if(galleryState) {
const empty__container = document.createRange().createContextualFragment(empty__container__string);
//const gallery__navbar = document.createRange().createContextualFragment(gallery__navbar__string);
const add__skin__button = document.createRange().createContextualFragment(add__skin__button__string);
const gallery__text = document.querySelector('.gallery__label');
gallery__text.innerText = 'My Skins';
container.remove();
//containerOfContainer.parentElement.insertBefore(gallery__navbar, containerOfContainer.parentElement.children[1]);
containerOfContainer.appendChild(empty__container);
submit__button__parent.remove();
containerHeader.appendChild(add__skin__button);
const grid = document.querySelector('.gallery__container');
grid.style.gridTemplateColumns = `repeat(${defaultCols},minmax(0,1fr))`;
//Add skins here
update__gallery();
document.querySelector('.add__skin__button').addEventListener('click', handle__click);
}else {
const gallery__text = document.querySelector('.gallery__label');
gallery__text.innerText = 'Gallery';
document.querySelector('.add__skin__button').removeEventListener("click", handle__click, false);
document.querySelector('.add__skin__button__container').remove();
containerHeader.appendChild(submit__button__parent);
document.querySelector('.gallery__container').remove();
containerOfContainer.appendChild(container);
}
});
document.querySelector('.search__input').addEventListener('input', function (e) {
if(galleryState === false) {
updateSkins();
searchedSkins = {};
for(const element in skinElements) {
if(element.includes(e.srcElement.value)) {
searchedSkins[element] = skinElements[element];
}
}
removeSkins();
insertSkins(container, searchedSkins);
}else {
const gallery__cont = document.querySelector('.gallery__container');
searched__gallery__skins = {};
for(const element in gallery__skins__data) {
if(element.includes(e.srcElement.value)) {
searched__gallery__skins[element] = gallery__skins__data[element];
}
}
removeSkins(true);
insertSkins(gallery__cont, searched__gallery__skins, true);
}
}, false);
document.querySelector('.corner-button').addEventListener('click', function (e) {
const gallery__cont = document.querySelector('.gallery__container');
if(galleryState && !isEmpty(searched__gallery__skins)){
sortSkins(gallery__cont, searched__gallery__skins, true);
//update__gallery();
}else if(galleryState && isEmpty(searched__gallery__skins)){;
sortSkins(gallery__cont, gallery__skins__data, true);
//update__gallery();
}else if(isEmpty(searchedSkins)) {
sortSkins(container, skinElements);
}else {
sortSkins(container, searchedSkins);
}
});
document.querySelector('.skinSlider').addEventListener('input', function (e) {
const span = document.querySelector('.skinSpan');
span.innerText = e.srcElement.value;
if(galleryState === false) {
skins.forEach(skin => {
const img = skin.querySelector('img');
img.style.width = `${e.srcElement.value}px`;
});
}else {
const gallery__skins = document.querySelectorAll('.gallery__skin');
gallery__skins.forEach(skin => {
const img = skin.querySelector('img');
img.style.width = `${e.srcElement.value}px`;
});
}
}, false);
document.querySelector('.colSlider').addEventListener('input', function (e) {
const span = document.querySelector('.colSpan');
span.innerText = e.srcElement.value;
const grid = document.querySelector('.grid.grid-cols-4.gap-4');
grid.style.gridTemplateColumns = `repeat(${e.srcElement.value},minmax(0,1fr))`;
}, false);
//Remove the annoying logo
const containerSize = document.querySelector('.container.flex.flex-col.items-center.justify-center.mx-auto');
containerSize.firstElementChild.remove();
containerSize.firstElementChild.style.width = '100%';
// ⬇------⬇ Functions ⬇------⬇
function sortSkins(cont, elem, gal = false) {
updateSkins(gal);
elem = sortSkinElements(elem);
removeSkins(gal);
insertSkins(cont, elem, gal);
};
//Sort object
function sortSkinElements(elems) {
elems = sortObject(elems);
return elems;
}
//Update skins object
function updateSkins(gal = false) {
if(gal) {
return 0;
}else{
skinElements = {};
for(let i = 0; i < names.length; i++) {
skinElements[names[i].outerText] = skins[i];
}
}
};
//Remove skins from DOM
function removeSkins(gal = false) {
if(gal) {
const gal__container = document.querySelector('.gallery__container');
gal__container.innerHTML = '';
}else {
for(let i = 0; i < names.length; i++) {
skins[i].remove();
}
}
};
//Insert skins in DOM
function insertSkins(cont, elements, gal = false) {
if(gal === false) {
for(const element in elements) {
cont.appendChild(elements[element]);
}
}else {
for(const element in elements) {
const skin__template__string = `<div class="gallery__skin flex flex-col" style="justify-content: center; align-items: center;"><a href="/skins/${elements[element]}"><img class="rounded-full" src="https://skin-data.gota.io/${elements[element]}.png" style="max-width: none; width: 250px;"></a><div class="inline-flex justify-center items-center"><span class="text-lg font-bold">${element}</span></div></div>`;
const skin__template = document.createRange().createContextualFragment(skin__template__string);
cont.appendChild(skin__template);
}
}
}
function sortObject(o) {
var sorted = {},
key, a = [];
for (key in o) {
if (o.hasOwnProperty(key)) {
a.push(key);
}
}
a.sort();
for (key = 0; key < a.length; key++) {
sorted[a[key]] = o[a[key]];
}
return sorted;
}
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop)) {
return false;
}
}
return true;
}
function handle__click(e) {
skin__code = prompt("Enter skin code:\nHere you find how to get code for a skin:\nhttps://github.com/Aymayy/css-files", "");
if(skin__code === null || skin__code === '') {
console.log("Cancelled");
return 0;
}else {
handle__request(skin__code);
}
}
async function handle__request(code) {
const url = `https://skins.gota.io/skins/${code.toString()}`;
let is__valid = false;
is__valid = await fetch(url, {method: "GET"}).then(data => {if(data.status === 200) {return true;}else if(data.status === 400) {return false}} ).catch(err => {return false;})
if(is__valid) {
const requet__string = httpGetAsync(url, getHtml);
} else {
alert("Invalid Skin Code!");
}
}
function httpGetAsync(theUrl, callback) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
callback(xmlHttp.responseText);
}
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
function getHtml(dom){
const DOM = dom.toString();
const request = document.createRange().createContextualFragment(DOM);
const skin__name = request.querySelector('dd.mt-1.text-sm.text-gray-300').innerText;
add__skin__to__gallery({
name: skin__name.trim(),
code: skin__code
})
}
function add__skin__to__gallery(skin) {
if(local__storage.getItem('__skins')) {
gallery__skins__data = JSON.parse(local__storage.getItem('__skins'));
}
if(gallery__skins__data.hasOwnProperty(skin.name)) {
alert('Skin already saved!');
return 0;
}
gallery__skins__data[skin.name] = skin.code;
update__local__storage();
update__gallery();
}
function update__gallery() {
if(local__storage.getItem('__skins')) {
gallery__skins__data = JSON.parse(local__storage.getItem('__skins'));
}
const gal__container = document.querySelector('.gallery__container');
gal__container.innerHTML = '';
for(const skin in gallery__skins__data) {
const skin__template__string = `<div class="gallery__skin flex flex-col" style="justify-content: center; align-items: center;"><a href="/skins/${gallery__skins__data[skin]}"><img class="rounded-full" src="https://skin-data.gota.io/${gallery__skins__data[skin]}.png" style="max-width: none; width: 250px;"></a><div class="inline-flex justify-center items-center"><span class="text-lg font-bold">${skin}</span></div></div>`;
const skin__template = document.createRange().createContextualFragment(skin__template__string);
document.querySelector('.gallery__container').appendChild(skin__template);
}
}
function update__local__storage() {
local__storage.setItem('__skins', JSON.stringify(gallery__skins__data));
}
function get__gallery__skins__DOMElement() {
skins
}
})();