@sonoransoftware/sonoran.js 1.0.35 → 1.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,11 +41,9 @@ class CMSManager extends BaseManager_1.BaseManager {
41
41
  this.buildManager(instance);
42
42
  }
43
43
  async buildManager(instance) {
44
- var _a;
45
44
  const mutableThis = this;
46
45
  try {
47
- const versionResp = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('GET_SUB_VERSION'));
48
- const version = Number.parseInt(versionResp.replace(/(^\d+)(.+$)/i, '$1'));
46
+ const version = await this.getSubscriptionVersion();
49
47
  if (version >= globalTypes.CMSSubscriptionVersionEnum.STANDARD) {
50
48
  this.servers = new CMSServerManager_1.CMSServerManager(instance, this);
51
49
  }
@@ -60,6 +58,15 @@ class CMSManager extends BaseManager_1.BaseManager {
60
58
  throw err;
61
59
  }
62
60
  }
61
+ /**
62
+ * Retrieves the community's CMS subscription version.
63
+ */
64
+ async getSubscriptionVersion() {
65
+ var _a;
66
+ const versionResp = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('GET_SUB_VERSION'));
67
+ const versionString = String(versionResp);
68
+ return Number.parseInt(versionString.replace(/(^\d+)(.+$)/i, '$1'), 10);
69
+ }
63
70
  /**
64
71
  * Verifies the whitelist of a given account with the given parameters to search of said account.
65
72
  * @param {Object | string} data The object or [accId | apiId as a string] that contains data to get a community account to verify if it has whitelist to the specified server. *If given as a string it will default to the set or default cms server id (1).
@@ -373,6 +380,49 @@ class CMSManager extends BaseManager_1.BaseManager {
373
380
  }
374
381
  });
375
382
  }
383
+ /**
384
+ * Triggers promotion flows for the specified users.
385
+ */
386
+ async triggerPromotionFlows(flows) {
387
+ if (!Array.isArray(flows) || flows.length === 0) {
388
+ throw new Error('flows array must include at least one promotion flow payload.');
389
+ }
390
+ return new Promise(async (resolve, reject) => {
391
+ var _a;
392
+ try {
393
+ const response = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('TRIGGER_PROMOTION_FLOWS', flows));
394
+ resolve({ success: true, data: response });
395
+ }
396
+ catch (err) {
397
+ if (err instanceof src_1.APIError) {
398
+ resolve({ success: false, reason: err.response });
399
+ }
400
+ else {
401
+ reject(err);
402
+ }
403
+ }
404
+ });
405
+ }
406
+ /**
407
+ * Retrieves the available promotion flows configured in CMS.
408
+ */
409
+ async getPromotionFlows() {
410
+ return new Promise(async (resolve, reject) => {
411
+ var _a;
412
+ try {
413
+ const response = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('GET_PROMOTION_FLOWS'));
414
+ resolve({ success: true, data: response });
415
+ }
416
+ catch (err) {
417
+ if (err instanceof src_1.APIError) {
418
+ resolve({ success: false, reason: err.response });
419
+ }
420
+ else {
421
+ reject(err);
422
+ }
423
+ }
424
+ });
425
+ }
376
426
  /**
377
427
  * Gets a list of online ERLC players for the given roblox join code.
378
428
  * @param {string} robloxJoinCode The roblox join code to get the online players for.
@@ -420,6 +470,32 @@ class CMSManager extends BaseManager_1.BaseManager {
420
470
  }
421
471
  });
422
472
  }
473
+ /**
474
+ * Updates the stage of a form for the specified account.
475
+ */
476
+ async changeFormStage(params) {
477
+ if (!params.formId || !params.newStageId) {
478
+ throw new Error('formId and newStageId are required to change a form stage.');
479
+ }
480
+ if (params.uniqueId === undefined || Number.isNaN(Number(params.uniqueId))) {
481
+ throw new Error('uniqueId is required to change a form stage.');
482
+ }
483
+ return new Promise(async (resolve, reject) => {
484
+ var _a;
485
+ try {
486
+ const response = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('CHANGE_FORM_STAGE', params.accId, params.formId, params.newStageId, params.apiId, params.username, params.discord, params.uniqueId));
487
+ resolve({ success: true, data: response });
488
+ }
489
+ catch (err) {
490
+ if (err instanceof src_1.APIError) {
491
+ resolve({ success: false, reason: err.response });
492
+ }
493
+ else {
494
+ reject(err);
495
+ }
496
+ }
497
+ });
498
+ }
423
499
  /**
424
500
  * Retrieves submissions for a specific form template.
425
501
  */
