Hidden Disc Documentation

repository·main·Indexed 41 days ago

https://github.com/doggybootsy/hidden-disc-docs

Documentation and tools for advanced Discord API interaction, focusing on client modding, self-bots, and internal structures. Includes guides on re-enabling DevTools in the Discord desktop app, analyzing Discord token and Snowflake UserID structures, and utilizing self-bot frameworks like Discord.py-Self, Discord.JS-Selfbot-V13, and Discord.JS-Pure.

Tokens
15.4K
Snippets
25
Records
30
Agent score
53%

What's inside Hidden Disc

  1. Use Webhooks for data routing

    main

    Webhooks allow sending and receiving data without creating a formal bot. They are channel-specific and do not require external authorization if you possess the Webhook URL.

    Supported HTTP Methods:

    • POST: Send a message.
    • GET: Retrieve data about the webhook.
    • DELETE: Delete the webhook remotely.
  2. Understand Discord UserID (Snowflake) structure

    main

    Discord UserIDs follow a modified Snowflake format. The binary representation of a UserID is broken down as follows:

    • Timestamp: The first 42 bits represent the time elapsed since the Discord Epoch (1420070400000).
    • Worker ID: The next 5 bits.
    • Process ID: The next 5 bits.
    • Sequence/Count: The final 12 bits represent a count of Discord IDs.
  3. Understand Discord Token structure

    main

    A Discord token is an authorization string for an account. It consists of three sections separated by periods (.):

    1. User ID: The first section is the account's unique identifier, encoded in Base64. Decoding this section reveals the owner's UserID.
    2. Mint Date: The second section is the token's creation date in Unix time. It is encoded by converting the Unix timestamp to Hex, and then to Base64. To decode: Base64 $\rightarrow$ Hex $\rightarrow$ Decimal $\rightarrow$ Unix Date.
    3. Verification: The third section is a cryptographic HMAC (Hash-based Message Authentication Code) used by Discord for verification.

    Example token format: ODU4OTMyMDU4NjAwMjQzMjMw.YY4OOw.1hs4tL-J0dBMS_yKSTN6iuhqcPo

  4. API Authentication and Encoding

    main

    Authentication

    To access most endpoints, set the Authorization header of your request to a User or Bot token.

    • User tokens generally have fewer limitations but carry higher risk of account flags.
    • Bot tokens are subject to more frequent rate-limiting.

    Gateway Encoding

    When connecting to the Gateway, be aware of the encoding used by the client:

    • Discord Client Application: Uses etf encoding.
    • Web Browser: Uses json encoding.

    Using the incorrect encoding can allow Discord to identify your connection type (e.g., detecting a 'Browser' connection vs a 'Client' connection).

  5. Harvest Discord Internal Endpoints

    main

    You can extract the full list of Discord internal API endpoints directly from the client by using the getModule function in the browser console.

    Prerequisites:

    • You must have the getModule function available in your environment (refer to the getModule guide).

    Steps:

    1. Paste the getModule function into the console.
    2. Run the following script to iterate through the Endpoints module and construct full URLs using the client's GLOBAL_ENV.API_ENDPOINT and GLOBAL_ENV.API_VERSION constants.
    let e = [];
    for (let arrObj in Object.values(getModule("Endpoints").Endpoints).filter(arrObj => typeof arrObj === "string")) {
        e.push(`https:${window.GLOBAL_ENV.API_ENDPOINT }/v${window.GLOBAL_ENV.API_VERSION }${Object.values(getModule("Endpoints").Endpoints).filter(arrObj=>typeof arrObj==="string")[arrObj]}`)
    };
    console.log(e);
  6. Change HypeSquad Badge via API

    main

    Each HypeSquad badge is associated with a specific ID. You can change your badge by sending a POST request to the HypeSquad endpoint with your authorization token and the desired house_id.

    import requests
    
    token = input('What\'s your token?: ') 
    # Badge IDs: 1 = Bravery, 2 = Brilliance, 3 = Balance
    house = input('Which HypeSquad Badge do you want?\n[1]: Bravery\n[2]: Brilliance\n[3]: Balance\n\n> ') 
    
    try:
      house_id = int(house)
    except:
      print("You must input 1, 2, or 3!")
    
    JSON_PAYLOAD = {'house_id': house_id}
    JSON_HEADERS = {'Authorization': f'{token}'}
    
    r = requests.post('https://discordapp.com/api/v9/hypesquad/online', headers=JSON_HEADERS, json=JSON_PAYLOAD, timeout=10)
    if r.status_code == 204:
      print(f"Badge successfully changed!")
    else:
      print("There was an error changing your badge.")
  7. Re-enable Inspect Element in the Discord Desktop App

    main

    Discord disables the developer tools (Inspect Element) by default in the desktop application. To re-enable them, you must modify the settings.json file for your specific operating system.

    Steps:

    1. Locate your settings.json file:
      • Windows: %APPDATA%\discord\settings.json
      • Linux: ~/.config/discord/settings.json (or ~/.var/app/com.discordapp.Discord/config/discord/settings.json for Flatpak)
      • MacOS: ~/Library/Application Support/discord/settings.json
    2. Delete the existing content of the file.
    3. Paste the following configuration:
      {
        "BACKGROUND_COLOR": "#202225",
        "DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING": true
      }
    4. Restart Discord.
    5. Use CTRL + SHIFT + I to launch the DevTools.

    Note: Discord app updates may override this configuration file, requiring you to repeat these steps.

    {
    "BACKGROUND_COLOR": "#202225",
    "DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING": true
    }
  8. Create Friend Invites via JS snippet

    main

    You can generate a direct link that prompts others to add you as a friend by running this snippet in the Discord console. It automatically finds the createFriendInvite method within the Discord webpack modules and logs the resulting URL.

    webpackChunkdiscord_app.push([
        [Symbol()], {},
        async r => r?.c && console.log('https://discord.gg/' + (await Object.values(r.c).find(a => a.exports?.Z?.createFriendInvite).exports.Z.createFriendInvite()).code)
    ]);
    !!webpackChunkdiscord_app.pop();
  9. Log into Discord webapp using a User Token via Selenium

    main

    Because the Discord web frontend uses an iframe to handle login via localStorage, you can automate the login process using Selenium by injecting a script that sets the token in the iframe's localStorage and then reloads the page.

    Warning: This involves automating user accounts and should be used with caution regarding Discord's terms of service.

    # SCRIPT TAKEN FROM "https://github.com/Monst3red/Discord-Token-Login-Tool"
    
    import selenium
    from selenium import webdriver
    
    token = input("Token here: ")
    
    script = '''
        const login = (token) => {
            setInterval(() => document.body.appendChild(document.createElement `iframe`).contentWindow.localStorage.token = `"${token}"`, 50);
            setTimeout(() => location.reload(), 2500);
        };''' + f'login("{token}")' # adapted from "https://gist.github.com/m-Phoenix852/b47fffb0fd579bc210420cedbda30b61"
    
    driver = webdriver.Chrome("chromedriver.exe")
    driver.get("https://discord.com/login")
    driver.execute_script(script)
  10. Reveal injected JavaScript objects and variables

    main

    You can use the following JavaScript snippet in a browser console (like Chrome, Firefox, or the re-enabled Discord DevTools) to identify which objects, functions, and variables a website has added to the global window object. It works by comparing the current window keys against a list of standard default keys for the detected browser engine.

    To use it, paste the code into the console and call getAddedWindowValues().

    getAddedWindowValues = () => {
        const defaultWindowKeys = window.navigator.userAgent.toLowerCase().includes("chrome") ? ["window", "self", "document", "name", "location", "customElements", "history", "locationbar", "menubar", "personalbar", "scrollbars", "statusbar", "toolbar", "status", "closed", "frames", "length", "top", "opener", "parent", "frameElement", "navigator", "origin", "external", "screen", "innerWidth", "innerHeight", "scrollX", "pageXOffset", "scrollY", "pageYOffset", "visualViewport", "screenX", "screenY", "outerWidth", "outerHeight", "devicePixelRatio", "clientInformation", "screenLeft", "screenTop", "defaultStatus", "defaultstatus", "styleMedia", "onsearch", "isSecureContext", "performance", "onappinstalled", "onbeforeinstallprompt", "crypto", "indexedDB", "webkitStorageInfo", "sessionStorage", "localStorage", "onbeforexrselect", "onabort", "onblur", "oncancel", "oncanplay", "oncanplaythrough", "onchange", "onclick", "onclose", "oncontextmenu", "oncuechange", "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave", "ondragover", "ondragstart", "ondrop", "ondurationchange", "onemptied", "onended", "onerror", "onfocus", "onformdata", "oninput", "oninvalid", "onkeydown", "onkeypress", "onkeyup", "onload", "onloadeddata", "onloadedmetadata", "onloadstart", "onmousedown", "onmouseenter", "onmouseleave", "onmousemove", "onmouseover", "onmouseup", "onmousewheel", "onpause", "onplay", "onplaying", "onprogress", "onratechange", "onreset", "onresize", "onscroll", "onsecuritypolicyviolation", "onseeked", "onseeking", "onselect", "onslotchange", "onstalled", "onsubmit", "onsuspend", "ontimeupdate", "ontoggle", "onvolumechange", "onwaiting", "onwebkitanimationend", "onwebkitanimationiteration", "onwebkitanimationstart", "onwebkittransitionend", "onwheel", "onauxclick", "ongotpointercapture", "onlostpointercapture", "onpointerdown", "onpointermove", "onpointerup", "onpointercancel", "onpointerover", "onpointerout", "onpointerenter", "onpointerleave", "onselectstart", "onselectionchange", "onanimationend", "onanimationiteration", "onanimationstart", "ontransitionrun", "ontransitionstart", "ontransitionend", "ontransitioncancel", "onafterprint", "onbeforeprint", "onbeforeunload", "onhashchange", "onlanguagechange", "onmessage", "onmessageerror", "onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate", "onrejectionhandled", "onstorage", "onunhandledrejection", "onunload", "alert", "atob", "blur", "btoa", "cancelAnimationFrame", "cancelIdleCallback", "captureEvents", "clearInterval", "clearTimeout", "close", "confirm", "createImageBitmap", "fetch", "find", "focus", "getComputedStyle", "getSelection", "matchMedia", "moveBy", "moveTo", "open", "postMessage", "print", "prompt", "queueMicrotask", "releaseEvents", "reportError", "requestAnimationFrame", "requestIdleCallback", "resizeBy", "resizeTo", "scroll", "scrollBy", "scrollTo", "setInterval", "setTimeout", "stop", "structuredClone", "webkitCancelAnimationFrame", "webkitRequestAnimationFrame", "chrome", "caches", "cookieStore", "ondevicemotion", "ondeviceorientation", "ondeviceorientationabsolute", "oncontextlost", "oncontextrestored", "getScreenDetails", "showDirectoryPicker", "showOpenFilePicker", "showSaveFilePicker", "originAgentCluster", "trustedTypes", "speechSynthesis", "onpointerrawupdate", "crossOriginIsolated", "scheduler", "openDatabase", "webkitRequestFileSystem", "webkitResolveLocalFileSystemURL", "getAddedWindowValues"] : ["close", "stop", "focus", "blur", "open", "alert", "confirm", "prompt", "print", "postMessage", "captureEvents", "releaseEvents", "getSelection", "getComputedStyle", "matchMedia", "moveTo", "moveBy", "resizeTo", "resizeBy", "scroll", "scrollTo", "getDefaultComputedStyle", "scrollByLines", "scrollByPages", "sizeToContent", "updateCommands", "find", "dump", "setResizable", "requestIdleCallback", "cancelIdleCallback", "requestAnimationFrame", "cancelAnimationFrame", "reportError", "btoa", "atob", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "queueMicrotask", "createImageBitmap", "structuredClone", "fetch", "self", "name", "history", "customElements", "locationbar", "menubar", "personalbar", "scrollbars", "statusbar", "toolbar", "status", "closed", "event", "frames", "length", "opener", "parent", "frameElement", "navigator", "clientInformation", "external", "applicationCache", "screen", "innerWidth", "innerHeight", "scrollX", "pageXOffset", "scrollY", "pageYOffset", "screenLeft", "screenTop", "screenX", "screenY", "outerWidth", "performance", "mozInnerScreenX", "mozInnerScreenY", "devicePixelRatio", "scrollMaxX", "scrollMaxY", "fullScreen", "ondevicemotion", "ondeviceorientation", "onabsolutedeviceorientation", "InstallTrigger", "sidebar", "visualViewport", "crypto", "onabort", "onblur", "onfocus", "onauxclick", "onbeforeinput", "oncanplay", "oncanplaythrough", "onchange", "onclick", "onclose", "oncontextmenu", "oncuechange", "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragexit", "ondragleave", "ondragover", "ondragstart", "ondrop", "ondurationchange", "onemptied", "onended", "onformdata", "oninput", "oninvalid", "onkeydown", "onkeypress", "onkeyup", "onload", "onloadeddata", "onloadedmetadata", "onloadend", "onloadstart", "onmousedown", "onmouseenter", "onmouseleave", "onmousemove", "onmouseover", "onmouseup", "onwheel", "onpause", "onplay", "onplaying", "onprogress", "onratechange", "onreset", "onresize", "onscroll", "onsecuritypolicyviolation", "onseeked", "onseeking", "onselect", "onslotchange", "onstalled", "onsubmit", "onsuspend", "ontimeupdate", "ontoggle", "onvolumechange", "onwaiting", "onselectstart", "onselectionchange", "ontoggle", "onpointercancel", "onpointerdown", "onpointerup", "onpointermove", "onpointerout", "onpointerenter", "onpointerleave", "ongotpointercapture", "onlostpointercapture", "onmozfullscreenchange", "onmozfullscreenerror", "onanimationcancel", "onanimationend", "onanimationiteration", "onanimationstart", "ontransitioncancel", "ontransitionend", "ontransitionrun", "ontransitionstart", "onwebkitanimationend", "onwebkitanimationiteration", "onwebkitanimationstart", "ontransitionend", "u2f", "onerror", "speechSynthesis", "onafterprint", "onbeforeprint", "onbeforeunload", "onhashchange", "onlanguagechange", "onmessage", "onmessageerror", "onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate", "onrejectionhandled", "onstorage", "onunhandledrejection", "onunload", "ongamepadconnected", "ongamepaddisconnected", "localStorage", "origin", "crossOriginIsolated", "isSecureContext", "indexedDB", "caches", "sessionStorage", "window", "document", "location", "top", "ASRouterMessage", "ASRouterAddParentListener", "ASRouterRemoveParentListener", "RPMSendAsyncMessage", "RPMAddMessageListener", "RPMRemoveMessageListener", "ContentSearchUIController", "ContentSearchHandoffUIController", "React", "ReactDOM", "PropTypes", "ReactTransitionGroup", "Redux", "ReactRedux", "NewtabRenderUtils", "getAddedWindowValues"];
        return Object.fromEntries(Object.keys(window)
            .filter(key => !defaultWindowKeys.includes(key))
            .map(key => [key, window[key]]));
    };
    
    console.log(getAddedWindowValues());
  11. Retrieve hidden channels via JS snippet

    main

    Hidden channels are suppressed on the frontend but remain accessible via the API. You can use the following JavaScript snippet in the browser console to find all channel IDs for a specific guild that are not currently visible in the UI. The function returns an array of Channel objects (excluding categories).

    getHiddenChannels = (guildID) => { 
        const webpackCache = webpackChunkdiscord_app.push([
            [Symbol()], {}, (req) => Object.values(req.c)
        ]);
    
        // Prevent memory leak
        webpackChunkdiscord_app.pop();
        
        const { getMutableGuildChannelsForGuild } = webpackCache.find(m => m?.exports?.default?.getMutableGuildChannelsForGuild).exports.default;
    
        const allChannels = Object.keys(getMutableGuildChannelsForGuild(guildID));
        
        const { getChannels } = webpackCache.find(m => m?.exports?.default?.getChannels).exports.default;
        
        const visibleChannels = getChannels(guildID).SELECTABLE.map(c => c.channel.id);
    
        const { getChannel } = webpackCache.find(m => m?.exports?.default?.hasChannel).exports.default;
        
        return allChannels
            .filter(id => !visibleChannels.includes(id))
            .map(id => getChannel(id))
            .filter(c => !c.isCategory());
    };
    
    // Usage:
    getHiddenChannels("guildid12419012490owo");
  12. Enable or Disable Developer Mode via JS snippet

    main

    You can force the client to treat your account as a developer by overriding the isDeveloper property in the Discord webpack modules. This enables developer-specific options in the UI.

    // Enable Developer Mode
    Object.defineProperty(
        (window.webpackChunkdiscord_app.push([
                [""],
                {},
                (e) => {
                    m = [];
                    for (let c in e.c) {
                        m.push(e.c[c]);
                    }
                },
            ]),
            m).find((m) => m?.exports?.default?.isDeveloper !== void 0)
        .exports.default,
        "isDeveloper", {
            get: () => true,
            configurable: true,
        },
        window.webpackChunkdiscord_app.pop();
    );
    // Disable Developer Mode
    Object.defineProperty(
        (window.webpackChunkdiscord_app.push([
                [""],
                {},
                (e) => {
                    m = [];
                    for (let c in e.c) {
                        m.push(e.c[c]);
                    }
                },
            ]),
            m).find((m) => m?.exports?.default?.isDeveloper !== void 0)
        .exports.default,
        "isDeveloper", {
            get: () => false,
            configurable: true,
        },
        window.webpackChunkdiscord_app.pop();
    );