new great divide feature and avatar dimension toggle feature

- new great divide event feature

- event place cards now have a animated gradient instead of a still gradient

- you can now extract textures from an official polytoria item easily in the extension popup (temporarily disabled)

- new avatar dimension toggle feature

- fixed library-download.js errors due to it trying to run on official polytoria item pages
This commit is contained in:
Index 2024-06-18 00:07:21 -05:00
parent 35bc026724
commit b3cfe05657
16 changed files with 653 additions and 232 deletions

176
css/settings.css Normal file
View file

@ -0,0 +1,176 @@
html,
body,
#page {
background: #202020;
color: #fff;
}
#page {
margin-top: 7.5rem;
width: 65%;
margin-right: auto;
margin-left: auto;
margin-bottom: 3.5rem;
}
h1 {
font-size: 4.6rem;
/*color: rgb(48, 48, 48);*/
}
h1 span.indent {
border-left: 10px solid rgb(48, 48, 48);
margin-right: 15px;
}
h1 span.highlight {
color: red;
}
h2 {
color: rgb(48, 48, 48);
}
h2 span.indent {
border-left: 7.5px solid rgb(48, 48, 48);
margin-right: 15px;
}
.setting-container:not(:last-child) {
margin-bottom: 20px;
}
.setting-container .title {
font-size: 1.4rem;
font-weight: lighter;
}
.setting-container .desc {
color: rgb(120, 120, 120);
}
.goback {
color: rgb(120, 120, 120);
text-decoration: none;
}
dialog {
background-color: #080808;
color: #c4c4c4;
border: 1px solid #3bafff;
border-radius: 10px;
}
.input-group-text {
background-color: #000;
border-color: #000;
color: #fff;
}
label {
font-size: 0.8rem;
margin-bottom: 2.75px;
}
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.73);
}
dialog .modal-header p {
margin-bottom: 0px;
color: #fff;
}
dialog .modal-body p:first-child {
font-size: 0.9rem;
}
.setting-container .indicator {
border-radius: 5rem;
display: inline-block;
cursor: default;
}
.setting-container.enabled .indicator {
background-color: #007bff;
}
.setting-container.disabled .indicator {
background-color: orangered;
}
.toggle-btn {
float: right;
width: 100px;
}
.limited-time {
background: transparent;
border-color: transparent;
box-shadow: -3px -3px 15px 0 rgba(255, 116, 16, 0.25) inset, 3px 3px 15px 0 rgba(205, 96, 255, 0.25) inset;
}
.limited-time * {
position: relative;
z-index: 2;
}
.limited-time .row {
--bs-gutter-x: 10px;
}
.limited-time .indicator {
height: 100%;
}
.limited-time .desc {
margin-bottom: 10px;
width: 85%;
}
.limited-time-tag {
font-size: 0.7rem;
color: rgba(255, 116, 16, 0.25);
-webkit-animation: LimitedTimeTag 5s ease infinite alternate;
-moz-animation: LimitedTimeTag 5s ease infinite alternate;
animation: LimitedTimeTag 5s ease infinite alternate;
}
.limited-time::before {
content: '';
position: absolute;
inset: 0;
padding: 3px;
background:
linear-gradient(
45deg,
rgba(255, 116, 16, 1),
rgba(205, 96, 255, 1)
);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
display: block;
border-radius: inherit;
}
@-webkit-keyframes LimitedTimeTag {
0%{color:rgba(255, 116, 16, 1);}
50%{color:rgba(23, 107, 233, 1);}
100%{color:rgba(205, 96, 255, 1);}
}
@-moz-keyframes LimitedTimeTag {
0%{color:rgba(255, 116, 16, 1);}
50%{color:rgba(23, 107, 233, 1);}
100%{color:rgba(205, 96, 255, 1);}
}
@keyframes LimitedTimeTag {
0%{color:rgba(255, 116, 16, 1);}
50%{color:rgba(23, 107, 233, 1);}
100%{color:rgba(205, 96, 255, 1);}
}

View file

@ -20,6 +20,10 @@ body[data-URL^='/create/'] .col.d-flex.align-content-between.flex-wrap {
text-overflow: ellipsis !important;
}
#servers-tabpane .card {
margin-bottom: 10px;
}
/* ------------------------------------------ */
/*
@ -56,3 +60,35 @@ body:has(.polyplus-modal[open]) {
}
/* ------------------------------------------ */
/*
EVENT PLACE CARD HIGHLIGHT ANIMATION
CSS BY @Dragonism ON POLYTORIA
*/
.event-card {
background-size: 200% 200% !important;
-webkit-animation: EventPlace 5s ease infinite;
-moz-animation: EventPlace 5s ease infinite;
animation: EventPlace 5s ease infinite;
}
@-webkit-keyframes EventPlace {
0%{background-position:10% 0%}
50%{background-position:91% 100%}
100%{background-position:10% 0%}
}
@-moz-keyframes EventPlace {
0%{background-position:10% 0%}
50%{background-position:91% 100%}
100%{background-position:10% 0%}
}
@keyframes EventPlace {
0%{background-position:10% 0%}
50%{background-position:91% 100%}
100%{background-position:10% 0%}
}

View file

