Files
discord-decomp/modules/gateway/GatewaySocket.tsx
T
2026-11-01 12:12:55 +02:00

941 lines
34 KiB
TypeScript

// Metro module 12692 (f12693).
import _slicedToArray from "../../_bundle/_slicedToArray";
import DeveloperOptionsStore from "../../stores/DeveloperOptionsStore";
import { Endpoints, AnalyticEvents } from "../../Constants";
import Logger from "../debug/Logger";
import GatewayEncoding from "./GatewayEncoding";
import createWebSocket_android from "./createWebSocket.android";
import Durations from "../../utils/Durations";
import GatewaySocketOpCodes, { Opcode } from "./GatewaySocketOpCodes";
import Backoff from "../../_bundle/Backoff";
import AltGatewayTracker from "./AltGatewayTracker";
import GatewaySocketDispatcher from "./GatewaySocketDispatcher";
import ConnectionState from "./ConnectionState";
import { getCompressionHandler } from "./GatewayCompressionHandler";
import { getIsPaused } from "./PauseGatewaySocket";
import Module10 from "../../_bundle/Module10";
import TTITracker from "../tti_analytics/TTITracker";
import CrossPlatformNativeUtils_native from "../../utils/CrossPlatformNativeUtils.native";
import { getConnectionPath, logGatewayConnected, createResumeAnalytics } from "./GatewaySocketAnalytics";
import { isIOS } from "../../utils/PlatformUtils";
import { HTTP } from "../../_bundle/sendRequest";
import AnalyticsUtils from "../../utils/AnalyticsUtils";
import Module38 from "../../_bundle/Module38";
import Module589 from "../../_bundle/Module589";
import { isCacheEnabled } from "../cache/isCacheEnabled.native";
import GuildVersions from "../app_database/modules/GuildVersions";
import NonGuildVersions from "../app_database/modules/NonGuildVersions";
import KvCacheVersion from "../app_database/modules/KvCacheVersion";
import { getClientCapabilities } from "./GatewayCapabilities";
import { isChannelMetadataObfuscationEnabled } from "./PrivateChannelHidingExperiment";
import { deflate } from "../../_bundle/Module12711";
import { usesClientMods } from "../../_bundle/Module667";
import MonitoringAgent from "../monitoring/MonitoringAgent";
import { MetricEvents } from "../../_bundle/Module5872";
import SentryUtils_native from "../../utils/SentryUtils.native";
import Dispatcher from "../../Dispatcher";
let byteSize, c8746_9, c8746_10, c8746_13, c8746_14, c8746_15, c8746_16, GATEWAY_ENDPOINT, c8746_19;
let env8746 = {};
const noop = function noop() {};
byteSize = function byteSize(a0) {
return a0 == null ? 0 : typeof a0 === "string" ? a0.length : a0.byteLength;
};
c8746_9 = new Logger("GatewaySocket");
c8746_10 = new GatewayEncoding();
env8746[11] = null;
c8746_13 = 4004;
c8746_14 = 30 * Durations.Millis.SECOND;
c8746_15 = 3 * Durations.Millis.MINUTE;
c8746_16 = 1 * Durations.Millis.MINUTE;
GATEWAY_ENDPOINT = window.GLOBAL_ENV.GATEWAY_ENDPOINT;
class GatewaySocket extends GatewaySocketOpCodes {
dispatchExceptionBackoff = new Backoff(1000, c8746_16);
dispatchSuccessTimer = 0;
didForceClearGuildHashes = false;
identifyUncompressedByteSize = 0;
identifyCompressedByteSize = 0;
analytics = {};
identifyCount = 0;
resumeUrl = null;
iosGoingAwayEventCount = 0;
altGateway = new AltGatewayTracker();
failedConnectAttempts = 0;
receivedHelloThisAttempt = false;
heartbeatQOSState = {
currentPayload: null,
upcomingState: null
};
send = (a0, a1, a2) => {
if (DeveloperOptionsStore.isLoggingGatewayEvents) {
c8746_9.verboseDangerously("~>", a0, Opcode[a0], a1);
}
const r24 = c8746_10.pack({
op: a0,
d: a1
});
if (a2 && !this.isSessionEstablished()) {
c8746_9.warn(`Attempted to send while not being in a connected state opcode: ${a0}`);
} else {
try {
if (this.webSocket != null) {
this.webSocket.send(r24);
}
} catch ($e) {}
}
};
dispatcher = new GatewaySocketDispatcher(this);
gatewayBackoff = new Backoff(1000, 60000);
connectionState_ = ConnectionState.CLOSED;
webSocket = null;
seq = 0;
sessionId = null;
token = null;
initialHeartbeatTimeout = null;
expeditedHeartbeatTimeout = null;
lastHeartbeatTime = null;
lastHeartbeatAckTime = null;
helloTimeout = null;
heartbeatInterval = null;
heartbeater = null;
heartbeatAck = true;
connectionStartTime = 0;
firstConnectAttemptStartTime = 0;
identifyStartTime = 0;
nextReconnectIsImmediate = false;
compressionHandler = getCompressionHandler(c8746_10);
hasConnectedOnce = false;
isFastConnect = false;
constructor() {
super();
this.identifyCount = 0;
this.iosGoingAwayEventCount = 0;
this.failedConnectAttempts = 0;
this.receivedHelloThisAttempt = false;
}
get connectionState() {
return this.connectionState_;
}
set connectionState(a0) {
c8746_9.verbose(`Setting connection state to ${a0}`);
this.connectionState_ = a0;
}
addAnalytics(a0) {
this.analytics = {
...this.analytics,
...a0
};
}
setResumeUrl(a0) {
const resumeUrl = a0 != null && a0.endsWith("/") ? a0.substring(0, a0.length - 1) : a0;
if (resumeUrl !== null) {
c8746_9.verbose(`Updating resume url to ${resumeUrl}`);
}
this.resumeUrl = resumeUrl;
}
handleActiveStateChange(a0) {
const active = this.heartbeatQOSState.currentPayload?.active;
let r7 = !active;
if (this.heartbeatQOSState.currentPayload == null) {
this.heartbeatQOSState.currentPayload = a0;
}
const currentPayload = this.heartbeatQOSState.currentPayload;
if (a0.active) {
currentPayload.active = true;
currentPayload.reasons = [...new Set([...currentPayload.reasons, ...a0.reasons])].sort();
if (!active) {
r7 = this.isSessionEstablished();
}
if (r7) {
this._sendHeartbeat();
}
}
this.heartbeatQOSState.upcomingState = a0;
}
handleUpdateTimeSpentSessionId(a0, a1, a2) {
if (this.connectionState_ === ConnectionState.SESSION_ESTABLISHED) {
this.send(Opcode.UPDATE_TIME_SPENT_SESSION_ID, {
initialization_timestamp: a0,
session_id: a1,
client_launch_id: a2
});
this._sendHeartbeat();
}
}
_connect() {
let env19967 = {
$parent: env8746
};
env19967[1] = this;
if (this.willReconnect()) {
if (getIsPaused()) {
c8746_9.info("Skipping _connect because socket is paused");
} else {
this.connectionState = ConnectionState.CONNECTING;
this.nextReconnectIsImmediate = false;
const algorithm = this.compressionHandler.getAlgorithm();
const name = c8746_10.getName();
const r12 = this._getGatewayUrl();
const API_VERSION = window.GLOBAL_ENV.API_VERSION;
this.receivedHelloThisAttempt = false;
Module10.mark("🌐", "Socket._connect");
let r24 = algorithm;
if (r24 == null) {
r24 = "none";
}
c8746_9.info(`[CONNECT] ${r12}, encoding: ${name}, version: ${API_VERSION}, compression: ${r24}`);
if (this.webSocket !== null) {
c8746_9.error("_connect called with already existing websocket");
this._cleanup((a0) => a0.close(4000));
}
this.connectionStartTime = Date.now();
if (this.firstConnectAttemptStartTime === 0) {
this.firstConnectAttemptStartTime = this.connectionStartTime;
}
this.helloTimeout = setTimeout(() => {
const r5 = Date.now();
const r9 = env19967[1];
r9._handleClose(false, 0, `The connection timed out after ${r5 - r9.connectionStartTime} ms - did not receive OP_HELLO in time.`);
r9.setResumeUrl(null);
}, c8746_14);
const uRL = new URL(r12);
env19967[0] = uRL;
uRL.searchParams.append("encoding", name);
uRL.searchParams.append("v", API_VERSION.toString());
if (algorithm != null) {
uRL.searchParams.append("compress", algorithm);
}
let c19968_3, c19968_4;
let onOpen2, identify;
const r22 = uRL.toString();
const compressionHandler2 = this.compressionHandler;
const r104 = this._handleClose.bind(this);
const compressionHandler = compressionHandler2;
let c19968_2 = (a0, a1) => {
const r17 = Date.now();
const r26 = c8746_10.unpack(a0);
const { op, s: seq, t: r9, d: r7 } = r26;
if (op !== Opcode.DISPATCH) {
Module10.mark("🌐", `GatewaySocket.onMessage ${op} ${Opcode[op]}`);
}
if (DeveloperOptionsStore.isLoggingGatewayEvents) {
const r43 = [op];
if (op === Opcode.DISPATCH) {
r43.push(r9);
}
r43.push(r7);
c8746_9.verboseDangerously.apply(c8746_9, ["<~", ...r43]);
}
const unpack_duration_ms = Date.now() - r17;
const r3 = r9 === "READY";
if (r3) {
TTITracker.parseReady.set(r17, unpack_duration_ms);
} else if (r9 === "READY_SUPPLEMENTAL") {
TTITracker.parseReadySupplemental.set(r17, unpack_duration_ms);
} else if (unpack_duration_ms > 10) {
Module10.mark("🌐", "Parse " + r9, unpack_duration_ms);
}
if (seq != null) {
env19967[1].seq = seq;
}
if (Opcode.HELLO === op) {
const r145 = env19967[1];
r145._clearHelloTimeout();
r145._handleHello(r7);
} else if (Opcode.RECONNECT === op) {
env19967[1]._handleReconnect();
} else if (Opcode.INVALID_SESSION === op) {
env19967[1]._handleInvalidSession(r7);
} else if (Opcode.HEARTBEAT === op) {
env19967[1]._handleHeartbeatReceive();
} else if (Opcode.HEARTBEAT_ACK === op) {
env19967[1]._handleHeartbeatAck(r7);
} else if (Opcode.DISPATCH === op) {
const r119 = env19967[1];
r119._handleDispatch(r7, r9, r3 ? {
compressed_byte_size: a1,
uncompressed_byte_size: a0 == null ? 0 : typeof a0 === "string" ? a0.length : a0.byteLength,
compression_algorithm: r119.compressionHandler.getAlgorithm(),
packing_algorithm: c8746_10.getName(),
unpack_duration_ms
} : null);
} else {
c8746_9.info(`Unhandled op ${op}`);
}
env19967[1]._sendHeartbeatIfDue();
};
c19968_4 = void 0;
c19968_3 = 0;
compressionHandler.dataReady((a0) => {
try {
c19968_2(a0, c19968_3);
} catch (r7) {
c19968_3 = 0;
throw r7;
}
c19968_3 = 0;
});
c19968_4 = false;
onOpen2 = (a0) => {};
identify = void 0;
c8746_9.enableNativeLogger(true);
const _ws = window._ws;
identify = false;
window._ws = null;
const r117 = _ws != null;
let r118 = null;
let isFastConnect = false;
let r120 = false;
let webSocket = void 0;
if (r117) {
const ws = _ws.ws;
const userId = _ws.state.userId;
const r124 = userId != null && env8746[11] != null && userId !== env8746[11];
if (_ws.state.gateway !== r22) {
c8746_9.verbose(`[FAST CONNECT] gatewayURL mismatch: ${_ws.state.gateway} !== ${r22}`);
ws.close(1000);
r118 = null;
isFastConnect = false;
r120 = false;
webSocket = null;
} else if (r124) {
c8746_9.log(`[FAST CONNECT] refusing to adopt socket: identified user ${userId} does not match switch target ${env8746[11]}`);
ws.close(1000);
r118 = null;
isFastConnect = false;
r120 = false;
webSocket = null;
} else {
const r129 = {
..._ws.state
};
if (r129.messages != null) {
r129.messages = r129.messages.map((message) => message.data != null ? typeof message.data === "string" ? {
...message,
data: message.data.substring(0, 100)
} : message : message);
}
c8746_9.log("[FAST CONNECT] successfully took over websocket, state:", {
...r129,
messages: r129.messages?.length
});
r120 = _ws.state.open;
const identify2 = _ws.state.identify;
identify = identify2;
r118 = _ws.state.messages;
_ws.state.clientState;
isFastConnect = identify2;
webSocket = ws;
}
}
if (webSocket == null) {
const webSocket_android = createWebSocket_android(r22);
webSocket_android.binaryType = "arraybuffer";
webSocket = webSocket_android;
}
this.webSocket = webSocket;
this.compressionHandler.bindWebSocket(webSocket);
if (r120) {
Module10.mark("🌐", `GatewaySocket.onOpen ${isFastConnect}`);
const r192 = Date.now() - this.connectionStartTime;
c8746_9.info(`[CONNECTED] ${uRL.toString()} in ${r192} ms`);
this.isFastConnect = isFastConnect;
if (isFastConnect) {
this._doFastConnectIdentify();
} else {
this._doResumeOrIdentify();
}
}
const onmessage = (a0) => {
const data = a0.data;
if (a0.raw_length != null) {
c19968_3 = c19968_3 + a0.raw_length;
} else {
c19968_3 = c19968_3 + byteSize(data);
}
try {
compressionHandler.feed(data);
} catch (r18) {
if (!c19968_4) {
c19968_4 = true;
this(false, 0, "A decompression error occurred");
}
throw r18;
}
};
if (r118 != null) {
r118.forEach(onmessage);
}
const onError = () => {
const r5 = env19967[1];
r5.setResumeUrl(null);
CrossPlatformNativeUtils_native.flushDNSCache();
r5._handleClose(false, 0, "An error with the websocket occurred");
};
const onClose = (a0) => env19967[1]._handleClose(a0.wasClean, a0.code, a0.reason);
webSocket.onopen = () => {
Module10.mark("🌐", `GatewaySocket.onOpen ${identify}`);
const r26 = Date.now();
const r27 = env19967[1];
const r12 = r26 - r27.connectionStartTime;
c8746_9.info(`[CONNECTED] ${env19967[0].toString()} in ${r12} ms`);
r27.isFastConnect = identify;
if (identify) {
r27._doFastConnectIdentify();
} else {
r27._doResumeOrIdentify();
}
};
webSocket.onmessage = onmessage;
webSocket.onclose = onClose;
webSocket.onerror = onError;
}
} else {
c8746_9.verbose("Skipping _connect because willReconnect is false");
}
}
_handleHello(a0) {
const heartbeat_interval = a0.heartbeat_interval;
this.heartbeatInterval = heartbeat_interval;
const now = Date.now();
const r18 = now - this.connectionStartTime;
c8746_9.verbose(`[HELLO] via ${getConnectionPath(a0)}, heartbeat interval: ${heartbeat_interval}, took ${r18} ms`);
logGatewayConnected({
socket: this,
altGateway: this.altGateway,
gatewayUrl: this._getGatewayUrl(),
now
});
this.receivedHelloThisAttempt = true;
this.failedConnectAttempts = 0;
this.firstConnectAttemptStartTime = 0;
this._startHeartbeater();
}
_handleReconnect() {
c8746_9.verbose("[RECONNECT] gateway requested I reconnect.");
this._cleanup((a0) => a0.close(4000));
this.connectionState = ConnectionState.WILL_RECONNECT;
this._connect();
}
_handleInvalidSession(a0) {
c8746_9.info("[INVALID_SESSION]" + (a0 ? " can resume)" : ""));
if (a0) {
this._doResumeOrIdentify();
} else {
this._doIdentify();
}
}
_handleDispatch(a0, a1, a2) {
const r15 = Date.now() - this.connectionStartTime;
if (a1 === "READY") {
const session_id = a0.session_id;
this.sessionId = session_id;
const connectionPath = getConnectionPath(a0);
Module10.setServerTrace(connectionPath);
c8746_9.info(`[READY] took ${r15}ms, as ${session_id}`);
c8746_9.verbose(`${connectionPath}`);
this.connectionState = ConnectionState.SESSION_ESTABLISHED;
this.gatewayBackoff.succeed();
this.iosGoingAwayEventCount = 0;
this.altGateway.recordSuccess();
this.setResumeUrl(a0.resume_gateway_url);
} else if (a1 === "READY_SUPPLEMENTAL") {
c8746_9.info(`[READY_SUPPLEMENTAL] took ${r15}ms`);
this.connectionState = ConnectionState.SESSION_ESTABLISHED;
this.gatewayBackoff.succeed();
this.iosGoingAwayEventCount = 0;
this.altGateway.recordSuccess();
} else if (a1 === "RESUMED") {
c8746_9.verbose(getConnectionPath(a0));
this.connectionState = ConnectionState.SESSION_ESTABLISHED;
this.gatewayBackoff.succeed();
this.iosGoingAwayEventCount = 0;
this.altGateway.recordSuccess();
}
this.dispatcher.receiveDispatch(a0, a1, a2);
}
handleResumeDispatched() {
c8746_9.info(`[RESUMED] took ${Date.now() - this.connectionStartTime}ms, replayed ${this.dispatcher.resumeAnalytics.numEvents} events, new seq: ${this.seq}`);
}
handleReadyDispatched() {
this.didForceClearGuildHashes = false;
this.hasConnectedOnce = true;
}
_getGatewayUrl() {
let resumeUrl;
if (this.resumeUrl != null) {
resumeUrl = this.resumeUrl;
} else {
resumeUrl = this.altGateway.getAltGatewayUrl();
if (resumeUrl == null) {
resumeUrl = GATEWAY_ENDPOINT;
}
}
return resumeUrl;
}
_maybeFallBackFromAltGateway() {
if (this.altGateway.shouldUseAltGateway()) {
this.altGateway.recordFailure();
if (!this.altGateway.shouldUseAltGateway()) {
this.gatewayBackoff.succeed();
this.setResumeUrl(null);
c8746_9.warn("[ALT GATEWAY] 3 consecutive failures, falling back to default URL for this session.");
}
}
}
_handleHeartbeatReceive() {
this._sendHeartbeat();
if (this.heartbeater != null && this.heartbeatInterval != null) {
clearInterval(this.heartbeater);
this.heartbeater = setInterval(this._doHeartbeatInterval.bind(this), this.heartbeatInterval);
}
}
_handleHeartbeatAck() {
this.lastHeartbeatAckTime = Date.now();
this.heartbeatAck = true;
if (this.expeditedHeartbeatTimeout !== null) {
clearTimeout(this.expeditedHeartbeatTimeout);
this.expeditedHeartbeatTimeout = null;
c8746_9.verbose("Expedited heartbeat succeeded");
}
}
_handleHeartbeatTimeout() {
this._cleanup((a0) => a0.close(4000));
this.connectionState = ConnectionState.WILL_RECONNECT;
this._maybeFallBackFromAltGateway();
c8746_9.warn(`[ACK TIMEOUT] reconnecting in ${(this.gatewayBackoff.fail(() => this._connect()) / 1000).toFixed(2)} seconds.`);
}
_handleClose(a0, a1, a2) {
const r6 = a0 ? a0 : false;
this._cleanup();
this.emit("close", {
code: a1,
reason: a2
});
if (a1 === c8746_13) {
this.connectionState = ConnectionState.CLOSED;
c8746_9.warn("[WS CLOSED] because of authentication failure, marking as closed.");
return this._reset(r6, a1, a2);
}
this._tryDetectInvalidIOSToken(a1, a2, r6);
this.connectionState = ConnectionState.WILL_RECONNECT;
if (!this.receivedHelloThisAttempt) {
this.failedConnectAttempts = this.failedConnectAttempts + 1;
}
this._maybeFallBackFromAltGateway();
if (this.nextReconnectIsImmediate) {
c8746_9.info(`[WS CLOSED] (${r6.toString()}, ${a1}, ${a2}) retrying immediately.`);
this._connect();
} else {
const r46 = this.gatewayBackoff.fail(() => this._connect());
c8746_9.info(`[WS CLOSED] (${r6.toString()}, ${a1}, ${a2}) retrying in ${(r46 / 1000).toFixed(2)} seconds.`);
if (this.gatewayBackoff.fails > 4) {
this._reset(r6, a1, a2);
}
}
}
_tryDetectInvalidIOSToken(a0, a1, c19972_0) {
if (isIOS() && this.token != null && a0 === 1001 && a1 === "Stream end encountered") {
this.iosGoingAwayEventCount = this.iosGoingAwayEventCount + 1;
if (this.iosGoingAwayEventCount === 3) {
HTTP.get({
url: Endpoints.ME,
headers: {
authorization: this.token
},
rejectWithError: false
}).then((result) => {
AnalyticsUtils.track(AnalyticEvents.IOS_INVALID_TOKEN_WORKAROUND_TRIGGERED, {
api_status_code: result.status
});
}, ({ status }) => {
if (status === 401) {
this.connectionState = ConnectionState.CLOSED;
c8746_9.warn("[WS CLOSED] because of manual authentication failure, marking as closed.");
this._reset(c19972_0, c8746_13, "invalid token manually detected");
}
AnalyticsUtils.track(AnalyticEvents.IOS_INVALID_TOKEN_WORKAROUND_TRIGGERED, {
api_status_code: status
});
});
}
}
}
_reset(a0, a1, a2) {
this.sessionId = null;
this.seq = 0;
c8746_9.warn(`[RESET] (${a0.toString()}, ${a1}, ${a2})`);
this.emit("disconnect", {
wasClean: a0,
code: a1,
reason: a2
});
}
_sendHeartbeatIfDue() {
if (this.heartbeatInterval != null && this.heartbeater != null) {
const lastHeartbeatTime = this.lastHeartbeatTime;
if (lastHeartbeatTime != null && Date.now() - lastHeartbeatTime > this.heartbeatInterval + 5000) {
this._sendHeartbeat();
}
}
}
_doHeartbeatInterval() {
if (this.heartbeatAck) {
this.heartbeatAck = false;
this._sendHeartbeat();
} else if (this.expeditedHeartbeatTimeout === null) {
this._handleHeartbeatTimeout();
}
}
_startHeartbeater() {
const heartbeatInterval = this.heartbeatInterval;
Module38(heartbeatInterval != null, "GatewaySocket: Heartbeat interval should never null here.");
if (this.initialHeartbeatTimeout !== null) {
clearTimeout(this.initialHeartbeatTimeout);
}
if (this.heartbeater !== null) {
clearInterval(this.heartbeater);
this.heartbeater = null;
}
this.initialHeartbeatTimeout = setTimeout(() => {
this.initialHeartbeatTimeout = null;
this.heartbeatAck = true;
this.heartbeater = setInterval(this._doHeartbeatInterval.bind(this), heartbeatInterval);
this._doHeartbeatInterval();
}, Math.floor(Math.random() * heartbeatInterval));
}
_stopHeartbeater() {
if (this.heartbeater !== null) {
clearInterval(this.heartbeater);
this.heartbeater = null;
}
if (this.initialHeartbeatTimeout !== null) {
clearTimeout(this.initialHeartbeatTimeout);
this.initialHeartbeatTimeout = null;
}
if (this.expeditedHeartbeatTimeout !== null) {
clearTimeout(this.expeditedHeartbeatTimeout);
this.expeditedHeartbeatTimeout = null;
}
}
_clearHelloTimeout() {
if (this.helloTimeout != null) {
clearTimeout(this.helloTimeout);
this.helloTimeout = null;
}
}
_cleanup(a0) {
Module589.Emitter.resume();
this._stopHeartbeater();
this._clearHelloTimeout();
const webSocket = this.webSocket;
this.webSocket = null;
if (webSocket != null) {
webSocket.onopen = noop;
webSocket.onmessage = noop;
webSocket.onerror = noop;
webSocket.onclose = noop;
if (a0 != null) {
a0(webSocket);
}
}
this.gatewayBackoff.cancel();
this.compressionHandler.close();
this.compressionHandler = getCompressionHandler(c8746_10);
}
_doResume() {
this.connectionState = ConnectionState.RESUMING;
this.dispatcher.resumeAnalytics = createResumeAnalytics(Date.now() - this.connectionStartTime);
let sessionId = this.sessionId;
if (sessionId == null) {
sessionId = "";
}
c8746_9.info(`[RESUME] resuming session ${sessionId}, seq: ${this.seq}`);
this.send(Opcode.RESUME, {
token: this.token,
session_id: this.sessionId,
seq: this.seq
}, false);
}
async _doIdentify() {
const _this = this;
let c27352_1;
let c30572_0, c30572_1, c30572_2, c30572_3, c30572_4, c30572_5, c30572_6, c30572_7, c30572_8, c30572_9, c30572_10, c30572_11, c30572_12;
L31: {
c27352_1 = void 0;
c30572_0 = void 0;
c30572_1 = void 0;
c30572_2 = void 0;
c30572_3 = void 0;
c30572_4 = void 0;
c30572_5 = void 0;
c30572_6 = void 0;
c30572_7 = void 0;
c30572_8 = void 0;
c30572_9 = void 0;
c30572_10 = void 0;
c30572_11 = void 0;
c30572_12 = void 0;
_this.seq = 0;
_this.sessionId = null;
const r35 = _this.handleIdentify();
c30572_0 = r35;
if (r35 !== null) {
_this.connectionState = ConnectionState.IDENTIFYING;
const identifyStartTime = Date.now();
c30572_1 = identifyStartTime;
_this.identifyStartTime = identifyStartTime;
c30572_2 = await Promise.all([isCacheEnabled() ? GuildVersions.getCommittedVersions() : {}, isCacheEnabled() ? NonGuildVersions.getCommittedVersions() : {}, !!isCacheEnabled() && KvCacheVersion.canUseGuildVersions()]);
c30572_3 = (0, _slicedToArray)(c30572_2, 3);
c30572_4 = c30572_3[0];
c30572_5 = c30572_3[1];
c30572_6 = c30572_3[2] ? {
guild_versions: c30572_4,
highest_last_message_id: c30572_5.highest_last_message_id,
read_state_version: c30572_5.read_state_version,
user_guild_settings_version: c30572_5.user_guild_settings_version,
user_settings_version: c30572_5.user_settings_version,
private_channels_version: c30572_5.private_channels_version,
api_code_version: c30572_5.api_code_version,
initial_guild_id: c30572_5.initial_guild_id
} : {
guild_versions: {}
};
if (_this.connectionState === ConnectionState.IDENTIFYING && _this.identifyStartTime === c30572_1) {
c30572_7 = c30572_0.token;
c30572_8 = c30572_0.properties;
c30572_9 = c30572_8 === void 0 ? {} : c30572_8;
c30572_10 = c30572_0.presence;
_this.token = c30572_7;
c8746_9.verbose("[IDENTIFY]");
c30572_11 = {
token: c30572_7,
capabilities: getClientCapabilities({
useChannelObfuscation: isChannelMetadataObfuscationEnabled("GatewaySocket")
}),
properties: c30572_9,
presence: c30572_10,
compress: _this.compressionHandler.usesLegacyCompression(),
client_state: c30572_6
};
c30572_12 = JSON.stringify(c30572_11);
_this.identifyUncompressedByteSize = c30572_12.length;
_this.identifyCompressedByteSize = deflate(c30572_12).length;
_this.identifyCount = _this.identifyCount + 1;
_this.send(Opcode.IDENTIFY, c30572_11, false);
AnalyticsUtils.track(AnalyticEvents.SESSION_START_CLIENT, {});
break L31;
}
c8746_9.warn("Skipping identify because connectionState or identifyStartTime has changed");
break L31;
}
_this._handleClose(true, c8746_13, "No connection info provided");
return void 0;
}
}
_doFastConnectIdentify() {
this.seq = 0;
this.sessionId = null;
const r8 = this.handleIdentify();
if (r8 !== null) {
this.token = r8.token;
this.connectionState = ConnectionState.IDENTIFYING;
this.identifyStartTime = Date.now();
this.identifyCount = this.identifyCount + 1;
c8746_9.verbose("[IDENTIFY, fast-connect]");
this._updateLastHeartbeatAckTime();
} else {
this._handleClose(true, c8746_13, "No connection info provided");
}
}
_doResumeOrIdentify() {
L5: {
L3: {
const r4 = Date.now();
if (this.sessionId !== null) {
if (this.lastHeartbeatAckTime != null && !(r4 - this.lastHeartbeatAckTime <= c8746_15)) {
break L3;
}
this._doResume();
break L5;
}
}
this._doIdentify();
}
this._updateLastHeartbeatAckTime();
}
_updateLastHeartbeatAckTime() {
this.lastHeartbeatAckTime = Date.now();
}
_consumeQOSPayload() {
const currentPayload = this.heartbeatQOSState.currentPayload;
const heartbeatQOSState = this.heartbeatQOSState;
let upcomingState = this.heartbeatQOSState.upcomingState;
if (upcomingState == null) {
upcomingState = this.heartbeatQOSState.currentPayload;
}
heartbeatQOSState.currentPayload = upcomingState;
this.heartbeatQOSState.upcomingState = null;
return currentPayload;
}
_sendHeartbeat() {
this.send(Opcode.QOS_HEARTBEAT, {
seq: this.seq,
qos: this._consumeQOSPayload()
}, false);
this.lastHeartbeatTime = Date.now();
}
getLogger() {
return c8746_9;
}
willReconnect() {
return this.connectionState === ConnectionState.WILL_RECONNECT;
}
isClosed() {
return this.connectionState === ConnectionState.CLOSED;
}
isSessionEstablished() {
return this.connectionState === ConnectionState.SESSION_ESTABLISHED || this.connectionState === ConnectionState.RESUMING;
}
isConnected() {
return this.connectionState === ConnectionState.IDENTIFYING || this.connectionState === ConnectionState.RESUMING || this.connectionState === ConnectionState.SESSION_ESTABLISHED;
}
connect() {
let r1;
if (this.isClosed()) {
this.altGateway.reset();
c8746_9.verbose(".connect() called, new state is WILL_RECONNECT");
this.connectionState = ConnectionState.WILL_RECONNECT;
this.firstConnectAttemptStartTime = 0;
this._connect();
r1 = true;
} else {
c8746_9.error("Cannot start a new connection, connection state is not closed");
r1 = false;
}
return r1;
}
resetSocketAndClearCacheOnError(a0) {
const { action, error } = a0;
let metricAction = a0.metricAction;
c8746_9.error(`resetSocketAndClearCacheOnError during ${action}: ${error.message}`, error.stack);
const has_client_mods = usesClientMods();
if (metricAction == null) {
metricAction = action;
}
MonitoringAgent.increment({
name: MetricEvents.SOCKET_CRASHED,
tags: [`action:${metricAction}`, `modded_client:${has_client_mods}`]
}, true);
if (a0.sentry !== false) {
SentryUtils_native.captureException(error, {
tags: {
socketCrashedAction: action
}
});
}
AnalyticsUtils.track(AnalyticEvents.GATEWAY_SOCKET_RESET, {
error_message: error.message,
error_stack: error.stack,
has_client_mods,
action
});
this._cleanup((a0) => a0.close());
this._reset(true, 1000, "Resetting socket due to error.");
this.dispatcher.clear();
this.connectionState = ConnectionState.WILL_RECONNECT;
this.dispatchExceptionBackoff.cancel();
if (this.dispatchExceptionBackoff._fails === 0) {
c8746_9.verbose("Triggering fast reconnect");
this.dispatchExceptionBackoff.fail(() => {});
setTimeout(() => this._connect(), 0);
} else {
this.dispatchExceptionBackoff.fail(() => this._connect());
}
this.didForceClearGuildHashes = true;
Dispatcher.dispatch({
type: "CLEAR_CACHES",
reason: `Socket reset during ${action}`
});
Dispatcher.dispatch({
type: "LIBDISCORE_RESET"
});
clearTimeout(this.dispatchSuccessTimer);
this.dispatchSuccessTimer = setTimeout(() => this.dispatchExceptionBackoff.succeed(), 2 * c8746_16);
}
resetSocketOnDispatchError(a0) {
this.resetSocketAndClearCacheOnError({
...a0,
sentry: !(a0.error.message != null && a0.error.message.indexOf("Guild data was missing from store") >= 0)
});
}
close(r3 = false) {
const isClosed2 = this.isClosed();
if (isClosed2) {
c8746_9.verbose("close() called, but socket is already closed.");
if (!r3) {
this.sessionId = null;
this.token = null;
}
return void 0;
}
c8746_9.info(`Closing connection, current state is ${this.connectionState}`);
let c19976_0 = r3 ? 4000 : void 0;
this._cleanup((a0) => a0.close(c19976_0));
this.connectionState = ConnectionState.CLOSED;
if (!r3) {
this.sessionId = null;
this.token = null;
setImmediate(() => {
this._reset(true, 1000, "Disconnect requested by user");
});
}
}
networkStateChange(a0, a1, r6 = true) {
this.expeditedHeartbeat(a0, a1, r6, false);
}
expeditedHeartbeat(a0, r10 = "", r7 = true, r9 = true) {
if (this.isClosed()) {
return void 0;
}
if (this.isConnected()) {
c8746_9.verbose("Performing an expedited heartbeat " + (r10 != null ? r10 !== "" ? "reason: " + r10 : "" : ""));
this.heartbeatAck = false;
this._sendHeartbeat();
if (this.expeditedHeartbeatTimeout !== null) {
clearTimeout(this.expeditedHeartbeatTimeout);
}
this.expeditedHeartbeatTimeout = setTimeout(() => {
this.expeditedHeartbeatTimeout = null;
if (this.heartbeatAck === false) {
this._handleHeartbeatTimeout();
}
}, a0);
} else if (r7) {
this.resetBackoff(r10, r9);
} else {
c8746_9.verbose(`Expedited heartbeat requested, but, connection state is ${this.connectionState} and reconnectImmediately was not requested ${r10 != null ? r10 !== "" ? "reason: " + r10 : "" : ""}`);
}
}
resetBackoff(r6 = "", r4 = true) {
c8746_9.verbose("Connection has reset backoff" + (r6 != null ? r6 !== "" ? " for reason: " + r6 : "" : ""));
this.gatewayBackoff.succeed();
this.iosGoingAwayEventCount = 0;
this.nextReconnectIsImmediate = true;
if (this.willReconnect()) {
this._connect();
} else {
if (r4) {
r4 = this.connectionState !== ConnectionState.SESSION_ESTABLISHED;
}
if (r4) {
this._handleClose(true, 0, r6);
}
}
}
}
c8746_19 = GatewaySocket;
export default GatewaySocket;
export function setAccountSwitchUserId(a0) {
env8746[11] = a0;
}