polyv-live-api-sdk 1.0.2 → 1.0.5

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.
Files changed (41) hide show
  1. package/dist/client.d.ts +5 -0
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/index.cjs +959 -14
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +5894 -4891
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +956 -15
  9. package/dist/index.js.map +1 -1
  10. package/dist/services/channel.service.d.ts +43 -2
  11. package/dist/services/channel.service.d.ts.map +1 -1
  12. package/dist/services/player.service.d.ts +38 -1
  13. package/dist/services/player.service.d.ts.map +1 -1
  14. package/dist/services/statistics.service.d.ts +211 -0
  15. package/dist/services/statistics.service.d.ts.map +1 -0
  16. package/dist/services/v4/channel.service.d.ts.map +1 -1
  17. package/dist/services/v4/user.service.d.ts +31 -1
  18. package/dist/services/v4/user.service.d.ts.map +1 -1
  19. package/dist/services/web.service.d.ts +11 -1
  20. package/dist/services/web.service.d.ts.map +1 -1
  21. package/dist/types/channel.d.ts +119 -5
  22. package/dist/types/channel.d.ts.map +1 -1
  23. package/dist/types/index.d.ts +7 -1
  24. package/dist/types/index.d.ts.map +1 -1
  25. package/dist/types/player.d.ts +103 -0
  26. package/dist/types/player.d.ts.map +1 -1
  27. package/dist/types/statistics-export.d.ts +133 -0
  28. package/dist/types/statistics-export.d.ts.map +1 -0
  29. package/dist/types/statistics.d.ts +217 -0
  30. package/dist/types/statistics.d.ts.map +1 -0
  31. package/dist/types/v4-channel.d.ts +16 -16
  32. package/dist/types/v4-channel.d.ts.map +1 -1
  33. package/dist/types/v4-user.d.ts +42 -0
  34. package/dist/types/v4-user.d.ts.map +1 -1
  35. package/dist/types/web.d.ts +9 -5
  36. package/dist/types/web.d.ts.map +1 -1
  37. package/dist/utils/date-validation.d.ts +128 -0
  38. package/dist/utils/date-validation.d.ts.map +1 -0
  39. package/dist/utils/index.d.ts +1 -0
  40. package/dist/utils/index.d.ts.map +1 -1
  41. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -431,6 +431,117 @@ async function collectAll(fetcher, options = {}) {
431
431
  return allItems;
432
432
  }
433
433
 
434
+ // src/utils/date-validation.ts
435
+ var MAX_DATE_RANGE_DAYS = 60;
436
+ var MAX_TIME_RANGE_MONTHS = 3;
437
+ var MAX_AUDIENCE_TIME_RANGE_DAYS = 90;
438
+ var DATE_FORMAT_REGEX = /^\d{4}-\d{2}-\d{2}$/;
439
+ function isValidDateFormat(dateStr) {
440
+ if (!dateStr || typeof dateStr !== "string") {
441
+ return false;
442
+ }
443
+ if (!DATE_FORMAT_REGEX.test(dateStr)) {
444
+ return false;
445
+ }
446
+ const date = new Date(dateStr);
447
+ if (isNaN(date.getTime())) {
448
+ return false;
449
+ }
450
+ const [year, month, day] = dateStr.split("-").map(Number);
451
+ return date.getFullYear() === year && date.getMonth() + 1 === month && date.getDate() === day;
452
+ }
453
+ function isStartDateBeforeEndDate(startDay, endDay) {
454
+ const startDate = new Date(startDay);
455
+ const endDate = new Date(endDay);
456
+ return startDate <= endDate;
457
+ }
458
+ function isStartTimeBeforeEndTime(startTime, endTime) {
459
+ return startTime <= endTime;
460
+ }
461
+ function isValidTimestamp(value) {
462
+ if (typeof value !== "number" || !Number.isFinite(value)) {
463
+ return false;
464
+ }
465
+ return value > 9466848e5;
466
+ }
467
+ function validateDateRange(startDay, endDay, maxDays = MAX_DATE_RANGE_DAYS) {
468
+ if (!isStartDateBeforeEndDate(startDay, endDay)) {
469
+ return {
470
+ valid: false,
471
+ error: "startDay must be before or equal to endDay"
472
+ };
473
+ }
474
+ const startDate = new Date(startDay);
475
+ const endDate = new Date(endDay);
476
+ const diffTime = endDate.getTime() - startDate.getTime();
477
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
478
+ if (diffDays > maxDays) {
479
+ return {
480
+ valid: false,
481
+ error: `Date range cannot exceed ${maxDays} days`,
482
+ daysDiff: diffDays
483
+ };
484
+ }
485
+ return { valid: true, daysDiff: diffDays };
486
+ }
487
+ function validateTimestampRange(startTime, endTime, maxMonths = MAX_TIME_RANGE_MONTHS) {
488
+ if (!isStartTimeBeforeEndTime(startTime, endTime)) {
489
+ return {
490
+ valid: false,
491
+ error: "startTime must be before or equal to endTime"
492
+ };
493
+ }
494
+ const diffTime = endTime - startTime;
495
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
496
+ const maxDays = maxMonths * 31;
497
+ if (diffDays > maxDays) {
498
+ return {
499
+ valid: false,
500
+ error: `Time range cannot exceed ${maxMonths} months`,
501
+ daysDiff: diffDays
502
+ };
503
+ }
504
+ return { valid: true, daysDiff: diffDays };
505
+ }
506
+ function validate90DayTimestampRange(startTime, endTime) {
507
+ if (!isStartTimeBeforeEndTime(startTime, endTime)) {
508
+ return {
509
+ valid: false,
510
+ error: "startTime must be before or equal to endTime"
511
+ };
512
+ }
513
+ const diffTime = endTime - startTime;
514
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
515
+ if (diffDays > MAX_AUDIENCE_TIME_RANGE_DAYS) {
516
+ return {
517
+ valid: false,
518
+ error: `Time range cannot exceed ${MAX_AUDIENCE_TIME_RANGE_DAYS} days`,
519
+ daysDiff: diffDays
520
+ };
521
+ }
522
+ return { valid: true, daysDiff: diffDays };
523
+ }
524
+ function validateConcurrencyDateRange(startDate, endDate, maxDays = MAX_DATE_RANGE_DAYS) {
525
+ if (!isStartDateBeforeEndDate(startDate, endDate)) {
526
+ return {
527
+ valid: false,
528
+ error: "startDate must be before or equal to endDate"
529
+ };
530
+ }
531
+ const start = new Date(startDate);
532
+ const end = new Date(endDate);
533
+ const diffTime = end.getTime() - start.getTime();
534
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
535
+ if (diffDays > maxDays) {
536
+ return {
537
+ valid: false,
538
+ error: `Date range cannot exceed ${maxDays} days`,
539
+ daysDiff: diffDays
540
+ };
541
+ }
542
+ return { valid: true, daysDiff: diffDays };
543
+ }
544
+
434
545
  // src/services/channel.service.ts
