mirror of
https://github.com/Equicord/Equicord.git
synced 2025-02-20 15:18:50 -05:00
Cute Pats
This commit is contained in:
parent
0d9457e1bc
commit
8266478227
8 changed files with 354 additions and 10 deletions
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
|
@ -58,6 +58,9 @@ jobs:
|
|||
- name: Generate plugin list
|
||||
run: pnpm generatePluginJson dist/plugins.json dist/plugin-readmes.json
|
||||
|
||||
- name: Generate Equicord plugin list
|
||||
run: pnpm generateEquicordPluginJson dist/equicordplugins.json
|
||||
|
||||
- name: Clean up obsolete files
|
||||
run: |
|
||||
rm -rf dist/*-unpacked dist/monaco Vencord.user.css vencordDesktopRenderer.css vencordDesktopRenderer.css.map
|
||||
|
@ -66,3 +69,23 @@ jobs:
|
|||
if: github.repository == 'Equicord/Equicord'
|
||||
run: |
|
||||
gh release upload latest --clobber dist/*
|
||||
|
||||
- name: Upload DevBuild to builds repo
|
||||
if: github.repository == 'Equicord/Equicord'
|
||||
run: |
|
||||
git config --global user.name "$USERNAME"
|
||||
git config --global user.email "78185467+thororen1234@users.noreply.github.com"
|
||||
|
||||
git clone https://$USERNAME:$API_TOKEN@github.com/$GH_REPO.git upload
|
||||
cd upload
|
||||
|
||||
rm plugins.json
|
||||
cp -r ../dist/equicordplugins.json plugins.json
|
||||
|
||||
git add -A
|
||||
git commit -m "Plugins for https://github.com/$GITHUB_REPOSITORY/commit/$GITHUB_SHA"
|
||||
git push --force https://$USERNAME:$API_TOKEN@github.com/$GH_REPO.git
|
||||
env:
|
||||
API_TOKEN: ${{ secrets.ETOKEN }}
|
||||
GH_REPO: Equicord/Ignore
|
||||
USERNAME: thororen1234
|
||||
|
|
37
README.md
37
README.md
|
@ -21,7 +21,7 @@ An enhanced version of [Vencord](https://github.com/Vendicated/Vencord) by [Vend
|
|||
- Request for plugins from Discord.
|
||||
|
||||
<details>
|
||||
<summary>Extra included plugins (61 additional plugins)</summary>
|
||||
<summary>Extra included plugins (113 additional plugins)</summary>
|
||||
|
||||
- AllCallTimers by MaxHerbold and D3SOX
|
||||
- AltKrispSwitch by newwares
|
||||
|
@ -31,45 +31,69 @@ An enhanced version of [Vencord](https://github.com/Vendicated/Vencord) by [Vend
|
|||
- BetterActivities by D3SOX, Arjix, AutumnVN
|
||||
- BetterBanReasons by Inbestigator
|
||||
- BetterQuickReact by Ven and Sqaaakoi
|
||||
- BetterUserArea by Samwich
|
||||
- BlockKeywords by catcraft
|
||||
- BlockKrsip by D3SOX
|
||||
- BypassDND by Inbestigator
|
||||
- CleanChannelName by AutumnVN
|
||||
- ClientSideBlock by Samwich
|
||||
- ColorMessage by Kyuuhachi
|
||||
- CommandPalette by Ethan
|
||||
- CopyUserMention by Cortex and castdrian
|
||||
- CustomAppIcons by Happy Enderman and SerStars
|
||||
- CustomSounds by ScattrdBlade
|
||||
- CuteAnimeBoys by ShadyGoat
|
||||
- CuteNekos by echo
|
||||
- CutePats by thororen
|
||||
- DeadMembers by Kyuuhachi
|
||||
- Demonstration by Samwich
|
||||
- DiscordColorways by DaBluLite
|
||||
- DNDWhilePlaying by thororen
|
||||
- DoNotLeak by Perny
|
||||
- DontFilterMe by Samwich
|
||||
- DoubleCounterBypass by nyx
|
||||
- EmojiDumper by Cortex, Samwich, Woosh
|
||||
- Encryptcord by Inbestigator
|
||||
- EquicordCSS by FoxStorm1 and thororen (and all respective css developers)
|
||||
- ExportContacts by dat_insanity
|
||||
- FindReply by newwares
|
||||
- FrequentQuickSwitcher by Samwich
|
||||
- FriendshipRanks by Samwich
|
||||
- FriendTags by Samwich
|
||||
- GensokyoRadioRPC by RyanCaoDev and Prince527
|
||||
- GifRoulette by Samwich
|
||||
- Glide by Samwich
|
||||
- GlobalBadges by HypedDomi and Hosted by Wolfie
|
||||
- GodMode by Tolgchu
|
||||
- GoogleThat by Samwich
|
||||
- Grammar by Samwich
|
||||
- GrammarFix by unstream
|
||||
- HideMessage by Hanzy
|
||||
- HolyNotes by Wolfie
|
||||
- Hop On by ImLvna
|
||||
- HomeTyping by Samwich
|
||||
- HopOn by ImLvna
|
||||
- Identity by Samwich
|
||||
- IgnoreTerms by D3SOX
|
||||
- IrcColors by Grzesiek11
|
||||
- IRememberYou by zoodogood
|
||||
- JumpToStart by Samwich
|
||||
- KeyboardSounds by HypedDomi
|
||||
- KeywordNotify by camila314
|
||||
- MediaDownloader by Colorman
|
||||
- Meow by Samwich
|
||||
- MessageLinkTooltip by Kyuuhachi
|
||||
- MessageLoggerEnhanced by Aria
|
||||
- MessageTranslate by Samwich
|
||||
- ModalFade by Kyuuhachi
|
||||
- ModViewBypass by Sqaaakoi
|
||||
- NewPluginsManager by Sqaaakoi
|
||||
- noAppsAllowed by kvba
|
||||
- NoBulletPoints by Samwich
|
||||
- NoDefaultEmojis by Samwich
|
||||
- NoDeleteSafety by Samwich
|
||||
- NoModalAnimation by AutumnVN
|
||||
- NoNitroUpsell by thororen
|
||||
- NoRoleHeaders by Samwich
|
||||
- NotificationTitle by Kyuuhachi
|
||||
- NotifyUserChanges by D3SOX
|
||||
- OnePingPerDM by ProffDea
|
||||
|
@ -78,11 +102,13 @@ An enhanced version of [Vencord](https://github.com/Vendicated/Vencord) by [Vend
|
|||
- PhilsPluginLibrary by Philhk
|
||||
- PlatformSpoofer by Drag
|
||||
- PurgeMessages by bhop and nyx
|
||||
- Quest Completer by HappyEnderman, SerStars, thororen
|
||||
- QuestCompleter by HappyEnderman, SerStars, thororen
|
||||
- QuestionMarkReplacement by nyx
|
||||
- Quoter by Samwich
|
||||
- RepeatMessage by Tolgchu
|
||||
- ReplaceActivityTypes by Nyako
|
||||
- ReplyPingControl by ant0n and MrDiamond
|
||||
- RPCStats by Samwich
|
||||
- ScreenRecorder by AutumnVN
|
||||
- SearchFix by Jaxx
|
||||
- SekaiStickers by MaiKokain
|
||||
|
@ -92,14 +118,19 @@ An enhanced version of [Vencord](https://github.com/Vendicated/Vencord) by [Vend
|
|||
- SoundBoardLogger by Moxxie, fres, echo, thororen
|
||||
- TalkInReverse by Tolgchu
|
||||
- TeX by Kyuuhachi
|
||||
- TextToSpeech by Samwich
|
||||
- ThemeLibrary by Fafa
|
||||
- Title by Kyuuhachi
|
||||
- TosuRPC by AutumnVN
|
||||
- Translate+ by Prince527 (Using Translate by Ven)
|
||||
- TriggerWarning by Joona
|
||||
- UnlimitedAccounts by Balaclava and thororen
|
||||
- UserPFP by nexpid and thororen
|
||||
- UtilityDock by Samwich
|
||||
- UwUifier by echo
|
||||
- VCSupport by thororen
|
||||
- VencordRPC by AutumnVN
|
||||
- VideoSpeed by Samwich
|
||||
- ViewRaw2 by Kyuuhachi
|
||||
- VoiceChatUtilities by Dams and D3SOX
|
||||
- WebpackTarball by Kyuuhachi
|
||||
|
|
263
scripts/generateEquicordPluginList.ts
Normal file
263
scripts/generateEquicordPluginList.ts
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Vencord, a modification for Discord's desktop app
|
||||
* Copyright (c) 2023 Vendicated and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Dirent, readdirSync, readFileSync, writeFileSync } from "fs";
|
||||
import { access, readFile } from "fs/promises";
|
||||
import { join, sep } from "path";
|
||||
import { normalize as posixNormalize, sep as posixSep } from "path/posix";
|
||||
import { BigIntLiteral, createSourceFile, Identifier, isArrayLiteralExpression, isCallExpression, isExportAssignment, isIdentifier, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isSatisfiesExpression, isStringLiteral, isVariableStatement, NamedDeclaration, NodeArray, ObjectLiteralExpression, ScriptTarget, StringLiteral, SyntaxKind } from "typescript";
|
||||
|
||||
import { getPluginTarget } from "./utils.mjs";
|
||||
|
||||
interface Dev {
|
||||
name: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface PluginData {
|
||||
name: string;
|
||||
description: string;
|
||||
tags: string[];
|
||||
authors: Dev[];
|
||||
dependencies: string[];
|
||||
hasPatches: boolean;
|
||||
hasCommands: boolean;
|
||||
required: boolean;
|
||||
enabledByDefault: boolean;
|
||||
target: "discordDesktop" | "vencordDesktop" | "equicordDesktop" | "desktop" | "web" | "dev";
|
||||
filePath: string;
|
||||
}
|
||||
|
||||
const devs = {} as Record<string, Dev>;
|
||||
const equicordDevs = {} as Record<string, Dev>;
|
||||
|
||||
function getName(node: NamedDeclaration) {
|
||||
return node.name && isIdentifier(node.name) ? node.name.text : undefined;
|
||||
}
|
||||
|
||||
function hasName(node: NamedDeclaration, name: string) {
|
||||
return getName(node) === name;
|
||||
}
|
||||
|
||||
function getObjectProp(node: ObjectLiteralExpression, name: string) {
|
||||
const prop = node.properties.find(p => hasName(p, name));
|
||||
if (prop && isPropertyAssignment(prop)) return prop.initializer;
|
||||
return prop;
|
||||
}
|
||||
|
||||
function parseDevs() {
|
||||
const file = createSourceFile("constants.ts", readFileSync("src/utils/constants.ts", "utf8"), ScriptTarget.Latest);
|
||||
|
||||
for (const child of file.getChildAt(0).getChildren()) {
|
||||
if (!isVariableStatement(child)) continue;
|
||||
|
||||
const devsDeclaration = child.declarationList.declarations.find(d => hasName(d, "Devs"));
|
||||
if (!devsDeclaration?.initializer || !isCallExpression(devsDeclaration.initializer)) continue;
|
||||
|
||||
const value = devsDeclaration.initializer.arguments[0];
|
||||
|
||||
if (!isSatisfiesExpression(value) || !isObjectLiteralExpression(value.expression)) throw new Error("Failed to parse devs: not an object literal");
|
||||
|
||||
for (const prop of value.expression.properties) {
|
||||
const name = (prop.name as Identifier).text;
|
||||
const value = isPropertyAssignment(prop) ? prop.initializer : prop;
|
||||
|
||||
if (!isObjectLiteralExpression(value)) throw new Error(`Failed to parse devs: ${name} is not an object literal`);
|
||||
|
||||
devs[name] = {
|
||||
name: (getObjectProp(value, "name") as StringLiteral).text,
|
||||
id: (getObjectProp(value, "id") as BigIntLiteral).text.slice(0, -1)
|
||||
};
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error("Could not find Devs constant");
|
||||
}
|
||||
|
||||
function parseEquicordDevs() {
|
||||
const file = createSourceFile("constants.ts", readFileSync("src/utils/constants.ts", "utf8"), ScriptTarget.Latest);
|
||||
|
||||
for (const child of file.getChildAt(0).getChildren()) {
|
||||
if (!isVariableStatement(child)) continue;
|
||||
|
||||
const devsDeclaration = child.declarationList.declarations.find(d => hasName(d, "EquicordDevs"));
|
||||
if (!devsDeclaration?.initializer || !isCallExpression(devsDeclaration.initializer)) continue;
|
||||
|
||||
const value = devsDeclaration.initializer.arguments[0];
|
||||
|
||||
if (!isSatisfiesExpression(value) || !isObjectLiteralExpression(value.expression)) throw new Error("Failed to parse EquicordDevs: not an object literal");
|
||||
|
||||
for (const prop of value.expression.properties) {
|
||||
const name = (prop.name as Identifier).text;
|
||||
const value = isPropertyAssignment(prop) ? prop.initializer : prop;
|
||||
|
||||
if (!isObjectLiteralExpression(value)) throw new Error(`Failed to parse EquicordDevs: ${name} is not an object literal`);
|
||||
|
||||
equicordDevs[name] = {
|
||||
name: (getObjectProp(value, "name") as StringLiteral).text,
|
||||
id: (getObjectProp(value, "id") as BigIntLiteral).text.slice(0, -1)
|
||||
};
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error("Could not find EquicordDevs constant");
|
||||
}
|
||||
|
||||
async function parseFile(fileName: string) {
|
||||
const file = createSourceFile(fileName, await readFile(fileName, "utf8"), ScriptTarget.Latest);
|
||||
|
||||
const fail = (reason: string) => {
|
||||
return new Error(`Invalid plugin ${fileName}, because ${reason}`);
|
||||
};
|
||||
|
||||
for (const node of file.getChildAt(0).getChildren()) {
|
||||
if (!isExportAssignment(node) || !isCallExpression(node.expression)) continue;
|
||||
|
||||
const call = node.expression;
|
||||
if (!isIdentifier(call.expression) || call.expression.text !== "definePlugin") continue;
|
||||
|
||||
const pluginObj = node.expression.arguments[0];
|
||||
if (!isObjectLiteralExpression(pluginObj)) throw fail("no object literal passed to definePlugin");
|
||||
|
||||
const data = {
|
||||
hasPatches: false,
|
||||
hasCommands: false,
|
||||
enabledByDefault: false,
|
||||
required: false,
|
||||
tags: [] as string[]
|
||||
} as PluginData;
|
||||
|
||||
for (const prop of pluginObj.properties) {
|
||||
const key = getName(prop);
|
||||
const value = isPropertyAssignment(prop) ? prop.initializer : prop;
|
||||
|
||||
switch (key) {
|
||||
case "name":
|
||||
case "description":
|
||||
if (!isStringLiteral(value)) throw fail(`${key} is not a string literal`);
|
||||
data[key] = value.text;
|
||||
break;
|
||||
case "patches":
|
||||
data.hasPatches = true;
|
||||
break;
|
||||
case "commands":
|
||||
data.hasCommands = true;
|
||||
break;
|
||||
case "authors":
|
||||
if (!isArrayLiteralExpression(value)) throw fail("authors is not an array literal");
|
||||
data.authors = value.elements.map(e => {
|
||||
if (!isPropertyAccessExpression(e)) throw fail("authors array contains non-property access expressions");
|
||||
const d = devs[getName(e)!] || equicordDevs[getName(e)!];
|
||||
if (!d) throw fail(`couldn't look up author ${getName(e)}`);
|
||||
return d;
|
||||
});
|
||||
break;
|
||||
case "tags":
|
||||
if (!isArrayLiteralExpression(value)) throw fail("tags is not an array literal");
|
||||
data.tags = value.elements.map(e => {
|
||||
if (!isStringLiteral(e)) throw fail("tags array contains non-string literals");
|
||||
return e.text;
|
||||
});
|
||||
break;
|
||||
case "dependencies":
|
||||
if (!isArrayLiteralExpression(value)) throw fail("dependencies is not an array literal");
|
||||
const { elements } = value;
|
||||
if (elements.some(e => !isStringLiteral(e))) throw fail("dependencies array contains non-string elements");
|
||||
data.dependencies = (elements as NodeArray<StringLiteral>).map(e => e.text);
|
||||
break;
|
||||
case "required":
|
||||
case "enabledByDefault":
|
||||
data[key] = value.kind === SyntaxKind.TrueKeyword;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.name || !data.description || !data.authors) throw fail("name, description or authors are missing");
|
||||
|
||||
const target = getPluginTarget(fileName);
|
||||
if (target) {
|
||||
if (!["web", "discordDesktop", "vencordDesktop", "equicordDesktop", "desktop", "dev"].includes(target)) throw fail(`invalid target ${target}`);
|
||||
data.target = target as any;
|
||||
}
|
||||
|
||||
data.filePath = posixNormalize(fileName)
|
||||
.split(sep)
|
||||
.join(posixSep)
|
||||
.replace(/\/index\.([jt]sx?)$/, "")
|
||||
.replace(/^src\/plugins\//, "");
|
||||
|
||||
let readme = "";
|
||||
try {
|
||||
readme = readFileSync(join(fileName, "..", "README.md"), "utf-8");
|
||||
} catch { }
|
||||
return [data, readme] as const;
|
||||
}
|
||||
|
||||
throw fail("no default export called 'definePlugin' found");
|
||||
}
|
||||
|
||||
async function getEntryPoint(dir: string, dirent: Dirent) {
|
||||
const base = join(dir, dirent.name);
|
||||
if (!dirent.isDirectory()) return base;
|
||||
|
||||
for (const name of ["index.ts", "index.tsx"]) {
|
||||
const full = join(base, name);
|
||||
try {
|
||||
await access(full);
|
||||
return full;
|
||||
} catch { }
|
||||
}
|
||||
|
||||
throw new Error(`${dirent.name}: Couldn't find entry point`);
|
||||
}
|
||||
|
||||
function isPluginFile({ name }: { name: string; }) {
|
||||
if (name === "index.ts") return false;
|
||||
return !name.startsWith("_") && !name.startsWith(".");
|
||||
}
|
||||
|
||||
(async () => {
|
||||
parseDevs();
|
||||
parseEquicordDevs();
|
||||
|
||||
const plugins = [] as PluginData[];
|
||||
const readmes = {} as Record<string, string>;
|
||||
|
||||
await Promise.all(["src/equicordplugins"].flatMap(dir =>
|
||||
readdirSync(dir, { withFileTypes: true })
|
||||
.filter(isPluginFile)
|
||||
.map(async dirent => {
|
||||
const [data, readme] = await parseFile(await getEntryPoint(dir, dirent));
|
||||
plugins.push(data);
|
||||
if (readme) readmes[data.name] = readme;
|
||||
})
|
||||
));
|
||||
|
||||
const data = JSON.stringify(plugins);
|
||||
|
||||
if (process.argv.length > 3) {
|
||||
writeFileSync(process.argv[2], data);
|
||||
writeFileSync(process.argv[3], JSON.stringify(readmes));
|
||||
} else {
|
||||
console.log(data);
|
||||
}
|
||||
})();
|
|
@ -37,7 +37,7 @@ export const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "Anammox",
|
||||
description: "A microbial process that plays an important part in the nitrogen cycle",
|
||||
description: "Remove Some Discord Settings",
|
||||
authors: [Devs.Kyuuhachi],
|
||||
settings,
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ async function fetchReddit(sub: string) {
|
|||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "Cute-Anime-Boys",
|
||||
name: "CuteAnimeBoys",
|
||||
authors: [EquicordDevs.ShadyGoat],
|
||||
description: "Add a command to send cute anime boys in the chat",
|
||||
dependencies: ["CommandsAPI"],
|
||||
|
|
30
src/equicordplugins/cutePats/index.ts
Normal file
30
src/equicordplugins/cutePats/index.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
async function getcutepats(): Promise<string> {
|
||||
const res = await fetch("https://api.waifu.pics/sfw/pat");
|
||||
const url = (await res.json()).url as string;
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default definePlugin({
|
||||
name: "CutePats",
|
||||
description: "Pat Command",
|
||||
dependencies: ["CommandsAPI"],
|
||||
authors: [EquicordDevs.thororen],
|
||||
commands: [{
|
||||
name: "pat",
|
||||
description: "Baby don't hurt me no more",
|
||||
execute: async opts => ({
|
||||
content: await getcutepats()
|
||||
})
|
||||
}]
|
||||
});
|
|
@ -767,10 +767,7 @@ function getCSS(fontName) {
|
|||
export default definePlugin({
|
||||
name: "Glide",
|
||||
description: "A sleek, rounded theme for discord.",
|
||||
authors:
|
||||
[
|
||||
Devs.Samwich
|
||||
],
|
||||
authors: [Devs.Samwich],
|
||||
settings,
|
||||
start() {
|
||||
injectCSS();
|
||||
|
|
|
@ -112,7 +112,7 @@ function utilityDock({ children }: { children: ReactNode[]; }) {
|
|||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "utilityDock",
|
||||
name: "UtilityDock",
|
||||
description: "Adds a button on your titlebar with multiple useful features",
|
||||
authors: [Devs.Samwich],
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue