Revert backend API integration on all classic plugins

This commit is contained in:
Ally Founder 2026-08-20 14:30:48 -04:00
parent 150fd62ad3
commit 0283f2e224
27 changed files with 149 additions and 366 deletions

View file

@ -1,7 +1,6 @@
import { logger } from "@vendetta";
import { id, storage } from "@vendetta/plugin";
import { storage } from "@vendetta/plugin";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import patchRowManager from "./patches/rowManager";
import patchTimestamp from "./patches/timestamp";
import Settings from "./ui/Settings";
@ -14,10 +13,10 @@ export default {
storage.customFormat ??= "dddd, MMMM Do YYYY, h:mm:ss a";
storage.separateMessages ??= false;
unpatchAll = guardPlugin(id, () => applyPatches("BetterTimestamps", logger, {
unpatchAll = applyPatches("BetterTimestamps", logger, {
"message & day timestamps": patchRowManager,
"message timestamp component": patchTimestamp
}));
});
},
onUnload: () => unpatchAll(),
settings: Settings

View file

@ -1,5 +1,4 @@
import { logger } from "@vendetta";
import { id } from "@vendetta/plugin";
import { findByName, findByStoreName } from "@vendetta/metro";
import { after } from "@vendetta/patcher";
import { findInReactTree } from "@vendetta/utils";
@ -7,7 +6,6 @@ import { clipboard } from "@vendetta/metro/common";
import { getAssetIDByName } from "@vendetta/ui/assets";
import { showToast } from "@vendetta/ui/toasts";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import { registerTypeDetector, registerIntercept, patchCreateElement } from "@shared/lib/createElementIntercept";
// A gradient role's real colors live at role.colorStrings ({primaryColor, secondaryColor,
@ -121,10 +119,10 @@ let unpatchAll: () => void = () => {};
export default {
onLoad: () => {
unpatchAll = guardPlugin(id, () => applyPatches("CopyRoleColor", logger, {
unpatchAll = applyPatches("CopyRoleColor", logger, {
"role pill long-press": patchRolePill,
"profile role item long-press": patchProfileRoleItem
}));
});
},
onUnload: () => unpatchAll()
};

View file

