[Linux-only] basically bloxstap for sober

THE GOOBER PROJECT :fire:

+49 -4
src/features/roblox-logger.ts src/features/roblox-logger.opt.ts
+25
src/features/tgp.opt.ts
··· 1 + import { bloxstraprpc } from "../lib/Constants"; 2 + import * as fs from "fs"; 3 + import * as path from "path"; 4 + 5 + const loggedIdsFile = path.resolve(process.env.HOME || "~", ".tuxstrap_logged_ids"); 6 + 7 + // Ensure the file exists 8 + if (!fs.existsSync(loggedIdsFile)) { 9 + fs.writeFileSync(loggedIdsFile, "# TuxStrap thegooberproject.opt.ts\n# Here are the User IDs logged in order for The Goober Project to ban gooners.\n", { flag: "w" }); 10 + } 11 + 12 + bloxstraprpc.aw?.BloxstrapRPCEvent.on("PlayerEvent", (action: "JOIN" | "LEAVE", name: string, id: string) => { 13 + console.log(`[LOGGER] ${name} (${id}) ${action === "JOIN" ? "joined" : "left"} the server`); 14 + 15 + // Append the user ID to the file 16 + fs.appendFile(loggedIdsFile, `${id}\n`, (err) => { 17 + if (err) { 18 + console.error(`[ERROR] Failed to log ID ${id}:`, err); 19 + } 20 + }); 21 + }); 22 + 23 + bloxstraprpc.aw?.BloxstrapRPCEvent.on("ChatMessage", (text: string) => { 24 + console.log(`[CHAT] ${text}`); 25 + });
+5 -2
src/index.ts
··· 18 18 import chalk from "chalk"; 19 19 import { updateSoberConfigWithFeatures } from "./lib/SoberConfigManager"; 20 20 import { 21 + getOptionalFeaturesForCurrentProfile, 21 22 linkCurrentRobloxAccountCookies, 22 23 runSettingsManager, 23 24 } from "./lib/TuxstrapManager"; ··· 136 137 ); 137 138 process.exit(1); 138 139 } 139 - (opts.useFeatures as string[]) = readdirSync( 140 + (opts.useFeatures as string[]) = [...getOptionalFeaturesForCurrentProfile(), ...readdirSync( 140 141 join(__dirname, "features") 141 - ).map((a) => a.replace(".ts", "")); 142 + ).filter(a=>!a.endsWith(".opt.ts")).map((a) => a.replace(".ts", ""))]; 143 + 144 + 142 145 } 143 146 if (options.noFilemods === true) { 144 147 opts.useFilemods = false;
+5 -1
src/lib/SoberConfigManager/fflags.ts
··· 1 1 export const FeatureFFlags: {[feature: string]: { [key: string]: string | boolean | number }} = { 2 - ["roblox-logger"]: { 2 + ["roblox-logger.opt"]: { 3 + FStringDebugLuaLogLevel: "trace", 4 + FStringDebugLuaLogPattern: "ExpChat/mountClientApp" 5 + }, 6 + ["tgp.opt"]: { 3 7 FStringDebugLuaLogLevel: "trace", 4 8 FStringDebugLuaLogPattern: "ExpChat/mountClientApp" 5 9 }
+14 -1
src/lib/TuxstrapManager/index.ts
··· 36 36 nickname: string; 37 37 createdAt: string; 38 38 lastUsed: string; 39 + optionalFeatures?: string[]; 39 40 } 40 41 41 42 function createTuxstrapConfigDir(): void { ··· 130 131 nickname: profileName, 131 132 createdAt: new Date().toISOString(), 132 133 lastUsed: new Date().toISOString(), 134 + optionalFeatures: [], 133 135 }; 134 136 } 135 137 ··· 334 336 loadProfileState(current); 335 337 } 336 338 339 + export function getOptionalFeaturesForCurrentProfile(): string[] { 340 + const current = existsSync(CURRENT_PROFILE_FILE) 341 + ? readFileSync(CURRENT_PROFILE_FILE, "utf-8").trim() 342 + : null; 343 + if (!current) throw new Error("No current profile set."); 344 + return getProfileMetadata(current).optionalFeatures || []; 345 + } 346 + 337 347 /** 338 348 * Check if a directory is empty 339 349 */ ··· 354 364 * Debug function to list all files in a directory 355 365 */ 356 366 function debugListDirectory(dirPath: string, indent = ""): void { 357 - console.log(`${indent}Directory: ${dirPath}`); 367 + return; 368 + /* 369 + // console.log(`${indent}Directory: ${dirPath}`); 358 370 359 371 try { 360 372 if (!existsSync(dirPath)) { ··· 387 399 } catch (error) { 388 400 console.error(`Error listing directory: ${dirPath}`, error); 389 401 } 402 + */ 390 403 } 391 404 392 405 export async function runSettingsManager(): Promise<void> {