Files
discord-decomp/modules/rpc/server/commands/setActivity.tsx
T
2026-11-01 12:12:55 +02:00

227 lines
9.0 KiB
TypeScript

// Metro module 13549 (f13550).
import ApplicationStore from "../../../applications/ApplicationStore";
import * as _Constants from "../../Constants";
import { TransportTypes } from "../../Constants";
import { ActivityGamePlatforms, ActivityPartyPrivacy, ActivityTypes, AnalyticEvents, RPCErrors, RPCCommands } from "../../../../Constants";
import { OAuth2Scopes } from "../../../../_bundle/Module8174";
import createRpcJoiSchemaObject from "../../helpers/createRpcJoiSchemaObject";
import { StatusDisplayTypes } from "../../../../_bundle/Module9077";
import RPCError from "../../RPCError";
import Dispatcher from "../../../../Dispatcher";
import { computeActivityFlags } from "../../../activities/utils/ActivityFlagUtils";
import { canLaunchFrame } from "../../../frames/utils/canLaunchFrame";
import Module12 from "../../../../_bundle/Module12";
import Durations from "../../../../utils/Durations";
import { fetchAssetIds } from "../../../../utils/ApplicationAssetUtils";
import AnalyticsUtils from "../../../../utils/AnalyticsUtils";
const { RPC_SCOPE_CONFIG, RPC_LOCAL_SCOPE } = _Constants;
const _excluded = ["1402418171662569542"];
const r30 = {};
const SET_ACTIVITY = RPCCommands.SET_ACTIVITY;
const scope = {};
scope[RPC_SCOPE_CONFIG.ANY] = [OAuth2Scopes.RPC, OAuth2Scopes.RPC_ACTIVITIES_WRITE, RPC_LOCAL_SCOPE];
r30[SET_ACTIVITY] = {
scope,
validation: (a0) => createRpcJoiSchemaObject(a0).required().keys({
pid: a0.number().min(0),
activity: createRpcJoiSchemaObject(a0).keys({
name: a0.string().min(1).max(128),
state: a0.string().min(2).max(128),
state_url: a0.string().uri().min(1).max(256),
details: a0.string().min(2).max(128),
details_url: a0.string().uri().min(1).max(256),
timestamps: createRpcJoiSchemaObject(a0).keys({
start: a0.number().min(1),
end: a0.number().min(1)
}),
assets: createRpcJoiSchemaObject(a0).keys({
large_image: a0.string().min(1).max(300),
large_text: a0.string().min(2).max(128),
large_url: a0.string().uri().min(1).max(256),
small_image: a0.string().min(1).max(300),
small_text: a0.string().min(2).max(128),
small_url: a0.string().uri().min(1).max(256),
invite_cover_image: a0.string().min(1).max(300)
}),
party: createRpcJoiSchemaObject(a0).keys({
id: a0.string().min(2).max(128),
size: a0.array().items(a0.number().min(0)).length(2),
privacy: a0.number().default(ActivityPartyPrivacy.PRIVATE).valid([ActivityPartyPrivacy.PRIVATE, ActivityPartyPrivacy.PUBLIC])
}),
secrets: createRpcJoiSchemaObject(a0).keys({
match: a0.string().min(2).max(128),
join: a0.string().min(2).max(128),
spectate: a0.string().min(2).max(128)
}),
buttons: a0.array().items(createRpcJoiSchemaObject(a0).keys({
label: a0.string().min(1).max(32).required(),
url: a0.string().uri().min(1).max(512).required()
})).min(1).max(2),
instance: a0.boolean(),
supported_platforms: a0.array().items(a0.string().min(1).max(32)).min(1).max(10),
type: a0.number().default(ActivityTypes.PLAYING).valid(ActivityTypes.PLAYING, ActivityTypes.LISTENING, ActivityTypes.WATCHING, ActivityTypes.COMPETING),
status_display_type: a0.number().optional().valid(StatusDisplayTypes.NAME, StatusDisplayTypes.STATE, StatusDisplayTypes.DETAILS)
}).allow(null)
}),
handler: (a0) => {
let r205;
let privacy, assets;
const { socket, args } = a0;
const { pid, activity } = args;
const isSocketConnected = a0.isSocketConnected;
privacy = void 0;
assets = void 0;
if ([TransportTypes.IPC, TransportTypes.WEBSOCKET, TransportTypes.POST_MESSAGE].includes(socket.transport)) {
if (pid == null && TransportTypes.IPC === socket.transport) {
throw new RPCError({
errorCode: RPCErrors.INVALID_COMMAND
}, "nonzero pid required");
}
if (activity == null) {
Dispatcher.dispatch({
type: "LOCAL_ACTIVITY_UPDATE",
socketId: socket.id,
pid,
activity
});
return Promise.resolve(activity);
}
if (!activity.name) {
activity.name = socket.application.name;
}
let id = socket.application.id;
activity.application_id = id;
const r67 = socket.transport === TransportTypes.POST_MESSAGE;
activity.platform = r67 ? ActivityGamePlatforms.EMBEDDED : ActivityGamePlatforms.DESKTOP;
if (id == null) {
id = void 0;
}
const application = ApplicationStore.getApplication(id);
let instance = activity.instance;
if (instance == null) {
instance = false;
}
privacy = activity.party?.privacy;
delete activity["instance"];
const party = activity.party;
if (party != null) {
delete party["privacy"];
}
const flags = computeActivityFlags(activity, instance, r67, application != null && canLaunchFrame(application) && r67, privacy);
if (flags > 0) {
activity.flags = flags;
}
assets = activity.assets;
const { party: party2, secrets, timestamps, buttons } = activity;
if (activity.type == null) {
activity.type = ActivityTypes.PLAYING;
}
if (secrets != null) {
const r112 = Module12.values(secrets).filter((item) => !!item);
if (party2 != null && Module12.intersection(r112, [party2.id]).length > 0 && !_excluded.includes(socket.application.id)) {
throw new RPCError({
errorCode: RPCErrors.INVALID_ACTIVITY_SECRET
}, "secrets cannot match the party id");
}
if (Module12.uniq(r112).length < r112.length) {
throw new RPCError({
errorCode: RPCErrors.INVALID_ACTIVITY_SECRET
}, "secrets must be unique");
}
if (buttons != null) {
throw new RPCError({
errorCode: RPCErrors.INVALID_ACTIVITY_SECRET
}, "secrets cannot currently be sent with buttons");
}
}
const metadata = {};
if (buttons != null) {
metadata.button_urls = buttons.map((button) => button.url);
activity.buttons = buttons.map((button) => button.label);
}
activity.metadata = metadata;
if (timestamps != null) {
for (const item of Object.keys(timestamps)) {
if (Date.now().toString().length - timestamps[item].toString().length > 2) {
timestamps[item] = Math.floor(timestamps[item] * Durations.Millis.SECOND);
}
}
}
L48: {
if (assets != null) {
if (socket.application != null && socket.application.id != null) {
r205 = fetchAssetIds(socket.application.id, [assets.large_image, assets.small_image, assets.invite_cover_image]);
break L48;
}
throw new Error();
}
r205 = Promise.resolve([]);
}
return r205.then((result) => {
const [large_image, small_image, invite_cover_image] = result;
if (assets != null) {
if (large_image != null) {
assets.large_image = large_image;
} else {
delete assets["large_image"];
}
if (small_image != null) {
assets.small_image = small_image;
} else {
delete assets["small_image"];
}
if (invite_cover_image != null) {
assets.invite_cover_image = invite_cover_image;
} else {
delete assets["invite_cover_image"];
}
}
if (isSocketConnected()) {
Dispatcher.dispatch({
type: "LOCAL_ACTIVITY_UPDATE",
socketId: socket.id,
pid,
activity,
partyPrivacy: privacy
});
const { secrets, party } = activity;
let details = activity.details;
if (details == null) {
details = "";
}
let state = activity.state;
if (state == null) {
state = "";
}
const r62 = {
application_id: socket.application.id,
type: activity.type,
name: activity.name,
status_display_type: activity.status_display_type,
details,
state,
has_urls: activity.state_url != null || activity.details_url != null || activity.assets?.large_url != null || activity.assets?.small_url != null
};
if (secrets != null) {
r62.has_match_secret = !!secrets.match;
r62.has_join_secret = !!secrets.join;
}
if (assets != null) {
r62.has_images = !!(assets.large_image || assets.small_image || assets.invite_cover_image);
}
if (party != null) {
r62.party_max = party.size != null ? party.size[1] > 0 ? party.size[1] : void 0 : void 0;
r62.party_id = party.id;
}
AnalyticsUtils.track(AnalyticEvents.ACTIVITY_UPDATED, r62);
return activity;
}
});
}
throw new RPCError({
errorCode: RPCErrors.INVALID_COMMAND
}, `command not available from "${socket.transport}" transport`);
}
};
export default r30;