@ -1,7 +1,6 @@
import { logger } from "@vendetta";
import { id, storage } from "@vendetta/plugin";
import { storage } from "@vendetta/plugin";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import patchChat from "./patches/chat";
import patchName from "./patches/name";
import patchDetails from "./patches/details";
@ -15,13 +14,13 @@ export default {
onLoad: () => {
storage.tags ??= {};
unpatchAll = guardPlugin(id, () => applyPatches("Custom User Tags", logger, {
unpatchAll = applyPatches("Custom User Tags", logger, {
tag: patchTag,
chat: patchChat,
name: patchName,
details: patchDetails,
profile: patchProfile
}));
});
},
onUnload: () => unpatchAll(),
settings: Settings

View file

@ -1,7 +1,6 @@
import { logger } from "@vendetta";
import { id, storage } from "@vendetta/plugin";
import { storage } from "@vendetta/plugin";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import { FluxDispatcher } from "@fpte/lib/flux";
import { UserProfileStore, UserStore } from "@fpte/lib/stores";
import {
@ -37,7 +36,7 @@ export default {
// self-contained fallback picker instead.
storage.forceFallbackEffectPicker ??= true;
unpatchAll = guardPlugin(id, () => applyPatches("FakeProfileThemesAndEffects", logger, {
unpatchAll = applyPatches("FakeProfileThemesAndEffects", logger, {
"purchase check": patchGetPurchase,
"user profile data": patchGetUserProfile,
"profile effect sections": () => {
@ -47,7 +46,7 @@ export default {
"profile theme": patchUseProfileTheme,
"profile edit form": patchUserProfileEditForm,
"nitro upsell card": patchNitroUpsellCard
}));
});
updateProfileThemeAndEffect();
},
onUnload() {

View file

@ -1,10 +1,5 @@
import { id } from "@vendetta/plugin";
import { checkForUpdate } from "@shared/lib/reload";
import Settings from "./ui/Settings";
export default {
onLoad: () => {
checkForUpdate(id).catch(() => {});
},
settings: Settings
};

View file

@ -1,13 +1,12 @@
import { logger } from "@vendetta";
import { id, storage } from "@vendetta/plugin";
import { guardPlugin } from "@shared/lib/guard";
import { storage } from "@vendetta/plugin";
import Settings from "./ui/Settings";
import { patchFluxIntercept, rehydrateFromLog, revertFakedMessages } from "./patches/fluxIntercept";
import { patchRowStyling } from "./patches/rowStyling";
import { initCloudSync } from "./lib/cloudSync";
const TAG = "[MessageLogger]";
let unpatchAll: () => void = () => {};
const cleanups: (() => void)[] = [];
function initStorage() {
storage.options ??= {};
@ -33,20 +32,13 @@ export default {
initStorage();
console.log(TAG, "onLoad");
unpatchAll = guardPlugin(id, () => {
const cleanups: (() => void)[] = [];
let patched = 0;
if (patchFluxIntercept(cleanups)) patched++;
if (patchRowStyling(cleanups)) patched++;
cleanups.push(initCloudSync());
rehydrateFromLog();
let patched = 0;
if (patchFluxIntercept(cleanups)) patched++;
if (patchRowStyling(cleanups)) patched++;
cleanups.push(initCloudSync());
rehydrateFromLog();
console.log(TAG, `onLoad done - ${patched}/2 patches applied`);
return () => {
for (const fn of cleanups) fn();
cleanups.length = 0;
};
});
console.log(TAG, `onLoad done - ${patched}/2 patches applied`);
},
onUnload() {
console.log(TAG, "onUnload");
@ -55,7 +47,8 @@ export default {
} catch (e: any) {
logger.error("[MessageLogger] Failed to revert faked messages:", e?.message ?? e);
}
unpatchAll();
for (const fn of cleanups) fn();
cleanups.length = 0;
},
settings: Settings,
};

View file

@ -1,17 +1,12 @@
import { id } from "@vendetta/plugin";
import { guardPlugin } from "@shared/lib/guard";
import loadCommands from "./commands";
import Settings from "./ui/Settings";
let unpatchAll: () => void = () => {};
let unregisterFns: (() => void)[] = [];
export default {
onLoad: () => {
unpatchAll = guardPlugin(id, () => {
const unregisterFns = loadCommands();
return () => unregisterFns.forEach((fn) => fn());
});
unregisterFns = loadCommands();
},
onUnload: () => unpatchAll(),
onUnload: () => unregisterFns.forEach((fn) => fn()),
settings: Settings
};

View file

@ -1,7 +1,5 @@
import { logger } from "@vendetta";
import { id } from "@vendetta/plugin";
import { getAssetIDByName } from "@vendetta/ui/assets";
import { guardPlugin } from "@shared/lib/guard";
import Settings from "./ui/Settings";
import patchMoreAltsSection, { SectionRow } from "./patches/sidebarPin";
import patchContextMenu from "./patches/contextMenu";
@ -9,7 +7,10 @@ import patchNativeSwitcher from "./lib/nativeSwitcher";
import loadCommands from "./commands";
import { ensureStorage, getSettings } from "./lib/accounts";
let teardown: () => void = () => {};
let unpatchSidebar: (() => void) | undefined;
let unpatchContextMenu: (() => void) | undefined;
let unpatchNativeSwitcher: (() => void) | undefined;
let unregisterCommands: (() => void)[] = [];
function buildRows(): SectionRow[] {
if (!getSettings().addToSidebar) return [];
@ -29,47 +30,36 @@ export default {
onLoad() {
ensureStorage();
teardown = guardPlugin(id, () => {
let unpatchSidebar: (() => void) | undefined;
let unpatchContextMenu: (() => void) | undefined;
let unpatchNativeSwitcher: (() => void) | undefined;
let unregisterCommands: (() => void)[] = [];
try {
unpatchSidebar = patchMoreAltsSection(buildRows);
} catch (e: any) {
logger.error("[MoreAlts] Failed to patch sidebar:", e?.message ?? e);
}
try {
unpatchSidebar = patchMoreAltsSection(buildRows);
} catch (e: any) {
logger.error("[MoreAlts] Failed to patch sidebar:", e?.message ?? e);
}
try {
unpatchContextMenu = patchContextMenu();
} catch (e: any) {
logger.error("[MoreAlts] Failed to patch context menu:", e?.message ?? e);
}
try {
unpatchContextMenu = patchContextMenu();
} catch (e: any) {
logger.error("[MoreAlts] Failed to patch context menu:", e?.message ?? e);
}
try {
unpatchNativeSwitcher = patchNativeSwitcher();
} catch (e: any) {
logger.error("[MoreAlts] Failed to patch native switcher:", e?.message ?? e);
}
try {
unpatchNativeSwitcher = patchNativeSwitcher();
} catch (e: any) {
logger.error("[MoreAlts] Failed to patch native switcher:", e?.message ?? e);
}
try {
unregisterCommands = loadCommands();
} catch (e: any) {
logger.error("[MoreAlts] Failed to register commands:", e?.message ?? e);
}
return () => {
unpatchSidebar?.();
unpatchContextMenu?.();
unpatchNativeSwitcher?.();
unregisterCommands.forEach((u) => u());
unregisterCommands = [];
};
});
try {
unregisterCommands = loadCommands();
} catch (e: any) {
logger.error("[MoreAlts] Failed to register commands:", e?.message ?? e);
}
},
onUnload() {
teardown();
unpatchSidebar?.();
unpatchContextMenu?.();
unpatchNativeSwitcher?.();
unregisterCommands.forEach((u) => u());
unregisterCommands = [];
}
};

View file

@ -1,9 +1,7 @@
import { logger } from "@vendetta";
import { id } from "@vendetta/plugin";
import { after } from "@vendetta/patcher";
import { findInReactTree } from "@vendetta/utils";
import { rawFindByTypeName } from "@shared/lib/rawFind";
import { guardPlugin } from "@shared/lib/guard";
import PronounSection from "./ui/PronounSection";
import Settings from "./ui/Settings";
@ -68,25 +66,20 @@ function attempt() {
}
}
let teardown: () => void = () => {};
export default {
onLoad: () => {
teardown = guardPlugin(id, () => {
attempt();
if (!patched) {
let ticks = 0;
retryHandle = setInterval(() => {
attempt();
if (++ticks >= 30) stopRetrying(); // ~9s at 300ms, then give up
}, 300);
}
return () => {
stopRetrying();
unpatch();
};
});
attempt();
if (!patched) {
let ticks = 0;
retryHandle = setInterval(() => {
attempt();
if (++ticks >= 30) stopRetrying(); // ~9s at 300ms, then give up
}, 300);
}
},
onUnload: () => {
stopRetrying();
unpatch();
},
onUnload: () => teardown(),
settings: Settings
};

View file

@ -1,25 +1,14 @@
import { logger } from "@vendetta";
import { id } from "@vendetta/plugin";
import { findByStoreName } from "@vendetta/metro";
import { checkPluginStatus } from "@shared/lib/backend";
import { checkForUpdate } from "@shared/lib/reload";
import Settings from "./ui/Settings";
import { completeAllVideoQuests } from "./lib/questCompleter";
const UserStore = findByStoreName("UserStore");
export default {
onLoad: () => {
checkForUpdate(id).catch(() => {});
// Fire-and-forget: never blocks Discord's own boot, and a failure here (e.g. QuestStore
// not populated yet this session) is logged, not thrown - onLoad must not crash the app.
checkPluginStatus(UserStore?.getCurrentUser?.()?.id, id).then((status) => {
if (status.blocked) return;
completeAllVideoQuests().catch((e) => {
logger.error(`[QuestOrbs] Auto-run on load failed: ${e}`);
});
completeAllVideoQuests().catch((e) => {
logger.error(`[QuestOrbs] Auto-run on load failed: ${e}`);
});
},
onUnload: () => {},

View file

@ -1,7 +1,6 @@
import { logger } from "@vendetta";
import { id, storage } from "@vendetta/plugin";
import { storage } from "@vendetta/plugin";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import patchRing from "./patches/ringPatch";
import Settings from "./ui/Settings";
@ -22,9 +21,9 @@ export default {
};
storage.ringThickness ??= 2;
unpatchAll = guardPlugin(id, () => applyPatches("Radial Status", logger, {
unpatchAll = applyPatches("Radial Status", logger, {
ring: patchRing
}));
});
},
onUnload: () => unpatchAll(),
settings: Settings

View file

@ -1,22 +1,17 @@
import { id } from "@vendetta/plugin";
import { guardPlugin } from "@shared/lib/guard";
import loadCommands from "./commands";
import { startScheduler, stopScheduler } from "./lib/reminders";
import Settings from "./ui/Settings";
let unpatchAll: () => void = () => {};
let unregisterFns: (() => void)[] = [];
export default {
onLoad: () => {
unpatchAll = guardPlugin(id, () => {
const unregisterFns = loadCommands();
startScheduler();
return () => {
unregisterFns.forEach((fn) => fn());
stopScheduler();
};
});
unregisterFns = loadCommands();
startScheduler();
},
onUnload: () => {
unregisterFns.forEach((fn) => fn());
stopScheduler();
},
onUnload: () => unpatchAll(),
settings: Settings
};

View file

@ -1,15 +1,10 @@
import { id } from "@vendetta/plugin";
import { guardPlugin } from "@shared/lib/guard";
import loadCommands from "./commands";
let unpatchAll: () => void = () => {};
let unregisterFns: (() => void)[] = [];
export default {
onLoad: () => {
unpatchAll = guardPlugin(id, () => {
const unregisterFns = loadCommands();
return () => unregisterFns.forEach((fn) => fn());
});
unregisterFns = loadCommands();
},
onUnload: () => unpatchAll()
onUnload: () => unregisterFns.forEach((fn) => fn())
};

View file

@ -1,7 +1,6 @@
import { logger } from "@vendetta";
import { id, storage } from "@vendetta/plugin";
import { storage } from "@vendetta/plugin";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import patchRows from "./patches/rows";
import patchMemberList from "./patches/memberList";
import patchTypingWrapper from "./patches/typingWrapper";
@ -18,12 +17,12 @@ export default {
storage.hideTyping ??= false;
storage.chatInterpolation ??= 0;
unpatchAll = guardPlugin(id, () => applyPatches("RoleColorEverywhere", logger, {
unpatchAll = applyPatches("RoleColorEverywhere", logger, {
"mentions & chat text": patchRows,
"member list role headers": patchMemberList,
"typing indicator": patchTypingWrapper,
"voice channel names": patchVoiceUserConnected
}));
});
},
onUnload: () => unpatchAll(),
settings: Settings

View file

@ -1,13 +1,11 @@
import { logger } from "@vendetta";
import { id } from "@vendetta/plugin";
import { getAssetIDByName } from "@vendetta/ui/assets";
import { guardPlugin } from "@shared/lib/guard";
import Settings from "./ui/Settings";
import PluginsBrowser from "./ui/PluginsBrowser";
import patchRosiesPlugsSection, { SectionRow } from "./patches/settings";
import { discoverRosiesPlugins } from "./patches/discoverPlugins";
let teardown: () => void = () => {};
let unpatch: (() => void) | undefined;
function buildRows(): SectionRow[] {
const rows: SectionRow[] = [
@ -40,18 +38,15 @@ function buildRows(): SectionRow[] {
export default {
onLoad: () => {
teardown = guardPlugin(id, () => {
let unpatch: (() => void) | undefined;
try {
unpatch = patchRosiesPlugsSection(buildRows);
} catch (e: any) {
logger.error("[RosePlugs] Failed to patch settings:", e?.message ?? e);
}
return () => unpatch?.();
});
try {
unpatch = patchRosiesPlugsSection(buildRows);
} catch (e: any) {
logger.error("[RosePlugs] Failed to patch settings:", e?.message ?? e);
}
},
onUnload: () => {
teardown();
unpatch?.();
unpatch = undefined;
},
settings: Settings,
};

View file

@ -1,37 +1,28 @@
import { logger } from "@vendetta";
import { id } from "@vendetta/plugin";
import { guardPlugin } from "@shared/lib/guard";
import modules from "./modules";
import { vstorage } from "./lib/Module";
import Settings from "./ui/Settings";
let teardown: () => void = () => {};
export default {
onLoad() {
vstorage.modules ??= {};
teardown = guardPlugin(id, () => {
for (const module of modules) {
try {
if (module.storage.enabled) module.start();
} catch (e) {
logger.error(`[RoseUtils] Failed to start "${module.label}" on load: ${e}`);
}
for (const module of modules) {
try {
if (module.storage.enabled) module.start();
} catch (e) {
logger.error(`[RoseUtils] Failed to start "${module.label}" on load: ${e}`);
}
return () => {
for (const module of modules) {
try {
module.stop();
} catch (e) {
logger.error(`[RoseUtils] Failed to stop "${module.label}" cleanly: ${e}`);
}
}
};
});
}
},
onUnload() {
teardown();
for (const module of modules) {
try {
module.stop();
} catch (e) {
logger.error(`[RoseUtils] Failed to stop "${module.label}" cleanly: ${e}`);
}
}
},
settings: Settings,
};

View file

@ -6,12 +6,11 @@ import { patchExpanded, patchEmpty } from "./patches/contentPatch";
import { patchHideGuildsBar } from "./patches/hideGuildsBar";
import { patchTransparentBackground } from "./patches/transparentBackground";
import { patchCreateElement } from "./patches/createElementIntercept";
import { id, storage } from "@vendetta/plugin";
import { guardPlugin } from "@shared/lib/guard";
import { storage } from "@vendetta/plugin";
import Settings from "./ui/Settings";
const TAG = "[ServerDrawer]";
let unpatchAll: () => void = () => {};
const cleanups: (() => void)[] = [];
export default {
onLoad() {
@ -20,36 +19,30 @@ export default {
console.log(TAG, "onLoad");
unpatchAll = guardPlugin(id, () => {
const cleanups: (() => void)[] = [];
let patched = 0;
let patched = 0;
patchCreateElement(cleanups);
patched++;
patchCreateElement(cleanups);
patched++;
if (patchQuestDockRender(cleanups)) patched++;
if (patchQuestDockBase(cleanups)) patched++;
if (patchMobileQuestDock(cleanups)) patched++;
if (patchGetQuestAsset(cleanups)) patched++;
if (patchExpanded(cleanups)) patched++;
if (patchEmpty("QuestDockContentCollapsed", cleanups)) patched++;
if (patchEmpty("QuestDockEnrolledHeader", cleanups)) patched++;
if (patchEmpty("QuestDockUnenrolledHeader", cleanups)) patched++;
if (patchEmpty("QuestDockEnrolledBody", cleanups)) patched++;
if (patchEmpty("QuestDockUnenrolledBody", cleanups)) patched++;
if (patchHideGuildsBar(cleanups)) patched++;
if (patchTransparentBackground(cleanups)) patched++;
if (patchQuestDockRender(cleanups)) patched++;
if (patchQuestDockBase(cleanups)) patched++;
if (patchMobileQuestDock(cleanups)) patched++;
if (patchGetQuestAsset(cleanups)) patched++;
if (patchExpanded(cleanups)) patched++;
if (patchEmpty("QuestDockContentCollapsed", cleanups)) patched++;
if (patchEmpty("QuestDockEnrolledHeader", cleanups)) patched++;
if (patchEmpty("QuestDockUnenrolledHeader", cleanups)) patched++;
if (patchEmpty("QuestDockEnrolledBody", cleanups)) patched++;
if (patchEmpty("QuestDockUnenrolledBody", cleanups)) patched++;
if (patchHideGuildsBar(cleanups)) patched++;
if (patchTransparentBackground(cleanups)) patched++;
console.log(TAG, `onLoad done — ${patched} patches applied, ${cleanups.length} cleanups`);
return () => {
for (const fn of cleanups) fn();
cleanups.length = 0;
};
});
console.log(TAG, `onLoad done — ${patched} patches applied, ${cleanups.length} cleanups`);
},
onUnload() {
console.log(TAG, "onUnload");
unpatchAll();
for (const fn of cleanups) fn();
cleanups.length = 0;
},
settings: Settings,
};

View file

@ -1,10 +1,8 @@
import { findByProps, findByStoreName } from "@vendetta/metro";
import { instead } from "@vendetta/patcher";
import { id, storage } from "@vendetta/plugin";
import { storage } from "@vendetta/plugin";
import { getAssetIDByName } from "@vendetta/ui/assets";
import { showToast } from "@vendetta/ui/toasts";
import { checkPluginStatus } from "@shared/lib/backend";
import { checkForUpdate } from "@shared/lib/reload";
import { intoChunks } from "./lib/split";
import Settings from "./ui/Settings";
@ -22,8 +20,6 @@ export default {
onLoad() {
storage.splitOnWords ??= false;
checkForUpdate(id).catch(() => {});
const MaxLengthModule = findByProps("getMaxMessageLength");
const MessageActions = findByProps("sendMessage", "editMessage");
const UserStore = findByStoreName("UserStore");
@ -75,12 +71,6 @@ export default {
}
return (async () => {
const status = await checkPluginStatus(UserStore.getCurrentUser()?.id, id);
if (status.blocked) {
showToast("Split Messages is unavailable right now", getAssetIDByName("Small"));
return orig(args);
}
if (hasAttachments) {
await sendChunks(channelId, chunks, message);
if (chunks.length) await sleep(delayFor(channelId));
@ -108,12 +98,6 @@ export default {
}
return (async () => {
const status = await checkPluginStatus(UserStore.getCurrentUser()?.id, id);
if (status.blocked) {
showToast("Split Messages is unavailable right now", getAssetIDByName("Small"));
return orig(args);
}
const result = await orig(withArg(args, 2, { ...message, content: chunks.shift() }));
await sendChunks(channelId, chunks, message);
return result;

View file

@ -1,7 +1,6 @@
import { logger } from "@vendetta";
import { id, storage } from "@vendetta/plugin";
import { storage } from "@vendetta/plugin";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import patchChat from "./patches/chat";
import patchDetails from "./patches/details";
import patchName from "./patches/name";
@ -16,13 +15,13 @@ export default {
storage.useRoleColor ??= false;
storage.tags ??= {};
unpatchAll = guardPlugin(id, () => applyPatches("Staff Tags", logger, {
unpatchAll = applyPatches("Staff Tags", logger, {
tag: patchTag,
chat: patchChat,
name: patchName,
details: patchDetails,
profile: patchProfile
}));
});
},
onUnload: () => unpatchAll(),
settings: Settings

View file

@ -1,16 +1,14 @@
import { logger } from "@vendetta";
import { id } from "@vendetta/plugin";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import patchTypingIndicator from "./patches/typingIndicator";
let unpatchAll: () => void = () => {};
export default {
onLoad: () => {
unpatchAll = guardPlugin(id, () => applyPatches("TypingAvatars", logger, {
unpatchAll = applyPatches("TypingAvatars", logger, {
"typing indicator avatars": patchTypingIndicator
}));
});
},
onUnload: () => unpatchAll()
};

View file

@ -1,15 +1,10 @@
import { id } from "@vendetta/plugin";
import { guardPlugin } from "@shared/lib/guard";
import loadCommands from "./commands";
let unpatchAll: () => void = () => {};
let unregisterFns: (() => void)[] = [];
export default {
onLoad: () => {
unpatchAll = guardPlugin(id, () => {
const unregisterFns = loadCommands();
return () => unregisterFns.forEach((fn) => fn());
});
unregisterFns = loadCommands();
},
onUnload: () => unpatchAll()
onUnload: () => unregisterFns.forEach((fn) => fn())
};

View file

@ -1,13 +1,11 @@
// Forked from bwlok/revenge-plugins (plugins/ViewRaw), GPLv3. Original authors: sapphire, Vendicated, Bwlok.
// https://github.com/bwlok/revenge-plugins/tree/master/plugins/ViewRaw
import { before, after } from "@vendetta/patcher";
import { id } from "@vendetta/plugin";
import { getAssetIDByName } from "@vendetta/ui/assets";
import { findInReactTree } from "@vendetta/utils";
import { findByName, findByProps } from "@vendetta/metro";
import { React } from "@vendetta/metro/common";
import { Forms } from "@vendetta/ui/components";
import { guardPlugin } from "@shared/lib/guard";
import RawPage from "./RawPage";
import { recordDetection } from "./lib/diagnostics";
import Settings from "./ui/Settings";
@ -66,10 +64,9 @@ function actionSheetRowButton(navigator: () => JSX.Element) {
);
}
function applyViewRawPatches(): () => void {
const patches: (() => void)[] = [];
const patches: (() => void)[] = [];
const unpatchOpenLazy = before("openLazy", LazyActionSheet, ([component, key, msg]) => {
const unpatchOpenLazy = before("openLazy", LazyActionSheet, ([component, key, msg]) => {
if (key !== "MessageLongPressActionSheet" || !msg?.message) return;
component.then((instance: any) => {
@ -159,15 +156,7 @@ function applyViewRawPatches(): () => void {
patches.push(unpatchOpenLazy);
return () => patches.forEach((unpatch) => unpatch());
}
let unpatchAll: () => void = () => {};
export default {
onLoad: () => {
unpatchAll = guardPlugin(id, applyViewRawPatches);
},
onUnload: () => unpatchAll(),
onUnload: () => patches.forEach((unpatch) => unpatch()),
settings: Settings,
};

View file

@ -1,6 +1,5 @@
import { logger } from "@vendetta";
import { id, storage } from "@vendetta/plugin";
import { guardPlugin } from "@shared/lib/guard";
import { storage } from "@vendetta/plugin";
import patchYouBarButtons from "./patches/youBarButtons";
import { setInboxTracking } from "./lib/notifications";
import Settings from "./ui/Settings";
@ -32,8 +31,6 @@ function attempt() {
}
}
let teardown: () => void = () => {};
export default {
onLoad: () => {
storage.showDMButton ??= false;
@ -43,23 +40,18 @@ export default {
setInboxTracking(!!storage.showInboxButton);
teardown = guardPlugin(id, () => {
attempt();
if (!patched) {
let ticks = 0;
retryHandle = setInterval(() => {
attempt();
if (++ticks >= 30) stopRetrying(); // ~9s at 300ms, then give up
}, 300);
}
return () => {
stopRetrying();
unpatchButtons();
};
});
attempt();
if (!patched) {
let ticks = 0;
retryHandle = setInterval(() => {
attempt();
if (++ticks >= 30) stopRetrying(); // ~9s at 300ms, then give up
}, 300);
}
},
onUnload: () => {
teardown();
stopRetrying();
unpatchButtons();
setInboxTracking(false);
},
settings: Settings

View file

@ -1,7 +1,5 @@
import { logger } from "@vendetta";
import { id } from "@vendetta/plugin";
import { applyPatches } from "@shared/lib/patcher";
import { guardPlugin } from "@shared/lib/guard";
import patchAutoProcess from "./patches/autoProcess";
import { zStorage } from "./lib/api";
import Settings from "./ui/Settings";
@ -12,9 +10,9 @@ export default {
onLoad: () => {
zStorage();
unpatchAll = guardPlugin(id, () => applyPatches("Zipline", logger, {
unpatchAll = applyPatches("Zipline", logger, {
autoProcess: patchAutoProcess,
}));
});
},
onUnload: () => unpatchAll(),
settings: Settings,

View file

@ -1,48 +0,0 @@
const BASE_URL = "https://revenge-plugins-backend.allyapp.workers.dev";
export interface PluginStatus {
blocked: boolean;
latestHash: string | null;
}
export async function checkPluginStatus(userId: string | undefined, manifestUrl?: string): Promise<PluginStatus> {
if (!userId) return { blocked: true, latestHash: null };
try {
const params = new URLSearchParams({ userId });
if (manifestUrl) params.set("manifestUrl", manifestUrl);
const res = await fetch(`${BASE_URL}/status?${params}`);
if (!res.ok) return { blocked: true, latestHash: null };
const data = await res.json();
return { blocked: data?.blocked !== false, latestHash: data?.latestHash ?? null };
} catch {
return { blocked: true, latestHash: null };
}
}
export async function syncPull(pluginId: string, authToken: string): Promise<unknown> {
const res = await fetch(`${BASE_URL}/sync/${pluginId}`, {
headers: { Authorization: authToken }
});
if (!res.ok) throw new Error(`Sync pull failed: ${res.status}`);
return res.json();
}
export async function syncPush(pluginId: string, authToken: string, data: unknown): Promise<void> {
const res = await fetch(`${BASE_URL}/sync/${pluginId}`, {
method: "PUT",
headers: { Authorization: authToken, "Content-Type": "application/json" },
body: JSON.stringify(data)
});
if (!res.ok) throw new Error(`Sync push failed: ${res.status}`);
}
export async function syncDelete(pluginId: string, authToken: string): Promise<void> {
const res = await fetch(`${BASE_URL}/sync/${pluginId}`, {
method: "DELETE",
headers: { Authorization: authToken }
});
if (!res.ok) throw new Error(`Sync delete failed: ${res.status}`);
}

View file

@ -1,23 +0,0 @@
import { findByStoreName } from "@vendetta/metro";
import { checkPluginStatus } from "./backend";
import { checkForUpdate } from "./reload";
const UserStore = findByStoreName("UserStore");
export function guardPlugin(pluginId: string, applyPatches: () => () => void): () => void {
let unpatch = applyPatches();
let unloaded = false;
checkPluginStatus(UserStore?.getCurrentUser?.()?.id, pluginId).then((status) => {
if (unloaded || !status.blocked) return;
unpatch();
unpatch = () => {};
});
checkForUpdate(pluginId).catch(() => {});
return () => {
unloaded = true;
unpatch();
};
}

View file

@ -1,18 +0,0 @@
import { fetchPlugin, plugins, startPlugin, stopPlugin } from "@vendetta/plugins";
import { findByStoreName } from "@vendetta/metro";
import { checkPluginStatus } from "./backend";
const UserStore = findByStoreName("UserStore");
export async function checkForUpdate(pluginId: string): Promise<void> {
const plugin = plugins[pluginId];
if (!plugin) return;
const userId = UserStore?.getCurrentUser?.()?.id;
const status = await checkPluginStatus(userId, pluginId);
if (status.blocked || !status.latestHash || status.latestHash === plugin.manifest.hash) return;
stopPlugin(pluginId);
await fetchPlugin(pluginId);
await startPlugin(pluginId);
}