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

feat: reorganize API methods & types

Index f1084ac4 5304bf27

Changed files
+122 -123
entrypoints
utils
+3 -3
entrypoints/home.content.ts
···
import { preferences, _favoritedPlaces, _bestFriends } from "@/utils/storage";
-
import { placeApiSchema, userApiSchema } from "@/utils/types";
import { pullCache } from "@/utils/utilities";
import * as api from "@/utils/api";
export default defineContentScript({
matches: ['https://polytoria.com/', 'https://polytoria.com/home'],
···
column.insertBefore(container, column.children[1]);
};
-
const placeData: Array<placeApiSchema> | "disabled" = await pullCache(
'favoritedPlaces',
async () => await api.batch('public', 'places/', places),
300000,
···
const friendsRow = document.querySelector('.card:has(.friendsPopup) .d-flex')!;
const createHeadshot = async function(id: string) {
-
const user: userApiSchema = (await (await fetch('https://api.polytoria.com/v1/users/' + id)).json());
const headshot = document.createElement('div');
// ? surely a better way to do this but who cares
···
import { preferences, _favoritedPlaces, _bestFriends } from "@/utils/storage";
import { pullCache } from "@/utils/utilities";
import * as api from "@/utils/api";
+
import * as apiTypes from "@/utils/api/types";
export default defineContentScript({
matches: ['https://polytoria.com/', 'https://polytoria.com/home'],
···
column.insertBefore(container, column.children[1]);
};
+
const placeData: Array<apiTypes.placeApiSchema> | "disabled" = await pullCache(
'favoritedPlaces',
async () => await api.batch('public', 'places/', places),
300000,
···
const friendsRow = document.querySelector('.card:has(.friendsPopup) .d-flex')!;
const createHeadshot = async function(id: string) {
+
const user: apiTypes.userApiSchema = (await (await fetch('https://api.polytoria.com/v1/users/' + id)).json());
const headshot = document.createElement('div');
// ? surely a better way to do this but who cares
+2 -4
entrypoints/store.content/index.ts
···
import { getUserDetails } from "@/utils/utilities";
import { preferences } from "@/utils/storage";
import * as discovery from "./discovery";
import * as view from "./view";
-
import { userDetails, avatarApiSchema } from "@/utils/types";
export default defineContentScript({
matches: ['*://polytoria.com/store/*'],
···
} else {
// View
if (values.irlBrickPrice.enabled) view.irlBrickPrice();
-
-
//@ts-ignore
-
view.tryOn(user);
};
})
});
···
import { getUserDetails } from "@/utils/utilities";
import { preferences } from "@/utils/storage";
+
import * as discovery from "./discovery";
import * as view from "./view";
export default defineContentScript({
matches: ['*://polytoria.com/store/*'],
···
} else {
// View
if (values.irlBrickPrice.enabled) view.irlBrickPrice();
+
if (values.tryItems.enabled) view.tryOn(user);
};
})
});
+9 -7
entrypoints/store.content/view.ts
···
import config from "@/utils/config.json";
-
import { avatarApiSchema, itemApiSchema, meshApiSchema, textureApiSchema, userDetails } from "@/utils/types";
import { bricksToCurrency } from "@/utils/utilities";
-
import "@/public/css/specific.css";
export function irlBrickPrice() {
try {
···
document.body.prepend(modal);
favoriteBtn.parentElement!.appendChild(button);
-
const loadFrame = async (source: avatarApiSchema) => {
console.info('[Poly+] Loading avatar preview with avatar data: ', source);
for (const [key, value] of Object.entries(source.colors)) {
source.colors[key as keyof typeof source.colors] = "#" + value;
···
rightLegColor: source.colors.rightLeg,
};
-
const itemInfo: itemApiSchema = (await (await fetch(config.api.urls.public + "store/" + itemId)).json());
for (const item of [
-
...source.assets.filter((item) => (item.type != itemInfo.type || itemInfo.type == "hat")),
{
id: itemInfo.id,
type: itemInfo.type
}
]) {
if (item.type == "hat" || item.type == "tool") {
-
const mesh: meshApiSchema = (await (await fetch(config.api.urls.public + "assets/serve-mesh/" + item.id)).json());
if (mesh.success) {
if (item.type == "hat") {
avatar.items.push(mesh.url)
···
};
};
} else {
-
const texture: textureApiSchema = (await (await fetch(config.api.urls.public + "assets/serve/" + item.id + "/Asset")).json());
if (texture.success) avatar[item.type] = texture.url;
};
};
···
+
import "@/public/css/specific.css";
import config from "@/utils/config.json";
+
import { bricksToCurrency } from "@/utils/utilities";
+
import { userDetails } from "@/utils/types";
+
import * as apiTypes from "@/utils/api/types";
export function irlBrickPrice() {
try {
···
document.body.prepend(modal);
favoriteBtn.parentElement!.appendChild(button);
+
const loadFrame = async (source: apiTypes.avatarApiSchema) => {
console.info('[Poly+] Loading avatar preview with avatar data: ', source);
for (const [key, value] of Object.entries(source.colors)) {
source.colors[key as keyof typeof source.colors] = "#" + value;
···
rightLegColor: source.colors.rightLeg,
};
+
const itemInfo: apiTypes.itemApiSchema = (await (await fetch(config.api.urls.public + "store/" + itemId)).json());
for (const item of [
+
...source.assets.filter((item: any) => (item.type != itemInfo.type || itemInfo.type == "hat")),
{
id: itemInfo.id,
type: itemInfo.type
}
]) {
if (item.type == "hat" || item.type == "tool") {
+
const mesh: apiTypes.meshApiSchema = (await (await fetch(config.api.urls.public + "assets/serve-mesh/" + item.id)).json());
if (mesh.success) {
if (item.type == "hat") {
avatar.items.push(mesh.url)
···
};
};
} else {
+
const texture: apiTypes.textureApiSchema = (await (await fetch(config.api.urls.public + "assets/serve/" + item.id + "/Asset")).json());
if (texture.success) avatar[item.type] = texture.url;
};
};
+1 -1
utils/api.ts utils/api/index.ts
···
-
import config from "./config.json";
export async function batch(
type: "public" | "internal",
···
+
import config from "../config.json";
export async function batch(
type: "public" | "internal",
+106
utils/api/types.ts
···
···
+
type itemTypes = "hat" | "tool" | "face" | "shirt" | "pants" | "profileTheme";
+
+
export type userApiSchema = {
+
id: number,
+
username: string,
+
description: string,
+
signature: string,
+
thumbnail: {
+
avatar: string,
+
icon: string
+
},
+
playing: null|{},
+
netWorth: number,
+
placeVisits: number,
+
profileViews: number,
+
forumPosts: number,
+
assetSales: number,
+
membershipType: string,
+
isStaff: boolean,
+
registeredAt: string,
+
lastSeenAt: string
+
};
+
+
export type placeApiSchema = {
+
id: number,
+
name: string,
+
description: string,
+
creator: object,
+
thumbnail: string,
+
genre: string,
+
maxPlayers: number,
+
isActive: boolean,
+
visits: number,
+
uniqueVisits: number,
+
playing: number,
+
rating: object,
+
accessType: string,
+
accessPrice: number|null,
+
createdAt: string,
+
updatedAt: string
+
};
+
+
export type avatarApiSchema = {
+
id: string,
+
colors: {
+
head: string,
+
torso: string,
+
leftArm: string,
+
rightArm: string,
+
leftLeg: string,
+
rightLeg: string
+
},
+
assets: Array<{
+
id: number,
+
type: itemTypes,
+
accessoryType: string,
+
name: string,
+
thumbnail: string,
+
path: string
+
}>,
+
isDefault: boolean
+
};
+
+
export type itemApiSchema = {
+
id: number,
+
type: itemTypes,
+
accessoryType: string,
+
name: string,
+
description: string,
+
tags: Array<string>,
+
creator: {
+
type: string,
+
id: number,
+
name: string,
+
thumbnail: string
+
},
+
thumbnail: string,
+
price: number | null,
+
averagePrice: number | null,
+
version: number,
+
sales: number,
+
favorites: number,
+
totalStock: number | null,
+
onSaleUntil: string | null,
+
isLimited: boolean,
+
createdAt: string,
+
updatedAt: string | null
+
}
+
+
export type meshApiSchema = {
+
success: boolean,
+
url?: string,
+
errors?: Array<{
+
code: string,
+
message: string
+
}>
+
};
+
+
export type textureApiSchema = {
+
success: boolean,
+
url?: string,
+
errors?: Array<{
+
code: string,
+
message: string
+
}>
+
};
+1 -1
utils/storage.ts
···
irlBrickPrice: { enabled: true },
hideNotificationBadges: { enabled: false },
storeOwnedTags: { enabled: true },
-
membershipThemes: { enabled: false, themeId: "plus" },
}
export type preferencesSchema = typeof defaultPreferences & {
···
irlBrickPrice: { enabled: true },
hideNotificationBadges: { enabled: false },
storeOwnedTags: { enabled: true },
membershipThemes: { enabled: false, themeId: "plus" },
+
tryItems: { enabled: true }
}
export type preferencesSchema = typeof defaultPreferences & {
-107
utils/types.ts
···
-
type itemTypes = "hat" | "tool" | "face" | "shirt" | "pants";
-
-
export type userApiSchema = {
-
id: number,
-
username: string,
-
description: string,
-
signature: string,
-
thumbnail: {
-
avatar: string,
-
icon: string
-
},
-
playing: null|{},
-
netWorth: number,
-
placeVisits: number,
-
profileViews: number,
-
forumPosts: number,
-
assetSales: number,
-
membershipType: string,
-
isStaff: boolean,
-
registeredAt: string,
-
lastSeenAt: string
-
};
-
-
export type placeApiSchema = {
-
id: number,
-
name: string,
-
description: string,
-
creator: object,
-
thumbnail: string,
-
genre: string,
-
maxPlayers: number,
-
isActive: boolean,
-
visits: number,
-
uniqueVisits: number,
-
playing: number,
-
rating: object,
-
accessType: string,
-
accessPrice: number|null,
-
createdAt: string,
-
updatedAt: string
-
};
-
-
export type avatarApiSchema = {
-
id: string,
-
colors: {
-
head: string,
-
torso: string,
-
leftArm: string,
-
rightArm: string,
-
leftLeg: string,
-
rightLeg: string
-
},
-
assets: Array<{
-
id: number,
-
type: itemTypes,
-
accessoryType: string,
-
name: string,
-
thumbnail: string,
-
path: string
-
}>,
-
isDefault: boolean
-
}
-
-
export type itemApiSchema = {
-
id: number,
-
type: itemTypes,
-
accessoryType: string,
-
name: string,
-
description: string,
-
tags: Array<string>,
-
creator: {
-
type: string,
-
id: number,
-
name: string,
-
thumbnail: string
-
},
-
thumbnail: string,
-
price: number | null,
-
averagePrice: number | null,
-
version: number,
-
sales: number,
-
favorites: number,
-
totalStock: number | null,
-
onSaleUntil: string | null,
-
isLimited: boolean,
-
createdAt: string,
-
updatedAt: string | null
-
}
-
-
export type meshApiSchema = {
-
success: boolean,
-
url?: string,
-
errors?: Array<{
-
code: string,
-
message: string
-
}>
-
};
-
-
export type textureApiSchema = {
-
success: boolean,
-
url?: string,
-
errors?: Array<{
-
code: string,
-
message: string
-
}>
-
};
-
export type userDetails = {
username: string,
userId: number,
···
export type userDetails = {
username: string,
userId: number,