@sonoransoftware/sonoran.js 1.0.41 → 1.0.45

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.
@@ -111,6 +111,29 @@ export interface CMSClockInType {
111
111
  id: string;
112
112
  label: string;
113
113
  }
114
+ export interface AccountActivityLog {
115
+ id: string;
116
+ status: boolean;
117
+ accId: string;
118
+ serverId: number;
119
+ start: string;
120
+ end: string | null;
121
+ clearReason: string | null;
122
+ metadata: Record<string, any>;
123
+ objKey: string;
124
+ }
125
+ export interface AccountClockInLog {
126
+ id: number;
127
+ startTime: string | null;
128
+ endTime: string | null;
129
+ completed: boolean;
130
+ notes: {
131
+ timestamp: string;
132
+ message: string;
133
+ }[];
134
+ type?: string;
135
+ objKey: string;
136
+ }
114
137
  export interface CMSGetClockInTypesPromiseResult {
115
138
  success: boolean;
116
139
  reason?: string;
@@ -119,7 +142,7 @@ export interface CMSGetClockInTypesPromiseResult {
119
142
  export interface CMSGetLatestActivityPromiseResult {
120
143
  success: boolean;
121
144
  reason?: string;
122
- data?: string | null;
145
+ data?: AccountClockInLog[] | AccountActivityLog[];
123
146
  }
124
147
  export interface CMSClockInOutParams {
125
148
  accId?: string;
@@ -195,6 +195,18 @@ class REST extends events_1.EventEmitter {
195
195
  type: args[5]
196
196
  };
197
197
  }
198
+ case 'UNIT_STATUS': {
199
+ const payload = args[0];
200
+ if (payload && typeof payload === 'object' && !Array.isArray(payload)) {
201
+ const { apiId, account, status, serverId } = payload;
202
+ return { apiId, account, status, serverId };
203
+ }
204
+ return {
205
+ apiId: args[0],
206
+ status: args[1],
207
+ serverId: args[2]
208
+ };
209
+ }
198
210
  case 'CHECK_COM_APIID': {
199
211
  return {
200
212
  apiId: args[0]
@@ -348,8 +360,9 @@ class REST extends events_1.EventEmitter {
348
360
  }
349
361
  case 'RADIO_SET_USER_CHANNELS': {
350
362
  return {
351
- identity: args[0],
352
- options: (_c = args[1]) !== null && _c !== void 0 ? _c : {}
363
+ roomId: args[0],
364
+ identity: args[1],
365
+ options: (_c = args[2]) !== null && _c !== void 0 ? _c : {}
353
366
  };
354
367
  }
355
368
  case 'RADIO_SET_USER_DISPLAY_NAME': {
@@ -238,7 +238,7 @@ class RequestManager extends events_1.EventEmitter {
238
238
  return apiData;
239
239
  }
240
240
  static resolveRadioRequest(instance, apiURL, apiType, request, apiData) {
241
- var _a, _b, _c;
241
+ var _a, _b, _c, _d;
242
242
  if (!apiURL || typeof apiURL !== 'string') {
243
243
  throw new Error('Radio API URL could not be resolved for request.');
244
244
  }
@@ -313,12 +313,20 @@ class RequestManager extends events_1.EventEmitter {
313
313
  }
314
314
  case 'RADIO_SET_USER_CHANNELS': {
315
315
  const auth = ensureAuth();
316
+ const roomIdRaw = (_b = payload === null || payload === void 0 ? void 0 : payload.roomId) !== null && _b !== void 0 ? _b : payload === null || payload === void 0 ? void 0 : payload.roomID;
317
+ if (roomIdRaw === undefined) {
318
+ throw new Error('roomId is required for RADIO_SET_USER_CHANNELS requests.');
319
+ }
320
+ const roomIdNumeric = typeof roomIdRaw === 'number' ? roomIdRaw : Number(roomIdRaw);
321
+ if (Number.isNaN(roomIdNumeric)) {
322
+ throw new Error('roomId must be a number for RADIO_SET_USER_CHANNELS requests.');
323
+ }
316
324
  const identity = payload === null || payload === void 0 ? void 0 : payload.identity;
317
325
  if (!identity) {
318
326
  throw new Error('identity is required for RADIO_SET_USER_CHANNELS requests.');
319
327
  }
320
- const options = (_b = payload === null || payload === void 0 ? void 0 : payload.options) !== null && _b !== void 0 ? _b : {};
321
- path = `${apiType.path}/${auth.encodedId}/${auth.encodedKey}/${encodeSegment(identity)}`;
328
+ const options = (_c = payload === null || payload === void 0 ? void 0 : payload.options) !== null && _c !== void 0 ? _c : {};
329
+ path = `${apiType.path}/${auth.encodedId}/${auth.encodedKey}/${encodeSegment(roomIdNumeric)}/${encodeSegment(identity)}`;
322
330
  method = 'POST';
323
331
  const requestBody = {};
324
332
  if ((options === null || options === void 0 ? void 0 : options.transmit) !== undefined) {
@@ -379,7 +387,7 @@ class RequestManager extends events_1.EventEmitter {
379
387
  key: auth.key,
380
388
  locations
381
389
  };
382
- const token = (_c = payload === null || payload === void 0 ? void 0 : payload.token) !== null && _c !== void 0 ? _c : auth.key;
390
+ const token = (_d = payload === null || payload === void 0 ? void 0 : payload.token) !== null && _d !== void 0 ? _d : auth.key;
383
391
  if (token) {
384
392
  headers.Authorization = `Bearer ${token}`;
385
393
  }
@@ -273,6 +273,12 @@ export interface CADUnitLocationStruct {
273
273
  apiId: string;
274
274
  location: string;
275
275
  }
276
+ export interface CADUnitStatusStruct {
277
+ apiId?: string;
278
+ account?: string;
279
+ status: number;
280
+ serverId: number;
281
+ }
276
282
  export interface RESTTypedAPIDataStructs {
277
283
  GET_SERVERS: [];
278
284
  SET_SERVERS: [
@@ -348,6 +354,8 @@ export interface RESTTypedAPIDataStructs {
348
354
  apiId: string | undefined,
349
355
  status: number,
350
356
  serverId: number
357
+ ] | [
358
+ data: CADUnitStatusStruct
351
359
  ];
352
360
  GET_BLIPS: [serverId: number];
353
361
  ADD_BLIP: [data: CADAddBlipStruct[]];
@@ -575,6 +583,7 @@ export interface RESTTypedAPIDataStructs {
575
583
  identity: string
576
584
  ];
577
585
  RADIO_SET_USER_CHANNELS: [
586
+ roomId: number,
578
587
  identity: string,
579
588
  options?: RadioSetUserChannelsOptions
580
589
  ];
@@ -636,7 +645,8 @@ export type PossibleRequestData = undefined | {
636
645
  apiId: string;
637
646
  isPanic: boolean;
638
647
  } | {
639
- apiId: string;
648
+ apiId?: string;
649
+ account?: string;
640
650
  status: number;
641
651
  serverId: number;
642
652
  } | {
@@ -160,6 +160,12 @@ export declare class CADManager extends BaseManager {
160
160
  * Updates a unit's status.
161
161
  */
162
162
  setUnitStatus(apiId: string | undefined, status: number, serverId: number): Promise<globalTypes.CADStandardResponse>;
163
+ setUnitStatus(params: {
164
+ apiId?: string;
165
+ account?: string;
166
+ status: number;
167
+ serverId: number;
168
+ }): Promise<globalTypes.CADStandardResponse>;
163
169
  /**
164
170
  * Retrieves live map blips for a CAD server.
165
171
  */
@@ -382,14 +382,30 @@ class CADManager extends BaseManager_1.BaseManager {
382
382
  async setUnitPanic(apiId, isPanic) {
383
383
  return this.executeCadRequest('UNIT_PANIC', apiId, isPanic);
384
384
  }
385
- /**
386
- * Updates a unit's status.
387
- */
388
- async setUnitStatus(apiId, status, serverId) {
389
- if (!Number.isInteger(serverId)) {
385
+ async setUnitStatus(apiIdOrParams, status, serverId) {
386
+ let payload;
387
+ if (apiIdOrParams && typeof apiIdOrParams === 'object' && !Array.isArray(apiIdOrParams)) {
388
+ payload = {
389
+ apiId: apiIdOrParams.apiId,
390
+ account: apiIdOrParams.account,
391
+ status: apiIdOrParams.status,
392
+ serverId: apiIdOrParams.serverId
393
+ };
394
+ }
395
+ else {
396
+ payload = { apiId: apiIdOrParams, status: status, serverId: serverId };
397
+ }
398
+ const { apiId, account, status: resolvedStatus, serverId: resolvedServerId } = payload;
399
+ if (!Number.isInteger(resolvedServerId)) {
390
400
  throw new Error('serverId must be an integer when updating unit status.');
391
401
  }
392
- return this.executeCadRequest('UNIT_STATUS', apiId, status, serverId);
402
+ if (resolvedStatus === undefined) {
403
+ throw new Error('status is required when updating unit status.');
404
+ }
405
+ if (!apiId && !account) {
406
+ throw new Error('Either apiId or account is required when updating unit status.');
407
+ }
408
+ return this.executeCadRequest('UNIT_STATUS', { apiId, account, status: resolvedStatus, serverId: resolvedServerId });
393
409
  }
394
410
  /**
395
411
  * Retrieves live map blips for a CAD server.
@@ -578,7 +578,8 @@ class CMSManager extends BaseManager_1.BaseManager {
578
578
  var _a;
579
579
  try {
580
580
  const response = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('GET_LATEST_ACTIVITY', params));
581
- resolve({ success: true, data: response });
581
+ const data = response && typeof response === 'object' && 'data' in response ? response.data : response;
582
+ resolve({ success: true, data });
582
583
  }
583
584
  catch (err) {
584
585
  if (err instanceof src_1.APIError) {
@@ -27,10 +27,11 @@ export declare class RadioManager extends BaseManager {
27
27
  getConnectedUser(roomId: number, identity: string): Promise<globalTypes.RadioGetConnectedUserPromiseResult>;
28
28
  /**
29
29
  * Updates a user's transmit and scanned channel configuration.
30
+ * @param {number} roomId Multi-server room id.
30
31
  * @param {string} identity The user's UUID.
31
32
  * @param {RadioSetUserChannelsOptions} options Transmit and scan channel configuration.
32
33
  */
33
- setUserChannels(identity: string, options?: globalTypes.RadioSetUserChannelsOptions): Promise<globalTypes.RadioSetUserChannelsPromiseResult>;
34
+ setUserChannels(roomId: number, identity: string, options?: globalTypes.RadioSetUserChannelsOptions): Promise<globalTypes.RadioSetUserChannelsPromiseResult>;
34
35
  /**
35
36
  * Updates a user's display name.
36
37
  * @param {string} accId The user's account UUID.
@@ -115,14 +115,15 @@ class RadioManager extends BaseManager_1.BaseManager {
115
115
  }
116
116
  /**
117
117
  * Updates a user's transmit and scanned channel configuration.
118
+ * @param {number} roomId Multi-server room id.
118
119
  * @param {string} identity The user's UUID.
119
120
  * @param {RadioSetUserChannelsOptions} options Transmit and scan channel configuration.
120
121
  */
121
- async setUserChannels(identity, options = {}) {
122
+ async setUserChannels(roomId, identity, options = {}) {
122
123
  return new Promise(async (resolve, reject) => {
123
124
  var _a, _b;
124
125
  try {
125
- const response = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('RADIO_SET_USER_CHANNELS', identity, options));
126
+ const response = await ((_a = this.rest) === null || _a === void 0 ? void 0 : _a.request('RADIO_SET_USER_CHANNELS', roomId, identity, options));
126
127
  resolve({ success: true, result: (_b = response === null || response === void 0 ? void 0 : response.result) !== null && _b !== void 0 ? _b : response });
127
128
  }
128
129
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonoransoftware/sonoran.js",
3
- "version": "1.0.41",
3
+ "version": "1.0.45",
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
@@ -103,11 +103,18 @@ const lookup = await instance.cad.lookupRecords({ apiId: '1234567890', types: [2
103
103
  ### Identifiers & Units
104
104
  - **`getIdentifiers(apiId)`**
105
105
  - **`modifyIdentifier(change)`** / **`setIdentifier(apiId?, identId)`**
106
- - **`setUnitPanic(apiId?, isPanic)`** / **`setUnitStatus(apiId?, status, serverId)`**
106
+ - **`setUnitPanic(apiId?, isPanic)`** / **`setUnitStatus({ status, serverId, apiId?, account? })`**
107
107
  - **`getActiveUnits(options)`** - direct CAD fetch for active units.
108
108
  - **`kickUnit(apiId?, reason, serverId)`**
109
109
  - **`updateUnitLocations(locations)`**
110
110
 
111
+ ```js
112
+ // Update a unit's status using an account UUID
113
+ await instance.cad.setUnitStatus({ account: 'd5663516-ee35-11e9-9714-5600023b2434', status: 2, serverId: 1 });
114
+ // Legacy positional call using an API ID
115
+ await instance.cad.setUnitStatus('1234567890', 2, 1);
116
+ ```
117
+
111
118
  ### Map & Streetsigns
112
119
  - **`getBlips(serverId)`**
113
120
  - **`addBlips(blips)`** / **`updateBlips(blips)`** / **`removeBlip(id)`**
@@ -232,7 +239,7 @@ const getRanks = await instance.cms.getAccountRanks(params);
232
239
  ### clockInOut(obj)
233
240
  Clock a user in or out in the CMS system
234
241
  #### Arugment `obj`
235
- ##### Type `object` `{accId?: string, apiId?: string, forceClockIn?: boolean, discord?: string, uniqueId?: string}`
242
+ ##### Type `object` `{accId?: string, apiId?: string, forceClockIn?: boolean, discord?: string, uniqueId?: string, type?: string}`
236
243
  ```js
237
244
  const params = {
238
245
  accId: '',
@@ -240,11 +247,19 @@ const params = {
240
247
  forceClockIn: true,
241
248
  discord: '',
242
249
  uniqueId: '1234',
250
+ type: 'clockin-type-uuid'
243
251
  };
244
252
  // Clocks a user in or out
245
253
  const clock = await instance.cms.clockInOut(params);
246
254
  ```
247
255
 
256
+ ### getClockInTypes()
257
+ Returns the configured clock-in types.
258
+ ```js
259
+ const types = await instance.cms.getClockInTypes();
260
+ // [{ id: 'uuid', label: 'Patrol' }]
261
+ ```
262
+
248
263
  ### checkComApiId(apiId)
249
264
  Checks if a given API ID is attatched to any account within the community, and if true, returns the username of the associated account.
250
265
  #### Arugment `apiId`
@@ -327,6 +342,16 @@ Fetches the current clock-in entry for the account if one exists.
327
342
  const currentEntry = await instance.cms.getCurrentClockIn({ apiId: '1234' });
328
343
  ```
329
344
 
345
+ ### getLatestActivity(params)
346
+ Gets the latest clock-in or activity entries for an account.
347
+ ```js
348
+ // Clock-in history
349
+ const clockins = await instance.cms.getLatestActivity({ accId: 'account-uuid', type: 'clockin' });
350
+ // Activity history (requires serverId)
351
+ const activity = await instance.cms.getLatestActivity({ accId: 'account-uuid', type: 'activity', serverId: 1 });
352
+ ```
353
+ *Returns an array of clock-in logs (`AccountClockInLog`) or activity logs (`AccountActivityLog`); each item includes `objKey` alongside the other fields.*
354
+
330
355
  ### getAccounts(options)
331
356
  Retrieves CMS accounts with optional pagination and status filters.
332
357
  ```js
@@ -430,10 +455,10 @@ Fetches a specific connected radio user by room and identity.
430
455
  const user = await instance.radio.getConnectedUser(1, 'account-uuid');
431
456
  ```
432
457
 
433
- ### setUserChannels(identity, options)
434
- Updates a user's transmit or scan channels.
458
+ ### setUserChannels(roomId, identity, options)
459
+ Updates a user's transmit or scan channels for a specific radio room.
435
460
  ```js
436
- await instance.radio.setUserChannels('account-uuid', { transmit: 12, scan: [10, 11, 12] });
461
+ await instance.radio.setUserChannels(1, 'account-uuid', { transmit: 12, scan: [10, 11, 12] });
437
462
  ```
438
463
 
439
464
  ### setUserDisplayName(accId, displayName)
package/src/constants.ts CHANGED
@@ -127,6 +127,31 @@ export interface CMSClockInType {
127
127
  label: string;
128
128
  }
129
129
 
130
+ export interface AccountActivityLog {
131
+ id: string;
132
+ status: boolean;
133
+ accId: string;
134
+ serverId: number;
135
+ start: string;
136
+ end: string | null;
137
+ clearReason: string | null;
138
+ metadata: Record<string, any>;
139
+ objKey: string;
140
+ }
141
+
142
+ export interface AccountClockInLog {
143
+ id: number;
144
+ startTime: string | null;
145
+ endTime: string | null;
146
+ completed: boolean;
147
+ notes: {
148
+ timestamp: string;
149
+ message: string;
150
+ }[];
151
+ type?: string;
152
+ objKey: string;
153
+ }
154
+
130
155
  export interface CMSGetClockInTypesPromiseResult {
131
156
  success: boolean;
132
157
  reason?: string;
@@ -136,7 +161,7 @@ export interface CMSGetClockInTypesPromiseResult {
136
161
  export interface CMSGetLatestActivityPromiseResult {
137
162
  success: boolean;
138
163
  reason?: string;
139
- data?: string | null;
164
+ data?: AccountClockInLog[] | AccountActivityLog[];
140
165
  }
141
166
 
142
167
  export interface CMSClockInOutParams {
@@ -299,6 +299,23 @@ export class REST extends EventEmitter {
299
299
  type: args[5]
300
300
  };
301
301
  }
302
+ case 'UNIT_STATUS': {
303
+ const payload = args[0];
304
+ if (payload && typeof payload === 'object' && !Array.isArray(payload)) {
305
+ const { apiId, account, status, serverId } = payload as {
306
+ apiId?: string;
307
+ account?: string;
308
+ status: number;
309
+ serverId: number;
310
+ };
311
+ return { apiId, account, status, serverId };
312
+ }
313
+ return {
314
+ apiId: args[0],
315
+ status: args[1],
316
+ serverId: args[2]
317
+ };
318
+ }
302
319
  case 'CHECK_COM_APIID': {
303
320
  return {
304
321
  apiId: args[0]
@@ -452,8 +469,9 @@ export class REST extends EventEmitter {
452
469
  }
453
470
  case 'RADIO_SET_USER_CHANNELS': {
454
471
  return {
455
- identity: args[0],
456
- options: args[1] ?? {}
472
+ roomId: args[0],
473
+ identity: args[1],
474
+ options: args[2] ?? {}
457
475
  }
458
476
  }
459
477
  case 'RADIO_SET_USER_DISPLAY_NAME': {
@@ -392,12 +392,20 @@ export class RequestManager extends EventEmitter {
392
392
  }
393
393
  case 'RADIO_SET_USER_CHANNELS': {
394
394
  const auth = ensureAuth();
395
+ const roomIdRaw = payload?.roomId ?? payload?.roomID;
396
+ if (roomIdRaw === undefined) {
397
+ throw new Error('roomId is required for RADIO_SET_USER_CHANNELS requests.');
398
+ }
399
+ const roomIdNumeric = typeof roomIdRaw === 'number' ? roomIdRaw : Number(roomIdRaw);
400
+ if (Number.isNaN(roomIdNumeric)) {
401
+ throw new Error('roomId must be a number for RADIO_SET_USER_CHANNELS requests.');
402
+ }
395
403
  const identity = payload?.identity;
396
404
  if (!identity) {
397
405
  throw new Error('identity is required for RADIO_SET_USER_CHANNELS requests.');
398
406
  }
399
407
  const options = payload?.options ?? {};
400
- path = `${apiType.path}/${auth.encodedId}/${auth.encodedKey}/${encodeSegment(identity)}`;
408
+ path = `${apiType.path}/${auth.encodedId}/${auth.encodedKey}/${encodeSegment(roomIdNumeric)}/${encodeSegment(identity)}`;
401
409
  method = 'POST';
402
410
  const requestBody: Record<string, unknown> = {};
403
411
  if (options?.transmit !== undefined) {
@@ -900,7 +900,14 @@ export interface CADStreetSignStruct {
900
900
 
901
901
  export interface CADUnitLocationStruct {
902
902
  apiId: string;
903
- location: string;
903
+ location: string;
904
+ }
905
+
906
+ export interface CADUnitStatusStruct {
907
+ apiId?: string;
908
+ account?: string;
909
+ status: number;
910
+ serverId: number;
904
911
  }
905
912
 
906
913
  export interface RESTTypedAPIDataStructs {
@@ -977,6 +984,8 @@ export interface RESTTypedAPIDataStructs {
977
984
  apiId: string | undefined,
978
985
  status: number,
979
986
  serverId: number
987
+ ] | [
988
+ data: CADUnitStatusStruct
980
989
  ];
981
990
  GET_BLIPS: [serverId: number];
982
991
  ADD_BLIP: [data: CADAddBlipStruct[]];
@@ -1209,6 +1218,7 @@ export interface RESTTypedAPIDataStructs {
1209
1218
  identity: string
1210
1219
  ];
1211
1220
  RADIO_SET_USER_CHANNELS: [
1221
+ roomId: number,
1212
1222
  identity: string,
1213
1223
  options?: RadioSetUserChannelsOptions
1214
1224
  ];
@@ -1287,7 +1297,8 @@ export type PossibleRequestData =
1287
1297
  isPanic: boolean;
1288
1298
  } |
1289
1299
  {
1290
- apiId: string;
1300
+ apiId?: string;
1301
+ account?: string;
1291
1302
  status: number;
1292
1303
  serverId: number;
1293
1304
  } |
@@ -19,7 +19,8 @@ import type {
19
19
  CADGetActiveUnitsStruct,
20
20
  CADNewDispatchStruct,
21
21
  CADStreetSignStruct,
22
- CADUnitLocationStruct
22
+ CADUnitLocationStruct,
23
+ CADUnitStatusStruct
23
24
  } from '../libs/rest/src';
24
25
  import { BaseManager } from './BaseManager';
25
26
  import * as globalTypes from '../constants';
@@ -405,11 +406,35 @@ export class CADManager extends BaseManager {
405
406
  /**
406
407
  * Updates a unit's status.
407
408
  */
408
- public async setUnitStatus(apiId: string | undefined, status: number, serverId: number): Promise<globalTypes.CADStandardResponse> {
409
- if (!Number.isInteger(serverId)) {
409
+ public async setUnitStatus(apiId: string | undefined, status: number, serverId: number): Promise<globalTypes.CADStandardResponse>;
410
+ public async setUnitStatus(params: { apiId?: string; account?: string; status: number; serverId: number }): Promise<globalTypes.CADStandardResponse>;
411
+ public async setUnitStatus(
412
+ apiIdOrParams: string | undefined | { apiId?: string; account?: string; status: number; serverId: number },
413
+ status?: number,
414
+ serverId?: number
415
+ ): Promise<globalTypes.CADStandardResponse> {
416
+ let payload: CADUnitStatusStruct;
417
+ if (apiIdOrParams && typeof apiIdOrParams === 'object' && !Array.isArray(apiIdOrParams)) {
418
+ payload = {
419
+ apiId: apiIdOrParams.apiId,
420
+ account: apiIdOrParams.account,
421
+ status: apiIdOrParams.status,
422
+ serverId: apiIdOrParams.serverId
423
+ };
424
+ } else {
425
+ payload = { apiId: apiIdOrParams as string | undefined, status: status as number, serverId: serverId as number };
426
+ }
427
+ const { apiId, account, status: resolvedStatus, serverId: resolvedServerId } = payload;
428
+ if (!Number.isInteger(resolvedServerId)) {
410
429
  throw new Error('serverId must be an integer when updating unit status.');
411
430
  }
412
- return this.executeCadRequest('UNIT_STATUS', apiId, status, serverId);
431
+ if (resolvedStatus === undefined) {
432
+ throw new Error('status is required when updating unit status.');
433
+ }
434
+ if (!apiId && !account) {
435
+ throw new Error('Either apiId or account is required when updating unit status.');
436
+ }
437
+ return this.executeCadRequest('UNIT_STATUS', { apiId, account, status: resolvedStatus, serverId: resolvedServerId });
413
438
  }
414
439
 
415
440
  /**
@@ -520,7 +520,8 @@ export class CMSManager extends BaseManager {
520
520
  return new Promise(async (resolve, reject) => {
521
521
  try {
522
522
  const response: any = await this.rest?.request('GET_LATEST_ACTIVITY', params);
523
- resolve({ success: true, data: response });
523
+ const data = response && typeof response === 'object' && 'data' in response ? (response as any).data : response;
524
+ resolve({ success: true, data });
524
525
  } catch (err) {
525
526
  if (err instanceof APIError) {
526
527
  resolve({ success: false, reason: err.response });
@@ -90,13 +90,14 @@ export class RadioManager extends BaseManager {
90
90
 
91
91
  /**
92
92
  * Updates a user's transmit and scanned channel configuration.
93
+ * @param {number} roomId Multi-server room id.
93
94
  * @param {string} identity The user's UUID.
94
95
  * @param {RadioSetUserChannelsOptions} options Transmit and scan channel configuration.
95
96
  */
96
- public async setUserChannels(identity: string, options: globalTypes.RadioSetUserChannelsOptions = {}): Promise<globalTypes.RadioSetUserChannelsPromiseResult> {
97
+ public async setUserChannels(roomId: number, identity: string, options: globalTypes.RadioSetUserChannelsOptions = {}): Promise<globalTypes.RadioSetUserChannelsPromiseResult> {
97
98
  return new Promise(async (resolve, reject) => {
98
99
  try {
99
- const response: any = await this.rest?.request('RADIO_SET_USER_CHANNELS', identity, options);
100
+ const response: any = await this.rest?.request('RADIO_SET_USER_CHANNELS', roomId, identity, options);
100
101
  resolve({ success: true, result: response?.result ?? response });
101
102
  } catch (err) {
102
103
  if (err instanceof APIError) {