diff --git a/src/client/Client.js b/src/client/Client.js index 09bee5357efd..7377b7a80030 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -520,6 +520,9 @@ class Client extends BaseClient { if (typeof options.failIfNotExists !== 'boolean') { throw new TypeError('CLIENT_INVALID_OPTION', 'failIfNotExists', 'a boolean'); } + if (!Array.isArray(options.userAgentSuffix)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'userAgentSuffix', 'an array of strings'); + } if ( typeof options.rejectOnRateLimit !== 'undefined' && !(typeof options.rejectOnRateLimit === 'function' || Array.isArray(options.rejectOnRateLimit)) diff --git a/src/rest/APIRequest.js b/src/rest/APIRequest.js index c4487bf2a708..f5136165634d 100644 --- a/src/rest/APIRequest.js +++ b/src/rest/APIRequest.js @@ -17,6 +17,9 @@ class APIRequest { this.options = options; this.retries = 0; + const { userAgentSuffix } = this.client.options; + this.fullUserAgent = `${UserAgent}${userAgentSuffix.length ? `, ${userAgentSuffix.join(', ')}` : ''}`; + let queryString = ''; if (options.query) { const query = Object.entries(options.query) @@ -33,11 +36,14 @@ class APIRequest { ? this.client.options.http.api : `${this.client.options.http.api}/v${this.client.options.http.version}`; const url = API + this.path; - let headers = { ...this.client.options.http.headers }; + + let headers = { + ...this.client.options.http.headers, + 'User-Agent': this.fullUserAgent, + }; if (this.options.auth !== false) headers.Authorization = this.rest.getAuth(); if (this.options.reason) headers['X-Audit-Log-Reason'] = encodeURIComponent(this.options.reason); - headers['User-Agent'] = UserAgent; if (this.options.headers) headers = Object.assign(headers, this.options.headers); let body; diff --git a/src/util/Options.js b/src/util/Options.js index 01685be66e6e..cb366cb09be8 100644 --- a/src/util/Options.js +++ b/src/util/Options.js @@ -62,6 +62,8 @@ * {@link RateLimitError} will be thrown. Otherwise the request will be queued for later * @property {number} [retryLimit=1] How many times to retry on 5XX errors (Infinity for indefinite amount of retries) * @property {boolean} [failIfNotExists=true] Default value for {@link ReplyMessageOptions#failIfNotExists} + * @property {string[]} [userAgentSuffix] An array of additional bot info to be appended to the end of the required + * [User Agent](https://discord.com/developers/docs/reference#user-agent) header * @property {PresenceData} [presence={}] Presence data to use upon login * @property {IntentsResolvable} intents Intents to enable for this connection * @property {WebsocketOptions} [ws] Options for the WebSocket @@ -109,6 +111,7 @@ class Options extends null { restTimeOffset: 500, restSweepInterval: 60, failIfNotExists: true, + userAgentSuffix: [], presence: {}, ws: { large_threshold: 50, diff --git a/typings/index.d.ts b/typings/index.d.ts index 1dab6bd51aae..5e0320f37bc4 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2908,6 +2908,7 @@ export interface ClientOptions { restSweepInterval?: number; retryLimit?: number; failIfNotExists?: boolean; + userAgentSuffix?: string[]; presence?: PresenceData; intents: BitFieldResolvable; ws?: WebSocketOptions;