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.js CHANGED
@@ -424,6 +424,117 @@ async function collectAll(fetcher, options = {}) {
424
424
  return allItems;
425
425
  }
426
426
 
427
+ // src/utils/date-validation.ts
428
+ var MAX_DATE_RANGE_DAYS = 60;
429
+ var MAX_TIME_RANGE_MONTHS = 3;
430
+ var MAX_AUDIENCE_TIME_RANGE_DAYS = 90;
431
+ var DATE_FORMAT_REGEX = /^\d{4}-\d{2}-\d{2}$/;
432
+ function isValidDateFormat(dateStr) {
433
+ if (!dateStr || typeof dateStr !== "string") {
434
+ return false;
435
+ }
436
+ if (!DATE_FORMAT_REGEX.test(dateStr)) {
437
+ return false;
438
+ }
439
+ const date = new Date(dateStr);
440
+ if (isNaN(date.getTime())) {
441
+ return false;
442
+ }
443
+ const [year, month, day] = dateStr.split("-").map(Number);
444
+ return date.getFullYear() === year && date.getMonth() + 1 === month && date.getDate() === day;
445
+ }
446
+ function isStartDateBeforeEndDate(startDay, endDay) {
447
+ const startDate = new Date(startDay);
448
+ const endDate = new Date(endDay);
449
+ return startDate <= endDate;
450
+ }
451
+ function isStartTimeBeforeEndTime(startTime, endTime) {
452
+ return startTime <= endTime;
453
+ }
454
+ function isValidTimestamp(value) {
455
+ if (typeof value !== "number" || !Number.isFinite(value)) {
456
+ return false;
457
+ }
458
+ return value > 9466848e5;
459
+ }
460
+ function validateDateRange(startDay, endDay, maxDays = MAX_DATE_RANGE_DAYS) {
461
+ if (!isStartDateBeforeEndDate(startDay, endDay)) {
462
+ return {
463
+ valid: false,
464
+ error: "startDay must be before or equal to endDay"
465
+ };
466
+ }
467
+ const startDate = new Date(startDay);
468
+ const endDate = new Date(endDay);
469
+ const diffTime = endDate.getTime() - startDate.getTime();
470
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
471
+ if (diffDays > maxDays) {
472
+ return {
473
+ valid: false,
474
+ error: `Date range cannot exceed ${maxDays} days`,
475
+ daysDiff: diffDays
476
+ };
477
+ }
478
+ return { valid: true, daysDiff: diffDays };
479
+ }
480
+ function validateTimestampRange(startTime, endTime, maxMonths = MAX_TIME_RANGE_MONTHS) {
481
+ if (!isStartTimeBeforeEndTime(startTime, endTime)) {
482
+ return {
483
+ valid: false,
484
+ error: "startTime must be before or equal to endTime"
485
+ };
486
+ }
487
+ const diffTime = endTime - startTime;
488
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
489
+ const maxDays = maxMonths * 31;
490
+ if (diffDays > maxDays) {
491
+ return {
492
+ valid: false,
493
+ error: `Time range cannot exceed ${maxMonths} months`,
494
+ daysDiff: diffDays
495
+ };
496
+ }
497
+ return { valid: true, daysDiff: diffDays };
498
+ }
499
+ function validate90DayTimestampRange(startTime, endTime) {
500
+ if (!isStartTimeBeforeEndTime(startTime, endTime)) {
501
+ return {
502
+ valid: false,
503
+ error: "startTime must be before or equal to endTime"
504
+ };
505
+ }
506
+ const diffTime = endTime - startTime;
507
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
508
+ if (diffDays > MAX_AUDIENCE_TIME_RANGE_DAYS) {
509
+ return {
510
+ valid: false,
511
+ error: `Time range cannot exceed ${MAX_AUDIENCE_TIME_RANGE_DAYS} days`,
512
+ daysDiff: diffDays
513
+ };
514
+ }
515
+ return { valid: true, daysDiff: diffDays };
516
+ }
517
+ function validateConcurrencyDateRange(startDate, endDate, maxDays = MAX_DATE_RANGE_DAYS) {
518
+ if (!isStartDateBeforeEndDate(startDate, endDate)) {
519
+ return {
520
+ valid: false,
521
+ error: "startDate must be before or equal to endDate"
522
+ };
523
+ }
524
+ const start = new Date(startDate);
525
+ const end = new Date(endDate);
526
+ const diffTime = end.getTime() - start.getTime();
527
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
528
+ if (diffDays > maxDays) {
529
+ return {
530
+ valid: false,
531
+ error: `Date range cannot exceed ${maxDays} days`,
532
+ daysDiff: diffDays
533
+ };
534
+ }
535
+ return { valid: true, daysDiff: diffDays };
536
+ }
537
+
427
538
  // src/services/channel.service.ts
