A rewrite of Poly+, my quality-of-life browser extension for Polytoria. Built entirely fresh using the WXT extension framework, Typescript, and with added better overall code quality.
extension
1import config from "@/utils/config.json"; 2import { _favoritedPlaces } from "@/utils/storage"; 3import { expireCache } from "@/utils/utilities"; 4import * as apiTypes from "@/utils/api/types"; 5const placeID = window.location.pathname.split('/')[2]; 6 7/** 8 * Displays a row of user-selected places at the top of the user's dashboard. 9 */ 10export async function favoritedPlaces() { 11 let placeIDs = await _favoritedPlaces.getValue(); 12 13 const button = document.createElement('button'); 14 button.classList.add('btn', 'btn-primary', 'btn-sm'); 15 button.style.position = 'absolute'; 16 button.style.top = '0'; 17 button.style.right = '0'; 18 button.style.margin = '4px'; 19 button.style.fontSize = '1.3em'; 20 button.innerHTML = ` 21 <i class="fa-regular fa-star"></i> 22 `; 23 24 const update = function() { 25 button.classList.value = 'btn btn-primary btn-sm'; 26 button.disabled = false; 27 if (placeIDs.indexOf(placeID) == -1) { 28 // Not Pinned 29 if (placeIDs.length >= config.limits.favoritedPlaces) { 30 button.disabled = true; 31 } 32 button.children[0].classList.value = 'fa-regular fa-star'; 33 } else { 34 // Pinned 35 button.children[0].classList.value = 'fa-duotone fa-star'; 36 } 37 }; 38 39 button.addEventListener('mouseenter', function() { 40 if (placeIDs.indexOf(placeID) != -1) { 41 button.classList.add('btn-danger'); 42 button.classList.remove('btn-primary'); 43 button.children[0].classList.add('fa-star-half-stroke'); 44 button.children[0].classList.remove('fa-star'); 45 }; 46 }); 47 48 button.addEventListener('mouseleave', function() { 49 if (placeIDs.indexOf(placeID) != -1) { 50 button.classList.add('btn-primary'); 51 button.classList.remove('btn-danger'); 52 button.children[0].classList.add('fa-star'); 53 button.children[0].classList.remove('fa-star-half-stroke'); 54 }; 55 }); 56 57 update(); 58 document.querySelector('h1.my-0')!.parentElement!.appendChild(button); 59 60 button.addEventListener('click', function() { 61 if (placeIDs.indexOf(placeID) == -1) { 62 placeIDs.push(placeID); 63 } else { 64 placeIDs.splice(placeIDs.indexOf(placeID), 1); 65 } 66 67 expireCache('favoritedPlaces'); 68 _favoritedPlaces.setValue(placeIDs); 69 update(); 70 }); 71 72 storage.watch<Array<string>>('sync:favoritedPlaces', (value, previous) => { 73 placeIDs = value!; 74 }); 75}; 76 77/** 78 * Displays the approximated amount of revenue generated from a certain place, based off the unique visits & any gamepass sales (taking into account the creator's current membership tax) 79 */ 80export async function approxPlaceRevenue() { 81 const round = (number: number) => Math.round(number / config.economy.visitorPayouts.visitors) * config.economy.visitorPayouts.visitors; 82 const infoCard = document.querySelector('.card-body .row:has(.fa-calendar)')!; 83 84 const key = document.createElement('li'); 85 const value = document.createElement('li'); 86 87 key.innerHTML = 'Revenue:'; 88 value.innerHTML = '...'; 89 value.classList.add(config.api.enabled ? 'text-success' : 'text-muted'); 90 91 infoCard.children[0].appendChild(key); 92 infoCard.children[1].appendChild(value); 93 94 const revenue = await pullKVCache( 95 "placeRevenue", 96 placeID, 97 async () => { 98 if (!config.api.enabled) return "disabled"; 99 100 const place: apiTypes.placeApiSchema = (await (await fetch(config.api.urls.public + 'places/' + placeID)).json()); 101 const store: apiTypes.gamepassesApiSchema = (await (await fetch(config.api.urls.public + 'places/' + placeID + '/gamepasses')).json()); 102 const creator: apiTypes.userApiSchema = (await (await fetch(config.api.urls.public + 'users/' + place.creator.id)).json()); 103 104 const visitorPayout = round(place.uniqueVisits) / config.economy.visitorPayouts.visitors; 105 let gamepassRevenue = 0; 106 107 for (const gamepass of store.gamepasses) { 108 const price = Math.floor(gamepass.asset.price - (gamepass.asset.price * config.economy.membershipTax[creator.membershipType])) 109 gamepassRevenue += price * gamepass.asset.sales; 110 }; 111 112 return visitorPayout + gamepassRevenue; 113 }, 114 300000, 115 false 116 ); 117 118 if (revenue == "disabled") { 119 value.innerText = 'Sorry, this feature is currently unavailable! Check back later!'; 120 throw new Error("[Poly+] API is disabled, cancelling approx. place revenue loading.."); 121 }; 122 123 value.innerHTML = '<i class="pi pi-brick me-2"></i> ~' + revenue.toLocaleString(); 124};