@@ -7,5 +7,10 @@ import { CMSManager } from './CMSManager';
7
7
  export declare class CMSServerManager extends CacheManager<number, CMSServer, CMSServerAPIStruct> {
8
8
  private readonly manager;
9
9
  constructor(instance: Instance, manager: CMSManager);
10
+ /**
11
+ * Retrieves the CMS game servers belonging to the community.
12
+ */
13
+ getGameServers(): Promise<CMSServerAPIStruct[]>;
14
+ private initialize;
10
15
  setGameServers(servers: globalTypes.CMSSetGameServerStruct[]): Promise<globalTypes.CMSSetGameServersPromiseResult>;
11
16
  }
@@ -8,30 +8,39 @@ class CMSServerManager extends CacheManager_1.CacheManager {
8
8
  constructor(instance, manager) {
9
9
  super(instance, CMSServer_1.CMSServer, []);
10
10
  this.manager = manager;
11
- (async () => {
12
- var _a;
13
- const managerRef = this.manager;
14
- while (!managerRef.ready) {
15
- await new Promise((resolve) => {
16
- setTimeout(resolve, 100);
17
- });
18
- }
19
- try {
20
- const serversRes = await ((_a = managerRef.rest) === null || _a === void 0 ? void 0 : _a.request('GET_GAME_SERVERS'));
21
- const servers = serversRes.servers;
22
- servers.forEach((server) => {
23
- const serverStruct = {
24
- id: server.id,
25
- config: server
26
- };
27
- this._add(serverStruct, true, server.id);
28
- });
29
- console.log(`Found ${servers.length} servers`);
30
- }
31
- catch (err) {
32
- throw new Error(String(err));
33
- }
34
- })();
11
+ void this.initialize();
12
+ }
13
+ /**
14
+ * Retrieves the CMS game servers belonging to the community.
15
+ */
16
+ async getGameServers() {
17
+ var _a;
18
+ const serversRes = await ((_a = this.manager.rest) === null || _a === void 0 ? void 0 : _a.request('GET_GAME_SERVERS'));
19
+ const parsed = typeof serversRes === 'string' ? JSON.parse(serversRes) : serversRes;
20
+ const servers = Array.isArray(parsed === null || parsed === void 0 ? void 0 : parsed.servers) ? parsed.servers : [];
21
+ return servers;
22
+ }
23
+ async initialize() {
24
+ const managerRef = this.manager;
25
+ while (!managerRef.ready) {
26
+ await new Promise((resolve) => {
27
+ setTimeout(resolve, 100);
28
+ });
29
+ }
30
+ try {
31
+ const servers = await this.getGameServers();
32
+ servers.forEach((server) => {
33
+ const serverStruct = {
34
+ id: server.id,
35
+ config: server
36
+ };
37
+ this._add(serverStruct, true, server.id);
38
+ });
39
+ console.log(`Found ${servers.length} servers`);
40
+ }
41
+ catch (err) {
42
+ throw new Error(String(err));
43
+ }
35
44
  }
36
45
  async setGameServers(servers) {
37
46
  if (!Array.isArray(servers) || servers.length === 0) {
@@ -52,4 +52,11 @@ export declare class RadioManager extends BaseManager {
52
52
  * @param {string} [token] Optional bearer token for authorization. Defaults to the community API key.
53
53
  */
54
54
  setInGameSpeakerLocations(locations: globalTypes.RadioSpeakerLocation[], token?: string): Promise<globalTypes.RadioSetInGameSpeakerLocationsPromiseResult>;
55
+ /**
56
+ * Plays one or more tones to radio channels, groups, or in-game speakers.
57
+ * @param {number} roomId Multi-server room id for tone playback.
58
+ * @param {number[]} tones Tone identifiers to play.
59
+ * @param {globalTypes.RadioTonePlayTarget[]} playTo Targets that should receive the tones.
60
+ */
61
+ playTone(roomId: number, tones: number[], playTo: globalTypes.RadioTonePlayTarget[]): Promise<globalTypes.RadioPlayTonePromiseResult>;
55
62
  }
@@ -220,5 +220,28 @@ class RadioManager extends BaseManager_1.BaseManager {
220
220
  }
221
221
  });
222
222
  }