428
539
  var ChannelService = class {
429
540
  client;
@@ -1839,17 +1950,21 @@ var ChannelService = class {
1839
1950
  * await channelService.setRecordDefault('ch123456', 'file123');
1840
1951
  * ```
1841
1952
  */
1842
- async setRecordDefault(channelId, fileId) {
1953
+ async setRecordDefault(channelId, fileId, listType) {
1843
1954
  if (!channelId || channelId.trim() === "") {
1844
1955
  throw PolyVValidationError.required("channelId");
1845
1956
  }
1846
1957
  if (!fileId || fileId.trim() === "") {
1847
1958
  throw PolyVValidationError.required("fileId");
1848
1959
  }
1960
+ const params = { channelId, fileId };
1961
+ if (listType) {
1962
+ params.listType = listType;
1963
+ }
1849
1964
  await this.client.httpClient.post(
1850
1965
  "/live/v3/channel/record/set-default",
1851
1966
  null,
1852
- { params: { channelId, fileId } }
1967
+ { params }
1853
1968
  );
1854
1969
  return true;
1855
1970
  }
@@ -1963,6 +2078,38 @@ var ChannelService = class {
1963
2078
  );
1964
2079
  return response;
1965
2080
  }
2081
+ /**
2082
+ * Set playback setting (Story 9.7)
2083
+ *
2084
+ * Sets the playback settings for a channel.
2085
+ * API: POST /live/v3/channel/playback/set-setting
2086
+ *
2087
+ * @param channelId - The channel ID
2088
+ * @param options - Playback setting options
2089
+ * @returns true if operation was successful
2090
+ * @throws PolyVValidationError if channelId is empty
2091
+ *
2092
+ * @example
2093
+ * ```typescript
2094
+ * await channelService.setPlaybackSetting('ch123456', {
2095
+ * playbackEnabled: 'Y',
2096
+ * type: 'single',
2097
+ * origin: 'playback',
2098
+ * });
2099
+ * ```
2100
+ */
2101
+ async setPlaybackSetting(channelId, options) {
2102
+ if (!channelId || channelId.trim() === "") {
2103
+ throw PolyVValidationError.required("channelId");
2104
+ }
2105
+ const params = { channelId, ...options };
2106
+ await this.client.httpClient.post(
2107
+ "/live/v3/channel/playback/set-setting",
2108
+ null,
2109
+ { params }
2110
+ );
2111
+ return true;
2112
+ }
1966
2113
  /**
1967
2114
  * Set playback sort
1968
2115
  *
@@ -2292,6 +2439,15 @@ var ChannelService = class {
2292
2439
  if (options.callbackUrl !== void 0) {
2293
2440
  params.callbackUrl = options.callbackUrl;
2294
2441
  }
2442
+ if (options.autoConvert !== void 0) {
2443
+ params.autoConvert = options.autoConvert;
2444
+ }
2445
+ if (options.mergeMp4 !== void 0) {
2446
+ params.mergeMp4 = options.mergeMp4;
2447
+ }
2448
+ if (options.orderByCustom !== void 0) {
2449
+ params.orderByCustom = options.orderByCustom;
2450
+ }
2295
2451
  await this.client.httpClient.post(
2296
2452
  "/live/v3/channel/record/merge-async",
2297
2453
  null,
@@ -4028,6 +4184,44 @@ var ChannelService = class {
4028
4184
  // ============================================
4029
4185
  // Product APIs (Story 8-2)
4030
4186
  // ============================================
4187
+ /**
4188
+ * List channel products
4189
+ *
4190
+ * Lists products in a channel with pagination support.
4191
+ *
4192
+ * @param params - Query parameters including channelId (required)
4193
+ * @returns Paginated product list
4194
+ * @throws PolyVValidationError if channelId is missing
4195
+ *
4196
+ * @example
4197
+ * ```typescript
4198
+ * const result = await channelService.listChannelProducts({
4199
+ * channelId: 'ch123456',
4200
+ * pageNumber: 1,
4201
+ * pageSize: 20,
4202
+ * });
4203
+ * console.log(result.contents);
4204
+ * ```
4205
+ */
4206
+ async listChannelProducts(params) {
4207
+ if (!params.channelId || params.channelId.trim() === "") {
4208
+ throw PolyVValidationError.required("channelId");
4209
+ }
4210
+ const queryParams = {
4211
+ channelId: params.channelId
4212
+ };
4213
+ if (params.pageNumber !== void 0) {
4214
+ queryParams.pageNumber = params.pageNumber;
4215
+ }
4216
+ if (params.pageSize !== void 0) {
4217
+ queryParams.pageSize = params.pageSize;
4218
+ }
4219
+ const response = await this.client.httpClient.get(
4220
+ "/live/v3/channel/product/list",
4221
+ { params: queryParams }
4222
+ );
4223
+ return response;
4224
+ }
4031
4225
  /**
4032
4226
  * Add channel product
4033
4227
  *
@@ -7425,7 +7619,8 @@ var WebService = class {
7425
7619
  * ```typescript
7426
7620
  * const result = await client.web.updateWhiteList({
7427
7621
  * rank: 1,
7428
- * code: '13800138000',
7622
+ * oldCode: '13800138000',
7623
+ * code: '13900139000',
7429
7624
  * name: 'Updated Name',
7430
7625
  * channelId: '123456',
7431
7626
  * });
@@ -7435,6 +7630,9 @@ var WebService = class {
7435
7630
  if (params.rank !== 1 && params.rank !== 2) {
7436
7631
  throw new PolyVValidationError("rank must be 1 or 2");
7437
7632
  }
7633
+ if (!params.oldCode || params.oldCode.trim() === "") {
7634
+ throw new PolyVValidationError("oldCode is required");
7635
+ }
7438
7636
  if (!params.code || params.code.trim() === "") {
7439
7637
  throw new PolyVValidationError("code is required");
7440
7638
  }
@@ -7446,6 +7644,7 @@ var WebService = class {
7446
7644
  }
7447
7645
  const apiParams = {
7448
7646
  rank: params.rank,
7647
+ oldCode: params.oldCode,
7449
7648
  code: params.code
7450
7649
  };
7451
7650
  if (params.name) {
@@ -7470,24 +7669,39 @@ var WebService = class {
7470
7669
  *
7471
7670
  * @example
7472
7671
  * ```typescript
7672
+ * // Delete specific codes
7473
7673
  * const result = await client.web.deleteWhiteList({
7474
7674
  * rank: 1,
7675
+ * isClear: 'N',
7475
7676
  * codes: '13800138000,13800138001',
7476
7677
  * channelId: '123456',
7477
7678
  * });
7679
+ *
7680
+ * // Clear all
7681
+ * const result = await client.web.deleteWhiteList({
7682
+ * rank: 1,
7683
+ * isClear: 'Y',
7684
+ * channelId: '123456',
7685
+ * });
7478
7686
  * ```
7479
7687
  */
7480
7688
  async deleteWhiteList(params) {
7481
7689
  if (params.rank !== 1 && params.rank !== 2) {
7482
7690
  throw new PolyVValidationError("rank must be 1 or 2");
7483
7691
  }
7484
- if (!params.codes || params.codes.trim() === "") {
7485
- throw new PolyVValidationError("codes is required");
7692
+ if (!params.isClear) {
7693
+ throw new PolyVValidationError("isClear is required");
7694
+ }
7695
+ if (params.isClear === "N" && (!params.codes || params.codes.trim() === "")) {
7696
+ throw new PolyVValidationError("codes is required when isClear=N");
7486
7697
  }
7487
7698
  const apiParams = {
7488
7699
  rank: params.rank,
7489
- codes: params.codes
7700
+ isClear: params.isClear
7490
7701
  };
7702
+ if (params.codes) {
7703
+ apiParams.code = params.codes;
7704
+ }
7491
7705
  if (params.channelId) {
7492
7706
  apiParams.channelId = params.channelId;
7493
7707
  }
@@ -9392,6 +9606,112 @@ var PlayerService = class {
9392
9606
  }
9393
9607
  }
9394
9608
  }
9609
+ // ============================================
9610
+ // Channel Decorate APIs (Story 10.5)
9611
+ // ============================================
9612
+ /**
9613
+ * Get channel decorate settings
9614
+ * Query channel player decoration settings (watermark, warmup image, etc.)
9615
+ *
9616
+ * @param channelId - Channel ID
9617
+ * @returns Channel decorate settings
9618
+ *
9619
+ * @example
9620
+ * ```typescript
9621
+ * const decorate = await client.player.getChannelDecorate(123456);
9622
+ * console.log(decorate.player.watermarkEnabled);
9623
+ * ```
9624
+ */
9625
+ async getChannelDecorate(channelId) {
9626
+ this.validateChannelId(channelId);
9627
+ const response = await this.client.httpClient.get(
9628
+ "/live/v4/channel/decorate/get",
9629
+ { params: { channelId } }
9630
+ );
9631
+ return response;
9632
+ }
9633
+ /**
9634
+ * Update channel decorate settings
9635
+ * Update channel player decoration settings (watermark, warmup image, etc.)
9636
+ *
9637
+ * @param channelId - Channel ID
9638
+ * @param params - Channel decorate update parameters
9639
+ * @returns true on success
9640
+ *
9641
+ * @example
9642
+ * ```typescript
9643
+ * await client.player.updateChannelDecorate(123456, {
9644
+ * watermarkEnabled: 'Y',
9645
+ * iconUrl: 'http://example.com/logo.png',
9646
+ * iconPosition: 'br',
9647
+ * logoOpacity: 0.8,
9648
+ * });
9649
+ * ```
9650
+ */
9651
+ async updateChannelDecorate(channelId, params) {
9652
+ this.validateChannelId(channelId);
9653
+ if (params.iconPosition !== void 0) {
9654
+ this.validateLogoPosition(params.iconPosition);
9655
+ }
9656
+ if (params.logoOpacity !== void 0) {
9657
+ this.validateDecorateOpacity(params.logoOpacity);
9658
+ }
9659
+ if (params.watermarkEnabled !== void 0) {
9660
+ this.validateYNValue(params.watermarkEnabled, "watermarkEnabled");
9661
+ }
9662
+ if (params.warmUpEnabled !== void 0) {
9663
+ this.validateYNValue(params.warmUpEnabled, "warmUpEnabled");
9664
+ }
9665
+ const playerBody = {};
9666
+ if (params.watermarkEnabled !== void 0) {
9667
+ playerBody.watermarkEnabled = params.watermarkEnabled;
9668
+ }
9669
+ if (params.iconUrl !== void 0) {
9670
+ playerBody.iconUrl = params.iconUrl;
9671
+ }
9672
+ if (params.iconPosition !== void 0) {
9673
+ playerBody.iconPosition = params.iconPosition;
9674
+ }
9675
+ if (params.logoOpacity !== void 0) {
9676
+ playerBody.logoOpacity = params.logoOpacity;
9677
+ }
9678
+ if (params.iconLink !== void 0) {
9679
+ playerBody.iconLink = params.iconLink;
9680
+ }
9681
+ if (params.warmUpEnabled !== void 0) {
9682
+ playerBody.warmUpEnabled = params.warmUpEnabled;
9683
+ }
9684
+ if (params.warmUpImageUrl !== void 0) {
9685
+ playerBody.warmUpImageUrl = params.warmUpImageUrl;
9686
+ }
9687
+ if (params.coverJumpUrl !== void 0) {
9688
+ playerBody.coverJumpUrl = params.coverJumpUrl;
9689
+ }
9690
+ if (params.backgroundUrl !== void 0) {
9691
+ playerBody.backgroundUrl = params.backgroundUrl;
9692
+ }
9693
+ if (params.basePV !== void 0) {
9694
+ playerBody.basePV = params.basePV;
9695
+ }
9696
+ if (params.actualPV !== void 0) {
9697
+ playerBody.actualPV = params.actualPV;
9698
+ }
9699
+ const body = { player: playerBody };
9700
+ const response = await this.client.httpClient.post(
9701
+ "/live/v4/channel/decorate/update",
9702
+ body,
9703
+ { params: { channelId } }
9704
+ );
9705
+ return response;
9706
+ }
9707
+ /**
9708
+ * Validate decorate opacity (0-1)
9709
+ */
9710
+ validateDecorateOpacity(opacity) {
9711
+ if (typeof opacity !== "number" || opacity < 0 || opacity > 1) {
9712
+ throw new PolyVValidationError("logoOpacity must be a number between 0 and 1");
9713
+ }
9714
+ }
9395
9715
  };
9396
9716
 
9397
9717
  // src/services/other.service.ts
@@ -10853,7 +11173,9 @@ var V4ChannelService = class {
10853
11173
  * @returns Sessions list
10854
11174
  */
10855
11175
  async sessionList(params) {
10856
- this.validateChannelId(params.channelId);
11176
+ if (params.channelId) {
11177
+ this.validateChannelId(params.channelId);
11178
+ }
10857
11179
  this.validatePaginationParams(params);
10858
11180
  const response = await this.client.httpClient.get(
10859
11181
  "/live/v4/channel/session/new/list",
@@ -12024,8 +12346,16 @@ var V4ChannelService = class {
12024
12346
  * Validate channel ID
12025
12347
  */
12026
12348
  validateChannelId(channelId) {
12027
- if (!channelId || channelId.trim() === "") {
12028
- throw new PolyVValidationError("channelId is required and cannot be empty", "channelId");
12349
+ if (typeof channelId === "string") {
12350
+ if (!channelId || channelId.trim() === "") {
12351
+ throw new PolyVValidationError("channelId is required and cannot be empty", "channelId");
12352
+ }
12353
+ } else if (typeof channelId === "number") {
12354
+ if (!channelId || channelId <= 0) {
12355
+ throw new PolyVValidationError("channelId is required and must be a positive number", "channelId");
12356
+ }
12357
+ } else {
12358
+ throw new PolyVValidationError("channelId must be a string or number", "channelId");
12029
12359
  }
12030
12360
  }
12031
12361
  /**
@@ -12809,7 +13139,7 @@ var V4UserService = class {
12809
13139
  */
12810
13140
  async listViewerLabels() {
12811
13141
  const response = await this.client.httpClient.get(
12812
- "/live/v4/user/viewer-record/label/list",
13142
+ "/live/v4/user/viewer-label/list",
12813
13143
  {}
12814
13144
  );
12815
13145
  return response;
@@ -12889,8 +13219,11 @@ var V4UserService = class {
12889
13219
  this.validateRequiredString(params.viewerUnionId, "viewerUnionId");
12890
13220
  this.validateRequiredNumber(params.labelId, "labelId");
12891
13221
  await this.client.httpClient.post(
12892
- "/live/v4/user/viewer-record/label/add",
12893
- params
13222
+ "/live/v4/user/viewer-label/add-viewers-label",
13223
+ {
13224
+ viewerUnionIds: [params.viewerUnionId],
13225
+ labelIds: [params.labelId]
13226
+ }
12894
13227
  );
12895
13228
  }
12896
13229
  /**
@@ -12910,8 +13243,11 @@ var V4UserService = class {
12910
13243
  this.validateRequiredString(params.viewerUnionId, "viewerUnionId");
12911
13244
  this.validateRequiredNumber(params.labelId, "labelId");
12912
13245
  await this.client.httpClient.post(
12913
- "/live/v4/user/viewer-record/label/delete-ref",
12914
- params
13246
+ "/live/v4/user/viewer-label/remove-viewers-label",
13247
+ {
13248
+ viewerUnionIds: [params.viewerUnionId],
13249
+ labelIds: [params.labelId]
13250
+ }
12915
13251
  );
12916
13252
  }
12917
13253
  // ============================================
@@ -13925,6 +14261,47 @@ var V4UserService = class {
13925
14261
  return response;
13926
14262
  }
13927
14263
  // ============================================
14264
+ // Story 13-3: Global Channel Settings APIs
14265
+ // ============================================
14266
+ /**
14267
+ * Get global channel settings
14268
+ *
14269
+ * @returns Global channel settings
14270
+ *
14271
+ * @example
14272
+ * ```typescript
14273
+ * const settings = await client.v4User.getGlobalChannelSettings();
14274
+ * ```
14275
+ */
14276
+ async getGlobalChannelSettings() {
14277
+ const response = await this.client.httpClient.get(
14278
+ "/live/v4/user/global-setting/switch/get",
14279
+ {}
14280
+ );
14281
+ return response;
14282
+ }
14283
+ /**
14284
+ * Update global channel settings
14285
+ *
14286
+ * @param params - Update parameters
14287
+ *
14288
+ * @example
14289
+ * ```typescript
14290
+ * await client.v4User.updateGlobalChannelSettings({
14291
+ * channelConcurrencesEnabled: 'Y',
14292
+ * donateEnabled: 'N',
14293
+ * coverImgType: 'contain',
14294
+ * });
14295
+ * ```
14296
+ */
14297
+ async updateGlobalChannelSettings(params) {
14298
+ this.validateGlobalSettingsParams(params);
14299
+ await this.client.httpClient.post(
14300
+ "/live/v4/user/global-setting/switch/update",
14301
+ params
14302
+ );
14303
+ }
14304
+ // ============================================
13928
14305
  // Private Validation Helpers
13929
14306
  // ============================================
13930
14307
  /**
@@ -13954,6 +14331,31 @@ var V4UserService = class {
13954
14331
  throw new PolyVValidationError(`${fieldName} is required`, fieldName, value);
13955
14332
  }
13956
14333
  }
14334
+ /**
14335
+ * Validate global settings update parameters
14336
+ */
14337
+ validateGlobalSettingsParams(params) {
14338
+ const booleanFields = [
14339
+ "channelConcurrencesEnabled",
14340
+ "timelyConvertEnabled",
14341
+ "donateEnabled",
14342
+ "rebirthAutoUploadEnabled",
14343
+ "rebirthAutoConvertEnabled",
14344
+ "pptCoveredEnabled",
14345
+ "testModeButtonEnabled"
14346
+ ];
14347
+ for (const field of booleanFields) {
14348
+ const value = params[field];
14349
+ if (value !== void 0 && value !== "Y" && value !== "N") {
14350
+ throw new PolyVValidationError(`${field} must be 'Y' or 'N'`, field, value);
14351
+ }
14352
+ }
14353
+ if (params.coverImgType !== void 0) {
14354
+ if (params.coverImgType !== "contain" && params.coverImgType !== "cover") {
14355
+ throw new PolyVValidationError("coverImgType must be 'contain' or 'cover'", "coverImgType", params.coverImgType);
14356
+ }
14357
+ }
14358
+ }
13957
14359
  };
13958
14360
 
13959
14361
  // src/services/v4/global.service.ts
@@ -14832,6 +15234,540 @@ var V4WebAppService = class {
14832
15234
  }
14833
15235
  };
14834
15236
 
15237
+ // src/services/statistics.service.ts
15238
+ var StatisticsService = class {
15239
+ client;
15240
+ /**
15241
+ * Create a new StatisticsService instance
15242
+ *
15243
+ * @param client - The PolyVClient instance to use for API calls
15244
+ */
15245
+ constructor(client) {
15246
+ this.client = client;
15247
+ }
15248
+ // ============================================
15249
+ // Daily View Statistics API
15250
+ // ============================================
15251
+ /**
15252
+ * Get daily view statistics
15253
+ *
15254
+ * Query daily view statistics for a channel within a date range.
15255
+ * The date range cannot exceed 60 days.
15256
+ *
15257
+ * @param params - Query parameters
15258
+ * @returns Daily view statistics response
15259
+ * @throws {PolyVValidationError} When parameters are invalid
15260
+ *
15261
+ * @example
15262
+ * ```typescript
15263
+ * const result = await client.statistics.getDailyViewStatistics({
15264
+ * channelId: '123456',
15265
+ * startDay: '2024-01-01',
15266
+ * endDay: '2024-01-31',
15267
+ * });
15268
+ * console.log(result.contents);
15269
+ * ```
15270
+ */
15271
+ async getDailyViewStatistics(params) {
15272
+ this.validateGetDailyViewStatisticsParams(params);
15273
+ const response = await this.client.httpClient.get(
15274
+ "/live/v3/channel/statistics/daily/summary",
15275
+ { params }
15276
+ );
15277
+ return {
15278
+ contents: response
15279
+ };
15280
+ }
15281
+ // ============================================
15282
+ // Private Validation Helpers
15283
+ // ============================================
15284
+ /**
15285
+ * Validate parameters for getDailyViewStatistics
15286
+ */
15287
+ validateGetDailyViewStatisticsParams(params) {
15288
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15289
+ throw new PolyVValidationError(
15290
+ "channelId is required and must be a non-empty string",
15291
+ "channelId",
15292
+ params.channelId
15293
+ );
15294
+ }
15295
+ if (!params.startDay || !isValidDateFormat(params.startDay)) {
15296
+ throw new PolyVValidationError(
15297
+ "startDay is required and must be in yyyy-MM-dd format",
15298
+ "startDay",
15299
+ params.startDay
15300
+ );
15301
+ }
15302
+ if (!params.endDay || !isValidDateFormat(params.endDay)) {
15303
+ throw new PolyVValidationError(
15304
+ "endDay is required and must be in yyyy-MM-dd format",
15305
+ "endDay",
15306
+ params.endDay
15307
+ );
15308
+ }
15309
+ const rangeValidation = validateDateRange(params.startDay, params.endDay, MAX_DATE_RANGE_DAYS);
15310
+ if (!rangeValidation.valid) {
15311
+ throw new PolyVValidationError(
15312
+ rangeValidation.error || "Invalid date range",
15313
+ "dateRange",
15314
+ { startDay: params.startDay, endDay: params.endDay, daysDiff: rangeValidation.daysDiff }
15315
+ );
15316
+ }
15317
+ }
15318
+ // ============================================
15319
+ // Concurrency Data API (Story 10.2)
15320
+ // ============================================
15321
+ /**
15322
+ * Get historical concurrency data
15323
+ *
15324
+ * Query historical concurrency data for a channel within a date range.
15325
+ * The date range cannot exceed 60 days.
15326
+ *
15327
+ * @param params - Query parameters
15328
+ * @returns Concurrency data response
15329
+ * @throws {PolyVValidationError} When parameters are invalid
15330
+ *
15331
+ * @example
15332
+ * ```typescript
15333
+ * const result = await client.statistics.getConcurrencyData({
15334
+ * channelId: '123456',
15335
+ * startDate: '2024-01-01',
15336
+ * endDate: '2024-01-31',
15337
+ * });
15338
+ * console.log(result.contents);
15339
+ * ```
15340
+ */
15341
+ async getConcurrencyData(params) {
15342
+ this.validateGetConcurrencyDataParams(params);
15343
+ const response = await this.client.httpClient.get(
15344
+ "/live/v3/channel/statistics/concurrence",
15345
+ { params }
15346
+ );
15347
+ return {
15348
+ contents: response
15349
+ };
15350
+ }
15351
+ /**
15352
+ * Validate parameters for getConcurrencyData
15353
+ */
15354
+ validateGetConcurrencyDataParams(params) {
15355
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15356
+ throw new PolyVValidationError(
15357
+ "channelId is required and must be a non-empty string",
15358
+ "channelId",
15359
+ params.channelId
15360
+ );
15361
+ }
15362
+ if (!params.startDate || !isValidDateFormat(params.startDate)) {
15363
+ throw new PolyVValidationError(
15364
+ "startDate is required and must be in yyyy-MM-dd format",
15365
+ "startDate",
15366
+ params.startDate
15367
+ );
15368
+ }
15369
+ if (!params.endDate || !isValidDateFormat(params.endDate)) {
15370
+ throw new PolyVValidationError(
15371
+ "endDate is required and must be in yyyy-MM-dd format",
15372
+ "endDate",
15373
+ params.endDate
15374
+ );
15375
+ }
15376
+ const rangeValidation = validateConcurrencyDateRange(params.startDate, params.endDate, MAX_DATE_RANGE_DAYS);
15377
+ if (!rangeValidation.valid) {
15378
+ throw new PolyVValidationError(
15379
+ rangeValidation.error || "Invalid date range",
15380
+ "dateRange",
15381
+ { startDate: params.startDate, endDate: params.endDate, daysDiff: rangeValidation.daysDiff }
15382
+ );
15383
+ }
15384
+ }
15385
+ // ============================================
15386
+ // Max Concurrent API (Story 10.2)
15387
+ // ============================================
15388
+ /**
15389
+ * Get maximum historical concurrent viewers
15390
+ *
15391
+ * Query the maximum concurrent viewers for a channel within a time range.
15392
+ * The time range cannot exceed 3 months.
15393
+ *
15394
+ * @param params - Query parameters
15395
+ * @returns Max concurrent response
15396
+ * @throws {PolyVValidationError} When parameters are invalid
15397
+ *
15398
+ * @example
15399
+ * ```typescript
15400
+ * const result = await client.statistics.getMaxConcurrent({
15401
+ * channelId: '123456',
15402
+ * startTime: 1704067200000,
15403
+ * endTime: 1735689600000,
15404
+ * });
15405
+ * console.log(result.contents);
15406
+ * ```
15407
+ */
15408
+ async getMaxConcurrent(params) {
15409
+ this.validateGetMaxConcurrentParams(params);
15410
+ const response = await this.client.httpClient.get(
15411
+ "/live/v3/channel/statistics/get-max-history-concurrent",
15412
+ { params }
15413
+ );
15414
+ return {
15415
+ contents: response
15416
+ };
15417
+ }
15418
+ /**
15419
+ * Validate parameters for getMaxConcurrent
15420
+ */
15421
+ validateGetMaxConcurrentParams(params) {
15422
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15423
+ throw new PolyVValidationError(
15424
+ "channelId is required and must be a non-empty string",
15425
+ "channelId",
15426
+ params.channelId
15427
+ );
15428
+ }
15429
+ if (!isValidTimestamp(params.startTime)) {
15430
+ throw new PolyVValidationError(
15431
+ "startTime is required and must be a valid timestamp",
15432
+ "startTime",
15433
+ params.startTime
15434
+ );
15435
+ }
15436
+ if (!isValidTimestamp(params.endTime)) {
15437
+ throw new PolyVValidationError(
15438
+ "endTime is required and must be a valid timestamp",
15439
+ "endTime",
15440
+ params.endTime
15441
+ );
15442
+ }
15443
+ const rangeValidation = validateTimestampRange(params.startTime, params.endTime);
15444
+ if (!rangeValidation.valid) {
15445
+ throw new PolyVValidationError(
15446
+ rangeValidation.error || "Invalid time range",
15447
+ "timeRange",
15448
+ { startTime: params.startTime, endTime: params.endTime, daysDiff: rangeValidation.daysDiff }
15449
+ );
15450
+ }
15451
+ }
15452
+ // ============================================
15453
+ // Region Distribution API (Story 10.3)
15454
+ // ============================================
15455
+ /**
15456
+ * Get region distribution
15457
+ *
15458
+ * Query the geographic distribution of viewers for a channel.
15459
+ * The time range cannot exceed 90 days.
15460
+ *
15461
+ * @param params - Query parameters
15462
+ * @returns Region distribution response
15463
+ * @throws {PolyVValidationError} When parameters are invalid
15464
+ *
15465
+ * @example
15466
+ * ```typescript
15467
+ * const result = await client.statistics.getRegionDistribution({
15468
+ * channelId: '123456',
15469
+ * startTime: 1648742400000,
15470
+ * endTime: 1651334399000,
15471
+ * type: 'province',
15472
+ * });
15473
+ * console.log(result.data);
15474
+ * ```
15475
+ */
15476
+ async getRegionDistribution(params) {
15477
+ this.validateGetRegionDistributionParams(params);
15478
+ const requestParams = {
15479
+ channelId: params.channelId,
15480
+ startTime: params.startTime,
15481
+ endTime: params.endTime
15482
+ };
15483
+ if (params.type) {
15484
+ requestParams.type = params.type;
15485
+ }
15486
+ const response = await this.client.httpClient.get(
15487
+ "/live/v4/channel/statistics/geo-summary-mc",
15488
+ { params: requestParams }
15489
+ );
15490
+ return response;
15491
+ }
15492
+ /**
15493
+ * Validate parameters for getRegionDistribution
15494
+ */
15495
+ validateGetRegionDistributionParams(params) {
15496
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15497
+ throw new PolyVValidationError(
15498
+ "channelId is required and must be a non-empty string",
15499
+ "channelId",
15500
+ params.channelId
15501
+ );
15502
+ }
15503
+ if (!isValidTimestamp(params.startTime)) {
15504
+ throw new PolyVValidationError(
15505
+ "startTime is required and must be a valid timestamp",
15506
+ "startTime",
15507
+ params.startTime
15508
+ );
15509
+ }
15510
+ if (!isValidTimestamp(params.endTime)) {
15511
+ throw new PolyVValidationError(
15512
+ "endTime is required and must be a valid timestamp",
15513
+ "endTime",
15514
+ params.endTime
15515
+ );
15516
+ }
15517
+ const rangeValidation = validate90DayTimestampRange(params.startTime, params.endTime);
15518
+ if (!rangeValidation.valid) {
15519
+ throw new PolyVValidationError(
15520
+ rangeValidation.error || "Invalid time range",
15521
+ "timeRange",
15522
+ { startTime: params.startTime, endTime: params.endTime, daysDiff: rangeValidation.daysDiff }
15523
+ );
15524
+ }
15525
+ if (params.type !== void 0) {
15526
+ const validTypes = ["country", "province", "city"];
15527
+ if (!validTypes.includes(params.type)) {
15528
+ throw new PolyVValidationError(
15529
+ "Type must be one of: country, province, city",
15530
+ "type",
15531
+ params.type
15532
+ );
15533
+ }
15534
+ }
15535
+ }
15536
+ // ============================================
15537
+ // Device Distribution API (Story 10.3)
15538
+ // ============================================
15539
+ /**
15540
+ * Get device distribution
15541
+ *
15542
+ * Query the browser/device distribution of viewers for a channel.
15543
+ * The time range cannot exceed 90 days.
15544
+ *
15545
+ * @param params - Query parameters
15546
+ * @returns Device distribution response
15547
+ * @throws {PolyVValidationError} When parameters are invalid
15548
+ *
15549
+ * @example
15550
+ * ```typescript
15551
+ * const result = await client.statistics.getDeviceDistribution({
15552
+ * channelId: '123456',
15553
+ * startTime: 1651386101000,
15554
+ * endTime: 1652336501462,
15555
+ * });
15556
+ * console.log(result.data);
15557
+ * ```
15558
+ */
15559
+ async getDeviceDistribution(params) {
15560
+ this.validateGetDeviceDistributionParams(params);
15561
+ const response = await this.client.httpClient.get(
15562
+ "/live/v4/channel/statistics/browser-summary",
15563
+ { params }
15564
+ );
15565
+ return response;
15566
+ }
15567
+ /**
15568
+ * Validate parameters for getDeviceDistribution
15569
+ */
15570
+ validateGetDeviceDistributionParams(params) {
15571
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15572
+ throw new PolyVValidationError(
15573
+ "channelId is required and must be a non-empty string",
15574
+ "channelId",
15575
+ params.channelId
15576
+ );
15577
+ }
15578
+ if (!isValidTimestamp(params.startTime)) {
15579
+ throw new PolyVValidationError(
15580
+ "startTime is required and must be a valid timestamp",
15581
+ "startTime",
15582
+ params.startTime
15583
+ );
15584
+ }
15585
+ if (!isValidTimestamp(params.endTime)) {
15586
+ throw new PolyVValidationError(
15587
+ "endTime is required and must be a valid timestamp",
15588
+ "endTime",
15589
+ params.endTime
15590
+ );
15591
+ }
15592
+ const rangeValidation = validate90DayTimestampRange(params.startTime, params.endTime);
15593
+ if (!rangeValidation.valid) {
15594
+ throw new PolyVValidationError(
15595
+ rangeValidation.error || "Invalid time range",
15596
+ "timeRange",
15597
+ { startTime: params.startTime, endTime: params.endTime, daysDiff: rangeValidation.daysDiff }
15598
+ );
15599
+ }
15600
+ }
15601
+ // ============================================
15602
+ // Viewlog Export API (Story 10.4)
15603
+ // ============================================
15604
+ /**
15605
+ * Get viewlog (viewing log) data
15606
+ *
15607
+ * Query viewing log data for a channel within a date range.
15608
+ * The date range must be within the same month.
15609
+ *
15610
+ * @param params - Query parameters
15611
+ * @returns Viewlog response with pagination
15612
+ * @throws {PolyVValidationError} When parameters are invalid
15613
+ *
15614
+ * @example
15615
+ * ```typescript
15616
+ * const result = await client.statistics.getViewlog({
15617
+ * channelId: '3151318',
15618
+ * startDate: '2024-01-01 00:00:00',
15619
+ * endDate: '2024-01-31 23:59:59',
15620
+ * });
15621
+ * console.log(result.contents);
15622
+ * ```
15623
+ */
15624
+ async getViewlog(params) {
15625
+ this.validateGetViewlogParams(params);
15626
+ const requestParams = {
15627
+ channelId: params.channelId,
15628
+ startDate: params.startDate,
15629
+ endDate: params.endDate,
15630
+ pageSize: params.pageSize ?? 1e3
15631
+ };
15632
+ if (params.page !== void 0) {
15633
+ requestParams.page = params.page;
15634
+ }
15635
+ if (params.watchType !== void 0) {
15636
+ requestParams.watchType = params.watchType;
15637
+ }
15638
+ const response = await this.client.httpClient.get(
15639
+ "/live/v3/user/statistics/viewlog",
15640
+ { params: requestParams }
15641
+ );
15642
+ if (response && typeof response === "object" && "data" in response) {
15643
+ const responseData = response;
15644
+ if (responseData.data && typeof responseData.data === "object") {
15645
+ return responseData.data;
15646
+ }
15647
+ }
15648
+ return response;
15649
+ }
15650
+ /**
15651
+ * Validate parameters for getViewlog
15652
+ */
15653
+ validateGetViewlogParams(params) {
15654
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15655
+ throw new PolyVValidationError(
15656
+ "channelId is required and must be a non-empty string",
15657
+ "channelId",
15658
+ params.channelId
15659
+ );
15660
+ }
15661
+ const dateTimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
15662
+ if (!params.startDate || !dateTimeRegex.test(params.startDate)) {
15663
+ throw new PolyVValidationError(
15664
+ "startDate is required and must be in yyyy-MM-dd HH:mm:ss format",
15665
+ "startDate",
15666
+ params.startDate
15667
+ );
15668
+ }
15669
+ if (!params.endDate || !dateTimeRegex.test(params.endDate)) {
15670
+ throw new PolyVValidationError(
15671
+ "endDate is required and must be in yyyy-MM-dd HH:mm:ss format",
15672
+ "endDate",
15673
+ params.endDate
15674
+ );
15675
+ }
15676
+ const startMonth = params.startDate.substring(0, 7);
15677
+ const endMonth = params.endDate.substring(0, 7);
15678
+ if (startMonth !== endMonth) {
15679
+ throw new PolyVValidationError(
15680
+ "startDate and endDate must be in the same month",
15681
+ "dateRange",
15682
+ { startDate: params.startDate, endDate: params.endDate }
15683
+ );
15684
+ }
15685
+ if (params.watchType !== void 0) {
15686
+ const validWatchTypes = ["live", "vod"];
15687
+ if (!validWatchTypes.includes(params.watchType)) {
15688
+ throw new PolyVValidationError(
15689
+ 'watchType must be either "live" or "vod"',
15690
+ "watchType",
15691
+ params.watchType
15692
+ );
15693
+ }
15694
+ }
15695
+ }
15696
+ // ============================================
15697
+ // Session Stats Export API (Story 10.4)
15698
+ // ============================================
15699
+ /**
15700
+ * Export session statistics report
15701
+ *
15702
+ * Export the session statistics report for a specific session.
15703
+ * Returns a download URL for the report file.
15704
+ *
15705
+ * @param params - Query parameters
15706
+ * @returns Export response with download URL
15707
+ * @throws {PolyVValidationError} When parameters are invalid
15708
+ *
15709
+ * @example
15710
+ * ```typescript
15711
+ * const result = await client.statistics.exportSessionStats({
15712
+ * channelId: '3151318',
15713
+ * sessionId: 'fv3ma84e63',
15714
+ * });
15715
+ * console.log(result.downloadUrl);
15716
+ * ```
15717
+ */
15718
+ async exportSessionStats(params) {
15719
+ this.validateExportSessionStatsParams(params);
15720
+ const response = await this.client.httpClient.get(
15721
+ "/live/v3/channel/session/stats/export",
15722
+ { params }
15723
+ );
15724
+ if (response && typeof response === "object" && "data" in response) {
15725
+ const responseData = response;
15726
+ if (responseData.data && typeof responseData.data === "object") {
15727
+ const innerData = responseData.data;
15728
+ if (innerData.code && innerData.code !== 200) {
15729
+ throw new Error(innerData.message || "API Error");
15730
+ }
15731
+ if ("downloadUrl" in innerData) {
15732
+ return innerData;
15733
+ }
15734
+ if (typeof innerData.data === "string" && innerData.data) {
15735
+ return { downloadUrl: innerData.data };
15736
+ }
15737
+ }
15738
+ }
15739
+ if (response && typeof response === "object" && "code" in response) {
15740
+ const apiResponse = response;
15741
+ if (apiResponse.code && apiResponse.code !== 200) {
15742
+ throw new Error(String(apiResponse.message || "API Error"));
15743
+ }
15744
+ if (typeof apiResponse.data === "string" && apiResponse.data) {
15745
+ return { downloadUrl: apiResponse.data };
15746
+ }
15747
+ }
15748
+ return response;
15749
+ }
15750
+ /**
15751
+ * Validate parameters for exportSessionStats
15752
+ */
15753
+ validateExportSessionStatsParams(params) {
15754
+ if (!params.channelId || typeof params.channelId !== "string" || params.channelId.trim() === "") {
15755
+ throw new PolyVValidationError(
15756
+ "channelId is required and must be a non-empty string",
15757
+ "channelId",
15758
+ params.channelId
15759
+ );
15760
+ }
15761
+ if (!params.sessionId || typeof params.sessionId !== "string" || params.sessionId.trim() === "") {
15762
+ throw new PolyVValidationError(
15763
+ "sessionId is required and must be a non-empty string",
15764
+ "sessionId",
15765
+ params.sessionId
15766
+ );
15767
+ }
15768
+ }
15769
+ };
15770
+
14835
15771
  // src/client.ts
14836
15772
  var DEFAULT_CONFIG = {
14837
15773
  baseUrl: "https://api.polyv.net",
@@ -14855,6 +15791,10 @@ var PolyVClient = class {
14855
15791
  * Channel service for managing live channels
14856
15792
  */
14857
15793
  channel;
15794
+ /**
15795
+ * Statistics service for managing statistics operations
15796
+ */
15797
+ statistics;
14858
15798
  /**
14859
15799
  * Chat service for managing chat messages
14860
15800
  */
@@ -14954,6 +15894,7 @@ var PolyVClient = class {
14954
15894
  };
14955
15895
  this.httpClient = this.createHttpClient();
14956
15896
  this.channel = new ChannelService(this);
15897
+ this.statistics = new StatisticsService(this);
14957
15898
  this.chat = new ChatService(this);
14958
15899
  this.liveInteraction = new LiveInteractionService(this);
14959
15900
  this.account = new AccountService(this);
@@ -15253,6 +16194,6 @@ function getErrorCodeCategory(code) {
15253
16194
  // src/index.ts
15254
16195
  var VERSION = "1.0.0";
15255
16196
 
15256
- export { ChannelService, ERROR_CATEGORIES, ERROR_MESSAGES, HttpMethod, PolyVAPIError, PolyVClient, PolyVError, PolyVErrorCode, PolyVValidationError, PptStatus, SignatureMethod, TtsVoiceTag, VERSION, VideoProduceStatus, collectAll, createSignature, generateSignature, generateTimestamp, getEnvironmentInfo, getErrorCodeCategory, getErrorMessage, getErrorMessageByCode, isBrowser, isNode, isPolyVAPIError, isPolyVError, isPolyVErrorCode, isPolyVValidationError, isWebWorker, paginate, sortParams };
16197
+ export { ChannelService, ERROR_CATEGORIES, ERROR_MESSAGES, HttpMethod, MAX_DATE_RANGE_DAYS, PolyVAPIError, PolyVClient, PolyVError, PolyVErrorCode, PolyVValidationError, PptStatus, SignatureMethod, TtsVoiceTag, VERSION, VideoProduceStatus, collectAll, createSignature, generateSignature, generateTimestamp, getEnvironmentInfo, getErrorCodeCategory, getErrorMessage, getErrorMessageByCode, isBrowser, isNode, isPolyVAPIError, isPolyVError, isPolyVErrorCode, isPolyVValidationError, isStartDateBeforeEndDate, isValidDateFormat, isWebWorker, paginate, sortParams, validateDateRange };
15257
16198
  //# sourceMappingURL=index.js.map
15258
16199
  //# sourceMappingURL=index.js.map