@amityco/ts-sdk 7.12.0 → 7.12.1-14007a1.0
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.
- package/dist/@types/domains/liveStreamPlayer.d.ts +6 -2
- package/dist/@types/domains/liveStreamPlayer.d.ts.map +1 -1
- package/dist/@types/domains/room.d.ts +29 -0
- package/dist/@types/domains/room.d.ts.map +1 -1
- package/dist/index.cjs.js +415 -79
- package/dist/index.esm.js +415 -79
- package/dist/index.umd.js +1 -1
- package/dist/liveStreamPlayer/utils/cryptoSignatureUtils.d.ts +2 -2
- package/dist/liveStreamPlayer/utils/cryptoSignatureUtils.d.ts.map +1 -1
- package/dist/roomRepository/api/analytics/AmityRoomAnalytics.d.ts +30 -0
- package/dist/roomRepository/api/analytics/AmityRoomAnalytics.d.ts.map +1 -0
- package/dist/roomRepository/api/analytics/WatchSessionStorage.d.ts +38 -0
- package/dist/roomRepository/api/analytics/WatchSessionStorage.d.ts.map +1 -0
- package/dist/roomRepository/api/analytics/index.d.ts +4 -0
- package/dist/roomRepository/api/analytics/index.d.ts.map +1 -0
- package/dist/roomRepository/api/analytics/syncWatchSessions.d.ts +6 -0
- package/dist/roomRepository/api/analytics/syncWatchSessions.d.ts.map +1 -0
- package/dist/roomRepository/api/index.d.ts +1 -0
- package/dist/roomRepository/api/index.d.ts.map +1 -1
- package/dist/utils/linkedObject/roomLinkedObject.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -3,11 +3,15 @@ declare global {
|
|
|
3
3
|
namespace Amity {
|
|
4
4
|
type UsageDataModel = {
|
|
5
5
|
sessionId: string;
|
|
6
|
-
|
|
6
|
+
roomId?: string;
|
|
7
7
|
startTime: string;
|
|
8
8
|
endTime: string;
|
|
9
9
|
watchSeconds: number;
|
|
10
|
-
resolution
|
|
10
|
+
resolution?: string;
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated Use `roomId` instead.
|
|
13
|
+
*/
|
|
14
|
+
streamId?: string;
|
|
11
15
|
};
|
|
12
16
|
}
|
|
13
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"liveStreamPlayer.d.ts","sourceRoot":"","sources":["../../../src/@types/domains/liveStreamPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC;AAEV,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK,CAAC;QACd,KAAK,cAAc,GAAG;YACpB,SAAS,EAAE,MAAM,CAAC;YAClB,
|
|
1
|
+
{"version":3,"file":"liveStreamPlayer.d.ts","sourceRoot":"","sources":["../../../src/@types/domains/liveStreamPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC;AAEV,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK,CAAC;QACd,KAAK,cAAc,GAAG;YACpB,SAAS,EAAE,MAAM,CAAC;YAClB,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,SAAS,EAAE,MAAM,CAAC;YAClB,OAAO,EAAE,MAAM,CAAC;YAChB,YAAY,EAAE,MAAM,CAAC;YACrB,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB;;eAEG;YACH,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH;CACF"}
|
|
@@ -66,6 +66,7 @@ declare global {
|
|
|
66
66
|
getLiveChat: () => Promise<Amity.Channel<'live'> | undefined>;
|
|
67
67
|
createInvitation: (userId: string) => Promise<Amity.Cached<Amity.InternalInvitation[]>>;
|
|
68
68
|
getInvitations: () => Promise<Amity.Invitation | undefined>;
|
|
69
|
+
analytics: () => Amity.RoomAnalytics;
|
|
69
70
|
};
|
|
70
71
|
type Room = Omit<InternalRoom, 'participants'> & RoomLinkedObject;
|
|
71
72
|
type RoomLiveCollection = {
|
|
@@ -105,6 +106,34 @@ declare global {
|
|
|
105
106
|
invitation?: Amity.Invitation;
|
|
106
107
|
actorInternalId?: string;
|
|
107
108
|
};
|
|
109
|
+
enum WatchSessionSyncStateEnum {
|
|
110
|
+
PENDING = "PENDING",
|
|
111
|
+
SYNCING = "SYNCING",
|
|
112
|
+
SYNCED = "SYNCED"
|
|
113
|
+
}
|
|
114
|
+
type WatchSessionSyncState = `${WatchSessionSyncStateEnum}`;
|
|
115
|
+
type WatchSessionEntity = {
|
|
116
|
+
sessionId: string;
|
|
117
|
+
roomId: string;
|
|
118
|
+
watchSeconds: number;
|
|
119
|
+
startTime: Date;
|
|
120
|
+
endTime?: Date | null;
|
|
121
|
+
syncState: WatchSessionSyncState;
|
|
122
|
+
syncedAt?: Date | null;
|
|
123
|
+
retryCount: number;
|
|
124
|
+
};
|
|
125
|
+
type WatchSessionData = {
|
|
126
|
+
sessionId: string;
|
|
127
|
+
roomId: string;
|
|
128
|
+
watchSeconds: number;
|
|
129
|
+
startTime: string;
|
|
130
|
+
endTime?: string;
|
|
131
|
+
};
|
|
132
|
+
interface RoomAnalytics {
|
|
133
|
+
createWatchSession(startedAt: Date): Promise<string>;
|
|
134
|
+
updateWatchSession(sessionId: string, duration: number, endedAt: Date): Promise<void>;
|
|
135
|
+
syncPendingWatchSessions(): void;
|
|
136
|
+
}
|
|
108
137
|
}
|
|
109
138
|
}
|
|
110
139
|
//# sourceMappingURL=room.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../../../src/@types/domains/room.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../../../src/@types/domains/room.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs.js
CHANGED
|
@@ -12542,6 +12542,414 @@ const getInvitation = async (params) => {
|
|
|
12542
12542
|
};
|
|
12543
12543
|
/* end_public_function */
|
|
12544
12544
|
|
|
12545
|
+
/**
|
|
12546
|
+
* WatchSessionStorage manages watch session data in memory
|
|
12547
|
+
* Similar to UsageCollector for stream watch minutes
|
|
12548
|
+
*/
|
|
12549
|
+
class WatchSessionStorage {
|
|
12550
|
+
constructor() {
|
|
12551
|
+
this.sessions = new Map();
|
|
12552
|
+
}
|
|
12553
|
+
/**
|
|
12554
|
+
* Add a new watch session
|
|
12555
|
+
*/
|
|
12556
|
+
addSession(session) {
|
|
12557
|
+
this.sessions.set(session.sessionId, session);
|
|
12558
|
+
}
|
|
12559
|
+
/**
|
|
12560
|
+
* Get a watch session by sessionId
|
|
12561
|
+
*/
|
|
12562
|
+
getSession(sessionId) {
|
|
12563
|
+
return this.sessions.get(sessionId);
|
|
12564
|
+
}
|
|
12565
|
+
/**
|
|
12566
|
+
* Update a watch session
|
|
12567
|
+
*/
|
|
12568
|
+
updateSession(sessionId, updates) {
|
|
12569
|
+
const session = this.sessions.get(sessionId);
|
|
12570
|
+
if (session) {
|
|
12571
|
+
this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
|
|
12572
|
+
}
|
|
12573
|
+
}
|
|
12574
|
+
/**
|
|
12575
|
+
* Get all sessions with a specific sync state
|
|
12576
|
+
*/
|
|
12577
|
+
getSessionsByState(state) {
|
|
12578
|
+
return Array.from(this.sessions.values()).filter(session => session.syncState === state);
|
|
12579
|
+
}
|
|
12580
|
+
/**
|
|
12581
|
+
* Delete a session
|
|
12582
|
+
*/
|
|
12583
|
+
deleteSession(sessionId) {
|
|
12584
|
+
this.sessions.delete(sessionId);
|
|
12585
|
+
}
|
|
12586
|
+
/**
|
|
12587
|
+
* Get all pending sessions
|
|
12588
|
+
*/
|
|
12589
|
+
getPendingSessions() {
|
|
12590
|
+
return this.getSessionsByState('PENDING');
|
|
12591
|
+
}
|
|
12592
|
+
/**
|
|
12593
|
+
* Get all syncing sessions
|
|
12594
|
+
*/
|
|
12595
|
+
getSyncingSessions() {
|
|
12596
|
+
return this.getSessionsByState('SYNCING');
|
|
12597
|
+
}
|
|
12598
|
+
}
|
|
12599
|
+
// Singleton instance
|
|
12600
|
+
let storageInstance = null;
|
|
12601
|
+
const getWatchSessionStorage = () => {
|
|
12602
|
+
if (!storageInstance) {
|
|
12603
|
+
storageInstance = new WatchSessionStorage();
|
|
12604
|
+
}
|
|
12605
|
+
return storageInstance;
|
|
12606
|
+
};
|
|
12607
|
+
|
|
12608
|
+
const privateKey = "MIIEpQIBAAKCAQEAwAEc/oZgYIvKSUG/C3mONYLR4ZPgAjMEX4bJ+xqqakUDRtqlNO+eZs2blQ1Ko0DBkqPExyQezvjibH5W2UZBV5RaBTlTcNVKTToMBEGesAfaEcM3qUyQHxdbFYZv6P4sb14dcwxTQ8usmaV8ooiR1Fcaso5ZWYcZ8Hb46FbQ7OoVumsBtPWwfZ4f003o5VCl6AIM6lcLv9UDLlFVYhE+PeXpRHtfWlGqxMvqC9oinlwhL6nWv6VjQXW4nhcib72dPBzfHT7k/PMKto2SxALYdb68ENiAGuJLWi3AUHSyYCJK2w7wIlWfJUAI0v26ub10IpExr6D5QuW2577jjP93iwIDAQABAoIBAFWfqXhwIIatkFY+9Z1+ZcbDQimgsmMIsUiQaX6Lk7e0cxOj6czDlxYtVtaPiNtow2pLkjNkjkCqiP7tEHnwdK9DvylZOTa2R15NJpK3WLcTqVIGhsn/FL5owfvFah6zSsmXZParZm5zY9NZE03ALZhOB9/cz0e3kf/EbpfeL2mW7MApyiUt5i09ycchroOpcWp73ipIxvgigtZyUGFmsQicWhUs28F0D7w4Qfk76yG3nqXeb+BAMhCaIaa/k/aAxhiZG/ygEQWQrcC8gfe+jyicMAQPDEVS9YuUMGsLjIjKuVLZzp2xirQnhc2i2zVNEIvG6soprPOBEMQugzrtX5ECgYEA3b7KAbBIbDl1e4ZSCWhHdHkiWVZHaopsR/LhqDDNhXjWjq3AesgV6k0j9EdziMn/HmmOso0bz99GTV3JZf4A9ztTLumJlkHbdVtlgOqSjrFLj12rH9KXTheyIhWSpUmm8+WB1xasFbqpvJaGo7F3pd2Fqj1XR4mp5BO7c/t7LJ0CgYEA3aouEzXQ9THRKYocdfY69EI1Il1t/d/RSqqd9BxEjxBgxkM13ZiYIn/R4WW/nCUrlmhxG44Aa2Gob4Ahfsui2xKTg/g/3Zk/rAxAEGkfOLGoenaJMD41fH4wUq3FRYwkvnaMb9Hd6f/TlBHslIRa2NN58bSBGJCyBP2b59+2+EcCgYEAixDVRXvV37GlYUOa/XVdosk5Zoe6oDGRuQm0xbNdoUBoZvDHDvme7ONWEiQha/8qtVsD+CyQ7awcPfb8kK9c0bBt+bTS6d4BkTcxkEkMgtrkBVR8Nqfu5jXsLH4VCv4G61zbMhZw8+ut+az5YX2yCN7Frj9sFlxapMRPQmzMEe0CgYEAumsAzM8ZqNv4mAK65Mnr0rhLj1cbxcKRdUYACOgtEFQpzxN/HZnTeFAe5nx3pI3uFlRHq3DFEYnT6dHMWaJQmAULYpVIwMi9L6gtyJ9fzoI6uqMtxRDMUqKdaSsTGOY/kJ6KhQ/unXi1K3XXjR+yd1+C0q+HUm1+CYxvrZYLfskCgYEArsEy+IQOiqniJ0NE2vVUF+UK/IRZaic9YKcpov5Ot7Vvzm/MnnW4N1ljVskocETBWMmPUvNSExVjPebi+rxd8fa5kY8BJScPTzMFbunZn/wjtGdcM10qdlVQ9doG61A/9P3ezFKCfS4AvF/H/59LcSx2Bh28fp3/efiVIOpVd4Y=";
|
|
12609
|
+
/*
|
|
12610
|
+
* The crypto algorithm used for importing key and signing string
|
|
12611
|
+
*/
|
|
12612
|
+
const ALGORITHM = {
|
|
12613
|
+
name: 'RSASSA-PKCS1-v1_5',
|
|
12614
|
+
hash: { name: 'SHA-256' },
|
|
12615
|
+
};
|
|
12616
|
+
/*
|
|
12617
|
+
* IMPORTANT!
|
|
12618
|
+
* If you are recieving key from other platforms use an online tool to convert
|
|
12619
|
+
* the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
|
|
12620
|
+
* PKCS1.
|
|
12621
|
+
*
|
|
12622
|
+
* If recieving from the platform, verify if it's already in the expected
|
|
12623
|
+
* format. Otherwise the crypto.subtle.importKey will throw a DOMException
|
|
12624
|
+
*/
|
|
12625
|
+
const PRIVATE_KEY_SIGNATURE = 'pkcs8';
|
|
12626
|
+
/*
|
|
12627
|
+
* Ensure that the private key in the .env follows this format
|
|
12628
|
+
*/
|
|
12629
|
+
const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
|
|
12630
|
+
const PEM_FOOTER = '-----END PRIVATE KEY-----';
|
|
12631
|
+
/*
|
|
12632
|
+
* The crypto.subtle.sign function returns an ArrayBuffer whereas the server
|
|
12633
|
+
* expects a base64 string. This util helps facilitate that process
|
|
12634
|
+
*/
|
|
12635
|
+
function base64FromArrayBuffer(buffer) {
|
|
12636
|
+
const uint8Array = new Uint8Array(buffer);
|
|
12637
|
+
let binary = '';
|
|
12638
|
+
uint8Array.forEach(byte => {
|
|
12639
|
+
binary += String.fromCharCode(byte);
|
|
12640
|
+
});
|
|
12641
|
+
return jsBase64.btoa(binary);
|
|
12642
|
+
}
|
|
12643
|
+
/*
|
|
12644
|
+
* Encode ASN.1 length field
|
|
12645
|
+
*/
|
|
12646
|
+
function encodeLength(length) {
|
|
12647
|
+
if (length < 128) {
|
|
12648
|
+
return new Uint8Array([length]);
|
|
12649
|
+
}
|
|
12650
|
+
if (length < 256) {
|
|
12651
|
+
return new Uint8Array([0x81, length]);
|
|
12652
|
+
}
|
|
12653
|
+
// eslint-disable-next-line no-bitwise
|
|
12654
|
+
return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
|
|
12655
|
+
}
|
|
12656
|
+
/*
|
|
12657
|
+
* Convert PKCS1 private key to PKCS8 format
|
|
12658
|
+
* PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
|
|
12659
|
+
* Android uses PKCS8EncodedKeySpec which expects PKCS8 format
|
|
12660
|
+
*/
|
|
12661
|
+
function pkcs1ToPkcs8(pkcs1) {
|
|
12662
|
+
// Algorithm identifier for RSA
|
|
12663
|
+
const algorithmIdentifier = new Uint8Array([
|
|
12664
|
+
0x30,
|
|
12665
|
+
0x0d,
|
|
12666
|
+
0x06,
|
|
12667
|
+
0x09,
|
|
12668
|
+
0x2a,
|
|
12669
|
+
0x86,
|
|
12670
|
+
0x48,
|
|
12671
|
+
0x86,
|
|
12672
|
+
0xf7,
|
|
12673
|
+
0x0d,
|
|
12674
|
+
0x01,
|
|
12675
|
+
0x01,
|
|
12676
|
+
0x01,
|
|
12677
|
+
0x05,
|
|
12678
|
+
0x00, // NULL
|
|
12679
|
+
]);
|
|
12680
|
+
// Version (INTEGER 0)
|
|
12681
|
+
const version = new Uint8Array([0x02, 0x01, 0x00]);
|
|
12682
|
+
// OCTET STRING tag + length + pkcs1 data
|
|
12683
|
+
const octetStringTag = 0x04;
|
|
12684
|
+
const octetStringLength = encodeLength(pkcs1.length);
|
|
12685
|
+
// Calculate total content length (version + algorithm + octet string)
|
|
12686
|
+
const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
|
|
12687
|
+
// SEQUENCE tag + length
|
|
12688
|
+
const sequenceTag = 0x30;
|
|
12689
|
+
const sequenceLength = encodeLength(contentLength);
|
|
12690
|
+
// Build the PKCS8 structure
|
|
12691
|
+
const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
|
|
12692
|
+
let offset = 0;
|
|
12693
|
+
pkcs8[offset] = sequenceTag;
|
|
12694
|
+
offset += 1;
|
|
12695
|
+
pkcs8.set(sequenceLength, offset);
|
|
12696
|
+
offset += sequenceLength.length;
|
|
12697
|
+
pkcs8.set(version, offset);
|
|
12698
|
+
offset += version.length;
|
|
12699
|
+
pkcs8.set(algorithmIdentifier, offset);
|
|
12700
|
+
offset += algorithmIdentifier.length;
|
|
12701
|
+
pkcs8[offset] = octetStringTag;
|
|
12702
|
+
offset += 1;
|
|
12703
|
+
pkcs8.set(octetStringLength, offset);
|
|
12704
|
+
offset += octetStringLength.length;
|
|
12705
|
+
pkcs8.set(pkcs1, offset);
|
|
12706
|
+
return pkcs8;
|
|
12707
|
+
}
|
|
12708
|
+
async function importPrivateKey(keyString) {
|
|
12709
|
+
// Remove PEM headers if present and any whitespace
|
|
12710
|
+
let base64Key = keyString;
|
|
12711
|
+
if (keyString.includes(PEM_HEADER)) {
|
|
12712
|
+
base64Key = keyString
|
|
12713
|
+
.substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
|
|
12714
|
+
.replace(/\s/g, '');
|
|
12715
|
+
}
|
|
12716
|
+
else {
|
|
12717
|
+
base64Key = keyString.replace(/\s/g, '');
|
|
12718
|
+
}
|
|
12719
|
+
// Base64 decode to get binary data
|
|
12720
|
+
const binaryDerString = jsBase64.atob(base64Key);
|
|
12721
|
+
// Convert to Uint8Array for manipulation
|
|
12722
|
+
const pkcs1 = new Uint8Array(binaryDerString.length);
|
|
12723
|
+
for (let i = 0; i < binaryDerString.length; i += 1) {
|
|
12724
|
+
pkcs1[i] = binaryDerString.charCodeAt(i);
|
|
12725
|
+
}
|
|
12726
|
+
// Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
|
|
12727
|
+
const pkcs8 = pkcs1ToPkcs8(pkcs1);
|
|
12728
|
+
// Import the key
|
|
12729
|
+
const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
|
|
12730
|
+
return key;
|
|
12731
|
+
}
|
|
12732
|
+
async function createSignature({ timestamp, rooms, }) {
|
|
12733
|
+
const dataStr = rooms
|
|
12734
|
+
.map(item => Object.keys(item)
|
|
12735
|
+
.sort()
|
|
12736
|
+
.map(key => `${key}=${item[key]}`)
|
|
12737
|
+
.join('&'))
|
|
12738
|
+
.join(';');
|
|
12739
|
+
/*
|
|
12740
|
+
* nonceStr needs to be unique for each request
|
|
12741
|
+
*/
|
|
12742
|
+
const nonceStr = uuid__default["default"].v4();
|
|
12743
|
+
const signStr = `nonceStr=${nonceStr}×tamp=${timestamp}&data=${dataStr}==`;
|
|
12744
|
+
const encoder = new TextEncoder();
|
|
12745
|
+
const data = encoder.encode(signStr);
|
|
12746
|
+
const key = await importPrivateKey(privateKey);
|
|
12747
|
+
const sign = await crypto.subtle.sign(ALGORITHM, key, data);
|
|
12748
|
+
return { signature: base64FromArrayBuffer(sign), nonceStr };
|
|
12749
|
+
}
|
|
12750
|
+
|
|
12751
|
+
/**
|
|
12752
|
+
* Sync pending watch sessions to backend
|
|
12753
|
+
* This function implements the full sync flow with network resilience
|
|
12754
|
+
*/
|
|
12755
|
+
async function syncWatchSessions() {
|
|
12756
|
+
const storage = getWatchSessionStorage();
|
|
12757
|
+
// Get all pending sessions
|
|
12758
|
+
const pendingSessions = storage.getPendingSessions();
|
|
12759
|
+
if (pendingSessions.length === 0) {
|
|
12760
|
+
return true;
|
|
12761
|
+
}
|
|
12762
|
+
try {
|
|
12763
|
+
const timestamp = new Date().toISOString();
|
|
12764
|
+
// Convert sessions to API format - always include all fields like syncUsage does
|
|
12765
|
+
const rooms = pendingSessions.map(session => ({
|
|
12766
|
+
sessionId: session.sessionId,
|
|
12767
|
+
roomId: session.roomId,
|
|
12768
|
+
watchSeconds: session.watchSeconds,
|
|
12769
|
+
startTime: session.startTime.toISOString(),
|
|
12770
|
+
endTime: session.endTime ? session.endTime.toISOString() : '',
|
|
12771
|
+
}));
|
|
12772
|
+
// Create signature (reuse from stream feature) - pass directly like syncUsage
|
|
12773
|
+
const signatureData = await createSignature({
|
|
12774
|
+
timestamp,
|
|
12775
|
+
rooms,
|
|
12776
|
+
});
|
|
12777
|
+
if (!signatureData || !signatureData.signature) {
|
|
12778
|
+
throw new Error('Signature is undefined');
|
|
12779
|
+
}
|
|
12780
|
+
// Update sync state to SYNCING
|
|
12781
|
+
pendingSessions.forEach(session => {
|
|
12782
|
+
storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
|
|
12783
|
+
});
|
|
12784
|
+
const payload = {
|
|
12785
|
+
signature: signatureData.signature,
|
|
12786
|
+
nonceStr: signatureData.nonceStr,
|
|
12787
|
+
timestamp,
|
|
12788
|
+
rooms,
|
|
12789
|
+
};
|
|
12790
|
+
const client = getActiveClient();
|
|
12791
|
+
// Send to backend
|
|
12792
|
+
await client.http.post('/api/v3/user-event/room', payload);
|
|
12793
|
+
// Success - update to SYNCED
|
|
12794
|
+
pendingSessions.forEach(session => {
|
|
12795
|
+
storage.updateSession(session.sessionId, {
|
|
12796
|
+
syncState: 'SYNCED',
|
|
12797
|
+
syncedAt: new Date(),
|
|
12798
|
+
});
|
|
12799
|
+
});
|
|
12800
|
+
return true;
|
|
12801
|
+
}
|
|
12802
|
+
catch (err) {
|
|
12803
|
+
console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
|
|
12804
|
+
// Failure - update back to PENDING and increment retry count
|
|
12805
|
+
pendingSessions.forEach(session => {
|
|
12806
|
+
const currentSession = storage.getSession(session.sessionId);
|
|
12807
|
+
if (currentSession) {
|
|
12808
|
+
const newRetryCount = currentSession.retryCount + 1;
|
|
12809
|
+
if (newRetryCount >= 3) {
|
|
12810
|
+
// Delete session if retry count exceeds 3
|
|
12811
|
+
storage.deleteSession(session.sessionId);
|
|
12812
|
+
}
|
|
12813
|
+
else {
|
|
12814
|
+
// Update to PENDING with incremented retry count
|
|
12815
|
+
storage.updateSession(session.sessionId, {
|
|
12816
|
+
syncState: 'PENDING',
|
|
12817
|
+
retryCount: newRetryCount,
|
|
12818
|
+
});
|
|
12819
|
+
}
|
|
12820
|
+
}
|
|
12821
|
+
});
|
|
12822
|
+
return false;
|
|
12823
|
+
}
|
|
12824
|
+
}
|
|
12825
|
+
|
|
12826
|
+
/**
|
|
12827
|
+
* Room statuses that are considered watchable
|
|
12828
|
+
*/
|
|
12829
|
+
const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
|
|
12830
|
+
/**
|
|
12831
|
+
* Generate a random jitter delay between 5 and 30 seconds
|
|
12832
|
+
*/
|
|
12833
|
+
const getJitterDelay = () => {
|
|
12834
|
+
const minDelay = 5000; // 5 seconds
|
|
12835
|
+
const maxDelay = 30000; // 30 seconds
|
|
12836
|
+
return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
|
|
12837
|
+
};
|
|
12838
|
+
/**
|
|
12839
|
+
* Wait for network connection with timeout
|
|
12840
|
+
* @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
|
|
12841
|
+
* @returns Promise that resolves when network is available or timeout is reached
|
|
12842
|
+
*/
|
|
12843
|
+
const waitForNetwork = (maxWaitTime = 60000) => {
|
|
12844
|
+
return new Promise(resolve => {
|
|
12845
|
+
// Simple check - if navigator.onLine is available, use it
|
|
12846
|
+
// Otherwise, assume network is available
|
|
12847
|
+
if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
|
|
12848
|
+
resolve();
|
|
12849
|
+
return;
|
|
12850
|
+
}
|
|
12851
|
+
const startTime = Date.now();
|
|
12852
|
+
const checkInterval = 1000; // 1 second
|
|
12853
|
+
const checkConnection = () => {
|
|
12854
|
+
if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
|
|
12855
|
+
resolve();
|
|
12856
|
+
}
|
|
12857
|
+
else {
|
|
12858
|
+
setTimeout(checkConnection, checkInterval);
|
|
12859
|
+
}
|
|
12860
|
+
};
|
|
12861
|
+
checkConnection();
|
|
12862
|
+
});
|
|
12863
|
+
};
|
|
12864
|
+
/**
|
|
12865
|
+
* AmityRoomAnalytics provides analytics capabilities for room watch sessions
|
|
12866
|
+
*/
|
|
12867
|
+
class AmityRoomAnalytics {
|
|
12868
|
+
constructor(room) {
|
|
12869
|
+
this.storage = getWatchSessionStorage();
|
|
12870
|
+
this.client = getActiveClient();
|
|
12871
|
+
this.room = room;
|
|
12872
|
+
}
|
|
12873
|
+
/**
|
|
12874
|
+
* Create a new watch session for the current room
|
|
12875
|
+
* @param startedAt The timestamp when watching started
|
|
12876
|
+
* @returns Promise<string> sessionId unique identifier for this watch session
|
|
12877
|
+
* @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
|
|
12878
|
+
*/
|
|
12879
|
+
async createWatchSession(startedAt) {
|
|
12880
|
+
// Validate room status
|
|
12881
|
+
if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
|
|
12882
|
+
throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
|
|
12883
|
+
}
|
|
12884
|
+
// Generate session ID with prefix
|
|
12885
|
+
const prefix = this.room.status === 'live' ? 'room_' : 'room_playback';
|
|
12886
|
+
const sessionId = prefix + uuid__default["default"].v4();
|
|
12887
|
+
// Create watch session entity
|
|
12888
|
+
const session = {
|
|
12889
|
+
sessionId,
|
|
12890
|
+
roomId: this.room.roomId,
|
|
12891
|
+
watchSeconds: 0,
|
|
12892
|
+
startTime: startedAt,
|
|
12893
|
+
endTime: null,
|
|
12894
|
+
syncState: 'PENDING',
|
|
12895
|
+
syncedAt: null,
|
|
12896
|
+
retryCount: 0,
|
|
12897
|
+
};
|
|
12898
|
+
// Persist to storage
|
|
12899
|
+
this.storage.addSession(session);
|
|
12900
|
+
return sessionId;
|
|
12901
|
+
}
|
|
12902
|
+
/**
|
|
12903
|
+
* Update an existing watch session with duration
|
|
12904
|
+
* @param sessionId The unique identifier of the watch session
|
|
12905
|
+
* @param duration The total watch duration in seconds
|
|
12906
|
+
* @param endedAt The timestamp when this update occurred
|
|
12907
|
+
* @returns Promise<void> Completion status
|
|
12908
|
+
*/
|
|
12909
|
+
async updateWatchSession(sessionId, duration, endedAt) {
|
|
12910
|
+
const session = this.storage.getSession(sessionId);
|
|
12911
|
+
if (!session) {
|
|
12912
|
+
throw new Error(`Watch session ${sessionId} not found`);
|
|
12913
|
+
}
|
|
12914
|
+
// Update session
|
|
12915
|
+
this.storage.updateSession(sessionId, {
|
|
12916
|
+
watchSeconds: duration,
|
|
12917
|
+
endTime: endedAt,
|
|
12918
|
+
});
|
|
12919
|
+
}
|
|
12920
|
+
/**
|
|
12921
|
+
* Sync all pending watch sessions to backend
|
|
12922
|
+
* This function uses jitter delay and handles network resilience
|
|
12923
|
+
*/
|
|
12924
|
+
syncPendingWatchSessions() {
|
|
12925
|
+
// Execute with jitter delay (5-30 seconds)
|
|
12926
|
+
const jitterDelay = getJitterDelay();
|
|
12927
|
+
this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
|
|
12928
|
+
setTimeout(async () => {
|
|
12929
|
+
this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
|
|
12930
|
+
try {
|
|
12931
|
+
// Reset any SYNCING sessions back to PENDING
|
|
12932
|
+
const syncingSessions = this.storage.getSyncingSessions();
|
|
12933
|
+
this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
|
|
12934
|
+
syncingSessions.forEach(session => {
|
|
12935
|
+
this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
|
|
12936
|
+
});
|
|
12937
|
+
// Wait for network connection (max 60 seconds)
|
|
12938
|
+
await waitForNetwork(60000);
|
|
12939
|
+
this.client.log('room/RoomAnalytics: Network available');
|
|
12940
|
+
// Sync pending sessions
|
|
12941
|
+
this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
|
|
12942
|
+
await syncWatchSessions();
|
|
12943
|
+
this.client.log('room/RoomAnalytics: syncWatchSessions completed');
|
|
12944
|
+
}
|
|
12945
|
+
catch (error) {
|
|
12946
|
+
// Error is already handled in syncWatchSessions
|
|
12947
|
+
console.error('Failed to sync watch sessions:', error);
|
|
12948
|
+
}
|
|
12949
|
+
}, jitterDelay);
|
|
12950
|
+
}
|
|
12951
|
+
}
|
|
12952
|
+
|
|
12545
12953
|
const roomLinkedObject = (room) => {
|
|
12546
12954
|
return Object.assign(Object.assign({}, room), { get post() {
|
|
12547
12955
|
var _a;
|
|
@@ -12588,6 +12996,9 @@ const roomLinkedObject = (room) => {
|
|
|
12588
12996
|
type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
|
|
12589
12997
|
});
|
|
12590
12998
|
return data;
|
|
12999
|
+
}, analytics() {
|
|
13000
|
+
// Use 'this' to avoid creating a new room object
|
|
13001
|
+
return new AmityRoomAnalytics(this);
|
|
12591
13002
|
} });
|
|
12592
13003
|
};
|
|
12593
13004
|
|
|
@@ -28966,6 +29377,10 @@ var index$b = /*#__PURE__*/Object.freeze({
|
|
|
28966
29377
|
getRecordedUrl: getRecordedUrl,
|
|
28967
29378
|
removeParticipant: removeParticipant,
|
|
28968
29379
|
leaveRoom: leaveRoom,
|
|
29380
|
+
AmityRoomAnalytics: AmityRoomAnalytics,
|
|
29381
|
+
WatchSessionStorage: WatchSessionStorage,
|
|
29382
|
+
getWatchSessionStorage: getWatchSessionStorage,
|
|
29383
|
+
syncWatchSessions: syncWatchSessions,
|
|
28969
29384
|
onRoomStartBroadcasting: onRoomStartBroadcasting,
|
|
28970
29385
|
onRoomWaitingReconnect: onRoomWaitingReconnect,
|
|
28971
29386
|
onRoomEndBroadcasting: onRoomEndBroadcasting,
|
|
@@ -30481,85 +30896,6 @@ var index$7 = /*#__PURE__*/Object.freeze({
|
|
|
30481
30896
|
getPoll: getPoll
|
|
30482
30897
|
});
|
|
30483
30898
|
|
|
30484
|
-
const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHo80SecH7FuF2\nhFYnb+l26/VN8UMLXAQFLnxciNTEwkGVFMpdezlH8rU2HtUJL4RETogbAOLVY0XM\njs6sPn8G1nALmh9qeDpUtVqFOVtBHxEZ910TLOtQiunjqJKO5nWdqZ71EC3OFluR\niGQkO84BiIFbv37ub7xl3S8XarbtKoLcyVpkDHi+1wx1pgCAn6gtBUgckPL5NR8j\nLseabl3HAXQfhTCKo4tmOFM2Dxwl1IUMmIJrJg/aIU/U0tj/1Eoo7mG0JcNWX19l\nW3EecCbi0ncCJOrkUdwlBrcjaMayaX/ubEwyUeTGiLdyc4L3GRLHjyK8xgVNXRMH\nbZWJ2a5NAgMBAAECggEASxuE+35zTFO/XydKgmvIGcWL9FbgMlXb7Vcf0nBoG945\nbiz0NVc2paraIhJXc608xbYF3qLmtAE1MVBI0ORyRdBHNxY024l/6H6SH60Ed+uI\nM4ysp5ourY6Vj+DLwpdRiI9YDjqYAQDIUmhNxJP7XPhOMoZI6st+xZQBM34ic/bv\nAMSJm9OZphSp3+qXVkFZztr2mxD2EZSJJLYxi8BCdgM2qhazalbcJ6zDKHCZWVWm\n8RRxDGldyMb/237JxETzP40tAlzOZDmBAbUgEnurDJ93RVDIE3rbZUshwgeQd18a\nem096mWgvB1AIKYgsTAR3pw+V19YWAjq/glP6fz8wQKBgQD/oQq+ukKF0PRgBeM5\ngeTjSwsdGppQLmf5ndujvoiz/TpdjDEPu6R8kigQr1rG2t4K/yfdZoI8RdmJD1al\n3Q7N9hofooSy4rj6E3txzWZCHJjHad2cnCp/O26HiReGAl7wTcfTmNdiFHhZQzm5\nJBkvWAiwuvQMNfEbnXxw6/vIDwKBgQDH7fX8gsc77JLvAWgp1MaQN/sbqVb6JeT1\nFQfR8E/WFCSmzQBtNzd5KgYuCeelwr/8DyYytvN2BzCYZXp73gI1jF3YlW5jVn74\nOY6TwQ095digwo6Z0yuxopdIOApKgAkL9PRKgNrqAf3NAyMua6lOGifzjDojC3KU\nfylQmxMn4wKBgHp2B9O/H0dEBw5JQ8W0+JX6yWQz7mEjGiR2/1W+XXb8hQ1zr709\nw1r6Gb+EghRpnZ3fBpYGGbYOMFx8wKHM+N6qW3F0ReX8v2juFGE8aRSa5oYBrWzt\nU16Idjbv8hj84cZ1PJmdyvDtpYn9rpWHOZl4rxEbPvbqkIsOMyNVqdT5AoGAOSge\nmwIIU2le2FVeohbibXiToWTYKMuMmURZ5/r72AgKMmWJKbAPe+Q3wBG01/7FRBpQ\noU8Ma0HC8s6QJbliiEyIx9JwrJWd1vkdecBHONrtA4ibm/5zD2WcOllLF+FitLhi\n3qnX6+6F0IaFGFBPJrTzlv0P4dTz/OAdv52V7GECgYEA2TttOKBAqWllgOaZOkql\nLVMJVmgR7s6tLi1+cEP8ZcapV9aRbRzTAKXm4f8AEhtlG9F9kCOvHYCYGi6JaiWJ\nZkHjeex3T+eE6Di6y5Bm/Ift5jtVhJ4jCVwHOKTMej79NPUFTJfv8hCo29haBDv6\nRXFrv+T21KCcw8k3sJeJWWQ=\n-----END PRIVATE KEY-----";
|
|
30485
|
-
/*
|
|
30486
|
-
* The crypto algorithm used for importing key and signing string
|
|
30487
|
-
*/
|
|
30488
|
-
const ALGORITHM = {
|
|
30489
|
-
name: 'RSASSA-PKCS1-v1_5',
|
|
30490
|
-
hash: { name: 'SHA-256' },
|
|
30491
|
-
};
|
|
30492
|
-
/*
|
|
30493
|
-
* IMPORTANT!
|
|
30494
|
-
* If you are recieving key from other platforms use an online tool to convert
|
|
30495
|
-
* the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
|
|
30496
|
-
* PKCS1.
|
|
30497
|
-
*
|
|
30498
|
-
* If recieving from the platform, verify if it's already in the expected
|
|
30499
|
-
* format. Otherwise the crypto.subtle.importKey will throw a DOMException
|
|
30500
|
-
*/
|
|
30501
|
-
const PRIVATE_KEY_SIGNATURE = 'pkcs8';
|
|
30502
|
-
/*
|
|
30503
|
-
* Ensure that the private key in the .env follows this format
|
|
30504
|
-
*/
|
|
30505
|
-
const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
|
|
30506
|
-
const PEM_FOOTER = '-----END PRIVATE KEY-----';
|
|
30507
|
-
/*
|
|
30508
|
-
* The crypto.subtle.sign function returns an ArrayBuffer whereas the server
|
|
30509
|
-
* expects a base64 string. This util helps facilitate that process
|
|
30510
|
-
*/
|
|
30511
|
-
function base64FromArrayBuffer(buffer) {
|
|
30512
|
-
const uint8Array = new Uint8Array(buffer);
|
|
30513
|
-
let binary = '';
|
|
30514
|
-
uint8Array.forEach(byte => {
|
|
30515
|
-
binary += String.fromCharCode(byte);
|
|
30516
|
-
});
|
|
30517
|
-
return jsBase64.btoa(binary);
|
|
30518
|
-
}
|
|
30519
|
-
/*
|
|
30520
|
-
* Convert a string into an ArrayBuffer
|
|
30521
|
-
* from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
|
|
30522
|
-
*
|
|
30523
|
-
* Solely used by the importPrivateKey method
|
|
30524
|
-
*/
|
|
30525
|
-
function str2ab(str) {
|
|
30526
|
-
const buf = new ArrayBuffer(str.length);
|
|
30527
|
-
const bufView = new Uint8Array(buf);
|
|
30528
|
-
for (let i = 0, strLen = str.length; i < strLen; i += 1) {
|
|
30529
|
-
bufView[i] = str.charCodeAt(i);
|
|
30530
|
-
}
|
|
30531
|
-
return buf;
|
|
30532
|
-
}
|
|
30533
|
-
function importPrivateKey(pem) {
|
|
30534
|
-
// fetch the part of the PEM string between header and footer
|
|
30535
|
-
const pemContents = pem.substring(PEM_HEADER.length, pem.length - PEM_FOOTER.length);
|
|
30536
|
-
/*
|
|
30537
|
-
* base64 decode the string to get the binary data
|
|
30538
|
-
*/
|
|
30539
|
-
const binaryDerString = jsBase64.atob(pemContents);
|
|
30540
|
-
// convert from a binary string to an ArrayBuffer
|
|
30541
|
-
const binaryDer = str2ab(binaryDerString);
|
|
30542
|
-
return crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, binaryDer, ALGORITHM, false, ['sign']);
|
|
30543
|
-
}
|
|
30544
|
-
async function createSignature({ timestamp, streams, }) {
|
|
30545
|
-
const dataStr = streams
|
|
30546
|
-
.map(item => Object.keys(item)
|
|
30547
|
-
.sort()
|
|
30548
|
-
.map(key => `${key}=${item[key]}`)
|
|
30549
|
-
.join('&'))
|
|
30550
|
-
.join(';');
|
|
30551
|
-
/*
|
|
30552
|
-
* nonceStr needs to be unique for each request
|
|
30553
|
-
*/
|
|
30554
|
-
const nonceStr = uuid__default["default"].v4();
|
|
30555
|
-
const signStr = `nonceStr=${nonceStr}×tamp=${timestamp}&data=${dataStr}==`;
|
|
30556
|
-
const encoder = new TextEncoder();
|
|
30557
|
-
const data = encoder.encode(signStr);
|
|
30558
|
-
const key = await importPrivateKey(privateKey);
|
|
30559
|
-
const sign = await crypto.subtle.sign(ALGORITHM, key, data);
|
|
30560
|
-
return { signature: base64FromArrayBuffer(sign), nonceStr };
|
|
30561
|
-
}
|
|
30562
|
-
|
|
30563
30899
|
async function syncUsage({ bufferCurrentUsage, getActiveStreams, updateUsage, dispose, }) {
|
|
30564
30900
|
const streams = bufferCurrentUsage();
|
|
30565
30901
|
if (!streams.length)
|