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) =>
82 Math.round(number / config.economy.visitorPayouts.visitors) *
83 config.economy.visitorPayouts.visitors;
84 const infoCard = document.querySelector(".card-body .row:has(.fa-calendar)")!;
85
86 const key = document.createElement("li");
87 const value = document.createElement("li");
88
89 key.innerHTML = "Revenue:";
90 value.innerHTML = "...";
91 value.classList.add(config.api.enabled ? "text-success" : "text-muted");
92
93 infoCard.children[0].appendChild(key);
94 infoCard.children[1].appendChild(value);
95
96 const revenue = await pullKVCache(
97 "placeRevenue",
98 placeID,
99 async () => {
100 if (!config.api.enabled) return "disabled";
101
102 const place: apiTypes.placeApiSchema =
103 await (await fetch(config.api.urls.public + "places/" + placeID))
104 .json();
105 const store: apiTypes.gamepassesApiSchema = await (await fetch(
106 config.api.urls.public + "places/" + placeID + "/gamepasses",
107 )).json();
108 const creator: apiTypes.userApiSchema = await (await fetch(
109 config.api.urls.public + "users/" + place.creator.id,
110 )).json();
111
112 const visitorPayout = round(place.uniqueVisits) /
113 config.economy.visitorPayouts.visitors;
114 let gamepassRevenue = 0;
115
116 for (const gamepass of store.gamepasses) {
117 const price = Math.floor(
118 gamepass.asset.price -
119 (gamepass.asset.price *
120 config.economy.membershipTax[creator.membershipType]),
121 );
122 gamepassRevenue += price * gamepass.asset.sales;
123 }
124
125 return visitorPayout + gamepassRevenue;
126 },
127 300000,
128 false,
129 );
130
131 if (revenue == "disabled") {
132 value.innerText =
133 "Sorry, this feature is currently unavailable! Check back later!";
134 throw new Error(
135 "[Poly+] API is disabled, cancelling approx. place revenue loading..",
136 );
137 }
138
139 value.innerHTML = '<i class="pi pi-brick me-2"></i> ~' +
140 revenue.toLocaleString();
141}