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