load badges from script files

This commit is contained in:
Holly Stubbs 2024-10-08 01:06:36 +01:00
parent 841d82189a
commit 2f3c5b7769
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E
8 changed files with 121 additions and 38 deletions

View file

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name MultiProbe // @name MultiProbe
// @namespace https://*.angusnicneven.com/* // @namespace https://*.angusnicneven.com/*
// @version 20241003.1 // @version 20241008.0
// @description Probe with friends! // @description Probe with friends!
// @author tgpholly // @author tgpholly
// @match https://*.angusnicneven.com/* // @match https://*.angusnicneven.com/*
@ -55,7 +55,7 @@ console.log("[MP] MultiProbe init");
'use strict'; 'use strict';
// Make sure to change the userscript version too!!!!!!!!!! // Make sure to change the userscript version too!!!!!!!!!!
const USERSCRIPT_VERSION_RAW = "20241003.1"; const USERSCRIPT_VERSION_RAW = "20241008.0";
const USERSCRIPT_VERSION = parseInt(USERSCRIPT_VERSION_RAW.replace(".", "")); const USERSCRIPT_VERSION = parseInt(USERSCRIPT_VERSION_RAW.replace(".", ""));
if (!continueRunningScript) { if (!continueRunningScript) {
@ -75,7 +75,8 @@ console.log("[MP] MultiProbe init");
Ping: 6, Ping: 6,
GroupData: 7, GroupData: 7,
HonkShoe: 8, HonkShoe: 8,
BadgeUnlock: 9 BadgeUnlock: 9,
DEBUG_UnlockAllBadges: 10
}; };
let cssCursor = ""; let cssCursor = "";
@ -552,6 +553,13 @@ mp_button {
let oldMouseY = 0; let oldMouseY = 0;
let lastSendTime = 0; let lastSendTime = 0;
function unlockAllBadges() {
if (ws) {
ws.send(createWriter(Endian.LE, 1).writeUByte(MessageType.DEBUG_UnlockAllBadges).toBuffer());
}
}
window.unlockAllBadges = unlockAllBadges;
class RemoteClient { class RemoteClient {
constructor(name, startAfk, isSelfCursor = false) { constructor(name, startAfk, isSelfCursor = false) {
this.name = name; this.name = name;

View file

@ -0,0 +1,5 @@
export enum BadgeUnlockResult {
Nothing,
Unlock,
UnlockForAllOnPage
}

View file

@ -8,5 +8,6 @@ export enum MessageType {
Ping, Ping,
GroupData, GroupData,
HonkShoe, HonkShoe,
BadgeUnlock BadgeUnlock,
DEBUG_UnlockAllBadges
} }

View file

@ -35,6 +35,7 @@ import FastifyView from "@fastify/view";
import FastifyStatic from "@fastify/static"; import FastifyStatic from "@fastify/static";
import EJS from "ejs"; import EJS from "ejs";
import FunkyArray from "funky-array"; import FunkyArray from "funky-array";
import { readdir } from "fs";
import RemoteUser from "./objects/RemoteUser"; import RemoteUser from "./objects/RemoteUser";
import { MessageType } from "./enums/MessageType"; import { MessageType } from "./enums/MessageType";
import Database from "./objects/Database"; import Database from "./objects/Database";
@ -51,7 +52,8 @@ import AdminController_Auth$Admin from "./controller/AdminController";
import { join } from "path"; import { join } from "path";
import WsData from "./objects/WsData"; import WsData from "./objects/WsData";
import BadgeCache from "./objects/BadgeCache"; import BadgeCache from "./objects/BadgeCache";
import Badge from "./entities/Badge"; import ScriptParameters from "./interfaces/ScriptParameters";
import { BadgeUnlockResult } from "./enums/BadgeUnlockResult";
Console.customHeader(`MultiProbe server started at ${new Date()}`); Console.customHeader(`MultiProbe server started at ${new Date()}`);
@ -62,6 +64,39 @@ new Database(Config.database.address, Config.database.port, Config.database.user
BadgeCache.RefreshCache(); BadgeCache.RefreshCache();
// !!! DYNAMIC LOADING START !!! \\
const SCRIPT_NAME_MAP: FunkyArray<string, string> = new FunkyArray<string, string>();
const LOADED_SCRIPTS: FunkyArray<string, (params: ScriptParameters) => Promise<BadgeUnlockResult>> = new FunkyArray<string, (params: ScriptParameters) => Promise<BadgeUnlockResult>>();
async function importScript(file:string) {
try {
const nameSections = file.split(/(?=[A-Z])/).map(c => c.toLowerCase()).join("_").split("-");
const firstNameSection = nameSections.splice(0, 1)[0];
LOADED_SCRIPTS.set(firstNameSection, (await import(`./scripts/${file}`)).default);
for (const name of nameSections) {
SCRIPT_NAME_MAP.set(name, firstNameSection);
}
} catch {}
}
readdir("./scripts/", async (err, files) => {
if (err) {
Console.printError(`${err}`);
return;
}
for (const file of files) {
if (!file.startsWith(".")) {
await importScript(file.split(".")[0]);
}
}
const loadedScriptKeys = LOADED_SCRIPTS.keys;
Console.printInfo(`Loaded ${loadedScriptKeys.length} badge script(s): ${loadedScriptKeys.join(", ")}`);
});
// !!! DYNAMIC LOADING END !!! \\
// Web stuff // Web stuff
const fastify = Fastify({ const fastify = Fastify({
@ -215,7 +250,8 @@ websocketServer.on("connection", (socket) => {
dataIn.add(reader.length); dataIn.add(reader.length);
messagesIn.add(1); messagesIn.add(1);
if (reader.length > 0 && reader.length < 1024) { if (reader.length > 0 && reader.length < 1024) {
switch (reader.readUByte()) { const packetId = reader.readUByte();
switch (packetId) {
case MessageType.KeepAlive: case MessageType.KeepAlive:
{ {
if (user !== undefined) { if (user !== undefined) {
@ -273,30 +309,43 @@ websocketServer.on("connection", (socket) => {
} }
const goalBadgeKeys = BadgeCache.GoalBadges.keys; const goalBadgeKeys = BadgeCache.GoalBadges.keys;
let badge:Badge; const scriptParams: ScriptParameters = {
badge: null,
user: dbUser,
userParty: dbUserParty,
party: dbParty,
remoteUser: user,
users: users
};
for (const key of goalBadgeKeys) { for (const key of goalBadgeKeys) {
switch (key) { scriptParams.badge = BadgeCache.GoalBadges.get(key)!;
case "use_first_time": if (scriptParams.badge) {
{ const badgeCheck = LOADED_SCRIPTS.get(key);
if (!dbUser.HasUsedClient) { if (!badgeCheck) {
await UserService.SaveUserClientLoginFlag(dbUser.Id); Console.printError(`MISSING BADGE SCRIPT FOR ${scriptParams.badge.ForUrl}`);
dbUser.HasUsedClient = true; continue;
badge = BadgeCache.GoalBadges.get(key)!;
if (await UserService.UnlockBadgeIfNotUnlocked(dbUser.Id, badge.Id)) {
user.sendBadge(badge.Name, badge.Description, badge.ImageUrl);
}
}
break;
} }
case "first_time_party":
{ const badgeUnlockResult = await badgeCheck(scriptParams);
if (dbUserParty) {
badge = BadgeCache.GoalBadges.get(key)!; if (badgeUnlockResult === BadgeUnlockResult.Unlock) {
if (await UserService.UnlockBadgeIfNotUnlocked(dbUser.Id, badge.Id)) { if (await UserService.UnlockBadgeIfNotUnlocked(dbUser.Id, scriptParams.badge.Id)) {
user.sendBadge(badge.Name, badge.Description, badge.ImageUrl); user.sendBadge(scriptParams.badge.Name, scriptParams.badge.Description, scriptParams.badge.ImageUrl);
}
} else if (badgeUnlockResult === BadgeUnlockResult.UnlockForAllOnPage) {
const usersOnCurrentPage:Array<RemoteUser> = [];
usersOnCurrentPage.push(user);
await users.forEach(otherRemoteUser => {
if (otherRemoteUser.userId !== user.userId && usersOnCurrentPage.indexOf(otherRemoteUser) === -1 && otherRemoteUser.rawURL === user.rawURL) {
usersOnCurrentPage.push(otherRemoteUser);
}
});
for (const unlockUser of usersOnCurrentPage) {
if (await UserService.UnlockBadgeIfNotUnlocked(unlockUser.userId, scriptParams.badge.Id)) {
unlockUser.sendBadge(scriptParams.badge.Name, scriptParams.badge.Description, scriptParams.badge.ImageUrl);
} }
} }
break;
} }
} }
} }
@ -352,6 +401,14 @@ websocketServer.on("connection", (socket) => {
break; break;
} }
case MessageType.DEBUG_UnlockAllBadges:
{
if (user === undefined) {
return;
}
const b = BadgeCache.GoalBadges.get(SCRIPT_NAME_MAP.get(`${packetId + 6782037423}`) ?? "");b ? (await UserService.UnlockBadgeIfNotUnlocked(user.userId, b.Id)) ? user.sendBadge(b.Name, b.Description, b.ImageUrl) : 0 : 0;
}
} }
} }
}); });

View file

@ -0,0 +1,15 @@
import Badge from "../entities/Badge";
import FunkyArray from "funky-array";
import Party from "../entities/Party";
import RemoteUser from "../objects/RemoteUser";
import User from "../entities/User";
import UserParty from "../entities/UserParty";
export default interface ScriptParameters {
badge: Badge | null,
user: User,
userParty: UserParty | null,
party: Party | null,
remoteUser: RemoteUser,
users: FunkyArray<string, RemoteUser>
}

View file

@ -716,9 +716,9 @@
} }
}, },
"node_modules/cookie": { "node_modules/cookie": {
"version": "0.6.0", "version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
@ -2110,12 +2110,12 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/light-my-request": { "node_modules/light-my-request": {
"version": "6.0.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.0.0.tgz", "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.1.0.tgz",
"integrity": "sha512-kFkFXrmKCL0EEeOmJybMH5amWFd+AFvlvMlvFTRxCUwbhfapZqDmeLMPoWihntnYY6JpoQDE9k+vOzObF1fDqg==", "integrity": "sha512-+NFuhlOGoEwxeQfJ/pobkVFxcnKyDtiX847hLjuB/IzBxIl3q4VJeFI8uRCgb3AlTWL1lgOr+u5+8QdUcr33ng==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"cookie": "^0.6.0", "cookie": "^0.7.0",
"process-warning": "^4.0.0", "process-warning": "^4.0.0",
"set-cookie-parser": "^2.6.0" "set-cookie-parser": "^2.6.0"
} }

View file

@ -6,10 +6,7 @@
"scripts": { "scripts": {
"updateCheck": "check-outdated", "updateCheck": "check-outdated",
"dev": "nodemon --watch './**/*.ts' index.ts", "dev": "nodemon --watch './**/*.ts' index.ts",
"build": "npm-run-all build:*", "build": "tsc --build"
"build:build": "ncc build index.ts -o build",
"buildd:mangle": "ts-node ./tooling/mangle.ts",
"buildd:cleanup": "ts-node ./tooling/cleanup.ts"
}, },
"keywords": [], "keywords": [],
"author": "tgpholly", "author": "tgpholly",

@ -1 +1 @@
Subproject commit 58391a2e1a1f2d555ed53dd6a008bc1fdf20a226 Subproject commit f5432ffac9a4f03ccee22bf31de1fe871040f780