223
+ /**
224
+ * Plays one or more tones to radio channels, groups, or in-game speakers.
225
+ * @param {number} roomId Multi-server room id for tone playback.
226
+ * @param {number[]} tones Tone identifiers to play.
227
+ * @param {globalTypes.RadioTonePlayTarget[]} playTo Targets that should receive the tones.
228
+ */
229
+ async playTone(roomId, tones, playTo) {
230
+ return new Promise(async (resolve, reject) => {
231
+ var _a, _b;
232
+ try {
233
+ const response = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('PLAY_TONE', roomId, tones, playTo));
234
+ resolve({ success: true, result: (_b = response === null || response === void 0 ? void 0 : response.result) !== null && _b !== void 0 ? _b : response });
235
+ }
236
+ catch (err) {
237
+ if (err instanceof src_1.APIError) {
238
+ resolve({ success: false, reason: err.response });
239
+ }
240
+ else {
241
+ reject(err);
242
+ }
243
+ }
244
+ });
245
+ }
223
246
  }
224
247
  exports.RadioManager = RadioManager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonoransoftware/sonoran.js",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "description": "Sonoran.js is a library that allows you to interact with the Sonoran CAD and Sonoran CMS API. Based off of and utilizes several Discord.js library techniques for ease of use.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/readme.md CHANGED
@@ -1,9 +1,14 @@
1
1
  # Sonoran.js