435
546
  var ChannelService = class {
436
547
  client;
@@ -1846,17 +1957,21 @@ var ChannelService = class {
1846
1957
  * await channelService.setRecordDefault('ch123456', 'file123');
1847
1958
  * ```
1848
1959
  */
1849
- async setRecordDefault(channelId, fileId) {
1960
+ async setRecordDefault(channelId, fileId, listType) {
1850
1961
  if (!channelId || channelId.trim() === "") {
1851
1962
  throw PolyVValidationError.required("channelId");
1852
1963
  }
1853
1964
  if (!fileId || fileId.trim() === "") {
1854
1965
  throw PolyVValidationError.required("fileId");
1855
1966
  }
1967
+ const params = { channelId, fileId };
1968
+ if (listType) {
1969
+ params.listType = listType;
1970
+ }
1856
1971
  await this.client.httpClient.post(
1857
1972
  "/live/v3/channel/record/set-default",
1858
1973
  null,
1859
- { params: { channelId, fileId } }
1974
+ { params }
1860
1975
  );
1861
1976
  return true;
1862
1977
  }
@@ -1970,6 +2085,38 @@ var ChannelService = class {
1970
2085
  );
1971
2086
  return response;
1972
2087
  }
2088
+ /**
2089
+ * Set playback setting (Story 9.7)
2090
+ *
2091
+ * Sets the playback settings for a channel.
2092
+ * API: POST /live/v3/channel/playback/set-setting
2093
+ *
2094
+ * @param channelId - The channel ID
2095
+ * @param options - Playback setting options
2096
+ * @returns true if operation was successful
2097
+ * @throws PolyVValidationError if channelId is empty
2098
+ *
2099
+ * @example
2100
+ * ```typescript
2101
+ * await channelService.setPlaybackSetting('ch123456', {
2102
+ * playbackEnabled: 'Y',
2103
+ * type: 'single',
2104
+ * origin: 'playback',
2105
+ * });
2106
+ * ```
2107
+ */
2108
+ async setPlaybackSetting(channelId, options) {
2109
+ if (!channelId || channelId.trim() === "") {
2110
+ throw PolyVValidationError.required("channelId");
2111
+ }
2112
+ const params = { channelId, ...options };
2113
+ await this.client.httpClient.post(
2114
+ "/live/v3/channel/playback/set-setting",
2115
+ null,
2116
+ { params }
2117
+ );
2118
+ return true;
2119
+ }
1973
2120
  /**
1974
2121
  * Set playback sort
1975
2122
  *
@@ -2299,6 +2446,15 @@ var ChannelService = class {
2299
2446
  if (options.callbackUrl !== void 0) {
2300
2447
  params.callbackUrl = options.callbackUrl;
2301
2448
  }
2449
+ if (options.autoConvert !== void 0) {
2450
+ params.autoConvert = options.autoConvert;
2451
+ }
2452
+ if (options.mergeMp4 !== void 0) {
2453
+ params.mergeMp4 = options.mergeMp4;
2454
+ }
2455
+ if (options.orderByCustom !== void 0) {
2456
+ params.orderByCustom = options.orderByCustom;
2457
+ }
2302
2458
  await this.client.httpClient.post(
2303
2459
  "/live/v3/channel/record/merge-async",
2304
2460
  null,
@@ -4035,6 +4191,44 @@ var ChannelService = class {
4035
4191
  // ============================================
4036
4192
  // Product APIs (Story 8-2)
4037
4193
  // ============================================
4194
+ /**
4195
+ * List channel products
4196
+ *
4197
+ * Lists products in a channel with pagination support.
4198
+ *
4199
+ * @param params - Query parameters including channelId (required)
4200
+ * @returns Paginated product list
4201
+ * @throws PolyVValidationError if channelId is missing
4202
+ *
4203
+ * @example
4204
+ * ```typescript
4205
+ * const result = await channelService.listChannelProducts({
4206
+ * channelId: 'ch123456',
4207
+ * pageNumber: 1,
4208
+ * pageSize: 20,
4209
+ * });
4210
+ * console.log(result.contents);
4211
+ * ```
4212
+ */
4213
+ async listChannelProducts(params) {
4214
+ if (!params.channelId || params.channelId.trim() === "") {
4215
+ throw PolyVValidationError.required("channelId");
4216
+ }
4217
+ const queryParams = {
4218
+ channelId: params.channelId
4219
+ };
4220
+ if (params.pageNumber !== void 0) {
4221
+ queryParams.pageNumber = params.pageNumber;
4222
+ }
4223
+ if (params.pageSize !== void 0) {
4224
+ queryParams.pageSize = params.pageSize;
4225
+ }
4226
+ const response = await this.client.httpClient.get(
4227
+ "/live/v3/channel/product/list",
4228
+ { params: queryParams }
4229
+ );
4230
+ return response;
4231
+ }
4038
4232
  /**
4039
4233
  * Add channel product
4040
4234
  *
@@ -7432,7 +7626,8 @@ var WebService = class {
7432
7626
  * ```typescript
7433
7627
  * const result = await client.web.updateWhiteList({
7434
7628
  * rank: 1,
7435
- * code: '13800138000',
7629
+ * oldCode: '13800138000',
7630
+ * code: '13900139000',
7436
7631
  * name: 'Updated Name',
7437
7632
  * channelId: '123456',
7438
7633
  * });
@@ -7442,6 +7637,9 @@ var WebService = class {
7442
7637
  if (params.rank !== 1 && params.rank !== 2) {
7443
7638
  throw new PolyVValidationError("rank must be 1 or 2");
7444
7639
  }
7640
+ if (!params.oldCode || params.oldCode.trim() === "") {
7641
+ throw new PolyVValidationError("oldCode is required");
7642
+ }
7445
7643
  if (!params.code || params.code.trim() === "") {
7446
7644
  throw new PolyVValidationError("code is required");
7447
7645
  }
@@ -7453,6 +7651,7 @@ var WebService = class {
7453
7651
  }
7454
7652
  const apiParams = {
7455
7653
  rank: params.rank,
7654
+ oldCode: params.oldCode,
7456
7655
  code: params.code
7457
7656
  };
7458
7657
  if (params.name) {
@@ -7477,24 +7676,39 @@ var WebService = class {
7477
7676
  *
7478
7677
  * @example
7479
7678
  * ```typescript
7679
+ * // Delete specific codes
7480
7680
  * const result = await client.web.deleteWhiteList({
7481
7681
  * rank: 1,
7682
+ * isClear: 'N',
7482
7683
  * codes: '13800138000,13800138001',
7483
7684
  * channelId: '123456',
7484
7685
  * });
7686
+ *
7687
+ * // Clear all
7688
+ * const result = await client.web.deleteWhiteList({
7689
+ * rank: 1,
7690
+ * isClear: 'Y',
7691
+ * channelId: '123456',
7692
+ * });
7485
7693
  * ```
7486
7694
  */
7487
7695
  async deleteWhiteList(params) {
7488
7696
  if (params.rank !== 1 && params.rank !== 2) {
7489
7697
  throw new PolyVValidationError("rank must be 1 or 2");
7490
7698
  }
7491
- if (!params.codes || params.codes.trim() === "") {
7492
- throw new PolyVValidationError("codes is required");
7699
+ if (!params.isClear) {
7700
+ throw new PolyVValidationError("isClear is required");
7701
+ }
7702
+ if (params.isClear === "N" && (!params.codes || params.codes.trim() === "")) {
7703
+ throw new PolyVValidationError("codes is required when isClear=N");
7493
7704
  }
7494
7705
  const apiParams = {
7495
7706
  rank: params.rank,
7496
- codes: params.codes
7707
+ isClear: params.isClear
7497
7708
  };
7709
+ if (params.codes) {
7710
+ apiParams.code = params.codes;
7711
+ }
7498
7712
  if (params.channelId) {
7499
7713
  apiParams.channelId = params.channelId;
7500
7714
  }
@@ -9399,6 +9613,112 @@ var PlayerService = class {
9399
9613
  }
9400
9614
  }
9401
9615
  }
9616
+ // ============================================
9617
+ // Channel Decorate APIs (Story 10.5)
9618
+ // ============================================
9619
+ /**
9620
+ * Get channel decorate settings
9621
+ * Query channel player decoration settings (watermark, warmup image, etc.)
9622
+ *
9623
+ * @param channelId - Channel ID
9624
+ * @returns Channel decorate settings
9625
+ *
9626
+ * @example
9627
+ * ```typescript
9628
+ * const decorate = await client.player.getChannelDecorate(123456);
9629
+ * console.log(decorate.player.watermarkEnabled);
9630
+ * ```
9631
+ */
9632
+ async getChannelDecorate(channelId) {
9633
+ this.validateChannelId(channelId);
9634
+ const response = await this.client.httpClient.get(
9635
+ "/live/v4/channel/decorate/get",
9636
+ { params: { channelId } }
9637
+ );
9638
+ return response;
9639
+ }
9640
+ /**
9641
+ * Update channel decorate settings
9642
+ * Update channel player decoration settings (watermark, warmup image, etc.)
9643
+ *
9644
+ * @param channelId - Channel ID
9645
+ * @param params - Channel decorate update parameters
9646
+ * @returns true on success
9647
+ *
9648
+ * @example
9649
+ * ```typescript
9650
+ * await client.player.updateChannelDecorate(123456, {
9651
+ * watermarkEnabled: 'Y',
9652
+ * iconUrl: 'http://example.com/logo.png',
9653
+ * iconPosition: 'br',
9654
+ * logoOpacity: 0.8,
9655
+ * });
9656
+ * ```
9657
+ */
9658
+ async updateChannelDecorate(channelId, params) {
9659
+ this.validateChannelId(channelId);
9660
+ if (params.iconPosition !== void 0) {
9661
+ this.validateLogoPosition(params.iconPosition);
9662
+ }
9663
+ if (params.logoOpacity !== void 0) {
9664
+ this.validateDecorateOpacity(params.logoOpacity);
9665
+ }
9666
+ if (params.watermarkEnabled !== void 0) {
9667
+ this.validateYNValue(params.watermarkEnabled, "watermarkEnabled");
9668
+ }
9669
+ if (params.warmUpEnabled !== void 0) {
9670
+ this.validateYNValue(params.warmUpEnabled, "warmUpEnabled");
9671
+ }
9672
+ const playerBody = {};
9673
+ if (params.watermarkEnabled !== void 0) {
9674
+ playerBody.watermarkEnabled = params.watermarkEnabled;
9675
+ }
9676
+ if (params.iconUrl !== void 0) {
9677
+ playerBody.iconUrl = params.iconUrl;
9678
+ }
9679
+ if (params.iconPosition !== void 0) {
9680
+ playerBody.iconPosition = params.iconPosition;
9681
+ }
9682
+ if (params.logoOpacity !== void 0) {
9683
+ playerBody.logoOpacity = params.logoOpacity;
9684
+ }
9685
+ if (params.iconLink !== void 0) {
9686
+ playerBody.iconLink = params.iconLink;
9687
+ }
9688
+ if (params.warmUpEnabled !== void 0) {
9689
+ playerBody.warmUpEnabled = params.warmUpEnabled;
9690
+ }
9691
+ if (params.warmUpImageUrl !== void 0) {
9692
+ playerBody.warmUpImageUrl = params.warmUpImageUrl;
9693
+ }
9694
+ if (params.coverJumpUrl !== void 0) {
9695
+ playerBody.coverJumpUrl = params.coverJumpUrl;
9696
+ }
9697
+ if (params.backgroundUrl !== void 0) {
9698
+ playerBody.backgroundUrl = params.backgroundUrl;
9699
+ }
9700
+ if (params.basePV !== void 0) {
9701
+ playerBody.basePV = params.basePV;
9702
+ }
9703
+ if (params.actualPV !== void 0) {
9704
+ playerBody.actualPV = params.actualPV;
9705
+ }
9706
+ const body = { player: playerBody };
9707
+ const response = await this.client.httpClient.post(
9708
+ "/live/v4/channel/decorate/update",
9709
+ body,
9710
+ { params: { channelId } }
9711
+ );
9712
+ return response;
9713
+ }
9714
+ /**
9715
+ * Validate decorate opacity (0-1)
9716
+ */
9717
+ validateDecorateOpacity(opacity) {
9718
+ if (typeof opacity !== "number" || opacity < 0 || opacity > 1) {
9719
+ throw new PolyVValidationError("logoOpacity must be a number between 0 and 1");
9720
+ }
9721
+ }
9402
9722
  };
9403
9723
 
9404
9724
  // src/services/other.service.ts
@@ -10860,7 +11180,9 @@ var V4ChannelService = class {
10860
11180
  * @returns Sessions list
10861
11181
  */
10862
11182
  async sessionList(params) {
10863
- this.validateChannelId(params.channelId);
11183
+ if (params.channelId) {
11184
+ this.validateChannelId(params.channelId);
11185
+ }
10864
11186
  this.validatePaginationParams(params);
10865
11187
  const response = await this.client.httpClient.get(
10866
11188
  "/live/v4/channel/session/new/list",
@@ -12031,8 +12353,16 @@ var V4ChannelService = class {
12031
12353
  * Validate channel ID
12032
12354
  */
12033
12355
  validateChannelId(channelId) {
12034
- if (!channelId || channelId.trim() === "") {
12035
- throw new PolyVValidationError("channelId is required and cannot be empty", "channelId");
12356
+ if (typeof channelId === "string") {
12357
+ if (!channelId || channelId.trim() === "") {
12358
+ throw new PolyVValidationError("channelId is required and cannot be empty", "channelId");
12359
+ }
12360
+ } else if (typeof channelId === "number") {
12361
+ if (!channelId || channelId <= 0) {
12362
+ throw new PolyVValidationError("channelId is required and must be a positive number", "channelId");
12363
+ }
12364
+ } else {
12365
+ throw new PolyVValidationError("channelId must be a string or number", "channelId");
12036
12366
  }
12037
12367
  }
12038
12368
  /**
@@ -12816,7 +13146,7 @@ var V4UserService = class {
12816
13146
  */
12817
13147
  async listViewerLabels() {
12818
13148
  const response = await this.client.httpClient.get(
12819
- "/live/v4/user/viewer-record/label/list",
13149
+ "/live/v4/user/viewer-label/list",
12820
13150
  {}
12821
13151
  );
12822
13152
  return response;
@@ -12896,8 +13226,11 @@ var V4UserService = class {
12896
13226
  this.validateRequiredString(params.viewerUnionId, "viewerUnionId");
12897
13227
  this.validateRequiredNumber(params.labelId, "labelId");
12898
13228
  await this.client.httpClient.post(
12899
- "/live/v4/user/viewer-record/label/add",
12900
- params
13229
+ "/live/v4/user/viewer-label/add-viewers-label",
13230
+ {
13231
+ viewerUnionIds: [params.viewerUnionId],
13232
+ labelIds: [params.labelId]
13233
+ }
12901
13234
  );
12902
13235
  }
12903
13236
  /**
@@ -12917,8 +13250,11 @@ var V4UserService = class {
12917
13250
  this.validateRequiredString(params.viewerUnionId, "viewerUnionId");
12918
13251
  this.validateRequiredNumber(params.labelId, "labelId");
12919
13252
  await this.client.httpClient.post(
12920
- "/live/v4/user/viewer-record/label/delete-ref",
12921
- params
13253
+ "/live/v4/user/viewer-label/remove-viewers-label",
13254
+ {
13255
+ viewerUnionIds: [params.viewerUnionId],
13256
+ labelIds: [params.labelId]
13257
+ }
12922
13258
  );
12923
13259
  }
12924
13260
  // ============================================
@@ -13932,6 +14268,47 @@ var V4UserService = class {
13932
14268
  return response;
13933
14269
  }
13934
14270
  // ============================================
14271
+ // Story 13-3: Global Channel Settings APIs
14272
+ // ============================================
14273
+ /**
14274
+ * Get global channel settings
14275
+ *
14276
+ * @returns Global channel settings
14277
+ *
14278
+ * @example
14279
+ * ```typescript
14280
+ * const settings = await client.v4User.getGlobalChannelSettings();
14281
+ * ```
14282
+ */
14283
+ async getGlobalChannelSettings() {
14284
+ const response = await this.client.httpClient.get(
14285
+ "/live/v4/user/global-setting/switch/get",
14286
+ {}
14287
+ );
14288
+ return response;
14289
+ }
14290
+ /**
14291
+ * Update global channel settings
14292
+ *
14293
+ * @param params - Update parameters
14294
+ *
14295
+ * @example
14296
+ * ```typescript
14297
+ * await client.v4User.updateGlobalChannelSettings({
14298
+ * channelConcurrencesEnabled: 'Y',
14299
+ * donateEnabled: 'N',
14300
+ * coverImgType: 'contain',
14301
+ * });
14302
+ * ```
14303
+ */
14304
+ async updateGlobalChannelSettings(params) {
14305
+ this.validateGlobalSettingsParams(params);
14306
+ await this.client.httpClient.post(
14307
+ "/live/v4/user/global-setting/switch/update",
14308
+ params
14309
+ );
14310
+ }
14311
+ // ============================================
13935
14312
  // Private Validation Helpers
13936
14313
  // ============================================
13937
14314
  /**
@@ -13961,6 +14338,31 @@ var V4UserService = class {
13961
14338
  throw new PolyVValidationError(`${fieldName} is required`, fieldName, value);
13962
14339
  }
13963
14340
  }
14341
+ /**
14342
+ * Validate global settings update parameters
14343
+ */
14344
+ validateGlobalSettingsParams(params) {
14345
+ const booleanFields = [
14346
+ "channelConcurrencesEnabled",
14347
+ "timelyConvertEnabled",
14348
+ "donateEnabled",
14349
+ "rebirthAutoUploadEnabled",
14350
+ "rebirthAutoConvertEnabled",
14351
+ "pptCoveredEnabled",
14352
+ "testModeButtonEnabled"
14353
+ ];
14354
+ for (const field of booleanFields) {
14355
+ const value = params[field];
14356
+ if (value !== void 0 && value !== "Y" && value !== "N") {
14357
+ throw new PolyVValidationError(`${field} must be 'Y' or 'N'`, field, value);
14358
+ }
14359
+ }
14360
+ if (params.coverImgType !== void 0) {
14361
+ if (params.coverImgType !== "contain" && params.coverImgType !== "cover") {
14362
+ throw new PolyVValidationError("coverImgType must be 'contain' or 'cover'", "coverImgType", params.coverImgType);
14363
+ }
14364
+ }
14365
+ }
13964
14366
  };
13965
14367
 
13966
14368
  // src/services/v4/global.service.ts
@@ -14839,6 +15241,540 @@ var V4WebAppService = class {
14839
15241
  }
14840
15242
  };
14841
15243
 
15244
+ // src/services/statistics.service.ts
15245
+ var StatisticsService = class {
15246
+ client;
15247
+ /**
15248
+ * Create a new StatisticsService instance
15249
+ *
15250
+ * @param client - The PolyVClient instance to use for API calls
15251
+ */
15252
+ constructor(client) {
15253
+ this.client = client;
15254
+ }
15255
+ // ============================================
15256
+ // Daily View Statistics API
15257
+ // ============================================
15258
+ /**
15259
+ * Get daily view statistics
15260
+ *
15261
+ * Query daily view statistics for a channel within a date range.
15262
+ * The date range cannot exceed 60 days.
15263
+ *
15264
+ * @param params - Query parameters
15265
+ * @returns Daily view statistics response
15266
+ * @throws {PolyVValidationError} When parameters are invalid
15267
+ *
15268
+ * @example
15269
+ * ```typescript
15270
+ * const result = await client.statistics.getDailyViewStatistics({
15271
+ * channelId: '123456',
15272
+ * startDay: '2024-01-01',
15273
+ * endDay: '2024-01-31',
15274
+ * });
15275
+ * console.log(result.contents);
15276
+ * ```
15277
+ */
15278
+ async getDailyViewStatistics(params) {
15279
+ this.validateGetDailyViewStatisticsParams(params);
15280
+ const response = await this.client.httpClient.get(
15281
+ "/live/v3/channel/statistics/daily/summary",
15282
+ { params }
15283
+ );
15284
+ return {
15285
+ contents: response
15286
+ };
15287
+ }
15288
+ // ============================================
15289
+ // Private Validation Helpers
15290
+ // ============================================
15291
+ /**
15292
+ * Validate parameters for getDailyViewStatistics
15293
+ */
15294
+ validateGetDailyViewStatisticsParams(params) {
15295
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15296
+ throw new PolyVValidationError(
15297
+ "channelId is required and must be a non-empty string",
15298
+ "channelId",
15299
+ params.channelId
15300
+ );
15301
+ }
15302
+ if (!params.startDay || !isValidDateFormat(params.startDay)) {
15303
+ throw new PolyVValidationError(
15304
+ "startDay is required and must be in yyyy-MM-dd format",
15305
+ "startDay",
15306
+ params.startDay
15307
+ );
15308
+ }
15309
+ if (!params.endDay || !isValidDateFormat(params.endDay)) {
15310
+ throw new PolyVValidationError(
15311
+ "endDay is required and must be in yyyy-MM-dd format",
15312
+ "endDay",
15313
+ params.endDay
15314
+ );
15315
+ }
15316
+ const rangeValidation = validateDateRange(params.startDay, params.endDay, MAX_DATE_RANGE_DAYS);
15317
+ if (!rangeValidation.valid) {
15318
+ throw new PolyVValidationError(
15319
+ rangeValidation.error || "Invalid date range",
15320
+ "dateRange",
15321
+ { startDay: params.startDay, endDay: params.endDay, daysDiff: rangeValidation.daysDiff }
15322
+ );
15323
+ }
15324
+ }
15325
+ // ============================================
15326
+ // Concurrency Data API (Story 10.2)
15327
+ // ============================================
15328
+ /**
15329
+ * Get historical concurrency data
15330
+ *
15331
+ * Query historical concurrency data for a channel within a date range.
15332
+ * The date range cannot exceed 60 days.
15333
+ *
15334
+ * @param params - Query parameters
15335
+ * @returns Concurrency data response
15336
+ * @throws {PolyVValidationError} When parameters are invalid
15337
+ *
15338
+ * @example
15339
+ * ```typescript
15340
+ * const result = await client.statistics.getConcurrencyData({
15341
+ * channelId: '123456',
15342
+ * startDate: '2024-01-01',
15343
+ * endDate: '2024-01-31',
15344
+ * });
15345
+ * console.log(result.contents);
15346
+ * ```
15347
+ */
15348
+ async getConcurrencyData(params) {
15349
+ this.validateGetConcurrencyDataParams(params);
15350
+ const response = await this.client.httpClient.get(
15351
+ "/live/v3/channel/statistics/concurrence",
15352
+ { params }
15353
+ );
15354
+ return {
15355
+ contents: response
15356
+ };
15357
+ }
15358
+ /**
15359
+ * Validate parameters for getConcurrencyData
15360
+ */
15361
+ validateGetConcurrencyDataParams(params) {
15362
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15363
+ throw new PolyVValidationError(
15364
+ "channelId is required and must be a non-empty string",
15365
+ "channelId",
15366
+ params.channelId
15367
+ );
15368
+ }
15369
+ if (!params.startDate || !isValidDateFormat(params.startDate)) {
15370
+ throw new PolyVValidationError(
15371
+ "startDate is required and must be in yyyy-MM-dd format",
15372
+ "startDate",
15373
+ params.startDate
15374
+ );
15375
+ }
15376
+ if (!params.endDate || !isValidDateFormat(params.endDate)) {
15377
+ throw new PolyVValidationError(
15378
+ "endDate is required and must be in yyyy-MM-dd format",
15379
+ "endDate",
15380
+ params.endDate
15381
+ );
15382
+ }
15383
+ const rangeValidation = validateConcurrencyDateRange(params.startDate, params.endDate, MAX_DATE_RANGE_DAYS);
15384
+ if (!rangeValidation.valid) {
15385
+ throw new PolyVValidationError(
15386
+ rangeValidation.error || "Invalid date range",
15387
+ "dateRange",
15388
+ { startDate: params.startDate, endDate: params.endDate, daysDiff: rangeValidation.daysDiff }
15389
+ );
15390
+ }
15391
+ }
15392
+ // ============================================
15393
+ // Max Concurrent API (Story 10.2)
15394
+ // ============================================
15395
+ /**
15396
+ * Get maximum historical concurrent viewers
15397
+ *
15398
+ * Query the maximum concurrent viewers for a channel within a time range.
15399
+ * The time range cannot exceed 3 months.
15400
+ *
15401
+ * @param params - Query parameters
15402
+ * @returns Max concurrent response
15403
+ * @throws {PolyVValidationError} When parameters are invalid
15404
+ *
15405
+ * @example
15406
+ * ```typescript
15407
+ * const result = await client.statistics.getMaxConcurrent({
15408
+ * channelId: '123456',
15409
+ * startTime: 1704067200000,
15410
+ * endTime: 1735689600000,
15411
+ * });
15412
+ * console.log(result.contents);
15413
+ * ```
15414
+ */
15415
+ async getMaxConcurrent(params) {
15416
+ this.validateGetMaxConcurrentParams(params);
15417
+ const response = await this.client.httpClient.get(
15418
+ "/live/v3/channel/statistics/get-max-history-concurrent",
15419
+ { params }
15420
+ );
15421
+ return {
15422
+ contents: response
15423
+ };
15424
+ }
15425
+ /**
15426
+ * Validate parameters for getMaxConcurrent
15427
+ */
15428
+ validateGetMaxConcurrentParams(params) {
15429
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15430
+ throw new PolyVValidationError(
15431
+ "channelId is required and must be a non-empty string",
15432
+ "channelId",
15433
+ params.channelId
15434
+ );
15435
+ }
15436
+ if (!isValidTimestamp(params.startTime)) {
15437
+ throw new PolyVValidationError(
15438
+ "startTime is required and must be a valid timestamp",
15439
+ "startTime",
15440
+ params.startTime
15441
+ );
15442
+ }
15443
+ if (!isValidTimestamp(params.endTime)) {
15444
+ throw new PolyVValidationError(
15445
+ "endTime is required and must be a valid timestamp",
15446
+ "endTime",
15447
+ params.endTime
15448
+ );
15449
+ }
15450
+ const rangeValidation = validateTimestampRange(params.startTime, params.endTime);
15451
+ if (!rangeValidation.valid) {
15452
+ throw new PolyVValidationError(
15453
+ rangeValidation.error || "Invalid time range",
15454
+ "timeRange",
15455
+ { startTime: params.startTime, endTime: params.endTime, daysDiff: rangeValidation.daysDiff }
15456
+ );
15457
+ }
15458
+ }
15459
+ // ============================================
15460
+ // Region Distribution API (Story 10.3)
15461
+ // ============================================
15462
+ /**
15463
+ * Get region distribution
15464
+ *
15465
+ * Query the geographic distribution of viewers for a channel.
15466
+ * The time range cannot exceed 90 days.
15467
+ *
15468
+ * @param params - Query parameters
15469
+ * @returns Region distribution response
15470
+ * @throws {PolyVValidationError} When parameters are invalid
15471
+ *
15472
+ * @example
15473
+ * ```typescript
15474
+ * const result = await client.statistics.getRegionDistribution({
15475
+ * channelId: '123456',
15476
+ * startTime: 1648742400000,
15477
+ * endTime: 1651334399000,
15478
+ * type: 'province',
15479
+ * });
15480
+ * console.log(result.data);
15481
+ * ```
15482
+ */
15483
+ async getRegionDistribution(params) {
15484
+ this.validateGetRegionDistributionParams(params);
15485
+ const requestParams = {
15486
+ channelId: params.channelId,
15487
+ startTime: params.startTime,
15488
+ endTime: params.endTime
15489
+ };
15490
+ if (params.type) {
15491
+ requestParams.type = params.type;
15492
+ }
15493
+ const response = await this.client.httpClient.get(
15494
+ "/live/v4/channel/statistics/geo-summary-mc",
15495
+ { params: requestParams }
15496
+ );
15497
+ return response;
15498
+ }
15499
+ /**
15500
+ * Validate parameters for getRegionDistribution
15501
+ */
15502
+ validateGetRegionDistributionParams(params) {
15503
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15504
+ throw new PolyVValidationError(
15505
+ "channelId is required and must be a non-empty string",
15506
+ "channelId",
15507
+ params.channelId
15508
+ );
15509
+ }
15510
+ if (!isValidTimestamp(params.startTime)) {
15511
+ throw new PolyVValidationError(
15512
+ "startTime is required and must be a valid timestamp",
15513
+ "startTime",
15514
+ params.startTime
15515
+ );
15516
+ }
15517
+ if (!isValidTimestamp(params.endTime)) {
15518
+ throw new PolyVValidationError(
15519
+ "endTime is required and must be a valid timestamp",
15520
+ "endTime",
15521
+ params.endTime
15522
+ );
15523
+ }
15524
+ const rangeValidation = validate90DayTimestampRange(params.startTime, params.endTime);
15525
+ if (!rangeValidation.valid) {
15526
+ throw new PolyVValidationError(
15527
+ rangeValidation.error || "Invalid time range",
15528
+ "timeRange",
15529
+ { startTime: params.startTime, endTime: params.endTime, daysDiff: rangeValidation.daysDiff }
15530
+ );
15531
+ }
15532
+ if (params.type !== void 0) {
15533
+ const validTypes = ["country", "province", "city"];
15534
+ if (!validTypes.includes(params.type)) {
15535
+ throw new PolyVValidationError(
15536
+ "Type must be one of: country, province, city",
15537
+ "type",
15538
+ params.type
15539
+ );
15540
+ }
15541
+ }
15542
+ }
15543
+ // ============================================
15544
+ // Device Distribution API (Story 10.3)
15545
+ // ============================================
15546
+ /**
15547
+ * Get device distribution
15548
+ *
15549
+ * Query the browser/device distribution of viewers for a channel.
15550
+ * The time range cannot exceed 90 days.
15551
+ *
15552
+ * @param params - Query parameters
15553
+ * @returns Device distribution response
15554
+ * @throws {PolyVValidationError} When parameters are invalid
15555
+ *
15556
+ * @example
15557
+ * ```typescript
15558
+ * const result = await client.statistics.getDeviceDistribution({
15559
+ * channelId: '123456',
15560
+ * startTime: 1651386101000,
15561
+ * endTime: 1652336501462,
15562
+ * });
15563
+ * console.log(result.data);
15564
+ * ```
15565
+ */
15566
+ async getDeviceDistribution(params) {
15567
+ this.validateGetDeviceDistributionParams(params);
15568
+ const response = await this.client.httpClient.get(
15569
+ "/live/v4/channel/statistics/browser-summary",
15570
+ { params }
15571
+ );
15572
+ return response;
15573
+ }
15574
+ /**
15575
+ * Validate parameters for getDeviceDistribution
15576
+ */
15577
+ validateGetDeviceDistributionParams(params) {
15578
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15579
+ throw new PolyVValidationError(
15580
+ "channelId is required and must be a non-empty string",
15581
+ "channelId",
15582
+ params.channelId
15583
+ );
15584
+ }
15585
+ if (!isValidTimestamp(params.startTime)) {
15586
+ throw new PolyVValidationError(
15587
+ "startTime is required and must be a valid timestamp",
15588
+ "startTime",
15589
+ params.startTime
15590
+ );
15591
+ }
15592
+ if (!isValidTimestamp(params.endTime)) {
15593
+ throw new PolyVValidationError(
15594
+ "endTime is required and must be a valid timestamp",
15595
+ "endTime",
15596
+ params.endTime
15597
+ );
15598
+ }
15599
+ const rangeValidation = validate90DayTimestampRange(params.startTime, params.endTime);
15600
+ if (!rangeValidation.valid) {
15601
+ throw new PolyVValidationError(
15602
+ rangeValidation.error || "Invalid time range",
15603
+ "timeRange",
15604
+ { startTime: params.startTime, endTime: params.endTime, daysDiff: rangeValidation.daysDiff }
15605
+ );
15606
+ }
15607
+ }
15608
+ // ============================================
15609
+ // Viewlog Export API (Story 10.4)
15610
+ // ============================================
15611
+ /**
15612
+ * Get viewlog (viewing log) data
15613
+ *
15614
+ * Query viewing log data for a channel within a date range.
15615
+ * The date range must be within the same month.
15616
+ *
15617
+ * @param params - Query parameters
15618
+ * @returns Viewlog response with pagination
15619
+ * @throws {PolyVValidationError} When parameters are invalid
15620
+ *
15621
+ * @example
15622
+ * ```typescript
15623
+ * const result = await client.statistics.getViewlog({
15624
+ * channelId: '3151318',
15625
+ * startDate: '2024-01-01 00:00:00',
15626
+ * endDate: '2024-01-31 23:59:59',
15627
+ * });
15628
+ * console.log(result.contents);
15629
+ * ```
15630
+ */
15631
+ async getViewlog(params) {
15632
+ this.validateGetViewlogParams(params);
15633
+ const requestParams = {
15634
+ channelId: params.channelId,
15635
+ startDate: params.startDate,
15636
+ endDate: params.endDate,
15637
+ pageSize: params.pageSize ?? 1e3
15638
+ };
15639
+ if (params.page !== void 0) {
15640
+ requestParams.page = params.page;
15641
+ }
15642
+ if (params.watchType !== void 0) {
15643
+ requestParams.watchType = params.watchType;
15644
+ }
15645
+ const response = await this.client.httpClient.get(
15646
+ "/live/v3/user/statistics/viewlog",
15647
+ { params: requestParams }
15648
+ );
15649
+ if (response && typeof response === "object" && "data" in response) {
15650
+ const responseData = response;
15651
+ if (responseData.data && typeof responseData.data === "object") {
15652
+ return responseData.data;
15653
+ }
15654
+ }
15655
+ return response;
15656
+ }
15657
+ /**
15658
+ * Validate parameters for getViewlog
15659
+ */
15660
+ validateGetViewlogParams(params) {
15661
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15662
+ throw new PolyVValidationError(
15663
+ "channelId is required and must be a non-empty string",
15664
+ "channelId",
15665
+ params.channelId
15666
+ );
15667
+ }
15668
+ const dateTimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
15669
+ if (!params.startDate || !dateTimeRegex.test(params.startDate)) {
15670
+ throw new PolyVValidationError(
15671
+ "startDate is required and must be in yyyy-MM-dd HH:mm:ss format",
15672
+ "startDate",
15673
+ params.startDate
15674
+ );
15675
+ }
15676
+ if (!params.endDate || !dateTimeRegex.test(params.endDate)) {
15677
+ throw new PolyVValidationError(
15678
+ "endDate is required and must be in yyyy-MM-dd HH:mm:ss format",
15679
+ "endDate",
15680
+ params.endDate
15681
+ );
15682
+ }
15683
+ const startMonth = params.startDate.substring(0, 7);
15684
+ const endMonth = params.endDate.substring(0, 7);
15685
+ if (startMonth !== endMonth) {
15686
+ throw new PolyVValidationError(
15687
+ "startDate and endDate must be in the same month",
15688
+ "dateRange",
15689
+ { startDate: params.startDate, endDate: params.endDate }
15690
+ );
15691
+ }
15692
+ if (params.watchType !== void 0) {
15693
+ const validWatchTypes = ["live", "vod"];
15694
+ if (!validWatchTypes.includes(params.watchType)) {
15695
+ throw new PolyVValidationError(
15696
+ 'watchType must be either "live" or "vod"',
15697
+ "watchType",
15698
+ params.watchType
15699
+ );
15700
+ }
15701
+ }
15702
+ }
15703
+ // ============================================
15704
+ // Session Stats Export API (Story 10.4)
15705
+ // ============================================
15706
+ /**
15707
+ * Export session statistics report
15708
+ *
15709
+ * Export the session statistics report for a specific session.
15710
+ * Returns a download URL for the report file.
15711
+ *
15712
+ * @param params - Query parameters
15713
+ * @returns Export response with download URL
15714
+ * @throws {PolyVValidationError} When parameters are invalid
15715
+ *
15716
+ * @example
15717
+ * ```typescript
15718
+ * const result = await client.statistics.exportSessionStats({
15719
+ * channelId: '3151318',
15720
+ * sessionId: 'fv3ma84e63',
15721
+ * });
15722
+ * console.log(result.downloadUrl);
15723
+ * ```
15724
+ */
15725
+ async exportSessionStats(params) {
15726
+ this.validateExportSessionStatsParams(params);
15727
+ const response = await this.client.httpClient.get(
15728
+ "/live/v3/channel/session/stats/export",
15729
+ { params }
15730
+ );
15731
+ if (response && typeof response === "object" && "data" in response) {
15732
+ const responseData = response;
15733
+ if (responseData.data && typeof responseData.data === "object") {
15734
+ const innerData = responseData.data;
15735
+ if (innerData.code && innerData.code !== 200) {
15736
+ throw new Error(innerData.message || "API Error");
15737
+ }
15738
+ if ("downloadUrl" in innerData) {
15739
+ return innerData;
15740
+ }
15741
+ if (typeof innerData.data === "string" && innerData.data) {
15742
+ return { downloadUrl: innerData.data };
15743
+ }
15744
+ }
15745
+ }
15746
+ if (response && typeof response === "object" && "code" in response) {
15747
+ const apiResponse = response;
15748
+ if (apiResponse.code && apiResponse.code !== 200) {
15749
+ throw new Error(String(apiResponse.message || "API Error"));
15750
+ }
15751
+ if (typeof apiResponse.data === "string" && apiResponse.data) {
15752
+ return { downloadUrl: apiResponse.data };
15753
+ }
15754
+ }
15755
+ return response;
15756
+ }
15757
+ /**
15758
+ * Validate parameters for exportSessionStats
15759
+ */
15760
+ validateExportSessionStatsParams(params) {
15761
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15762
+ throw new PolyVValidationError(
15763
+ "channelId is required and must be a non-empty string",
15764
+ "channelId",
15765
+ params.channelId
15766
+ );
15767
+ }
15768
+ if (!params.sessionId || typeof params.sessionId !== "string" || params.sessionId.trim() === "") {
15769
+ throw new PolyVValidationError(
15770
+ "sessionId is required and must be a non-empty string",
15771
+ "sessionId",
15772
+ params.sessionId
15773
+ );
15774
+ }
15775
+ }
15776
+ };
15777
+
14842
15778
  // src/client.ts
14843
15779
  var DEFAULT_CONFIG = {
14844
15780
  baseUrl: "https://api.polyv.net",
@@ -14862,6 +15798,10 @@ var PolyVClient = class {
14862
15798
  * Channel service for managing live channels
14863
15799
  */
14864
15800
  channel;
15801
+ /**
15802
+ * Statistics service for managing statistics operations
15803
+ */
15804
+ statistics;
14865
15805
  /**
14866
15806
  * Chat service for managing chat messages
14867
15807
  */
@@ -14961,6 +15901,7 @@ var PolyVClient = class {
14961
15901
  };
14962
15902
  this.httpClient = this.createHttpClient();
14963
15903
  this.channel = new ChannelService(this);
15904
+ this.statistics = new StatisticsService(this);
14964
15905
  this.chat = new ChatService(this);
14965
15906
  this.liveInteraction = new LiveInteractionService(this);
14966
15907
  this.account = new AccountService(this);
@@ -15264,6 +16205,7 @@ exports.ChannelService = ChannelService;
15264
16205
  exports.ERROR_CATEGORIES = ERROR_CATEGORIES;
15265
16206
  exports.ERROR_MESSAGES = ERROR_MESSAGES;
15266
16207
  exports.HttpMethod = HttpMethod;
16208
+ exports.MAX_DATE_RANGE_DAYS = MAX_DATE_RANGE_DAYS;
15267
16209
  exports.PolyVAPIError = PolyVAPIError;
15268
16210
  exports.PolyVClient = PolyVClient;
15269
16211
  exports.PolyVError = PolyVError;
@@ -15288,8 +16230,11 @@ exports.isPolyVAPIError = isPolyVAPIError;
15288
16230
  exports.isPolyVError = isPolyVError;
15289
16231
  exports.isPolyVErrorCode = isPolyVErrorCode;
15290
16232
  exports.isPolyVValidationError = isPolyVValidationError;
16233
+ exports.isStartDateBeforeEndDate = isStartDateBeforeEndDate;
16234
+ exports.isValidDateFormat = isValidDateFormat;
15291
16235
  exports.isWebWorker = isWebWorker;
15292
16236
  exports.paginate = paginate;
15293
16237
  exports.sortParams = sortParams;
16238
+ exports.validateDateRange = validateDateRange;
15294
16239
  //# sourceMappingURL=index.cjs.map
15295
16240
  //# sourceMappingURL=index.cjs.map