diff --git a/LICENSE b/LICENSE index 9e9ef99..22c00c1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ BSD 3-Clause License Copyright (c) 2023, Team Vendetta +Copyright (c) 2024, pylixonly Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index 0dc8757..d32435a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ -# Vendetta +> [!NOTE] +> This fork is still progressing, own loader coming soon? +> TODO: better name + +# Pyondetta (Vendetta's fork) A mod for Discord's mobile apps. ## Installing -Vendetta's codebase is platform-agnostic, but you need a platform-specific loader. +Pyondetta's codebase is platform-agnostic, but you need a platform-specific loader. ### Android * Root - [VendettaXposed](https://github.com/vendetta-mod/VendettaXposed/releases/latest) @@ -17,13 +21,13 @@ Vendetta's codebase is platform-agnostic, but you need a platform-specific loade - These IPAs do *not* work with AltStore! You should use [Sideloadly](https://sideloadly.io). ## Contributing -1. Install a Vendetta loader with loader config support (any mentioned in the [Installing](#installing) section). +1. Install a Pyondetta loader with loader config support (any mentioned in the [Installing](#installing) section). 2. Go to Settings > General and enable Developer Settings. 3. Clone the repo: ``` - git clone https://github.com/vendetta-mod/Vendetta + git clone https://github.com/pyoncord/pyondetta ``` 4. Install dependencies: @@ -32,7 +36,7 @@ Vendetta's codebase is platform-agnostic, but you need a platform-specific loade ``` `npm` or `yarn` should also work. -5. Build Vendetta's code: +5. Build Pyondetta's code: ``` pnpm build ``` @@ -42,6 +46,6 @@ Vendetta's codebase is platform-agnostic, but you need a platform-specific loade 7. Go to Settings > Developer enabled earlier). Enable `Load from custom url` and input the IP address and port of the server (e.g. e.g. `http://192.168.1.236:4040`) in the new input box labelled `VENDETTA URL`. -8. Restart Discord. Upon reload, you should notice that your device will download Vendetta's bundled code from your server, rather than GitHub. +8. Restart Discord. Upon reload, you should notice that your device will download Pyondetta's bundled code from your server, rather than GitHub. 9. Make your changes, rebuild, reload, go wild! diff --git a/build.mjs b/build.mjs index 70d1b4a..1593917 100644 --- a/build.mjs +++ b/build.mjs @@ -1,34 +1,48 @@ -import { build } from "esbuild"; -import alias from "esbuild-plugin-alias"; +// eslint-disable-next-line simple-import-sort/imports import swc from "@swc/core"; -import { promisify } from "util"; -import { exec as _exec } from "child_process"; -import fs from "fs/promises"; -import path from "path"; +import { execSync } from "child_process"; +import esbuild from "esbuild"; +import { readFile } from "fs/promises"; +import { createServer } from "http"; import { argv } from "process"; -const exec = promisify(_exec); -const hasArg = condition => argv.some(i => condition.test(i)); -const isDev = hasArg(/-d|--dev/); +const isFlag = (s, l) => argv.slice(2).some(c => c === `-${s}` || c === `--${l}`); -const tsconfig = JSON.parse(await fs.readFile("./tsconfig.json")); -const aliases = Object.fromEntries(Object.entries(tsconfig.compilerOptions.paths).map(([alias, [target]]) => [alias, path.resolve(target)])); -const commit = (await exec("git rev-parse HEAD")).stdout.trim().substring(0, 7) || "custom"; +const isRelease = isFlag("r", "release"); +const shouldServe = isFlag("s", "serve"); +const shouldWatch = isFlag("w", "watch"); + +// TODO: This does not change unless you re-execute the script +const timeHash = Number(new Date).toString(36); +const commitHash = execSync("git rev-parse --short HEAD").toString().trim(); try { - await build({ - entryPoints: ["./src/entry.ts"], - outfile: "./dist/vendetta.js", - minify: !isDev, + const ctx = await esbuild.context({ + entryPoints: ["src/entry.js"], bundle: true, + minify: isRelease, format: "iife", target: "esnext", + outfile: "dist/pyoncord.js", + keepNames: true, + define: { + __vendettaIsDev: `${!isRelease}`, + __vendettaVersion: `"${isRelease ? commitHash : timeHash}"`, + }, + footer: { + js: "//# sourceURL=pyondetta" + }, + loader: { ".png": "dataurl" }, + legalComments: "none", + alias: { + "@*": "src*", + "@types": "src/def.d.ts" + }, plugins: [ { name: "swc", - setup: (build) => { - build.onLoad({ filter: /\.[jt]sx?/ }, async (args) => { - // This actually works for dependencies as well!! + setup(build) { + build.onLoad({ filter: /\.[jt]sx?/ }, async args => { const result = await swc.transformFile(args.path, { jsc: { externalHelpers: true, @@ -38,26 +52,56 @@ try { include: [ "transform-classes", "transform-arrow-functions", - ], + ] }, }); + return { contents: result.code }; }); - }, + } }, - alias(aliases), - ], - define: { - __vendettaIsDev: `${isDev}`, - __vendettaVersion: `"${isDev ? commit : "local build"}"`, - }, - footer: { - js: "//# sourceURL=Vendetta", - }, - legalComments: "none", + { + name: "buildLog", + setup: async build => { + build.onStart(() => console.log(`Building with commit hash "${commitHash}", isRelease="${isRelease}", timeHash="${timeHash}"`)); + build.onEnd(result => console.log(`Built with ${result.errors?.length} errors!`)); + } + } + ] }); - console.log("Build successful!", `isDev=${isDev}`); + if (shouldWatch) { + await ctx.watch(); + console.log("Watching..."); + } + + if (shouldServe) { + await ctx.rebuild(); + + const server = createServer(async (req, res) => { + try { + if (req.url === "/vendetta.js" || req.url === "/pyoncord.js" || req.url === "/pyondetta.js") { + await ctx.rebuild(); + res.writeHead(200); + res.end(await readFile("./dist/pyoncord.js"), "utf-8"); + } else { + res.writeHead(404); + res.end(); + } + } catch (error) { + res.writeHead(500); + res.end(); + } + }).listen(4040); + + // @ts-ignore + console.log(`Serving on port ${server.address()?.port}, CTRL+C to stop`); + } + + if (!shouldServe && !shouldWatch) { + ctx.rebuild(); + ctx.dispose(); + } } catch (e) { console.error("Build failed...", e); process.exit(1); diff --git a/package.json b/package.json index f155a94..7fd27bf 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,12 @@ { - "name": "vendetta", + "name": "pyondetta", "version": "1.0.0", "description": "A mod for Discord's mobile apps.", "scripts": { - "build": "node build.mjs" + "dev": "node build.mjs", + "build": "node build.mjs --release", + "serve": "node build.mjs --serve", + "watch": "node build.mjs --watch" }, "keywords": [ "discord", @@ -11,7 +14,7 @@ "ios", "react native" ], - "author": "Beef", + "author": "pylixonly, Team Vendetta", "license": "BSD-3-Clause", "devDependencies": { "@react-native-clipboard/clipboard": "1.10.0", diff --git a/src/entry.ts b/src/entry.ts index dec955b..0a06e95 100644 --- a/src/entry.ts +++ b/src/entry.ts @@ -1,7 +1,7 @@ import { ClientInfoManager } from "@lib/native"; // This logs in the native logging implementation, e.g. logcat -console.log("Hello from Vendetta!"); +console.log("Hello from Pyon-ified Vendetta!"); // Make 'freeze' and 'seal' do nothing Object.freeze = Object; diff --git a/src/ui/settings/components/SettingsSection.tsx b/src/ui/settings/components/SettingsSection.tsx index 5a7174f..e743846 100644 --- a/src/ui/settings/components/SettingsSection.tsx +++ b/src/ui/settings/components/SettingsSection.tsx @@ -15,7 +15,7 @@ export default function SettingsSection() { return ( - + {screens.map((s, i) => ( <> { return { getLayout: () => ({ - title: "Vendetta", - label: "Vendetta", + title: "Pyondetta", + label: "Pyondetta", // We can't use our keyMap function here since `settings` is an array not an object settings: getRenderableScreens(true).map(s => s.key) }), diff --git a/src/ui/settings/pages/Developer.tsx b/src/ui/settings/pages/Developer.tsx index 448d0db..62f8adb 100644 --- a/src/ui/settings/pages/Developer.tsx +++ b/src/ui/settings/pages/Developer.tsx @@ -61,7 +61,7 @@ export default function Developer() { } value={loaderConfig.customLoadUrl.enabled} onValueChange={(v: boolean) => { @@ -73,7 +73,7 @@ export default function Developer() { size="md" onChange={(v: string) => loaderConfig.customLoadUrl.url = v} placeholder="http://localhost:4040/vendetta.js" - label="Vendetta URL" + label="Pyondetta URL" />} />} {window.__vendetta_loader.features.devtools && navigation.push("VendettaCustomPage", { render: () => }) }, + { label: "Pyondetta", onPress: () => navigation.push("VendettaCustomPage", { render: () => }) }, { label: "Discord", isDestructive: true, onPress: () => navigation.push("VendettaCustomPage", { noErrorBoundary: true }) }, ], })} diff --git a/src/ui/settings/pages/General.tsx b/src/ui/settings/pages/General.tsx index ce9906f..5996526 100644 --- a/src/ui/settings/pages/General.tsx +++ b/src/ui/settings/pages/General.tsx @@ -24,7 +24,7 @@ export default function General() { const versions = [ { - label: "Vendetta", + label: "Pyondetta", version: debugInfo.vendetta.version, icon: "ic_progress_wrench_24px", }, diff --git a/src/ui/settings/patches/you.tsx b/src/ui/settings/patches/you.tsx index 62a4c44..6624150 100644 --- a/src/ui/settings/patches/you.tsx +++ b/src/ui/settings/patches/you.tsx @@ -44,7 +44,7 @@ function oldYouPatch(patches: Function[]) { ancestorRendererData: data.rendererConfigs[s.key], setting: s.key, title: data.titleConfig[s.key], - breadcrumbs: ["Vendetta"], + breadcrumbs: ["Pyondetta"], icon: data.rendererConfigs[s.key].icon, })), // .filter can be removed when dropping support for 189.3 and below (unless Discord changes things again) @@ -78,7 +78,7 @@ function newYouPatch(patches: Function[]) { patches.push(before("type", settingsListComponents.SearchableSettingsList, ([{ sections }]) => manipulateSections(sections, data.getLayout()))); patches.push(after("getSettingListSearchResultItems", gettersModule, (_, ret) => { - ret.forEach((s: any) => screens.some(b => b.key === s.setting) && (s.breadcrumbs = ["Vendetta"])) + ret.forEach((s: any) => screens.some(b => b.key === s.setting) && (s.breadcrumbs = ["Pyondetta"])) })); const oldRendererConfig = settingConstantsModule.SETTING_RENDERER_CONFIG; @@ -94,7 +94,7 @@ function newYouPatch(patches: Function[]) { const isLabel = (i: any, name: string) => i?.label === name || i?.title === name; function manipulateSections(sections: any[], layout: any) { - if (!Array.isArray(sections) || sections.find((i: any) => isLabel(i, "Vendetta"))) return; + if (!Array.isArray(sections) || sections.find((i: any) => isLabel(i, "Pyondetta"))) return; // Add our settings const accountSettingsIndex = sections.findIndex((i: any) => isLabel(i, i18n.Messages.ACCOUNT_SETTINGS));