@ -65,7 +65,7 @@ var FriendContainer = document.querySelector('.card:has(.friendsPopup) .card-bod
let NewContainer = document.createElement('div');
NewContainer.style.display = 'none';
NewContainer.classList = 'card card-dash mcard';
NewContainer.classList = 'card card-dash mcard mb-3';
NewContainer.style.animationDelay = '0.18s';
NewContainer.innerHTML = ContainerElement;
@ -87,7 +87,7 @@ FriendContainer.prepend(BestFriendsContainer);
async function Update() {
chrome.storage.sync.get(['PolyPlus_PinnedGames'], function (result) {
PinnedGamesData = result.PolyPlus_PinnedGames || [];
PinnedGamesData = result.PolyPlus_PinnedGames.toSorted((a, b) => b - a) || [];
if (Settings.PinnedGamesOn === true) {
PinnedGames();
@ -123,7 +123,7 @@ function PinnedGames() {
NewTitle.style.display = '';
}
PinnedGamesData.forEach((element) => {
for (let element of PinnedGamesData) {
fetch('https://api.polytoria.com/v1/places/' + element)
.then((response) => response.json())
.then((data) => {
@ -148,7 +148,7 @@ function PinnedGames() {
.catch((error) => {
console.error('Error:', error);
});
});
}
}
function BestFriends() {
@ -180,8 +180,13 @@ function BestFriends() {
}
var SecondaryColumn = document.getElementsByClassName('col-lg-8')[0];
SecondaryColumn.insertBefore(NewContainer, SecondaryColumn.children[0]);
SecondaryColumn.insertBefore(NewTitle, SecondaryColumn.children[0]);
if (document.getElementsByClassName('home-event-container')[0] === undefined) {
SecondaryColumn.insertBefore(NewContainer, SecondaryColumn.children[0]);
SecondaryColumn.insertBefore(NewTitle, SecondaryColumn.children[0]);
} else {
SecondaryColumn.insertBefore(NewContainer, SecondaryColumn.children[1]);
SecondaryColumn.insertBefore(NewTitle, SecondaryColumn.children[1]);
}
async function IRLPrice() {
(async () => {

View file

View file

@ -6,6 +6,7 @@ var Settings;
var BestFriends;
let FavoriteBtn;
let CalculateButton;
let AvatarIFrame;
let Utilities;
@ -18,6 +19,34 @@ if (Username) {
chrome.storage.sync.get(['PolyPlus_Settings'], function (result) {
Settings = result.PolyPlus_Settings || {};
const InfoColumns = document.getElementById('user-stats-card');
const UserIDRow = document.createElement('div')
UserIDRow.classList = 'mb-1'
UserIDRow.innerHTML = `
<b><i class="fa fa-hashtag text-center d-inline-block" style="width:1.2em"></i> Player ID</b>
<span class="float-end">
${UserID} <a id="copy" href="#copy"><i class="fad fa-copy" style="margin-left: 5px;"></i></a>
</span>
`
InfoColumns.children[0].insertBefore(UserIDRow, InfoColumns.children[0].children[1]);
const CopyButton = UserIDRow.getElementsByTagName('a')[0]
CopyButton.addEventListener('click', function(){
navigator.clipboard
.writeText(UserID)
.then(() => {
CopyButton.classList.add('text-success')
CopyButton.children[0].classList = 'fa-duotone fa-circle-check'
CopyButton.children[0].style.marginLeft = '3px'
setTimeout(() => {
CopyButton.classList.remove('text-success')
CopyButton.children[0].classList = 'fad fa-copy'
CopyButton.children[0].style.marginLeft = '5px'
}, 1500);
})
})
if (Settings.IRLPriceWithCurrency && Settings.IRLPriceWithCurrency.Enabled === true) {
IRLPrice();
}
@ -49,10 +78,55 @@ if (Username) {
}
});
}
/*
<button class="btn btn-outline-primary 3dviewtoggler isactive" style="position:absolute;bottom:15px;right:10px;width:60px"><i class="toggleIcn fad fa-image"></i></button>
<button class="btn btn-outline-primary 3dviewtoggler" style="position:absolute;bottom:15px;right:10px;width:60px"><i class="toggleIcn fad fa-360-degrees"></i></button>
*/
AvatarIFrame = document.getElementById('user-avatar-card').getElementsByTagName('iframe')[0]
if (Settings.AvatarDimensionToggleOn === true || 1 === 1) {
const AvatarCard = document.getElementById('user-avatar-card')
const ToggleButton = document.createElement('button')
ToggleButton.classList = 'btn btn-primary btn-sm 3dviewtoggler isactive'
ToggleButton.style = 'position: absolute; right: 15px; margin: 10px;'
ToggleButton.innerHTML = '<i class="toggleIcn fad fa-image"></i>'
AvatarCard.children[0].insertBefore(ToggleButton, AvatarIFrame)
ToggleButton.addEventListener('click', async function(){
if (ToggleButton.children[0].classList.contains('fa-image')) {
if (document.getElementById('polyplus-2davatar')) {
AvatarIFrame.style.display = 'none'
document.getElementById('polyplus-2davatar').style.display = 'block'
ToggleButton.children[0].classList = 'toggleIcn fad fa-360-degrees'
} else {
const AvatarImage = document.createElement('img')
AvatarImage.id = 'polyplus-2davatar'
AvatarImage.width = AvatarIFrame.offsetWidth
AvatarImage.height = AvatarIFrame.offsetHeight
const UserDetails = (await (await fetch('https://api.polytoria.com/v1/users/' + UserID)).json())
AvatarImage.src = UserDetails.thumbnail.avatar
AvatarIFrame.style.display = 'none'
AvatarCard.children[0].insertBefore(AvatarImage, AvatarCard.getElementsByClassName('user-badges')[0])
ToggleButton.children[0].classList = 'toggleIcn fad fa-360-degrees'
}
} else {
document.getElementById('polyplus-2davatar').style.display = 'none'
AvatarIFrame.style.display = 'block'
ToggleButton.children[0].classList = 'toggleIcn fad fa-image'
}
})
}
});
})();
const AvatarIFrame = document.querySelector('[src^="/ptstatic"]');
if (AvatarIFrame === null) {
AvatarIFrame = document.getElementById('user-avatar-card').getElementsByTagName('iframe')[0]
}
const DropdownMenu = document.getElementsByClassName('dropdown-menu dropdown-menu-right')[0];
const CopyItem = document.createElement('a');

View file

@ -78,9 +78,12 @@ const DefaultSettings = {
Banners: true,
Rectangles: true
},
UploadMultipleDecals: true
UploadMultipleDecals: true,
GD_ServerBalanceOn: true,
AvatarDimensionToggleOn: true
}
// ON EXTENSION INSTALL / RELOAD
chrome.runtime.onInstalled.addListener(() => {
chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
const MergedSettings = MergeObjects((result.PolyPlus_Settings || DefaultSettings), DefaultSettings)
@ -90,6 +93,23 @@ chrome.runtime.onInstalled.addListener(() => {
})
});
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action === 'reload') {
chrome.runtime.reload();
} else if (request.action === 'sweetalert2') {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs){
console.log([request.icon, request.title, request.text])
chrome.scripting
.executeScript({
target: {tabId: tabs[0].id},
func: OpenSweetAlert2Modal,
// would have just let it pass thru the object for sweetalert2 - but probably not a good idea lol
args: [request.icon, request.title, request.text]
})
})
}
});
// WHEN CLICKING ON EXTENSION ICON OPEN THE SETTINGS PAGE
chrome.action.onClicked.addListener((tab) => {
chrome.tabs.create({active: true, url: SettingsURL});
@ -168,7 +188,9 @@ chrome.contextMenus.removeAll(function () {
title: 'Run Update Notifier',
id: 'PolyPlus-RunUpdateNotifier',
contexts: ['all'],
documentUrlPatterns: ['https://polytoria.com/my/settings/polyplus*']
documentUrlPatterns: [
'https://polytoria.com/my/settings/polyplus*'
]
});
// COPY ASSET ID CONTEXT MENU ITEM REGISTRATION
@ -177,7 +199,13 @@ chrome.contextMenus.removeAll(function () {
id: 'PolyPlus-CopyID',
contexts: ['link'],
documentUrlPatterns: ['https://polytoria.com/*', SettingsURL],
targetUrlPatterns: ['https://polytoria.com/places/**', 'https://polytoria.com/users/**', 'https://polytoria.com/u/**', 'https://polytoria.com/store/**', 'https://polytoria.com/guilds/**']
targetUrlPatterns: [
'https://polytoria.com/places/**',
'https://polytoria.com/users/**',
'https://polytoria.com/u/**',
'https://polytoria.com/store/**',
'https://polytoria.com/guilds/**'
]
});
// COPY AVATAR HASH CONTEXT MENU ITEM REGISTRATION
@ -186,7 +214,9 @@ chrome.contextMenus.removeAll(function () {
id: 'PolyPlus-CopyAvatarHash',
contexts: ['image'],
documentUrlPatterns: ['https://polytoria.com/*', SettingsURL],
targetUrlPatterns: ['https://c0.ptacdn.com/thumbnails/avatars/**', 'https://c0.ptacdn.com/thumbnails/avatars/**']
targetUrlPatterns: [
'https://c0.ptacdn.com/thumbnails/avatars/**'
]
});
});
@ -236,18 +266,18 @@ chrome.tabs.onActivated.addListener(function (info){
});
function CheckIfScriptApplies(url) {
return Manifest.content_scripts.forEach(script => {
COMMENT
if (matchesUrl(script.matches, url)) {
return true
}
const matches = Manifest.content_scripts.map(script => {
script.matches.forEach(match => {
if (url.startsWith(match.replaceAll('*', ''))) {
console.log(url, match, url.startsWith(match))
if (url.startsWith(match)) {
return true
}
} else {
return false
}
})
})
return matches
}
function matchesUrl(patterns, url) {
@ -260,11 +290,8 @@ function matchesUrl(patterns, url) {
function CopyAssetID(id) {
navigator.clipboard
.writeText(id)
.then(() => {
alert('Successfully copied ID!');
})
.catch(() => {
alert('Failure to copy ID.');
.catch((err) => {
alert('Failure to copy ID.', err);
});
}
@ -279,6 +306,15 @@ function CopyAvatarHash(hash) {
});
}
function OpenSweetAlert2Modal(icon, title, text) {
console.log(window, window.Swal, window.bootstrap)
window.Swal.fire({
icon: icon,
title: title,
text: text
})
}
// MergeObjects function was written by ChatGPT cause I was lazy and it was awhile ago
function MergeObjects(obj1, obj2) {
var mergedObj = {};
@ -296,10 +332,4 @@ function MergeObjects(obj1, obj2) {
}
return mergedObj;
}
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action === 'reload') {
chrome.runtime.reload();
}
});
}

View file

@ -2,7 +2,7 @@ const AssetID = window.location.pathname.split('/')[2];
const LibraryType = document.querySelectorAll('ol a')[1].innerText.toLowerCase();
const LibraryTypes = ['model', 'audio', 'decal', 'mesh', 'shirt', 'pant'];
if (LibraryTypes.filter((x) => !LibraryTypes.some(element => element.startsWith(LibraryType))).length > 0) {
if (LibraryTypes.some(element => element.startsWith(LibraryType))) {
chrome.storage.sync.get(['PolyPlus_Settings'], async function (result) {
Settings = result.PolyPlus_Settings || {};

View file

@ -35,28 +35,16 @@ async function ActivityToggle() {
ActivityBtn.innerText = Status === true ? 'Deactivate' : 'Activate';
DIV.appendChild(ActivityBtn);
ActivityBtn.addEventListener('click', function () {
fetch(`https://polytoria.com/api/places/${PlaceID}/toggle-active`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value
}
})
.then((response) => {
if (!response.ok) {
throw new Error('Network not ok ' + response.status);
}
return response.json();
})
.then((data) => {
Status = data.isActive;
ActivityBtn.innerText = Status === true ? 'Deactivate' : 'Activate';
ActivityBtn.classList = 'btn ' + (Status === true ? 'btn-danger' : 'btn-success');
})
.catch((error) => {
console.log(error);
});
ActivityBtn.addEventListener('click', async function () {
const Toggle = (await (await fetch(`https://polytoria.com/api/places/${PlaceID}/toggle-active`,{ method: 'POST' })).json())
console.log(Toggle)
if (Toggle.success) {
Status = data.isActive;
ActivityBtn.innerText = Status === true ? 'Deactivate' : 'Activate';
ActivityBtn.classList = 'btn ' + (Status === true ? 'btn-danger' : 'btn-success');
} else {
chrome.runtime.sendMessage({ action: "sweetalert2", icon: "error", title: "Error", text: Toggle.message });
}
});
}
@ -93,7 +81,6 @@ function RequestGameProfile() {
}
async function CopyOwnedPlace() {
console.log('ran function');
if (PlaceData === null) {
PlaceData = await fetch('https://api.polytoria.com/v1/places/' + PlaceID);
PlaceData = await PlaceData.json();
@ -122,11 +109,6 @@ async function CopyOwnedPlace() {
let CreatorToken = await fetch('https://polytoria.com/api/places/edit', {
method: 'POST',
/*
headers: {
'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value
},
*/
body: JSON.stringify({placeID: PlaceID})
});
CreatorToken = await CreatorToken.json();
@ -144,7 +126,6 @@ async function CopyOwnedPlace() {
return response.blob();
})
.then((data) => {
//const JSONBlob = new Blob([data], {type: "application/xml"})
const DownloadURL = URL.createObjectURL(data);
const Link = document.createElement('a');

View file

@ -50,6 +50,10 @@ const Gamepasses = Array.from(GamepassesTab.getElementsByClassName('card')) || [
Utilities = await import(chrome.runtime.getURL('resources/utils.js'));
Utilities = Utilities.default;
if (Settings.GD_ServerBalanceOn && PlaceID === '9656') {
TheGreatDivide()
}
if (Settings.PinnedGamesOn === true) {
PinnedGames();
}
@ -426,7 +430,7 @@ async function PlaceRevenue() {
const ResultText = document.createElement('li');
ResultText.classList = 'fw-normal text-success';
ResultText.style.letterSpacing = '0px';
ResultText.innerHTML = `<i class="pi pi-brick mx-1"></i> ~` + Revenue.toLocaleString();
ResultText.innerHTML = `<i class="pi pi-brick mx-1"></i> ~` + Revenue.toLocaleString() + ' <i class="fa fa-question"></i>';
CalculateRevenueButton.remove();
InfoColumns[1].appendChild(ResultText);
@ -513,3 +517,36 @@ function GetAchievementDifficulty(percent) {
return 'Impossible';
}
}
// Temp Feature for The Great Divide event
async function TheGreatDivide() {
const Team = (await (await fetch('https://api.polytoria.com/v1/users/' + UserID + '/greatdivide')).json()).team
if (Team !== undefined) {
const Servers = Array.from(document.getElementById('servers-tabpane').children)
Servers.forEach(server => {
const TeamCounts = {
phantoms: server.getElementsByClassName('border-phantoms').length,
cobras: server.getElementsByClassName('border-cobras').length
}
let Enemy = "cobras"
if (Team === "cobras") { Enemy = "phantoms" }
if (TeamCounts[Team] < TeamCounts[Enemy]) {
console.log(server.getElementsByTagName('button')[0])
const UnbalancedText = document.createElement('p')
UnbalancedText.classList = 'mb-2'
UnbalancedText.style.fontSize = '0.7rem'
UnbalancedText.style.color = 'orange'
UnbalancedText.innerHTML = `*Potentially Unbalanced <i class="fa-solid fa-circle-info" data-bs-toggle="tooltip" data-bs-title="${TeamCounts.cobras} Cobras and ${TeamCounts.phantoms} Phantoms"></i>`
const ServerInfoColumn = server.getElementsByClassName('col-3')[0]
ServerInfoColumn.children[0].style.marginBottom = '0px'
ServerInfoColumn.insertBefore(UnbalancedText, ServerInfoColumn.children[1])
Utilities.InjectResource("registerTooltips")
}
})
}
}

View file

@ -112,12 +112,11 @@ let Theme = ``;
}
});
const combination = "reload";
let currentCombination = "";
document.addEventListener("keypress", function(e) {
currentCombination += e.key;
if (currentCombination === combination && document.activeElement.tagName !== "INPUT") {
if (currentCombination === combination && document.activeElement.tagName !== "INPUT" && document.activeElement.tagName !== "TEXTAREA") {
console.log("Reloading Poly+...");
chrome.runtime.sendMessage({ action: "reload" });
window.location.reload();

View file

@ -44,12 +44,14 @@ var Utilities;
}
if (Settings.ReplaceItemSalesOn === true) {
const Sales = document.querySelectorAll('.col:has(h6):has(h3.small)')[2];
const Sales = document.querySelectorAll('.col:has(h6):has(h3.small)')[3];
if (Sales.children[1].innerText === '0') {
InitialOwners = await (await fetch('https://api.polytoria.com/v1/store/' + ItemID + '/owners?limit=100')).json();
Sales.children[0].innerText = 'Owners';
Sales.children[1].innerText = Owners.total.toLocaleString();
Sales.children[0].innerHTML = `Owners <i class="fa-solid fa-circle-info" data-bs-toggle="tooltip" data-bs-title="${ (InitialOwners.total <= 15) ? InitialOwners.inventories.map((x) => x.user.username).join(', ') : InitialOwners.inventories.slice(0, 14).map((x) => x.user.username).join(', ') + ' ...' }"></i>`;
Sales.children[1].innerText = InitialOwners.total.toLocaleString();
Utilities.InjectResource("registerTooltips")
}
}
@ -267,15 +269,12 @@ function TryOnItems() {
.then((data) => {
switch (AssetType) {
case 'Shirt':
console.log('IS SHIRT');
Avatar.shirt = data.url;
break;
case 'Pants':
console.log('IS PANTS');
Avatar.pants = data.url;
break;
case 'Face':
console.log('IS FACE');
Avatar.face = data.url;
break;
}
@ -301,7 +300,7 @@ function TryOnItems() {
<div class="row text-muted mb-2" style="font-size: 0.8rem;">
<div class="col">
<h5 class="mb-0" style="color: #fff;">Preview</h5>
Try this avatar on your avatar before purchasing it!
Try this item on your avatar before purchasing it!
</div>
<div class="col-md-2">
<button class="btn btn-info w-100 mx-auto" onclick="this.parentElement.parentElement.parentElement.close();">X</button>

25
popup.html Normal file
View file

@ -0,0 +1,25 @@
<!doctype html>
<html>
<head>
<!-- META TAGS -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- PUBLIC -->
<title>Poly+ Settings</title>
<!-- RESOURCES -->
<link rel="stylesheet" href="css/polytoria.css" />
</head>
<body style="width: 245px; /*height: 200px;*/">
<div class="p-2 pt-0">
<small class="text-muted" style="font-size: 0.7rem;">extract texture from item</small>
<br>
<div class="input-group">
<input type="text" class="form-control form-control-sm" placeholder="Item ID..">
<button class="btn btn-success btn-sm" id="extract-texture">Extract</button>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>

87
popup.js Normal file
View file

@ -0,0 +1,87 @@
/*
ParseGLB & GetTexture function code made by ChatGPT (I didn't want to use external libraries because of storage space)
*/
const ExtractButton = document.getElementById('extract-texture')
ExtractButton.addEventListener('click', async function(){
const MeshURL = (await (await fetch('https://api.polytoria.com/v1/assets/serve-mesh/' + ExtractButton.previousElementSibling.value)).json()).url
if (MeshURL !== undefined) {
const Mesh = (await (await fetch(MeshURL)).arrayBuffer())
const ParsedGTLF = ParseGLB(Mesh)
const Texture = GetTexture(ParsedGTLF);
if (Texture) {
const DownloadLink = document.createElement('a');
DownloadLink.href = Texture;
DownloadLink.download = ExtractButton.previousElementSibling.value + '.png';
document.body.appendChild(DownloadLink)
DownloadLink.click()
DownloadLink.remove()
}
}
})
function ParseGLB(arrayBuffer) {
const MAGIC_glTF = 0x46546C67;
const dataView = new DataView(arrayBuffer);
const magic = dataView.getUint32(0, true);
if (magic !== MAGIC_glTF) {
throw new Error('Invalid GLB file.');
}
const version = dataView.getUint32(4, true);
if (version !== 2) {
throw new Error('Unsupported GLB version.');
}
const length = dataView.getUint32(8, true);
const chunkLength = dataView.getUint32(12, true);
const chunkType = dataView.getUint32(16, true);
if (chunkType !== 0x4E4F534A) {
throw new Error('Invalid GLB JSON chunk.');
}
const jsonChunk = new TextDecoder().decode(
new Uint8Array(arrayBuffer, 20, chunkLength)
);
const json = JSON.parse(jsonChunk);
const binChunkHeader = 20 + chunkLength;
const binChunkLength = dataView.getUint32(binChunkHeader, true);
const binChunkType = dataView.getUint32(binChunkHeader + 4, true);
if (binChunkType !== 0x004E4942) {
throw new Error('Invalid GLB BIN chunk.');
}
const binChunk = arrayBuffer.slice(binChunkHeader + 8, binChunkHeader + 8 + binChunkLength);
return {
json: json,
bin: binChunk
};
}
function GetTexture(gltf) {
let Texture = null
const images = gltf.json.images;
if (images.length === 0) {
return null;
}
const image = images[0];
const bufferView = gltf.json.bufferViews[image.bufferView];
const byteOffset = bufferView.byteOffset || 0;
const byteLength = bufferView.byteLength;
const buffer = new Uint8Array(gltf.bin, byteOffset, byteLength);
const blob = new Blob([buffer], { type: image.mimeType });
return URL.createObjectURL(blob);
}

View file

@ -99,6 +99,8 @@ export default {
Rectangles: true
},
UploadMultipleDecals: true,
GD_ServerBalanceOn: true,
AvatarDimensionToggleOn: true
},
Limits: {
PinnedGames: 10,

View file

@ -1,3 +1,4 @@
<!doctype html>
<html>
<head>
<!-- META TAGS -->
@ -9,111 +10,9 @@
<!-- RESOURCES -->
<link rel="stylesheet" href="css/polytoria.css" />
<link rel="stylesheet" href="css/settings.css" />
</head>
<body data-bs-theme="dark">
<style>
html,
body,
#page {
background: #202020;
color: #fff;
}
#page {
margin-top: 7.5rem;
width: 65%;
margin-right: auto;
margin-left: auto;
margin-bottom: 3.5rem;
}
h1 {
font-size: 4.6rem;
/*color: rgb(48, 48, 48);*/
}
h1 span.indent {
border-left: 10px solid rgb(48, 48, 48);
margin-right: 15px;
}
h1 span.highlight {
color: red;
}
h2 {
color: rgb(48, 48, 48);
}
h2 span.indent {
border-left: 7.5px solid rgb(48, 48, 48);
margin-right: 15px;
}
p span.title {
font-size: 1.4rem;
font-weight: lighter;
}
span.desc {
color: rgb(120, 120, 120);
}
.goback {
color: rgb(120, 120, 120);
text-decoration: none;
}
dialog {
background-color: #080808;
color: #c4c4c4;
border: 1px solid #3bafff;
border-radius: 10px;
}
.input-group-text {
background-color: #000;
border-color: #000;
color: #fff;
}
label {
font-size: 0.8rem;
margin-bottom: 2.75px;
}
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.73);
}
dialog .modal-header p {
margin-bottom: 0px;
color: #fff;
}
dialog .modal-body p:first-child {
font-size: 0.9rem;
}
.setting-container .indicator {
border-radius: 5rem;
display: inline-block;
cursor: default;
}
.setting-container.enabled .indicator {
background-color: #007bff;
}
.setting-container.disabled .indicator {
background-color: orangered;
}
.toggle-btn {
float: right;
width: 100px;
}
</style>
<dialog class="w-50" id="ResetDefaults-Modal">
<div class="modal-header">
<p>Are you sure?</p>
@ -380,7 +279,25 @@
</dialog>
<div id="page">
<h1 class="text-center" style="text-shadow: 0px 0px 5px orange; padding-bottom: 5px; margin-bottom: 10px;">Poly+ Settings</h1>
<p class="setting-container" id="pinned-games">
<div class="card card-body limited-time setting-container mb-3" id="greatdivide-server-unbalance">
<div class="row">
<div class="col-auto">
<span class="indicator">&nbsp;</span>
</div>
<div class="col">
<span class="title">
"Potentially Unbalanced" Server Tag
<button class="btn btn-sm toggle-btn" data-setting="GD_ServerBalanceOn">Toggle</button>
</span>
</div>
</div>
<span class="desc">Quickly check if The Great Divide official event place servers are balanced or not! To be unbalanced, the team opposite of you has to have at least 1 more member in the server than you.</span>
<small class="limited-time-tag mt-1">
* available until July 14th
</small>
</div>
<div class="setting-container" id="pinned-games">
<span class="indicator">&nbsp;</span>
<span class="title">
Pinned Games
@ -388,8 +305,8 @@
</span>
<br />
<span class="desc">Pin your favorite places to the top of the homepage! (limit: <span id="PinnedGames-limit"></span> places)</span>
</p>
<p class="setting-container" id="forum-mentions">
</div>
<div class="setting-container" id="forum-mentions">
<span class="indicator">&nbsp;</span>
<span class="title">
Forum Mentions
@ -399,9 +316,9 @@
<span class="desc">Get a quick link to the popular person everyone is talking about's profile!</span>
<br />
<span style="font-size: 0.8rem; color: orange;">* Forum Mentions do not notify the user or show up as a notification on their account.</span>
</p>
</div>
<!--
<p class="setting-container" id="best-friends">
<div class="setting-container" id="best-friends">
<span class="indicator">&nbsp;</span>
<span class="title">
Best Friends
@ -409,9 +326,9 @@
</span>
<br />
<span class="desc">Prioritize the bestest of friends on applicable friend lists! (limit: <span id="BestFriends-limit"></span> best friends)</span>
</p>
</div>
-->
<p class="setting-container" id="improved-friend-lists">
<div class="setting-container" id="improved-friend-lists">
<span class="indicator">&nbsp;</span>
<span class="title">
Improved Friend Lists
@ -423,8 +340,8 @@
<br />
<span style="font-size: 0.8rem; color: orange;">* You can only remove up to <span id="ImprovedFrLists-limit"></span> friends at once.</span>
</span>
</p>
<p class="setting-container" id="upload-multiple-decals">
</div>
<div class="setting-container" id="upload-multiple-decals">
<span class="indicator">&nbsp;</span>
<span class="title">
Upload multiple decals
@ -434,8 +351,8 @@
<span class="desc">
Lets you quickly upload multiple decals at once!
</span>
</p>
<p class="setting-container" id="irl-price-with-brick-count">
</div>
<div class="setting-container" id="irl-price-with-brick-count">
<span class="indicator">&nbsp;</span>
<span class="title">
Show IRL price with Brick Count
@ -469,8 +386,8 @@
<option value="5">$99.99 Brick Package</option>
</select>
-->
</p>
<p class="setting-container" id="hide-notification-badges">
</div>
<div class="setting-container" id="hide-notification-badges">
<span class="indicator">&nbsp;</span>
<span class="title">
Hide Notification Badges
@ -478,8 +395,8 @@
</span>
<br />
<span class="desc">Hide the annoying red circles on the sidebar!</span>
</p>
<p class="setting-container" id="store-own-tag">
</div>
<div class="setting-container" id="store-own-tag">
<span class="indicator">&nbsp;</span>
<span class="title">
Show "OWNED" Tag on Store Main Page
@ -487,8 +404,8 @@
</span>
<br />
<span class="desc">Quickly see if you own the item at a glance with a little tag in the top left corner of item cards on the main store page!</span>
</p>
<p class="setting-container" id="theme-creator">
</div>
<div class="setting-container" id="theme-creator">
<span class="indicator">&nbsp;</span>
<span class="title">
Theme Creator
@ -497,8 +414,8 @@
</span>
<br />
<span class="desc">Unleash your creativity and customize the Polytoria website to your liking! (this feature is still in development)</span>
</p>
<p class="setting-container" id="more-search-filters">
</div>
<div class="setting-container" id="more-search-filters">
<span class="indicator">&nbsp;</span>
<span class="title">
More Search Filters
@ -508,8 +425,8 @@
<span class="desc">Easily find what you're looking for with more search filters side-wide! (this does not affect the main site search on the navbar)</span>
<br />
<span style="font-size: 0.8rem; color: orange;">* This currently only has a "Creator" username filter on the forum search page, more search filters are yet to come.</span>
</p>
<p class="setting-container" id="apply-membership-theme">
</div>
<div class="setting-container" id="apply-membership-theme">
<span class="indicator">&nbsp;</span>
<span class="title">
Apply Membership Theme for <b>Free</b>
@ -521,8 +438,8 @@
<option value="Plus" selected>Plus</option>
<option value="PlusDX">Plus Deluxe</option>
</select>
</p>
<p class="setting-container" id="multi-cancel-outbound-trades">
</div>
<div class="setting-container" id="multi-cancel-outbound-trades">
<span class="indicator">&nbsp;</span>
<span class="title">
Multi-Cancel Outbound Trades
@ -534,8 +451,8 @@
<br />
<span style="font-size: 0.8rem; color: orange;">* You can only cancel up to 10 trades at once.</span>
</span>
</p>
<p class="setting-container" id="modify-navbar">
</div>
<div class="setting-container" id="modify-navbar">
<span class="indicator">&nbsp;</span>
<span class="title">
Modify Navbar
@ -544,8 +461,8 @@
</span>
<br />
<span class="desc"> Customize the navbar to your liking! </span>
</p>
<p class="setting-container" id="item-wishlist">
</div>
<div class="setting-container" id="item-wishlist">
<span class="indicator">&nbsp;</span>
<span class="title">
Item Wishlist
@ -553,8 +470,8 @@
</span>
<br />
<span class="desc"> Wishlist that item that you REALLY want! </span>
</p>
<p class="setting-container" id="try-on-items">
</div>
<div class="setting-container" id="try-on-items">
<span class="indicator">&nbsp;</span>
<span class="title">
Try-On Items
@ -562,8 +479,8 @@
</span>
<br />
<span class="desc">See how that new item looks on your avatar before spending your bricks!</span>
</p>
<p class="setting-container" id="outfit-cost">
</div>
<div class="setting-container" id="outfit-cost">
<span class="indicator">&nbsp;</span>
<span class="title">
Show Outfit Cost on Profiles
@ -571,8 +488,8 @@
</span>
<br />
<span class="desc">Quickly see how many bricks a user spent on their avatar!</span>
</p>
<p class="setting-container" id="outfit-cost">
</div>
<div class="setting-container" id="outfit-cost">
<span class="indicator">&nbsp;</span>
<span class="title">
Show Approximate Place Revenue
@ -584,8 +501,8 @@
<span style="font-size: 0.8rem; color: orange;"
>* Gamepass revenue is calculated assuming the price hasn't changed and all users that bought the gamepass, bought it at the same price that it is at the time of calculating.</span
>
</p>
<p class="setting-container" id="item-replace-sales">
</div>
<div class="setting-container" id="item-replace-sales">
<span class="indicator">&nbsp;</span>
<span class="title">
Show "Owners" instead of "Sales"
@ -593,8 +510,8 @@
</span>
<br />
<span class="desc">Replace the "Sales" statistic with the "Owners" statistic if the item has 0 sales (most likely meaning it is an item awarded by staff).</span>
</p>
<p class="setting-container" id="hoarders-list">
</div>
<div class="setting-container" id="hoarders-list">
<span class="indicator">&nbsp;</span>
<span class="title">
Collectibles' Hoarders List
@ -618,8 +535,8 @@
<option value="15">Min. 15+ Copies</option>
<option value="35">Min. 35+ Copies</option>
</select>
</p>
<p class="setting-container" id="hoarders-list">
</div>
<div class="setting-container" id="hoarders-list">
<span class="indicator">&nbsp;</span>
<span class="title">
Quick Library Downloads
@ -627,8 +544,8 @@
</span>
<br />
<span class="desc">Quickly download a model (as a <code>.ptmd</code> file), mesh, decal, or sound right from the page showing you details about the asset!</span>
</p>
<p class="setting-container" id="event-items-store">
</div>
<div class="setting-container" id="event-items-store">
<span class="indicator">&nbsp;</span>
<span class="title">
"Event Items" Store Category
@ -636,8 +553,8 @@
</span>
<br />
<span class="desc">List all the on-going and past event items separated by their event with a store category!</span>
</p>
<p class="setting-container" id="event-items-store">
</div>
<div class="setting-container" id="event-items-store">
<span class="indicator">&nbsp;</span>
<span class="title">
Show Friend Count on Homepage
@ -645,8 +562,8 @@
</span>
<br />
<span class="desc">See how many friends you have on your homepage/dashboard, just scroll to the "friends" section and you'll see it next to the heading!</span>
</p>
<p class="setting-container" id="timed-item-owner-check">
</div>
<div class="setting-container" id="timed-item-owner-check">
<span class="indicator">&nbsp;</span>
<span class="title">
Timed-Item Owner Check
@ -657,8 +574,8 @@
>Click the shopping bags icon in the bottom left-hand corner of the timed item's item thumbnail to toggle an input and a button. Then just enter someone's username and it'll tell you whether
they own it or not and if so what serial!</span
>
</p>
<p class="setting-container" id="hide-user-ads">
</div>
<div class="setting-container" id="hide-user-ads">
<span class="indicator">&nbsp;</span>
<span class="title">
Hide User Ads
@ -676,9 +593,20 @@
<input class="form-check-input" type="checkbox" role="switch" id="hide-user-ads-rectangle" data-setting="Rectangles" data-parent="HideUserAds" />
<label class="form-check-label" for="hide-user-ads-rectangle"> Hide Rectangle User Ads </label>
</span>
</p>
</div>
<div class="setting-container" id="avatar-dimension-toggle">
<span class="indicator">&nbsp;</span>
<span class="title">
Avatar Dimension Toggle
<button class="btn btn-sm toggle-btn" data-setting="AvatarDimensionToggleOn">Toggle</button>
</span>
<br />
<span class="desc">
Quickly switch between a 3D or 2D rendition of somebody's avatar on their profile page!
</span>
</div>
<!---
<p class="setting-container" id="auto-ad-bidding">
<div class="setting-container" id="auto-ad-bidding">
<span class="indicator">&nbsp;</span>
<span class="title">
Automatic Ad Bidding
@ -687,14 +615,14 @@
</span>
<br />
<span class="desc">description</span>
</p>
</div>
-->
<div class="card">
<div class="card-body">
<h3>EXPERIMENTAL SETTINGS</h3>
<p>These features are a work in progress.</p>
<hr />
<p class="setting-container" id="game-profiles">
<div class="setting-container" id="game-profiles">
<span class="indicator">&nbsp;</span>
<span class="title">
Game Profiles
@ -706,8 +634,8 @@
<span style="font-size: 0.8rem; color: orange;">* Place creators must request a game profile for one to be made.</span>
<br />
<span style="font-size: 0.8rem; color: orange;">* This feature will be expanded upon in the future.</span>
</p>
<p class="setting-container" id="inline-editing">
</div>
<div class="setting-container" id="inline-editing">
<span class="indicator">&nbsp;</span>
<span class="title">
Inline Editing
@ -719,8 +647,8 @@
<span style="font-size: 0.8rem; color: orange;">* This feature currently only supports places.</span>
<br />
<span style="font-size: 0.8rem; color: orange;">* This feature is not finished or polished.</span>
</p>
<p class="setting-container" id="forum-unix-timestamps">
</div>
<div class="setting-container" id="forum-unix-timestamps">
<span class="indicator">&nbsp;</span>
<span class="title">
Forum Unix Timestamps
@ -730,8 +658,8 @@
<span class="desc">See a date and time that is adjusted to everyone (who is using Poly+)'s local time</span>
<br />
<span style="font-size: 0.8rem; color: orange;">* The styling for this feature is not yet done.</span>
</p>
<p class="setting-container" id="avatar-sandbox">
</div>
<div class="setting-container" id="avatar-sandbox">
<span class="indicator">&nbsp;</span>
<span class="title">
Avatar Sandbox
@ -741,7 +669,7 @@
<span class="desc">Create an avatar with all the item possibilities available to your heart's content!</span>
<br />
<span style="font-size: 0.8rem; color: orange;">* This feature is not polished - things like modifying avatar "Body Colors", pagination, outfits, etc haven't been added.</span>
</p>
</div>
</div>
</div>
<hr />

View file

@ -328,6 +328,48 @@ function LoadThemeJSON(string) {
}
}
chrome.storage.sync.get(['PolyPlus_AutoAds'], function(result){
let AutoAds = result.PolyPlus_AutoAds || [];
const Modal = document.getElementById("AutoAdBidding-Modal")
const AddButton = document.getElementById('auto-ad-bidding-add')
AddButton.addEventListener('click', async function() {
const Page = new DOMParser().parseFromString((await (await fetch('https://polytoria.com/create/ad/' + AddButton.previousElementSibling.value)).text()), 'text/html')
})
const AddRow = function(index, info) {
const Row = document.createElement('tr')
Row.innerHTML = `
<th scope="row">${index+1}</th>
<td><a href="https://polytoria.com/create/ad/${info.id}">"${info.name}"</a></td>
<td class="text-success"><span class="pi">$</span> 150</td>
<td>
<select class="form-select ignore">
<option value="daily" selected>Daily</option>
<option value="weekly">Weekly</option>
<option value="monthly">Monthly</option>
</select>
</td>
<td>
<div role="group" class="btn-group w-100">
<button class="btn btn-success w-25">
BID
</button>
<button class="btn btn-orange w-25">
EDIT
</button>
<button class="btn btn-danger w-25">
DELETE
</button>
</div>
</td>
`
}
})
function AreIdentical(obj1, obj2) {
if (obj1.length !== obj2.length) { return false }
return JSON.stringify(obj1) === JSON.stringify(obj2)