wavedev / Game Badge Spoofer

Last active 2 months ago

Like 0

Spoof your stats in game badge thingy.

Revision e5291b6a5b656c92df8ad45c1e281da5dd0034de

snippet.md Raw

Game Badge Spoofer

How to use

  • Crtl+shift+i to open Chrome Devtools.
  • Go to "Console"
  • type "allow pasting"
  • enter (ignore errors)
  • copy and paste the snippet
  • enter
  • profit

Snippet

const cache = {};

if (typeof DiscordNative === 'undefined') {
    console.log(
        '[rpc-spoofer] Browser is not supported. Please use Discord client :wilted_rose:.',
    );
} else {
    const req = webpackChunkdiscord_app.push([[Symbol()], {}, (r) => r]);
    webpackChunkdiscord_app.pop();

    const mods = Object.values(req.c);

    const api = mods.find((x) => x?.exports?.Bo?.get)?.exports?.Bo;
    const store = mods.find(
        (x) => x?.exports?.Ay?.getRunningGames,
    )?.exports?.Ay;
    const dispatcher = mods.find(
        (x) => x?.exports?.h?.__proto__?.flushWaitQueue,
    )?.exports?.h;

    if (!api || !store || !dispatcher) {
        throw new Error(
            '[rpc-spoofer] Failed to locate Discord internals.',
        );
    }

    const startedAt = Date.now();

    const log = (...args) =>
        console.log(
            `[rpc-spoofer +${((Date.now() - startedAt) / 1000).toFixed(1)}s]`,
            ...args,
        );

    const error = (...args) =>
        console.error(
            `[rpc-spoofer +${((Date.now() - startedAt) / 1000).toFixed(1)}s]`,
            ...args,
        );

    log('Initializing...');
    log('Fetching detectable applications...');

    api.get('/applications/detectable')
        .then(async ({ body: apps }) => {
            log(`Received ${apps.length} detectable applications.`);

            const targetCount = Math.min(100, apps.length);

            while (Object.keys(cache).length < targetCount) {
                const app = apps[(Math.random() * apps.length) | 0];

                if (app?.id) {
                    cache[app.id] = app;
                }
            }

            const ids = Object.keys(cache);

            log(`Cached ${ids.length} unique applications.`);

            let i = 0;
            let switchTimer = null;
            let heartbeatTimer = null;
            let nextSwitchAt = null;

            const cleanup = () => {
                const state = window.__rpcSpooferState;

                if (!state) {
                    log('No active spoof state to clean up.');
                    return;
                }

                log(
                    `Removing spoofed game: ${state.game.name} (${state.game.id})`,
                );

                state.store.getRunningGames = state.getGames;
                state.store.getGameForPID = state.getPID;

                state.dispatcher.dispatch({
                    type: 'RUNNING_GAMES_CHANGE',
                    removed: [state.game],
                    added: [],
                    games: state.getGames(),
                });

                delete window.__rpcSpooferState;

                log('Original RunningGameStore methods restored.');
            };

            const heartbeat = () => {
                const state = window.__rpcSpooferState;

                if (!state) {
                    log('HEARTBEAT | idle');
                    return;
                }

                const elapsed = Date.now() - state.game.start;
                const nextSwitch =
                    nextSwitchAt === null
                        ? 'none'
                        : `${Math.max(
                              0,
                              Math.ceil((nextSwitchAt - Date.now()) / 1000),
                          )}s`;

                let games;

                try {
                    games = state.store.getRunningGames();
                } catch (e) {
                    games = [];
                    error('Failed to read running games during heartbeat:', e);
                }

                log(
                    `HEARTBEAT | game="${state.game.name}"` +
                        ` id=${state.game.id}` +
                        ` pid=${state.game.pid}` +
                        ` alive=${games.some((x) => x?.pid === state.game.pid)}` +
                        ` uptime=${Math.floor(elapsed / 1000)}s` +
                        ` next=${nextSwitch}` +
                        ` progress=${i}/${ids.length}`,
                );
            };

            const spoof = async () => {
                cleanup();

                if (i >= ids.length) {
                    if (switchTimer) clearTimeout(switchTimer);
                    if (heartbeatTimer) clearInterval(heartbeatTimer);

                    log('All cached applications have been spoofed.');
                    return;
                }

                const id = ids[i];

                log(
                    `Fetching application ${id} (${i + 1}/${ids.length})...`,
                );

                try {
                    const requestStarted = performance.now();

                    const { body } = await api.get({
                        url: `/applications/public?application_ids=${id}`,
                    });

                    log(
                        `Application request completed in ${(
                            performance.now() - requestStarted
                        ).toFixed(1)}ms.`,
                    );

                    const app = body[0];

                    if (!app) {
                        error(`Cannot fetch application ${id}.`);
                        i++;
                        scheduleNext();
                        return;
                    }

                    const pid = (Math.random() * 3e4 + 1e3) | 0;

                    const exe =
                        app.executables
                            ?.find((x) => x.os === 'win32')
                            ?.name?.replace('>', '') ||
                        app.name.replace(/[\/\\:*?"<>|]/g, '');

                    const game = {
                        cmdLine: `C:\\Program Files\\${app.name}\\${exe}`,
                        exeName: exe,
                        exePath: `c:/program files/${app.name.toLowerCase()}/${exe}`,
                        hidden: false,
                        isLauncher: false,
                        id,
                        name: app.name,
                        pid,
                        pidPath: [pid],
                        processName: app.name,
                        start: Date.now(),
                    };

                    const realGames = store.getRunningGames();

                    log(
                        `Current real games: ${
                            realGames.length
                                ? realGames
                                      .map((x) => `${x.name} (${x.pid})`)
                                      .join(', ')
                                : 'none'
                        }`,
                    );

                    window.__rpcSpooferState = {
                        store,
                        dispatcher,
                        game,

                        getGames: store.getRunningGames,
                        getPID: store.getGameForPID,
                    };

                    store.getRunningGames = () => [game];

                    store.getGameForPID = (requestedPid) =>
                        requestedPid === pid ? game : undefined;

                    log('Dispatching RUNNING_GAMES_CHANGE...', {
                        removed: realGames.map((x) => ({
                            name: x.name,
                            pid: x.pid,
                        })),
                        added: [
                            {
                                name: game.name,
                                pid: game.pid,
                            },
                        ],
                    });

                    dispatcher.dispatch({
                        type: 'RUNNING_GAMES_CHANGE',
                        removed: realGames,
                        added: [game],
                        games: [game],
                    });

                    i++;

                    log(
                        `SPOOF ACTIVE | Playing: ${app.name} (${id}) | PID ${pid}`,
                    );

                    log(`Executable: ${exe}`);
                    log(`Path: ${game.exePath}`);

                    heartbeat();

                    scheduleNext();
                } catch (e) {
                    error(`Spoof error for application ${id}:`, e);

                    i++;

                    scheduleNext();
                }
            };

            const scheduleNext = () => {
                if (i >= ids.length) {
                    nextSwitchAt = null;
                    switchTimer = setTimeout(spoof, 0);
                    return;
                }

                const delay = ((Math.random() * 2) | 0) + 1;
                const delayMs = delay * 61_000;

                nextSwitchAt = Date.now() + delayMs;

                log(
                    `Next application switch in ${delayMs / 1000}s at ${new Date(
                        nextSwitchAt,
                    ).toLocaleTimeString()}.`,
                );

                switchTimer = setTimeout(spoof, delayMs);
            };

            heartbeatTimer = setInterval(heartbeat, 15_000);

            window.__stopRpcSpoofer = () => {
                log('Manual stop requested.');

                if (switchTimer) clearTimeout(switchTimer);
                if (heartbeatTimer) clearInterval(heartbeatTimer);

                cleanup();

                log('Stopped.');
            };

            log('Heartbeat interval: 15s');
            log('Use __stopRpcSpoofer() to stop and restore the store.');

            spoof();
        })
        .catch((e) => {
            error('Failed to fetch detectable applications:', e);
        });
}