### Install Discord Bot Client via Winget Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/readme.md Installs the Discord Bot Client on Windows using the Windows Package Manager (Winget). This is a convenient way to get the latest stable version. ```shell winget install aiko-chan-ai.DiscordBotClient ``` -------------------------------- ### Install Dependencies and Fetch Vencord Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/readme.md Installs project dependencies and fetches the latest versions of Vencord and VencordDBCPlugin. If previously set up, it suggests running 'npm install' and 'git pull' for these components. ```sh npm run requirement ``` -------------------------------- ### Build Discord Bot Client from Source Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/readme.md Builds the Discord Bot Client from its source code. Requires NodeJS v16+ and Git. This process clones the repository, installs dependencies, and compiles the application. ```shell git clone https://github.com/aiko-chan-ai/DiscordBotClient.git cd DiscordBotClient npm run requirement npm run build ``` -------------------------------- ### Monaco Editor Setup and INI Language Features Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/AppCore/editor/index.html Initializes Monaco Editor, registers the INI language, and implements custom completion and hover providers. It fetches autocompletion data and applies it to the editor for enhanced INI file editing. ```JavaScript require.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@latest/min/vs', }, }); require(['vs/editor/editor.main'], async () => { monaco.languages.register({ id: 'ini' }); const AutoComplete = await window.settingsAPI.getAutoComplete(); monaco.languages.registerCompletionItemProvider('ini', { triggerCharacters: ['=', '\n', ...'abcdefghijklmnopqrstuvwxyz0123456789'.split('')], provideCompletionItems: function (model, position) { const existingKeys = new Set(); model.getLinesContent().forEach((line) => { const m = line.match(/^\s*([a-zA-Z0-9_]+)\s*=/); if (m) existingKeys.add(m[1]); }); const textUntilPos = model .getValueInRange({ startLineNumber: position.lineNumber, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column, }) .trim(); const KEYWORDS = Object.entries(AutoComplete).map(([key, value]) => ({ label: key, insertText: key + '=', kind: monaco.languages.CompletionItemKind.Property, documentation: { value: value.documentation, isTrusted: true, }, })); const ENUMS = {}; Object.entries(AutoComplete).forEach(([key, value]) => { if (value.enum) { ENUMS[key] = Object.entries(value.enum).map(([enumKey, enumValue]) => ({ label: enumKey, insertText: enumKey, kind: monaco.languages.CompletionItemKind.EnumMember, documentation: { value: enumValue.documentation, isTrusted: true, }, })); } }); if (/^[\[.*\]$/.test(textUntilPos) || textUntilPos === '') { return { suggestions: KEYWORDS.filter((k) => !existingKeys.has(k.label)), }; } const m = textUntilPos.match(/^([a-zA-Z0-9_]+)\s*=\s*([a-zA-Z0-9_]*)$/); if (m && ENUMS[m[1]]) { return { suggestions: ENUMS[m[1]], }; } return { suggestions: KEYWORDS.filter( (k) => !existingKeys.has(k.label) && k.label.includes(textUntilPos) ), }; }, }); monaco.languages.registerHoverProvider('ini', { provideHover: function (model, position) { const word = model.getWordAtPosition(position); if (!word) return; if (AutoComplete[word.word]) { return { range: new monaco.Range( position.lineNumber, word.startColumn, position.lineNumber, word.endColumn ), contents: [ { value: `**${word.word}**: ${AutoComplete[word.word].documentation}`, }, ], }; } }, }); let content = await window.settingsAPI.getCurrentSettings(); const editor = monaco.editor.create(document.getElementById('container'), { value: content, language: 'ini', theme: 'vs-dark', quickSuggestions: { other: true, comments: false, strings: true, }, automaticLayout: true, }); editor.onDidChangeModelContent(() => { if (editor.getValue() === content) { document.title = 'DiscordBotClient - Config Editor'; } else { document.title = 'DiscordBotClient - Config Editor (Unsaved Changes - Press Ctrl+S to save)'; } }); // Ctrl+S window.addEventListener('keydown', async (e) => { if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 's') { e.preventDefault(); await window.settingsAPI.saveCurrentSettings(editor.getValue()); content = await window.settingsAPI.getCurrentSettings(); const model = editor.getModel(); model.pushEditOperations([ { range: model.getFullModelRange(), text: content, }, ], () => null); } }); }); ``` -------------------------------- ### Optional: Update Discord-protos Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/readme.md Optional steps to update discord-protos, which requires the 'protoc' compiler to be installed. This process includes installing, updating, and building TypeScript definitions for protobuf files. ```sh npm run proto:install npm run proto:update npm run proto:build:ts ``` -------------------------------- ### Antivirus Exclusion Guides Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/readme.md Provides links to guides for excluding the DiscordBotClient from various antivirus software to prevent false positive detections. ```APIDOC Antivirus Exclusion Guides: - Windows Defender: https://support.microsoft.com/en-us/windows/add-an-exclusion-to-windows-security-811816c0-4dfd-af4a-47e4-c301afe13b26 - Avast: https://support.avast.com/en-ww/article/Antivirus-scan-exclusions#pc - AVG: https://support.avg.com/SupportArticleView?l=en&urlName=avg-antivirus-scan-exclusion - Norton: https://support.norton.com/sp/en/us/home/current/solutions/v3672136 - McAfee: https://www.mcafee.com/support/?page=shell&shell=article-view&articleId=TS102056 - For other antiviruses, try searching for " add exception" ``` -------------------------------- ### Get User Experiment Data (JavaScript) Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/AppAssets/Experiments.md Fetches and processes user experiment data from the Discord client. It uses Webpack to find necessary modules and retrieves experiment descriptors, filtering for user-specific experiments and cleaning the output. Requires access to the Discord client's internal modules. ```JavaScript (() => { var findByProps; if (window.Vencord) { findByProps = Vencord.Webpack.findByProps; } else { // https://discord.com/channels/603970300668805120/1085682686607249478/1085682686607249478 let _mods = webpackChunkdiscord_app.push([[Symbol()],{},r=>r.c]); webpackChunkdiscord_app.pop(); findByProps = (...props) => { for (let m of Object.values(_mods)) { try { if (!m.exports || m.exports === window) continue; if (props.every((x) => m.exports?.[x])) return m.exports; for (let ex in m.exports) { if (props.every((x) => m.exports?.[ex]?.[x]) && m.exports[ex][Symbol.toStringTag] !== 'IntlMessagesProxy') return m.exports[ex]; } } catch {} } } } const experimentModule = findByProps('getGuildExperimentBucket'); const experiments = Object.entries(experimentModule.getRegisteredExperiments()) .map(([id, data]) => ({ id, ...data })) .sort((a, b) => { const titleA = a.title.toLowerCase(); const titleB = b.title.toLowerCase(); return titleA < titleB ? -1 : titleA > titleB ? 1 : 0; }) .filter(exp => exp.type === "user"); const experimentData = {}; for (const experiment of experiments) { try { experimentData[experiment.id] = JSON.parse(JSON.stringify(experimentModule.getUserExperimentDescriptor(experiment.id))); delete experimentData[experiment.id].type delete experimentData[experiment.id].hashResult delete experimentData[experiment.id].assignmentSource delete experimentData[experiment.id].sessionId delete experimentData[experiment.id].loadedFromCache delete experimentData[experiment.id].fingerprint } catch (e) { console.log(experiment) } } copy(JSON.stringify(experimentData)); })(); ``` -------------------------------- ### Fast WebSocket Connection Logic (JavaScript) Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/DiscordCore/index.html Implements logic for establishing a fast WebSocket connection to the Discord gateway. It checks for existing tokens, determines encoding (ETF or JSON), and handles compression based on available browser features. ```javascript ! function() { if (null != window.WebSocket && function(n) { try { var o = localStorage.getItem(n); if (null == o) return null; return JSON.parse(o) } catch (e) { return null } }("token") && !window.__OVERLAY__) { var n = null != window.DiscordNative || null != window.require ? "etf" : "json", o = window.GLOBAL_ENV.GATEWAY_ENDPOINT + "/?encoding=" + n + "&v=" + window.GLOBAL_ENV.API_VERSION; null != window.DiscordNative && void 0 !== window.Uint8Array && void 0 !== window.TextDecoder ? o += "&compress=zstd-stream" : void 0 !== window.Uint8Array && (o += "&compress=zlib-stream"), console.log("[FAST CONNECT] " + o + ", encoding: " + n + ", version: " + window.GLOBAL_ENV.API_VERSION); var e = new WebSocket(o); e.binaryType = "arraybuffer"; var i = Date.now(), r = { open: !1, identify: !1, gateway: o, messages: [] }; e.onopen = function() { console.log("[FAST CONNECT] connected in " + (Date.now() - i) + "ms"), r.open = !0 }, e.onclose = e.onerror = function() { window._ws = null }, e.onmessage = function(n) { r.messages.push(n) }, window._ws = { ws: e, state: r } } }(); Discord window.__OVERLAY__ = /overlay/.test(location.pathname); window.__BILLING_STANDALONE__ = /^\/billing/.test(location.pathname); ``` -------------------------------- ### Cloudflare Challenge Platform Script (JavaScript) Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/DiscordCore/index.html Injects a script to handle Cloudflare's challenge platform, likely for security verification. It dynamically creates an iframe and appends a script to the head of the document. ```javascript (function() { function c() { var b = a.contentDocument || a.contentWindow.document; if (b) { var d = b.createElement('script'); d.nonce = 'MTg5LDE5Myw5NiwyNSw5MCwxMzYsODUsMTcx'; d.innerHTML = "window.__CF$cv$params={r:'95b87ad5dca9fd38',t:'MTc1MTkwMzI0MC4wMDAwMDA='};var a=document.createElement('script');a.nonce='MTg5LDE5Myw5NiwyNSw5MCwxMzYsODUsMTcx';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);"; b.getElementsByTagName('head')[0].appendChild(d) } } if (document.body) { var a = document.createElement('iframe'); a.height = 1; a.width = 1; a.style.position = 'absolute'; a.style.top = 0; a.style.left = 0; a.style.border = 'none'; a.style.visibility = 'hidden'; document.body.appendChild(a); if ('loading' !== document.readyState) c(); else if (window.addEventListener) document.addEventListener('DOMContentLoaded', c); else { var e = document.onreadystatechange || function() {}; document.onreadystatechange = function(b) { e(b); 'loading' !== document.readyState && (document.onreadystatechange = e, c()) } } } })(); ``` -------------------------------- ### Clone Repository Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/readme.md Clones the DiscordBotClient repository from GitHub and navigates into the project directory. This is the initial step for setting up or updating the project locally. ```sh git clone https://github.com/aiko-chan-ai/DiscordBotClient.git cd DiscordBotClient ``` -------------------------------- ### Global Environment Configuration (JavaScript) Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/DiscordCore/index.html Defines global environment variables for the Discord bot client, including API endpoints, build information, and feature flags. This object is crucial for the client's operation and customization. ```javascript window.GLOBAL_ENV = { "NODE_ENV": "production", "BUILT_AT": "1751578236599", "HTML_TIMESTAMP": Date.now(), "BUILD_NUMBER": "415772", "PROJECT_ENV": "production", "RELEASE_CHANNEL": "stable", "VERSION_HASH": "0c81c46c405c59b4774f3c2466ab6735d3f70cc1", "PRIMARY_DOMAIN": "discord.com", "SENTRY_TAGS": { "buildId": "0c81c46c405c59b4774f3c2466ab6735d3f70cc1", "buildType": "normal" }, "SENTRY_RELEASE": "2025-07-03-0c81c46c405c59b4774f3c2466ab6735d3f70cc1-discord_web", "PUBLIC_PATH": "/assets/", "LOCATION": "history", "API_VERSION": 9, "API_PROTOCOL": "https:", "API_ENDPOINT": "//discord.com/api", "GATEWAY_ENDPOINT": "wss://gateway.discord.gg", "STATIC_ENDPOINT": "", "ASSET_ENDPOINT": "//discord.com", "MEDIA_PROXY_ENDPOINT": "//media.discordapp.net", "IMAGE_PROXY_ENDPOINTS": "//images-ext-1.discordapp.net,//images-ext-2.discordapp.net", "CDN_HOST": "cdn.discordapp.com", "DEVELOPERS_ENDPOINT": "//discord.com", "MARKETING_ENDPOINT": "//discord.com", "WEBAPP_ENDPOINT": "//discord.com", "WIDGET_ENDPOINT": "//discord.com/widget", "SEO_ENDPOINT": "undefined", "NETWORKING_ENDPOINT": "//router.discordapp.net", "REMOTE_AUTH_ENDPOINT": "//remote-auth-gateway.discord.gg", "RTC_LATENCY_ENDPOINT": "//latency.discord.media/rtc", "INVITE_HOST": "discord.gg", "GUILD_TEMPLATE_HOST": "discord.new", "GIFT_CODE_HOST": "discord.gift", "ACTIVITY_APPLICATION_HOST": "discordsays.com", "MIGRATION_SOURCE_ORIGIN": "https://discordapp.com", "MIGRATION_DESTINATION_ORIGIN": "https://discord.com", "STRIPE_KEY": "pk_live_CUQtlpQUF0vufWpnpUmQvcdi", "ADYEN_KEY": "live_E3OQ33V6GVGTXOVQZEAFQJ6DJIDVG6SY", "BRAINTREE_KEY": "production_ktzp8hfp_49pp2rp4phym7387", "DEV_SESSION_KEY": "undefined" } ``` -------------------------------- ### Generate Discord Web Snapshot Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/readme.md Generates a snapshot for the latest version of Discord Web. This command is crucial for ensuring the client is compatible with the current Discord web client structure. ```sh npm run core:update ``` -------------------------------- ### User Experiment Structure Definition Source: https://github.com/aiko-chan-ai/discordbotclient/blob/electron-v3/AppAssets/Experiments.md Defines the structure of user experiment data as represented in the Discord client, detailing each field's purpose and type. ```APIDOC UserExperimentStructure: Represents the structure of user experiment data. Fields: hash (integer): 32-bit unsigned Murmur3 hash of the experiment's name. revision (integer): Current version of the rollout. bucket (integer): The requesting user or fingerprint's assigned experiment bucket. override (integer): Whether the user or fingerprint has an override for the experiment (-1 for false, 0 for true). population (integer): The internal population group the requesting user or fingerprint is in. hash_result (integer): The calculated rollout position to use, prioritized over local calculations. aa_mode (integer): The experiment's A/A testing mode, represented as an integer-casted boolean (0 for false, 1 for true). Note: The bucket for A/A tested experiments should always be None (-1) unless an override is present for the resource. trigger_debugging (integer): Whether the experiment's analytics trigger debugging is enabled, represented as an integer-casted boolean (0 for false, 1 for true). holdout_name (?string): A human-readable experiment name (formatted as year-month_name) that disables the experiment. holdout_revision (?integer): The revision of the holdout experiment. holdout_bucket (?integer): The requesting user or fingerprint's assigned bucket for the holdout experiment. Note: Holdout information is only present if the user or fingerprint has an assigned bucket for the holdout experiment. If holdout experiment information is present and the population bucket is set to None (-1), the experiment has been disabled by the holdout. Client handling is not required; follow the population field as usual. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.