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 { userDetails } from "@/utils/types";
3import * as apiTypes from "@/utils/api/types";
4import { getAPI } from "@/utils/api";
5const placeID = window.location.pathname.split("/")[3];
6
7/**
8 * Adds a button to the manage page of places allowing users to quickly download their place files from the website.
9 */
10export function placeFileExport() {
11 const publicAPI = getAPI("public");
12 const internalAPI = getAPI("internal");
13
14 if (!publicAPI.enabled || !internalAPI.enabled) {
15 throw new Error(
16 "[Poly+] API is disabled, cancelling place file export loading..",
17 );
18 }
19
20 const retrievePlaceFile = async function () {
21 const editReq: apiTypes.editApiSchema =
22 await (await fetch(internalAPI.url + "places/edit/", {
23 method: "POST",
24 body: JSON.stringify({
25 placeID: placeID,
26 }),
27 })).json();
28
29 if (!editReq.success) {
30 throw new Error(
31 "[Poly+] There was an error while retrieving the authenticated user's creator authorization token.",
32 );
33 }
34
35 const placeContents = await (await fetch(
36 `${publicAPI.url}places/get-place?id=${placeID}&tokenType=creator`,
37 {
38 headers: {
39 Authorization: editReq.token,
40 },
41 },
42 )).blob();
43
44 return placeContents;
45 };
46
47 const container = document.createElement("div");
48 container.classList.add("form-group", "mt-4");
49 container.innerHTML = `
50 <label class="mb-2">
51 <h5 class="mb-0">Download <code style="color: orange;">.poly</code> File</h5>
52 <small class="text-muted">Quickly download your place from the site!</small>
53 </label>
54 <br>
55 <button type="button" class="btn btn-primary">Download</button>
56 `;
57
58 const form = document.querySelector('form[action="/create/place/update"]')!;
59 const button = container.getElementsByTagName("button")[0]!;
60
61 form.insertBefore(container, form.children[form.children.length - 1]);
62
63 button.addEventListener("click", async () => {
64 button.innerHTML = `
65 <span class="spinner-grow spinner-grow-sm" aria-hidden="true"></span>
66 <span class="visually-hidden" role="status">Loading...</span>
67 `;
68
69 const placeContents = await retrievePlaceFile();
70 const blob = URL.createObjectURL(placeContents as any);
71 const link = document.createElement("a");
72
73 link.href = blob;
74 link.download = placeID + ".poly";
75 document.body.appendChild(link);
76 link.click();
77 link.remove();
78
79 button.textContent = "Download";
80 });
81}