Each installed script now saves a reference in IDB.

This commit is contained in:
wearrrrr 2024-04-16 12:41:08 -05:00
parent caf81f9f06
commit 3040dfc66e
5 changed files with 226 additions and 76 deletions

View file

@ -13,23 +13,23 @@ export async function masqrCheck(config) {
next(); next();
return; return;
} }
if (req.cookies["refreshcheck"] != "true") { if (req.cookies["refreshcheck"] != "true") {
res.cookie("refreshcheck", "true", { maxAge: 10000 }); // 10s refresh check res.cookie("refreshcheck", "true", { maxAge: 10000 }); // 10s refresh check
MasqFail(req, res); MasqFail(req, res);
return; return;
} }
if (!authheader) { if (!authheader) {
res.setHeader("WWW-Authenticate", "Basic"); res.setHeader("WWW-Authenticate", "Basic");
res.status(401); res.status(401);
MasqFail(req, res); MasqFail(req, res);
return; return;
} }
const auth = Buffer.from(authheader.split(" ")[1], "base64").toString().split(":"); const auth = Buffer.from(authheader.split(" ")[1], "base64").toString().split(":");
const pass = auth[1]; const pass = auth[1];
const licenseCheck = ( const licenseCheck = (
await (await fetch(config.licenseServer + pass + "&host=" + req.headers.host)).json() await (await fetch(config.licenseServer + pass + "&host=" + req.headers.host)).json()
)["status"]; )["status"];
@ -37,14 +37,16 @@ export async function masqrCheck(config) {
config.licenseServer + pass + "&host=" + req.headers.host + " returned " + licenseCheck config.licenseServer + pass + "&host=" + req.headers.host + " returned " + licenseCheck
); );
if (licenseCheck == "License valid") { if (licenseCheck == "License valid") {
res.cookie("authcheck", "true", { expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000) }); // authorize session, for like a year, by then the link will be expired lol res.cookie("authcheck", "true", {
expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000),
}); // authorize session, for like a year, by then the link will be expired lol
res.send(`<script> window.location.href = window.location.href </script>`); // fun hack to make the browser refresh and remove the auth params from the URL res.send(`<script> window.location.href = window.location.href </script>`); // fun hack to make the browser refresh and remove the auth params from the URL
return; return;
} }
MasqFail(req, res); MasqFail(req, res);
return; return;
} };
} }
async function MasqFail(req, res) { async function MasqFail(req, res) {

View file

@ -27,7 +27,7 @@
"footer.brand": "Alu", "footer.brand": "Alu",
"footer.madeWithLove": "Made with ❤️ by wearr", "footer.madeWithLove": "Made with ❤️ by wearr",
"footer.poweredBy": "Powered by Ultraviolet", "footer.poweredBy": "Titanium Network",
"footer.services": "Services", "footer.services": "Services",
"footer.socials": "Socials", "footer.socials": "Socials",
"footer.aluProject": "Alu Project", "footer.aluProject": "Alu Project",

View file

@ -27,7 +27,7 @@
"footer.brand": "アルー", "footer.brand": "アルー",
"footer.madeWithLove": "wearrによる❤で作られました", "footer.madeWithLove": "wearrによる❤で作られました",
"footer.poweredBy": "「ウルトラバイオレット」による駆動", "footer.poweredBy": "チタンネットワークサービス",
"footer.services": "サービス", "footer.services": "サービス",
"footer.socials": "ソーシャル", "footer.socials": "ソーシャル",
"footer.aluProject": "アループロジェクト", "footer.aluProject": "アループロジェクト",

View file

@ -1,9 +1,14 @@
{ {
"adblock": { "dev.wearr.adblock": {
"title": "Adblocker", "title": "Adblocker",
"version": "0.0.1", "version": "0.0.1",
"image": "/marketplace/adblock/adblock.png", "image": "/marketplace/adblock/adblock.png",
"script": "/marketplace/adblock/adblocker.js", "script": "/marketplace/adblock/adblocker.js"
"slug": "adblock" },
} "dev.wearr.adblock2": {
} "title": "Adblocker2",
"version": "0.0.2",
"image": "/marketplace/adblock/adblock.png",
"script": "/marketplace/adblock/adblocker.js"
}
}

View file

@ -1,76 +1,219 @@
--- ---
import { STATIC_PATHS } from "@i18n/utils"; import { STATIC_PATHS } from "@i18n/utils";
import Layout from "src/layouts/Layout.astro" import Layout from "src/layouts/Layout.astro";
import marketplace from "../../json/marketplace.json" import marketplace from "../../json/marketplace.json";
export const getStaticPaths = (() => { export const getStaticPaths = () => {
return STATIC_PATHS; return STATIC_PATHS;
}); };
type MarketplaceItem = { type MarketplaceItem = {
title: string, title: string;
version: string | number, version: string | number;
image: string, image: string;
script: string, script: string;
slug: string
}; };
--- ---
<Layout title="Marketplace | Alu"> <Layout title="Marketplace | Alu">
<div id="main-content"> <div id="main-content">
<h1 class="title-text">Marketplace</h1> <h1 class="title-text">Marketplace</h1>
<div class="marketplace-ext-grid"> <div class="marketplace-ext-grid">
{Object.keys(marketplace).map((mp_item) => { {
const item = (marketplace as {[key: string ]: MarketplaceItem})[mp_item] Object.keys(marketplace).map((mp_item) => {
return <div class="marketplace-item" id={item.slug}> const item = (marketplace as { [key: string]: MarketplaceItem })[mp_item];
<img class="marketplace-item-image" src={item.image} alt={`${item.title} Logo`}/> const slug = mp_item;
<div class="marketplace-item-title">{item.title}</div> console.log(slug);
<button class="marketplace-install-btn">Install</button> return (
</div> <div class="marketplace-item" data-slug={slug}>
})} <img class="marketplace-item-image" src={item.image} alt={`${item.title} Logo`} />
</div> <div class="marketplace-item-title">{item.title}</div>
<button class="marketplace-install-btn" data-slug={slug} data-title={item.title}>
Install
</button>
</div>
);
})
}
</div> </div>
</div>
</Layout> </Layout>
<script> <script>
const installButtons = document.getElementsByClassName("marketplace-install-btn") as HTMLCollectionOf<HTMLButtonElement>; import "notyf/notyf.min.css";
Array.from(installButtons).forEach(btn => { import { Notyf } from "notyf";
btn.addEventListener("click", (event) => { import marketplaceManifest from "../../json/marketplace.json";
console.log(event.target) const installButtons = document.getElementsByClassName(
}) "marketplace-install-btn"
) as HTMLCollectionOf<HTMLButtonElement>;
Array.from(installButtons).forEach((btn) => {
btn.addEventListener("click", async (event) => {
const ele = event.target as HTMLButtonElement;
const title = ele.dataset.title;
let notification = new Notyf({
duration: 999999,
position: { x: "right", y: "bottom" },
dismissible: true,
ripple: true,
});
let installNotif = notification.success(`Installing ${title}...`);
if (ele.dataset.slug) installExtension(getMarketplaceObj(ele.dataset.slug), ele.dataset.slug).then((code) => {
let notifMessage = "";
let timeout = 2000;
console.log(code)
switch (code) {
case 0:
notifMessage = `Installed ${title} Successfully!`;
break;
case 1:
notifMessage = `${title} is already installed!`;
timeout = 0;
break;
case -1:
// We should NEVER get here, but just in case.
notifMessage = `Failed to install ${title}!`;
break;
}
setTimeout(() => {
notification.dismiss(installNotif);
notification.options.duration = 2000;
notification.success(notifMessage)
notification.options.duration = 999999;
}, timeout)
}).catch(() => {
notification.dismiss(installNotif);
notification.options.duration = 2000;
notification.error(`Failed to install ${title}!`);
notification.options.duration = 999999;
});
else console.error("No slug found!");
}); });
});
type MarketplaceItem = {
title: string;
version: string | number;
image: string;
script: string;
};
function getMarketplaceObj(slug: string): ExtensionMetadata {
return (marketplaceManifest as { [key: string]: MarketplaceItem })[slug];
}
interface ExtensionMetadata {
title: string;
version: string | number;
script: string;
}
enum EXT_RETURN {
INSTALL_SUCCESS = 0,
INSTALL_FAILED = -1,
ALREADY_INSTALLED = 1,
}
async function installExtension(ext: ExtensionMetadata, slug: string) {
return new Promise((resolve, reject) => {
const request = window.indexedDB.open("AluDB", 1);
request.onupgradeneeded = (event) => {
const db = (event.target as IDBOpenDBRequest).result;
if (!db.objectStoreNames.contains("InstalledExtensions")) {
db.createObjectStore("InstalledExtensions", { keyPath: "slug" });
}
};
request.onsuccess = async (event) => {
const db = (event.target as IDBOpenDBRequest).result;
const transaction = db.transaction("InstalledExtensions", "readwrite");
const store = transaction.objectStore("InstalledExtensions");
const extensionObject = {
slug: slug,
title: ext.title,
version: ext.version,
script: ext.script,
};
// Check if the key already exists in the IDB
let slugCheck = store.get(slug);
slugCheck.onsuccess = (event) => {
if (slugCheck.result) {
resolve(EXT_RETURN.ALREADY_INSTALLED);
} else {
if (store.get(slug)) resolve(EXT_RETURN.ALREADY_INSTALLED);
const addRequest = store.add(extensionObject);
addRequest.onerror = (event) => {
console.error(`Error installing ${slug}!`)
reject(EXT_RETURN.INSTALL_FAILED);
};
addRequest.onsuccess = (event) => {
resolve(EXT_RETURN.INSTALL_SUCCESS);
};
}
};
slugCheck.onerror = (event) => {
console.error("Error checking install status!");
reject(EXT_RETURN.INSTALL_FAILED);
};
};
})
}
function InitIDB() {
if (!window.indexedDB) {
console.error("This browser doesn't support IndexedDB");
return;
}
const request = window.indexedDB.open("AluDB", 1);
request.onerror = (event: Event) => {
console.error("Database error: " + (event.target as any).errorCode);
};
request.onsuccess = (event) => {
console.log("Database opened successfully");
};
request.onupgradeneeded = (event) => {
const db = (event.target as IDBOpenDBRequest).result;
if (!db.objectStoreNames.contains("InstalledExtensions")) {
db.createObjectStore("InstalledExtensions", { keyPath: "slug" });
console.log("Database setup complete");
}
};
}
InitIDB();
</script> </script>
<style> <style>
.marketplace-ext-grid { .marketplace-ext-grid {
display: grid; display: grid;
width: 90%; width: 90%;
margin: 0 auto; margin: 0 auto;
color: var(--text-color); color: var(--text-color);
display: grid; display: grid;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
text-align: center; text-align: center;
justify-content: center; justify-content: center;
} gap: 20px;
.marketplace-item { }
border: 3px solid var(--accent-color); .marketplace-item {
padding: 20px; border: 3px solid var(--accent-color);
border-radius: 15px; padding: 20px;
} border-radius: 15px;
.marketplace-item-image { width: 180px;
width: 64px; }
height: 64px; .marketplace-item-image {
} width: 64px;
.marketplace-install-btn { height: 64px;
width: 100%; }
background-color: var(--accent-color); .marketplace-install-btn {
color: var(--text-color); width: 100%;
border: none; background-color: var(--accent-color);
margin-top: 3px; color: var(--text-color);
padding: 3px; border: none;
cursor: pointer; margin-top: 3px;
font-family: "Varela Round", sans-serif; padding: 3px;
} cursor: pointer;
</style> font-family: "Varela Round", sans-serif;
}
</style>