546 lines
16 KiB
JavaScript
546 lines
16 KiB
JavaScript
let currentMenu = $(".homepage");
|
|
|
|
$(".column button .card").on("click", function () {
|
|
let nextMenu = this.getAttribute("data");
|
|
|
|
if (nextMenu === "proxy") {
|
|
if (!config["proxy"]) {
|
|
$("#disabled").showModal();
|
|
return;
|
|
}
|
|
$("#everything-else").fadeOut(300, () => {
|
|
$("#page-loader").fadeIn(200);
|
|
$("#page-loader iframe").attr("src", config["proxyPath"] || "/proxy");
|
|
$("#page-loader iframe")[0].focus();
|
|
});
|
|
currentMenu = $("#page-loader");
|
|
inGame = true;
|
|
return;
|
|
}
|
|
|
|
currentMenu.fadeOut(300, () => {
|
|
$("." + nextMenu).fadeIn(200);
|
|
});
|
|
currentMenu = $("." + nextMenu);
|
|
});
|
|
|
|
$("logo img").on("click", returnHome);
|
|
$("#gameButton").on("click", returnHome);
|
|
$("#refresh").on("click", refreshPage);
|
|
|
|
$("dialog").on("click", function (e) {
|
|
if (!e.originalEvent.target.closest("div")) {
|
|
e.originalEvent.target.close();
|
|
}
|
|
});
|
|
|
|
// Function to calculate the
|
|
// Jaro Similarity of two strings
|
|
// from https://www.geeksforgeeks.org/jaro-and-jaro-winkler-similarity/
|
|
function jaro_distance(s1, s2) {
|
|
// If the strings are equal
|
|
if (s1 == s2)
|
|
return 1.0;
|
|
|
|
// Length of two strings
|
|
let len1 = s1.length, len2 = s2.length;
|
|
|
|
if (len1 == 0 || len2 == 0)
|
|
return 0.0;
|
|
|
|
// Maximum distance upto which matching
|
|
// is allowed
|
|
let max_dist = Math.floor(Math.max(len1, len2) / 2) - 1;
|
|
|
|
// Count of matches
|
|
let match = 0;
|
|
|
|
// Hash for matches
|
|
let hash_s1 = new Array(s1.length);
|
|
hash_s1.fill(0);
|
|
let hash_s2 = new Array(s2.length);
|
|
hash_s2.fill(0);
|
|
|
|
// Traverse through the first string
|
|
for (let i = 0; i < len1; i++) {
|
|
|
|
// Check if there is any matches
|
|
for (let j = Math.max(0, i - max_dist);
|
|
j < Math.min(len2, i + max_dist + 1); j++)
|
|
|
|
// If there is a match
|
|
if (s1[i] == s2[j] &&
|
|
hash_s2[j] == 0) {
|
|
hash_s1[i] = 1;
|
|
hash_s2[j] = 1;
|
|
match++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If there is no match
|
|
if (match == 0)
|
|
return 0.0;
|
|
|
|
// Number of transpositions
|
|
let t = 0;
|
|
|
|
let point = 0;
|
|
|
|
// Count number of occurrences
|
|
// where two characters match but
|
|
// there is a third matched character
|
|
// in between the indices
|
|
for (let i = 0; i < len1; i++)
|
|
if (hash_s1[i] == 1) {
|
|
|
|
// Find the next matched character
|
|
// in second string
|
|
while (hash_s2[point] == 0)
|
|
point++;
|
|
|
|
if (s1[i] != s2[point++])
|
|
t++;
|
|
}
|
|
t /= 2;
|
|
|
|
// Return the Jaro Similarity
|
|
return ((match) / (len1)
|
|
+ (match) / (len2)
|
|
+ (match - t) / (match))
|
|
/ 3.0;
|
|
}
|
|
|
|
// Jaro Winkler Similarity
|
|
function jaroWinklerSimilarity(s1, s2) {
|
|
let jaro_dist = jaro_distance(s1, s2);
|
|
|
|
// If the jaro Similarity is above a threshold
|
|
if (jaro_dist > 0.7) {
|
|
|
|
// Find the length of common prefix
|
|
let prefix = 0;
|
|
|
|
for (let i = 0; i < Math.min(s1.length, s2.length); i++) {
|
|
|
|
// If the characters match
|
|
if (s1[i] == s2[i])
|
|
prefix++;
|
|
|
|
// Else break
|
|
else
|
|
break;
|
|
}
|
|
|
|
// Maximum of 4 characters are allowed in prefix
|
|
prefix = Math.min(4, prefix);
|
|
|
|
// Calculate jaro winkler Similarity
|
|
jaro_dist += 0.1 * prefix * (1 - jaro_dist);
|
|
}
|
|
return jaro_dist.toFixed(6);
|
|
}
|
|
|
|
/**
|
|
* Updates the list of games based on the current search filter and sort type.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
function updateList() {
|
|
const filter = $("#search").val().toLowerCase();
|
|
const elems = Array.from(document.querySelectorAll("#gamesList li"));
|
|
const sortType = $("#sort").val();
|
|
|
|
// sort by selected sort type
|
|
elems.sort(function (a, b) {
|
|
if (sortType === 'alphabetical') {
|
|
return a.textContent.localeCompare(b.textContent);
|
|
} else if (sortType === 'reverse') {
|
|
return b.textContent.localeCompare(a.textContent);
|
|
}
|
|
});
|
|
|
|
// then filter items with the search input
|
|
elems.forEach(function (item) {
|
|
let similarity = jaroWinklerSimilarity(filter, item.innerHTML.toLowerCase().slice(0, filter.length - 1));
|
|
if (item.getAttribute("aliases")) {
|
|
for (alias in item.getAttribute("aliases").split(',')) {
|
|
if (alias.length > 1) {
|
|
console.log("alias");
|
|
console.log(alias);
|
|
console.log(typeof alias);
|
|
console.log(alias.length);
|
|
similarity += jaroWinklerSimilarity(filter, alias.toLowerCase().slice(0, filter.length - 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (similarity >= 0.7 && item.innerHTML.length > 2 || item.innerHTML.toLowerCase().indexOf(filter) > -1) {
|
|
item.style.display = "";
|
|
} else {
|
|
item.style.display = "none";
|
|
}
|
|
});
|
|
|
|
// now sort by jaro winkler distance
|
|
elems.sort(function (a, b) {
|
|
let distanceA = jaroWinklerSimilarity(filter, a.textContent.toLowerCase());
|
|
if (a.getAttribute("aliases")) {
|
|
for (alias in a.getAttribute("aliases").split(',')) {
|
|
distanceA += jaroWinklerSimilarity(filter, alias.toLowerCase());
|
|
}
|
|
}
|
|
|
|
let distanceB = jaroWinklerSimilarity(filter, b.textContent.toLowerCase());
|
|
if (b.getAttribute("aliases")) {
|
|
for (alias in b.getAttribute("aliases").split(',')) {
|
|
distanceB += jaroWinklerSimilarity(filter, alias.toLowerCase());
|
|
}
|
|
}
|
|
return distanceA - distanceB;
|
|
});
|
|
|
|
// then fill it with the sorted and filtered list
|
|
for (const item of elems) {
|
|
document.getElementById("gamesList").appendChild(item);
|
|
}
|
|
}
|
|
$("#search").on("input", updateList);
|
|
$("#sort").on("change", updateList);
|
|
|
|
dragElement(document.getElementById("gameButton"));
|
|
dragElement(document.getElementById("refresh"));
|
|
|
|
function toggleStar(event, star) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
star.classList.toggle('filled');
|
|
}
|
|
|
|
/**
|
|
* Adds drag functionality to an HTML element.
|
|
*
|
|
* @param {HTMLElement} elmnt - The element to be dragged.
|
|
* @return {void}
|
|
*/
|
|
function dragElement(elmnt) {
|
|
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
|
|
if (document.getElementById(elmnt.id)) {
|
|
document.getElementById(elmnt.id).onmousedown = dragMouseDown;
|
|
} else {
|
|
elmnt.onmousedown = dragMouseDown;
|
|
}
|
|
|
|
function dragMouseDown(e) {
|
|
e = e || window.event;
|
|
e.preventDefault();
|
|
pos3 = e.clientX;
|
|
pos4 = e.clientY;
|
|
document.onmouseup = closeDragElement;
|
|
document.onmousemove = elementDrag;
|
|
}
|
|
|
|
function elementDrag(e) {
|
|
e = e || window.event;
|
|
e.preventDefault();
|
|
|
|
pos1 = pos3 - e.clientX;
|
|
pos2 = pos4 - e.clientY;
|
|
pos3 = e.clientX;
|
|
pos4 = e.clientY;
|
|
window.click = 1;
|
|
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
|
|
|
|
}
|
|
|
|
function closeDragElement() {
|
|
|
|
document.onmouseup = null;
|
|
document.onmousemove = null;
|
|
|
|
if (window.click == 1) {
|
|
window.hold = true;
|
|
window.click = 0;
|
|
}
|
|
setTimeout(function () { window.hold = false; }, 100);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the user to the home page.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
function returnHome() {
|
|
currentMenu.fadeOut(300, () => {
|
|
$("#everything-else").fadeIn(200);
|
|
$(".games").hide();
|
|
$(".homepage").fadeIn(200);
|
|
});
|
|
currentMenu = $(".homepage");
|
|
inGame = false;
|
|
console.log("e");
|
|
}
|
|
|
|
/**
|
|
* Refreshes the current page by reloading it.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
function refreshPage() {
|
|
const oldUrl = $("#page-loader iframe").attr("src");
|
|
console.log(oldUrl);
|
|
$("#page-loader iframe").attr("src", "");
|
|
|
|
// delay is needed for some reason
|
|
setTimeout(() => {
|
|
$("#page-loader iframe").attr("src", oldUrl);
|
|
}, 10);
|
|
}
|
|
|
|
/**
|
|
* Generates a clone of the current window in an about:blank.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
function makecloak(replaceUrl = preferences.cloakUrl) {
|
|
if ((window.top.location.href !== "about:blank")) {
|
|
var url = window.location.href;
|
|
const win = window.open();
|
|
if (!win || win.closed || typeof win.closed == 'undefined') {
|
|
return;
|
|
}
|
|
win.document.body.style.margin = "0";
|
|
win.document.body.style.height = "100vh";
|
|
var iframe = win.document.createElement("iframe");
|
|
iframe.style.border = "none";
|
|
iframe.style.width = "100%";
|
|
iframe.style.height = "100%";
|
|
iframe.style.margin = "0";
|
|
iframe.referrerpolicy = "no-referrer";
|
|
iframe.allow = "fullscreen";
|
|
iframe.src = url.toString();
|
|
win.document.body.appendChild(iframe);
|
|
window.location.replace(replaceUrl);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Changes the browser tab's title and favicon
|
|
*
|
|
* @return {void}
|
|
*/
|
|
function mask(title = preferences.maskTitle, iconUrl = preferences.maskIconUrl) {
|
|
const e = window.top.document;
|
|
e.title = title;
|
|
var link = e.querySelector("link[rel*='icon']") || document.createElement('link');
|
|
link.type = 'image/x-icon';
|
|
link.rel = 'shortcut icon';
|
|
link.href = iconUrl;
|
|
e.getElementsByTagName('head')[0].appendChild(link);
|
|
}
|
|
|
|
function popupsAllowed() {
|
|
var windowName = 'userConsole';
|
|
var popUp = window.open('/popup-page.php', windowName, 'width=1000, height=700, left=24, top=24, scrollbars, resizable');
|
|
if (popUp == null || typeof (popUp) == 'undefined') {
|
|
return false;
|
|
}
|
|
else {
|
|
popUp.close();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function getMainSave() {
|
|
var mainSave = {};
|
|
|
|
localStorageSave = Object.entries(localStorage);
|
|
|
|
localStorageSave = btoa(JSON.stringify(localStorageSave));
|
|
|
|
mainSave.localStorage = localStorageSave;
|
|
|
|
cookiesSave = document.cookie;
|
|
|
|
cookiesSave = btoa(cookiesSave);
|
|
|
|
mainSave.cookies = cookiesSave;
|
|
|
|
mainSave = btoa(JSON.stringify(mainSave));
|
|
|
|
mainSave = CryptoJS.AES.encrypt(mainSave, "save").toString();
|
|
|
|
return mainSave;
|
|
}
|
|
|
|
function downloadMainSave() {
|
|
var data = new Blob([getMainSave()]);
|
|
var dataURL = URL.createObjectURL(data);
|
|
|
|
var fakeElement = document.createElement("a");
|
|
fakeElement.href = dataURL;
|
|
fakeElement.download = "monkey.data";
|
|
fakeElement.click();
|
|
URL.revokeObjectURL(dataURL);
|
|
}
|
|
|
|
function getMainSaveFromUpload(data) {
|
|
data = CryptoJS.AES.decrypt(data, "save").toString(CryptoJS.enc.Utf8);
|
|
|
|
var mainSave = JSON.parse(atob(data));
|
|
var mainLocalStorageSave = JSON.parse(atob(mainSave.localStorage));
|
|
var cookiesSave = atob(mainSave.cookies);
|
|
|
|
for (let item in mainLocalStorageSave) {
|
|
localStorage.setItem(mainLocalStorageSave[item][0], mainLocalStorageSave[item][1]);
|
|
}
|
|
|
|
document.cookie = cookiesSave;
|
|
}
|
|
|
|
function uploadMainSave() {
|
|
var hiddenUpload = document.createElement("input");
|
|
hiddenUpload.type = "file";
|
|
hiddenUpload.accept = ".data";
|
|
document.body.appendChild(hiddenUpload);
|
|
hiddenUpload.click();
|
|
|
|
hiddenUpload.addEventListener("change", function (e) {
|
|
var files = e.target.files;
|
|
var file = files[0];
|
|
|
|
if (!file) {
|
|
return;
|
|
}
|
|
|
|
var reader = new FileReader();
|
|
|
|
reader.onload = function (e) {
|
|
getMainSaveFromUpload(e.target.result);
|
|
|
|
var uploadResult = document.querySelector(".upload-result");
|
|
uploadResult.innerText = "Uploaded save!";
|
|
setTimeout(function () {
|
|
uploadResult.innerText = "";
|
|
}, 3000);
|
|
};
|
|
|
|
reader.readAsText(file);
|
|
|
|
document.body.removeChild(hiddenUpload);
|
|
});
|
|
}
|
|
|
|
const keySlots = document.querySelectorAll('.keySlot');
|
|
|
|
keySlots.forEach((slot) => {
|
|
slot.addEventListener('click', () => {
|
|
slot.textContent = 'Press any key';
|
|
|
|
// Add a one-time event listener to capture the key press
|
|
const keyPressHandler = (event) => {
|
|
slot.textContent = event.key;
|
|
document.removeEventListener('keydown', keyPressHandler);
|
|
};
|
|
|
|
document.addEventListener('keydown', keyPressHandler);
|
|
});
|
|
});
|
|
|
|
const preferencesDefaults = {
|
|
cloak: true,
|
|
cloakUrl: "https://classroom.google.com",
|
|
mask: true,
|
|
maskTitle: "Home",
|
|
maskIconUrl: "https://ssl.gstatic.com/classroom/ic_product_classroom_32.png"
|
|
};
|
|
|
|
|
|
if (localStorage.getItem("preferences") == null) {
|
|
localStorage.setItem("preferences", JSON.stringify(preferencesDefaults));
|
|
}
|
|
const preferences = JSON.parse(localStorage.getItem("preferences"));
|
|
const cloakCheckbox = document.getElementById('cloakCheckboxInput');
|
|
const cloakUrl = document.getElementById('cloakUrlInput');
|
|
const maskCheckbox = document.getElementById('maskCheckboxInput');
|
|
const maskTitle = document.getElementById('maskTitleInput');
|
|
const maskIcon = document.getElementById('maskIconInput');
|
|
cloakCheckbox.checked = preferences.cloak;
|
|
cloakUrl.value = preferences.cloakUrl;
|
|
maskCheckbox.checked = preferences.mask;
|
|
maskTitle.value = preferences.maskTitle;
|
|
maskIcon.value = preferences.maskIconUrl;
|
|
|
|
if (preferences.cloak && (window.location.href == window.top.location.href)) {
|
|
if (popupsAllowed()) {
|
|
makecloak();
|
|
}
|
|
else {
|
|
currentMenu.fadeOut(300, () => {
|
|
$(".cloaklaunch").fadeIn(200);
|
|
});
|
|
currentMenu = $(".cloaklaunch");
|
|
document.addEventListener("click", (event) => { event.preventDefault(); makecloak(); });
|
|
}
|
|
}
|
|
|
|
maskCheckbox.addEventListener('change', function () {
|
|
preferences.mask = maskCheckbox.checked;
|
|
localStorage.setItem('preferences', JSON.stringify(preferences));
|
|
});
|
|
|
|
cloakCheckbox.addEventListener('change', function () {
|
|
preferences.cloak = cloakCheckbox.checked;
|
|
localStorage.setItem('preferences', JSON.stringify(preferences));
|
|
});
|
|
|
|
|
|
/* if it is wanted to save on input change wather than submission
|
|
document.querySelector('.text-field').addEventListener('change', function () {
|
|
preferences.maskTitle = maskTitle.value;
|
|
localStorage.setItem('preferences', JSON.stringify(preferences));
|
|
});
|
|
*/
|
|
|
|
document.getElementById('cloakUrlSubmit').addEventListener('click', function () {
|
|
preferences.cloakUrl = cloakUrl.value;
|
|
localStorage.setItem('preferences', JSON.stringify(preferences));
|
|
alert("Submitted! Change will take place upon refresh");
|
|
});
|
|
|
|
document.getElementById('maskTitleSubmit').addEventListener('click', function () {
|
|
preferences.maskTitle = maskTitle.value;
|
|
localStorage.setItem('preferences', JSON.stringify(preferences));
|
|
alert("Submitted! Change will take place upon refresh");
|
|
});
|
|
|
|
document.getElementById('maskIconSubmit').addEventListener('click', function () {
|
|
preferences.maskIconUrl = maskIcon.value;
|
|
localStorage.setItem('preferences', JSON.stringify(preferences));
|
|
alert("Submitted! Change will take place upon refresh");
|
|
});
|
|
|
|
document.getElementById('download').addEventListener('click', function () {
|
|
downloadMainSave();
|
|
});
|
|
|
|
document.getElementById('upload').addEventListener('click', function () {
|
|
uploadMainSave();
|
|
})
|
|
|
|
/* if (preferences.cloak && !localStorage.getItem("cloakTabOpened")){
|
|
if (window.top.location.href !== "about:blank"){
|
|
localStorage.setItem("cloakTabOpened", "true");
|
|
document.addEventListener("click", (event) => {event.preventDefault(); makecloak()});
|
|
}
|
|
makecloak();
|
|
|
|
window.addEventListener("beforeunload", () => {
|
|
localStorage.removeItem("cloakTabOpened");
|
|
});
|
|
} */
|
|
|
|
if (preferences.mask) {
|
|
mask();
|
|
} |