2
- Sonoran.js is a library that allows you to interact with the [Sonoran CAD](https://sonorancad.com/) and [Sonoran CMS](https://sonorancms.com/) API. Based off of and utilizes several Discord.js library techniques for ease of use.
2
+ Sonoran.js is a library that allows you to interact with the [Sonoran CAD](https://docs.sonoransoftware.com/cad), [Sonoran Radio](https://docs.sonoransoftware.com/radio), and [Sonoran CMS](https://docs.sonoransoftware.com/cms) API. Based off of and utilizes several Discord.js library techniques for ease of use.
3
+
4
+ ## Installation
5
+ ```js
6
+ npm i @sonoransoftware/sonoran.js
7
+ ```
3
8
 
4
9
  ## Example Instance Setup
5
10
 
6
- Utilizing both Sonoran CMS & Sonoran CAD
11
+ Utilizing Sonoran CMS, Sonoran CAD & Sonoran Radio
7
12
  ```js
8
13
  const Sonoran = require('sonoran.js');
9
14
  const instance = Sonoran.instance({
@@ -11,6 +16,8 @@ const instance = Sonoran.instance({
11
16
  cadApiKey: 'DF58F1E-FD8A-44C5-BA',
12
17
  cmsCommunityId: 'mycommunity',
13
18
  cmsApiKey: 'e6ba9d68-ca7a-4e59-a9e2-93e275b4e0bf'
19
+ radioCommunityId: 'mycommunity'
20
+ radioApiKey: 'e6ba9d68-ca7a-4e59-a9e2-93e275b4e0bf'
14
21
  });
15
22
  ```
16
23
 
@@ -51,50 +58,117 @@ instance.cms.verifyWhitelist({
51
58
  ```
52
59
 
53
60
  ## CAD Functions
54
- ### getAccount
55
- Returns the user's account object.
56
- #### Argument `params`
57
- ##### Type: `object` `{apiId?, username?}`
61
+ Most CAD manager helpers return a `CADStandardResponse<T>` of `{ success, data?, reason? }`. Legacy helpers (`getAccount`, `setClockTime`, `joinCommunity`, `leaveCommunity`) keep their original response shapes.
62
+
63
+ ### Account & Configuration
64
+ - **`getVersion()`** - resolves to the numeric CAD subscription level.
65
+ - **`getAccount({ apiId?, username? })`** - fetches account details.
66
+ - **`setClockTime({ serverId, currentUtc, currentGame, secondsPerHour })`** - synchronizes in-game time.
67
+ - **`joinCommunity(internalKey, accounts)`** / **`leaveCommunity(internalKey, accounts)`** - manages community membership (requires an internal key).
68
+ - **`setPenalCodes(codes)`** - replaces the penal code configuration.
69
+ - **`setAccountApiIds(data)`** - assigns API IDs to a username.
70
+ - **`checkApiId(apiId)`** - confirms whether an API ID exists.
71
+ - **`applyPermissionKey(apiId?, permissionKey)`** - applies a permission key to an account.
72
+ - **`setAccountPermissions(changes)`** - bulk add/remove CAD permissions.
73
+ - **`banUser(data)`** - kicks or bans an account via the CAD API.
74
+ - **`verifySecret(secret)`** - validates a configured secret.
75
+ - **`authorizeStreetSigns(serverId)`** - authorizes map street-sign updates.
76
+ - **`setPostals(entries)`** - overwrites the postal table.
77
+ - **`sendPhoto(apiId?, url)`** - attaches a photo to an account.
78
+
79
+ ```js
80
+ const account = await instance.cad.getAccount({ apiId: '1234567890' });
81
+ const penalCodes = await instance.cad.setPenalCodes([
82
+ { code: '1A', type: 'Felony', title: 'Example', bondType: 'None', jailTime: '0', bondAmount: 0 }
83
+ ]);
84
+ await instance.cad.setAccountApiIds({ username: 'SomeUser', apiIds: ['1234567890'], pushNew: true });
85
+ const permissionUpdate = await instance.cad.setAccountPermissions({ apiId: '1234567890', add: ['admin'], remove: [] });
86
+ ```
87
+
88
+ ### Records & Lookups
89
+ - **`getRecordTemplates(recordTypeId?)`**
90
+ - **`createRecord(data)`** / **`updateRecord(data)`** / **`removeRecord(id)`**
91
+ - **`lookupByInt(criteria)`** - identifier-based lookup.
92
+ - **`lookupRecords(query)`** - plate/name-based lookup.
93
+
58
94
  ```js
59
- const params = {
60
- apiId: '',
61
- username: 'SomeUser',
62
- };
63
- // Get user account object
64
- const account = await instance.cad.getAccount(params);
95
+ await instance.cad.createRecord({ user: '1234567890', useDictionary: true, recordTypeId: 2, replaceValues: { NAME: 'Jane Doe' } });
96
+ const lookup = await instance.cad.lookupRecords({ apiId: '1234567890', types: [2], first: 'Jane', last: 'Doe', mi: '', plate: '', partial: false });
65
97
  ```
66
98
 
67
- ### setClockTime
68
- Synchronizes the CAD clock with your in-game time.
69
- #### Argument `params`
70
- ##### Type: `object` `{ serverId: number, currentUtc: string, currentGame: string, secondsPerHour: number }`
99
+ ### Civilian Tools
100
+ - **`getCharacters(apiId)`** - lists civilian characters for an API ID.
101
+ - **`createCharacter(data)`** / **`updateCharacter(data)`** / **`removeCharacter(id)`** - CRUD helpers for civilian profiles.
102
+
103
+ ### Identifiers & Units
104
+ - **`getIdentifiers(apiId)`**
105
+ - **`modifyIdentifier(change)`** / **`setIdentifier(apiId?, identId)`**
106
+ - **`setUnitPanic(apiId?, isPanic)`** / **`setUnitStatus(apiId?, status, serverId)`**
107
+ - **`getActiveUnits(options)`** - direct CAD fetch for active units.
108
+ - **`kickUnit(apiId?, reason, serverId)`**
109
+ - **`updateUnitLocations(locations)`**
110
+
111
+ ### Map & Streetsigns
112
+ - **`getBlips(serverId)`**
113
+ - **`addBlips(blips)`** / **`updateBlips(blips)`** / **`removeBlip(id)`**
114
+ - **`setStreetSignConfig(serverId, signConfig)`**
115
+ - **`updateStreetSign(serverId, signData)`**
116
+
117
+ ### Calls & Dispatch
118
+ - **`create911Call(details)`** / **`remove911Call(callId)`**
119
+ - **`getCalls(options)`**
120
+ - **`createDispatch(data)`**
121
+ - **`attachUnits(serverId, callId, units)`** / **`detachUnits(serverId, units)`**
122
+ - **`setCallPostal(serverId, callId, postal)`** / **`setCallPrimary(serverId, callId, primary, trackPrimary)`**
123
+ - **`addCallNote(serverId, callId, note)`**
124
+ - **`closeCall(serverId, callId)`**
125
+
71
126
  ```js
72
- await instance.cad.setClockTime({
127
+ const dispatch = await instance.cad.createDispatch({
73
128
  serverId: 1,
74
- currentUtc: new Date().toISOString(),
75
- currentGame: '2025-07-04T18:00:00Z',
76
- secondsPerHour: 60
129
+ origin: Sonoran.CADDispatchOriginEnums.Caller,
130
+ status: Sonoran.CADDispatchStatusEnums.Active,
131
+ priority: 1,
132
+ block: '123',
133
+ address: 'Main St',
134
+ postal: '100',
135
+ title: 'Traffic Stop',
136
+ code: 'TS',
137
+ primary: 42,
138
+ trackPrimary: true,
139
+ description: 'Blue sedan headed north',
140
+ metaData: {},
141
+ units: ['unit-1']
77
142
  });
143
+ await instance.cad.attachUnits(1, 1001, ['unit-2']);
78
144
  ```
79
145
 
80
- ### joinCommunity
81
- Adds one or more accounts to the community using an internal key.
146
+ ## CAD Server Functions
147
+ - **`getServers()`** - fetches configured CAD servers.
148
+ - **`setServers(servers, deployMap?)`** - updates server configuration and refreshes the cache.
149
+
82
150
  ```js
83
- await instance.cad.joinCommunity('internal-key', [
84
- { account: '1234567890' },
85
- '0987654321'
86
- ]);
151
+ const servers = await instance.cad.servers?.getServers();
152
+ await instance.cad.servers?.setServers(servers ?? [], false);
87
153
  ```
88
154
 
89
- ### leaveCommunity
90
- Removes one or more accounts from the community using an internal key.
155
+ ## CAD Active Unit Functions
156
+ `CADActiveUnitsManager#getActiveUnits(options?)` proxies the CAD endpoint and returns a `CADStandardResponse`.
157
+
91
158
  ```js
92
- await instance.cad.leaveCommunity('internal-key', [
93
- { account: '1234567890' }
94
- ]);
159
+ const activeUnits = await cadActiveUnitsManager.getActiveUnits({ includeOffline: true, limit: 25 });
160
+ if (activeUnits.success) {
161
+ console.log(activeUnits.data);
162
+ }
95
163
  ```
96
164
 
97
165
  ## CMS Functions
166
+ ### getSubscriptionVersion()
167
+ Returns the community's CMS subscription version.
168
+ ```js
169
+ const version = await instance.cms.getSubscriptionVersion();
170
+ ```
171
+
98
172
  ### verifyWhitelist(obj)
99
173
  Verifies that a user is whitelisted in the specified server.
100
174
  #### Arugment `params`
@@ -188,7 +262,7 @@ const getDepts = await instance.cms.getDepartments();
188
262
  ```
189
263
 
190
264
  ### setAccountRanks(obj, apiId, accId, username, discord, uniqueId)
191
- Gets all department information for a CMS community
265
+ Updates the CMS account's ranks using the identifiers provided.
192
266
  #### Arugment `params`
193
267
  ##### Type `object` `{set?: string[]; add?: string[]; remove?: string[]}`
194
268
  #### Arguments `apiId`, `accId`, `username`, `discord`, `uniqueId`
@@ -230,6 +304,23 @@ Manually triggers a CMS force-sync for the targeted identifiers.
230
304
  await instance.cms.forceSync({ username: 'SomeUser' });
231
305
  ```
232
306
 
307
+ ### getPromotionFlows()
308
+ Fetches the configured promotion flows.
309
+ ```js
310
+ const flows = await instance.cms.getPromotionFlows();
311
+ ```
312
+
313
+ ### triggerPromotionFlows(flows)
314
+ Executes promotion or demotion flows for one or more users.
315
+ ```js
316
+ await instance.cms.triggerPromotionFlows([{
317
+ userId: 'u-123',
318
+ flowId: 'flow-abc',
319
+ users: ['u-123', 'u-456'],
320
+ promote: true
321
+ }]);
322
+ ```
323
+
233
324
  ### getCurrentClockIn(params)
234
325
  Fetches the current clock-in entry for the account if one exists.
235
326
  ```js
@@ -260,6 +351,17 @@ Retrieves form submissions with optional pagination.
260
351
  const submissions = await instance.cms.getFormSubmissions(42, { skip: 0, take: 25 });
261
352
  ```
262
353
 
354
+ ### changeFormStage(params)
355
+ Moves a form to the specified stage for an account.
356
+ ```js
357
+ await instance.cms.changeFormStage({
358
+ formId: 42,
359
+ newStageId: 'approved',
360
+ accId: 'account-uuid',
361
+ uniqueId: 1234
362
+ });
363
+ ```
364
+
263
365
  ### editAccountProfileFields(params)
264
366
  Updates profile fields for an account.
265
367
  ```js
@@ -294,6 +396,21 @@ await instance.cms.erlcAddNewRecord({
294
396
  });
295
397
  ```
296
398
 
399
+ ## CMS Server Functions
400
+ ### getGameServers()
401
+ Fetches the configured CMS game servers. Returns an array of server objects.
402
+ ```js
403
+ const cmsServers = await instance.cms.servers?.getGameServers();
404
+ ```
405
+
406
+ ### setGameServers(servers)
407
+ Replaces the configured CMS game servers and refreshes the cache with the response payload.
408
+ ```js
409
+ await instance.cms.servers?.setGameServers([
410
+ { name: 'Server 1', description: 'Primary server', allowedRanks: ['admin'] }
411
+ ]);
412
+ ```
413
+
297
414
  ## Radio Functions
298
415
  ### getCommunityChannels()
299
416
  Retrieves configured community channel groups and channels.
@@ -346,5 +463,14 @@ await instance.radio.setInGameSpeakerLocations(
346
463
  );
347
464
  ```
348
465
 
466
+ ### playTone(roomId, tones, playTo)
467
+ Dispatches tones to channels, groups, or in-game speakers.
468
+ ```js
469
+ await instance.radio.playTone(1, [1001, 1002], [
470
+ { label: 'Primary Dispatch', type: 'channel', value: 10, group: 2 },
471
+ { label: 'Station Speakers', type: 'game', value: 'station-1', group: null }
472
+ ]);
473
+ ```
474
+
349
475
  ## Further Documentation
350
476
  More documentation for Sonoran CAD specific methods and usage can be found [here](/docs/CAD-Methods-and-Usage.md), Sonoran CMS specific methods and usage can be found [here](/docs/CMS-Methods-and-Usage.md), and usage information for the REST class [here](/docs/REST-Methods-and-Usage.md).
package/src/constants.ts CHANGED
@@ -271,6 +271,12 @@ export interface CADLeaveCommunityPromiseResult {
271
271
  data?: unknown;
272
272
  }
273
273
 
274
+ export interface CADStandardResponse<T = unknown> {
275
+ success: boolean;
276
+ data?: T;
277
+ reason?: unknown;
278
+ }
279
+
274
280
  export interface CMSProfileField {
275
281
  id: string;
276
282
  type: string;
@@ -348,6 +354,12 @@ export interface CMSRsvpPromiseResult {
348
354
  data?: unknown;
349
355
  }
350
356
 
357
+ export interface CMSChangeFormStagePromiseResult {
358
+ success: boolean;
359
+ reason?: string;
360
+ data?: unknown;
361
+ }
362
+
351
363
  export interface CMSSetGameServerStruct {
352
364
  id?: number;
353
365
  name: string;
@@ -365,6 +377,43 @@ export interface CMSSetGameServersPromiseResult {
365
377
  data?: CMSSetGameServerStruct[];
366
378
  }
367
379
 
380
+ export interface CMSExecuteRankPromotionResult {
381
+ users: string[];
382
+ flow: string;
383
+ promote: boolean;
384
+ succeeded: boolean;
385
+ message?: string;
386
+ }
387
+
388
+ export interface CMSTriggerPromotionFlowPayload {
389
+ userId: string;
390
+ flowId: string;
391
+ users: string[];
392
+ promote: boolean;
393
+ }
394
+
395
+ export interface CMSPromotionFlow {
396
+ id: string;
397
+ communityUuid: string;
398
+ labelFrom: string;
399
+ labelTo: string;
400
+ ranksToAdd: string[];
401
+ ranksToRemove: string[];
402
+ actions: unknown[];
403
+ }
404
+
405
+ export interface CMSTriggerPromotionFlowsPromiseResult {
406
+ success: boolean;
407
+ reason?: string;
408
+ data?: CMSExecuteRankPromotionResult[];
409
+ }
410
+
411
+ export interface CMSGetPromotionFlowsPromiseResult {
412
+ success: boolean;
413
+ reason?: string;
414
+ data?: CMSPromotionFlow[];
415
+ }
416
+
368
417
  export interface CMSGetFormSubmissionsPromiseResult<T = unknown> {
369
418
  success: boolean;
370
419
  reason?: string;
@@ -449,6 +498,17 @@ export interface RadioSpeakerLocation {
449
498
  id: string;
450
499
  }
451
500
 
501
+ export type RadioTonePlayTargetType = 'channel' | 'group' | 'game';
502
+
503
+ export interface RadioTonePlayTarget {
504
+ label: string;
505
+ type: RadioTonePlayTargetType;
506
+ value: unknown;
507
+ group: number | null;
508
+ icon?: string;
509
+ color?: string;
510
+ }
511
+
452
512
  export interface RadioSetUserChannelsOptions {
453
513
  transmit?: number;
454
514
  scan?: number[];
@@ -520,3 +580,9 @@ export interface RadioSetInGameSpeakerLocationsPromiseResult {
520
580
  reason?: string;
521
581
  result?: string;
522
582
  }
583
+
584
+ export interface RadioPlayTonePromiseResult {
585
+ success: boolean;
586
+ reason?: string;
587
+ result?: string;
588
+ }
package/src/index.ts CHANGED
@@ -23,6 +23,7 @@ export {
23
23
  CADSetClockTimePromiseResult,
24
24
  CADJoinCommunityPromiseResult,
25
25
  CADLeaveCommunityPromiseResult,
26
+ CADStandardResponse,
26
27
  CMSProfileField,
27
28
  CMSGetCurrentClockInPromiseResult,
28
29
  CMSAccountsPage,
@@ -32,7 +33,13 @@ export {
32
33
  CMSProfileFieldUpdate,
33
34
  CMSEditAccountProfileFieldsPromiseResult,
34
35
  CMSRsvpPromiseResult,
36
+ CMSChangeFormStagePromiseResult,
35
37
  CMSSetGameServerStruct,
36
38
  CMSSetGameServersPromiseResult,
39
+ CMSExecuteRankPromotionResult,
40
+ CMSTriggerPromotionFlowPayload,
41
+ CMSPromotionFlow,
42
+ CMSTriggerPromotionFlowsPromiseResult,
43
+ CMSGetPromotionFlowsPromiseResult,
37
44
  CMSGetFormSubmissionsPromiseResult
38
45
  } from './constants';
@@ -373,6 +373,16 @@ export class REST extends EventEmitter {
373
373
  uniqueId: args[4],
374
374
  }
375
375
  }
376
+ case 'TRIGGER_PROMOTION_FLOWS': {
377
+ const payload = args[0];
378
+ if (!Array.isArray(payload)) {
379
+ throw new Error('TRIGGER_PROMOTION_FLOWS requires an array of promotion flow payloads.');
380
+ }
381
+ return payload;
382
+ }
383
+ case 'GET_PROMOTION_FLOWS': {
384
+ return [];
385
+ }
376
386
  case 'ERLC_GET_ONLINE_PLAYERS': {
377
387
  return {
378
388
  robloxJoinCode: args[0]
@@ -428,6 +438,13 @@ export class REST extends EventEmitter {
428
438
  token: args[1]
429
439
  }
430
440
  }
441
+ case 'PLAY_TONE': {
442
+ return {
443
+ roomId: args[0],
444
+ tones: args[1],
445
+ playTo: args[2]
446
+ }
447
+ }
431
448
  default: {
432
449
  return args;
433
450
  }