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

446 lines
14 KiB
TypeScript

// Metro module 5721 (f5722).
import GatewayConnectionStore from "../gateway/GatewayConnectionStore";
import AuthenticationStore from "../../stores/AuthenticationStore";
import IdleStore from "../../stores/IdleStore";
import RTCConnectionStore from "../../stores/RTCConnectionStore";
import { AnalyticEvents, RTCConnectionStates, AppStates } from "../../Constants";
import Durations from "../../utils/Durations";
import Logger from "../debug/Logger";
import { isForegrounded } from "./SessionForegroundUtils.native";
import * as _SessionRouteUtils_native from "./SessionRouteUtils.native";
import { subscribeToLocationChanges } from "./SessionRouteUtils.native";
import SentryUtils_native from "../../utils/SentryUtils.native";
import { drainClickstream } from "../app_analytics/clickstream/Clickstream";
import { getClientHeartbeatPiggybackProperties } from "./ClientHeartbeatPiggyback";
import AnalyticsUtils from "../../utils/AnalyticsUtils";
import { shouldLogClientHeartbeatSkipped } from "./SkippedClientHeartbeatExperiment";
import { Storage } from "../../_bundle/Module595";
import { CLIENT_SESSION_STORAGE_VERSION, isSessionExpired } from "./SessionUtils";
import { clientLaunchId } from "../../_bundle/Module668";
import Dispatcher from "../../Dispatcher";
import Module589 from "../../_bundle/Module589";
import { v4 } from "../../_bundle/Module514";
import { HermesBuiltin } from "../../_hermes/prelude";
function $mk114799($env) {
return function maybeFlushSessionToStorage(a0) {
const r0 = $env;
const r7 = performance.now();
if (!(r7 - c3550_18 < SECOND)) {
try {
Storage.set(c3550_13, a0);
r0[18] = r7;
} catch ($e) {
SentryUtils_native.captureException($e);
}
}
};
}
let isActive, scheduleHeartbeatTracking, validateClientSession, forceDispatchSessionIdUpdate, handleAuthenticationChange, handleRTCStateChange, handleWindowFocus, handleLocationChange, handleAppStateUpdate, handleFluxInitialized, getSession, c3550_11, SECOND, c3550_13, c3550_14, c3550_15, c3550_18;
let env3550 = {};
const trackHeartbeat = async function trackHeartbeat() {
let idleSince;
let c29588_3, c29588_4;
c29588_3 = void 0;
c29588_4 = void 0;
let c29588_0 = Date.now();
let c29588_1 = await getSession();
let c29588_2 = Date.now();
if (c29588_1 != null) {
SentryUtils_native.addBreadcrumb({
category: c3550_14,
message: "Tracking Heartbeat",
data: {
initialized: c29588_1.createdAtTimestamp
}
});
const r65 = {
client_heartbeat_initialization_timestamp: c29588_1.createdAtTimestamp,
client_heartbeat_version: 29,
...getClientHeartbeatPiggybackProperties()
};
const idleSince2 = IdleStore.getIdleSince();
idleSince = idleSince2;
if (idleSince2 == null) {
idleSince = 0;
}
c29588_3 = idleSince;
HermesBuiltin.copyDataProperties(r65, {
is_idle: IdleStore.isIdle(),
idle_duration_ms: Date.now() - c29588_3,
is_afk: IdleStore.isAFK(),
is_system_suspended: IdleStore.getSystemSuspended(),
is_system_locked: IdleStore.getSystemLocked()
});
c29588_4 = r65;
AnalyticsUtils.track(AnalyticEvents.CLIENT_HEARTBEAT, c29588_4);
env3550[19] = performance.now();
drainClickstream();
} else {
SentryUtils_native.captureException(Error(`Null session when tracking session heartbeat. Waited ${c29588_2 - c29588_0}ms`));
}
};
isActive = function isActive() {
const r4 = env3550[24] != null && env3550[23];
const r6 = [];
if (r4) {
if (env3550[22]) {
r6.push("foregrounded");
}
if (env3550[21] === RTCConnectionStates.RTC_CONNECTED) {
r6.push("rtc_connected");
}
}
return r6.length > 0;
};
scheduleHeartbeatTracking = function scheduleHeartbeatTracking() {
SentryUtils_native.addBreadcrumb({
message: "Heartbeat Track State Parameters Changed. Foregrounded " + env3550[22] + ", Connection State: " + env3550[21]
});
const r23 = env3550[24] != null && env3550[23];
const r24 = [];
if (r23) {
if (env3550[22]) {
r24.push("foregrounded");
}
if (env3550[21] === RTCConnectionStates.RTC_CONNECTED) {
r24.push("rtc_connected");
}
}
if (r24.length > 0) {
if (env3550[16] == null) {
const r0 = env3550[19] !== 0 ? c3550_11 - (performance.now() - env3550[19]) : 0;
SentryUtils_native.addBreadcrumb({
message: `Received Last Heartbeat Event Timestamp. Time Until Next Heartbeat: ${r0 / 1000} seconds. Scheduling Heartbeat`
});
env3550[16] = {
type: "timeout",
id: setTimeout(() => {
trackHeartbeat();
env3550[16] = {
type: "interval",
id: setInterval(() => {
trackHeartbeat();
}, c3550_11)
};
}, r0)
};
}
} else {
const r6 = env3550[16] == null;
let r3 = false;
if (!r6) {
const type = env3550[16].type;
if (type === "timeout") {
clearTimeout(env3550[16].id);
} else if (type === "interval") {
clearInterval(env3550[16].id);
} else {
env3550[16].type;
}
env3550[16] = null;
r3 = true;
}
if (r3) {
SentryUtils_native.addBreadcrumb({
category: c3550_14,
message: "Stopping Analytics Heartbeat"
});
drainClickstream();
}
}
const socket = GatewayConnectionStore.getSocket();
if (socket != null) {
const r94 = env3550[24] != null && env3550[23];
const reasons = [];
if (r94) {
if (env3550[22]) {
reasons.push("foregrounded");
}
if (env3550[21] === RTCConnectionStates.RTC_CONNECTED) {
reasons.push("rtc_connected");
}
}
socket.handleActiveStateChange({
active: reasons.length > 0,
ver: 29,
reasons
});
}
};
validateClientSession = function validateClientSession(a0) {
const r0 = a0 == null;
let r2 = null;
if (!r0) {
const version = a0.version;
let r13 = a0;
if (version !== CLIENT_SESSION_STORAGE_VERSION) {
c3550_15.warn(`Throwing away client session with invalid version: ${a0.version}, expected ${CLIENT_SESSION_STORAGE_VERSION}`);
r13 = null;
}
r2 = r13;
}
return r2;
};
forceDispatchSessionIdUpdate = async function forceDispatchSessionIdUpdate() {
let c29589_0 = await getSession(false);
if (c29589_0 != null) {
const socket = GatewayConnectionStore.getSocket();
if (socket != null) {
socket.handleUpdateTimeSpentSessionId(c29589_0.createdAtTimestamp, c29589_0.uuid, clientLaunchId);
}
}
};
handleAuthenticationChange = function handleAuthenticationChange() {
const token = AuthenticationStore.getToken();
if (env3550[24] !== token) {
env3550[24] = token;
Storage.remove(c3550_13);
env3550[20] = {
state: "loaded",
session: null
};
const r4 = env3550[16] == null;
let r1 = false;
if (!r4) {
const type = env3550[16].type;
if (type === "timeout") {
clearTimeout(env3550[16].id);
} else if (type === "interval") {
clearInterval(env3550[16].id);
} else {
env3550[16].type;
}
env3550[16] = null;
r1 = true;
}
if (r1) {
SentryUtils_native.addBreadcrumb({
category: c3550_14,
message: "Stopping Analytics Heartbeat"
});
drainClickstream();
}
env3550[19] = 0;
}
scheduleHeartbeatTracking();
};
handleRTCStateChange = function handleRTCStateChange() {
const state = RTCConnectionStore.getState();
if (env3550[21] !== state) {
env3550[21] = state;
scheduleHeartbeatTracking();
}
};
handleWindowFocus = function handleWindowFocus({ focused }) {
if (env3550[22] !== focused) {
env3550[22] = focused;
scheduleHeartbeatTracking();
}
};
handleLocationChange = function handleLocationChange() {
const isActiveUserRoute = _SessionRouteUtils_native.isActiveUserRoute();
if (env3550[23] !== isActiveUserRoute) {
env3550[23] = isActiveUserRoute;
scheduleHeartbeatTracking();
}
};
handleAppStateUpdate = function handleAppStateUpdate(a0) {
const r1 = a0.state === AppStates.ACTIVE;
if (env3550[22] !== r1) {
env3550[22] = r1;
scheduleHeartbeatTracking();
}
};
handleFluxInitialized = function handleFluxInitialized() {
env3550[21] = RTCConnectionStore.getState();
env3550[22] = isForegrounded();
env3550[23] = _SessionRouteUtils_native.isActiveUserRoute();
handleAuthenticationChange();
};
getSession = async function getSession(c25580_0) {
let r82, r116;
let c25580_1, c25580_2, c25580_3, c25580_5;
let c25580_4 = 0;
const r14 = env3550;
L33: {
try {
let env29590;
c25580_3 = r14;
const r36 = env29590 = {
$parent: r14
};
c25580_2 = r36;
env29590[0] = void 0;
if (c25580_0 !== void 0) {
env29590[0] = c25580_0;
env29590[1] = void 0;
env29590[2] = void 0;
env29590[3] = void 0;
} else {
env29590[0] = true;
env29590[1] = void 0;
env29590[2] = void 0;
env29590[3] = void 0;
}
await void 0;
env29590[2] = null;
env29590[3] = env3550[20].state === "loaded" ? env3550[20].session?.uuid : null;
c25580_4 = 1;
if (env3550[20].state === "uninitialized") {
c25580_1 = validateClientSession;
r82 = c25580_1(await Storage.getAfterRefresh(c3550_13));
} else {
r82 = env3550[20].session;
}
env29590[2] = r82;
c25580_4 = 0;
env29590[1] = Date.now();
const r90 = (0, isActive)();
const r92 = env29590[2];
if (r90) {
if (r92 == null || isSessionExpired(env29590[2])) {
env29590[2] = {
uuid: v4(),
createdAtTimestamp: env29590[1],
lastUsedTimestamp: env29590[1],
version: CLIENT_SESSION_STORAGE_VERSION
};
env3550[18] = 0;
}
env29590[2].lastUsedTimestamp = env29590[1];
const r145 = env29590[2];
$mk114799(env3550)(r145);
} else if (r92 != null && isSessionExpired(env29590[2])) {
env29590[2] = null;
}
env3550[20] = {
state: "loaded",
session: env29590[2]
};
if (env29590[2] != null && env29590[3] !== env29590[2].uuid && env29590[0]) {
const socket = GatewayConnectionStore.getSocket();
if (socket != null) {
socket.handleUpdateTimeSpentSessionId(env29590[2].createdAtTimestamp, env29590[2].uuid, clientLaunchId);
}
}
r116 = env29590[2];
} catch ($e) {
const r34 = $e;
let r8 = r34;
c25580_5 = r34;
if (c25580_4 !== 0) {
while (true) {
try {
const r191 = c25580_5;
c25580_4 = 0;
env29590[4] = r191;
SentryUtils_native.captureException(env29590[4]);
env29590[1] = Date.now();
const r206 = (0, isActive)();
const r208 = env29590[2];
if (r206) {
if (r208 == null || isSessionExpired(env29590[2])) {
env29590[2] = {
uuid: v4(),
createdAtTimestamp: env29590[1],
lastUsedTimestamp: env29590[1],
version: CLIENT_SESSION_STORAGE_VERSION
};
env3550[18] = 0;
}
env29590[2].lastUsedTimestamp = env29590[1];
const r261 = env29590[2];
$mk114799(env3550)(r261);
} else if (r208 != null && isSessionExpired(env29590[2])) {
env29590[2] = null;
}
env3550[20] = {
state: "loaded",
session: env29590[2]
};
if (env29590[2] != null && env29590[3] !== env29590[2].uuid && env29590[0]) {
const socket2 = GatewayConnectionStore.getSocket();
if (socket2 != null) {
socket2.handleUpdateTimeSpentSessionId(env29590[2].createdAtTimestamp, env29590[2].uuid, clientLaunchId);
}
}
r116 = env29590[2];
break L33;
} catch (r187) {
r8 = r187;
c25580_5 = r187;
if (c25580_4 === 0) {
break;
}
}
}
}
throw r8;
}
}
return r116;
};
c3550_11 = 15 * Durations.Millis.MINUTE;
SECOND = Durations.Millis.SECOND;
c3550_13 = "LAST_CLIENT_HEARTBEAT_SESSION";
c3550_14 = "user";
c3550_15 = new Logger("SessionHeartbeatScheduler");
env3550[16] = null;
env3550[17] = null;
c3550_18 = 0;
env3550[19] = 0;
env3550[20] = {
state: "uninitialized"
};
env3550[21] = RTCConnectionStore.getState();
env3550[22] = isForegrounded();
env3550[23] = _SessionRouteUtils_native.isActiveUserRoute();
env3550[24] = AuthenticationStore.getToken();
export function initSessionHeartbeatScheduler() {
SentryUtils_native.addBreadcrumb({
message: "Initializing SessionHeartbeatScheduler"
});
RTCConnectionStore.addChangeListener(handleRTCStateChange);
AuthenticationStore.addChangeListener(handleAuthenticationChange);
Dispatcher.subscribe("WINDOW_FOCUS", handleWindowFocus);
Dispatcher.subscribe("APP_STATE_UPDATE", handleAppStateUpdate);
Dispatcher.subscribe("CONNECTION_OPEN", forceDispatchSessionIdUpdate);
subscribeToLocationChanges(handleLocationChange);
scheduleHeartbeatTracking();
if (env3550[17] == null) {
env3550[17] = {
id: setInterval(() => {
if (env3550[24] != null && shouldLogClientHeartbeatSkipped() && !(performance.now() - env3550[19] <= c3550_11)) {
AnalyticsUtils.track(AnalyticEvents.CLIENT_HEARTBEAT_SKIPPED, {
client_heartbeat_version: 29
});
}
}, c3550_11),
type: "interval"
};
}
Module589.initialized.then(handleFluxInitialized);
}
export { getSession };
export function getActiveSessionUnsafe() {
let r16;
if (env3550[20].state === "uninitialized") {
const r11 = Storage.get(c3550_13);
const r2 = r11 == null;
let r20 = null;
if (!r2) {
const version = r11.version;
let r24 = r11;
if (version !== CLIENT_SESSION_STORAGE_VERSION) {
c3550_15.warn(`Throwing away client session with invalid version: ${r11.version}, expected ${CLIENT_SESSION_STORAGE_VERSION}`);
r24 = null;
}
r20 = r24;
}
r16 = r20;
} else {
r16 = env3550[20].session;
}
return r16 == null ? null : isSessionExpired(r16) ? null : r16;
}