@amityco/ts-sdk 7.6.1-1a687cb5.0 → 7.6.1-316d940a.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/core/events.d.ts +6 -1
- package/dist/@types/core/events.d.ts.map +1 -1
- package/dist/@types/core/payload.d.ts +26 -1
- package/dist/@types/core/payload.d.ts.map +1 -1
- package/dist/@types/domains/channel.d.ts +6 -0
- package/dist/@types/domains/channel.d.ts.map +1 -1
- package/dist/@types/domains/content.d.ts +2 -8
- package/dist/@types/domains/content.d.ts.map +1 -1
- package/dist/@types/domains/feed.d.ts +1 -2
- package/dist/@types/domains/feed.d.ts.map +1 -1
- package/dist/@types/domains/file.d.ts +1 -3
- package/dist/@types/domains/file.d.ts.map +1 -1
- package/dist/@types/domains/liveReaction.d.ts +20 -0
- package/dist/@types/domains/liveReaction.d.ts.map +1 -0
- package/dist/@types/domains/post.d.ts +3 -3
- package/dist/@types/domains/post.d.ts.map +1 -1
- package/dist/@types/domains/stream.d.ts +9 -1
- package/dist/@types/domains/stream.d.ts.map +1 -1
- package/dist/@types/index.d.ts +1 -0
- package/dist/@types/index.d.ts.map +1 -1
- package/dist/channelRepository/api/createChannel.d.ts +3 -1
- package/dist/channelRepository/api/createChannel.d.ts.map +1 -1
- package/dist/channelRepository/channelMembership/observers/getMembers/ChannelMemberLiveCollectionController.d.ts.map +1 -1
- package/dist/channelRepository/events/index.d.ts +1 -1
- package/dist/channelRepository/events/index.d.ts.map +1 -1
- package/dist/channelRepository/events/onChannelSetMuted.d.ts +2 -0
- package/dist/channelRepository/events/onChannelSetMuted.d.ts.map +1 -0
- package/dist/channelRepository/events/onChannelSetUserMuted.d.ts +2 -0
- package/dist/channelRepository/events/onChannelSetUserMuted.d.ts.map +1 -0
- package/dist/channelRepository/internalApi/getChannel.d.ts.map +1 -1
- package/dist/channelRepository/internalApi/getMyMembership.d.ts +11 -0
- package/dist/channelRepository/internalApi/getMyMembership.d.ts.map +1 -0
- package/dist/channelRepository/observers/getChannels/ChannelLiveCollectionController.d.ts.map +1 -1
- package/dist/channelRepository/observers/getMyMembership.d.ts +2 -0
- package/dist/channelRepository/observers/getMyMembership.d.ts.map +1 -0
- package/dist/client/api/login.d.ts.map +1 -1
- package/dist/communityRepository/api/getCommunity.d.ts +1 -1
- package/dist/communityRepository/api/getCommunity.d.ts.map +1 -1
- package/dist/core/events.d.ts +3 -3
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/subscription.d.ts +2 -1
- package/dist/core/subscription.d.ts.map +1 -1
- package/dist/feedRepository/api/getCustomRankingGlobalFeed.d.ts +1 -1
- package/dist/feedRepository/api/getCustomRankingGlobalFeed.d.ts.map +1 -1
- package/dist/feedRepository/api/queryGlobalFeed.d.ts.map +1 -1
- package/dist/fileRepository/api/index.d.ts +0 -1
- package/dist/fileRepository/api/index.d.ts.map +1 -1
- package/dist/index.cjs.js +6323 -5744
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +6258 -5681
- package/dist/index.umd.js +3 -3
- package/dist/liveReactionRepository/api/createReaction.d.ts +20 -0
- package/dist/liveReactionRepository/api/createReaction.d.ts.map +1 -0
- package/dist/liveReactionRepository/api/index.d.ts +2 -0
- package/dist/liveReactionRepository/api/index.d.ts.map +1 -0
- package/dist/liveReactionRepository/events/index.d.ts +2 -0
- package/dist/liveReactionRepository/events/index.d.ts.map +1 -0
- package/dist/liveReactionRepository/events/onLiveReactionCreated.d.ts +17 -0
- package/dist/liveReactionRepository/events/onLiveReactionCreated.d.ts.map +1 -0
- package/dist/liveReactionRepository/events/onLiveReactionCreatedLocal.d.ts +17 -0
- package/dist/liveReactionRepository/events/onLiveReactionCreatedLocal.d.ts.map +1 -0
- package/dist/liveReactionRepository/index.d.ts +4 -0
- package/dist/liveReactionRepository/index.d.ts.map +1 -0
- package/dist/liveReactionRepository/internalApi/createLiveReaction.d.ts +20 -0
- package/dist/liveReactionRepository/internalApi/createLiveReaction.d.ts.map +1 -0
- package/dist/liveReactionRepository/observers/getReactions.d.ts +19 -0
- package/dist/liveReactionRepository/observers/getReactions.d.ts.map +1 -0
- package/dist/liveReactionRepository/observers/index.d.ts +2 -0
- package/dist/liveReactionRepository/observers/index.d.ts.map +1 -0
- package/dist/liveReactionRepository/service/ReactionSyncEngine.d.ts +26 -0
- package/dist/liveReactionRepository/service/ReactionSyncEngine.d.ts.map +1 -0
- package/dist/liveReactionRepository/utils/ReactionSyncEngineOnLoginHandler.d.ts +3 -0
- package/dist/liveReactionRepository/utils/ReactionSyncEngineOnLoginHandler.d.ts.map +1 -0
- package/dist/liveStreamPlayer/utils/eventRegister.d.ts +2 -1
- package/dist/liveStreamPlayer/utils/eventRegister.d.ts.map +1 -1
- package/dist/messagePreview/utils/getChannelMessagePreviewWithUser.d.ts +4 -0
- package/dist/messagePreview/utils/getChannelMessagePreviewWithUser.d.ts.map +1 -1
- package/dist/messagePreview/utils/getSubChannelMessagePreviewWithUser.d.ts +1 -1
- package/dist/messageRepository/api/deleteMessage.d.ts.map +1 -1
- package/dist/messageRepository/observers/getMessage.d.ts.map +1 -1
- package/dist/messageRepository/observers/getMessages/MessageLiveCollectionController.d.ts.map +1 -1
- package/dist/messageRepository/observers/getMessages/MessageQueryStreamController.d.ts.map +1 -1
- package/dist/postRepository/api/createPost.d.ts.map +1 -1
- package/dist/postRepository/api/index.d.ts +0 -1
- package/dist/postRepository/api/index.d.ts.map +1 -1
- package/dist/postRepository/utils/payload.d.ts.map +1 -1
- package/dist/streamRepository/api/createStream.d.ts +1 -1
- package/dist/streamRepository/api/createStream.d.ts.map +1 -1
- package/dist/streamRepository/api/editStream.d.ts +18 -0
- package/dist/streamRepository/api/editStream.d.ts.map +1 -0
- package/dist/streamRepository/api/index.d.ts +1 -0
- package/dist/streamRepository/api/index.d.ts.map +1 -1
- package/dist/streamRepository/api/updateStream.d.ts +4 -1
- package/dist/streamRepository/api/updateStream.d.ts.map +1 -1
- package/dist/streamRepository/events/index.d.ts +2 -0
- package/dist/streamRepository/events/index.d.ts.map +1 -1
- package/dist/streamRepository/events/onStreamViewerBanned.d.ts +17 -0
- package/dist/streamRepository/events/onStreamViewerBanned.d.ts.map +1 -0
- package/dist/streamRepository/events/onStreamViewerUnbanned.d.ts +17 -0
- package/dist/streamRepository/events/onStreamViewerUnbanned.d.ts.map +1 -0
- package/dist/streamRepository/internalApi/getLiveChat.d.ts +16 -0
- package/dist/streamRepository/internalApi/getLiveChat.d.ts.map +1 -0
- package/dist/streamRepository/internalApi/getStream.d.ts +2 -2
- package/dist/streamRepository/internalApi/getStream.d.ts.map +1 -1
- package/dist/streamRepository/observers/getStreamById.d.ts.map +1 -1
- package/dist/streamRepository/observers/getStreams/GetStreamsLiveCollectionController.d.ts.map +1 -1
- package/dist/utils/linkedObject/channelLinkedObject.d.ts.map +1 -1
- package/dist/utils/linkedObject/postLinkedObject.d.ts.map +1 -1
- package/dist/utils/linkedObject/streamLinkedObject.d.ts.map +1 -1
- package/dist/utils/postTypePredicate.d.ts +5 -4
- package/dist/utils/postTypePredicate.d.ts.map +1 -1
- package/dist/utils/tests/dummy/comment.d.ts +1 -1
- package/package.json +1 -1
- package/src/@types/core/events.ts +10 -1
- package/src/@types/core/payload.ts +33 -1
- package/src/@types/domains/channel.ts +9 -0
- package/src/@types/domains/content.ts +0 -10
- package/src/@types/domains/feed.ts +1 -2
- package/src/@types/domains/file.ts +0 -5
- package/src/@types/domains/liveReaction.ts +25 -0
- package/src/@types/domains/post.ts +4 -4
- package/src/@types/domains/stream.ts +13 -1
- package/src/@types/index.ts +1 -0
- package/src/channelRepository/api/createChannel.ts +11 -8
- package/src/channelRepository/channelMembership/observers/getMembers/ChannelMemberLiveCollectionController.ts +2 -0
- package/src/channelRepository/events/index.ts +1 -1
- package/src/channelRepository/events/onChannelSetMuted.ts +48 -0
- package/src/channelRepository/events/onChannelSetUserMuted.ts +65 -0
- package/src/channelRepository/internalApi/getChannel.ts +0 -1
- package/src/channelRepository/internalApi/getMyMembership.ts +37 -0
- package/src/channelRepository/observers/getChannel.ts +2 -2
- package/src/channelRepository/observers/getChannels/ChannelLiveCollectionController.ts +2 -2
- package/src/channelRepository/observers/getMyMembership.ts +98 -0
- package/src/channelRepository/utils/constructChannelObject.ts +2 -2
- package/src/client/api/login.ts +2 -0
- package/src/communityRepository/api/getCommunity.ts +9 -0
- package/src/core/events.ts +4 -1
- package/src/core/subscription.ts +10 -6
- package/src/feedRepository/api/getCustomRankingGlobalFeed.ts +1 -1
- package/src/feedRepository/api/queryGlobalFeed.ts +1 -3
- package/src/fileRepository/api/index.ts +0 -1
- package/src/index.ts +2 -0
- package/src/liveReactionRepository/api/createReaction.ts +58 -0
- package/src/liveReactionRepository/api/index.ts +1 -0
- package/src/liveReactionRepository/events/index.ts +1 -0
- package/src/liveReactionRepository/events/onLiveReactionCreated.ts +37 -0
- package/src/liveReactionRepository/events/onLiveReactionCreatedLocal.ts +29 -0
- package/src/liveReactionRepository/index.ts +3 -0
- package/src/liveReactionRepository/internalApi/createLiveReaction.ts +42 -0
- package/src/liveReactionRepository/observers/getReactions.ts +59 -0
- package/src/liveReactionRepository/observers/index.ts +1 -0
- package/src/liveReactionRepository/service/ReactionSyncEngine.ts +138 -0
- package/src/liveReactionRepository/utils/ReactionSyncEngineOnLoginHandler.ts +19 -0
- package/src/liveStreamPlayer/api/getPlayer.ts +1 -1
- package/src/liveStreamPlayer/utils/eventRegister.ts +16 -1
- package/src/messageRepository/api/deleteMessage.ts +16 -0
- package/src/messageRepository/observers/getMessage.ts +2 -0
- package/src/messageRepository/observers/getMessages/MessageLiveCollectionController.ts +2 -0
- package/src/messageRepository/observers/getMessages/MessageQueryStreamController.ts +13 -0
- package/src/postRepository/api/createPost.ts +3 -2
- package/src/postRepository/api/index.ts +0 -2
- package/src/postRepository/api/queryPosts.ts +1 -1
- package/src/postRepository/observers/getPosts/PostPaginationController.ts +1 -1
- package/src/postRepository/utils/payload.ts +37 -1
- package/src/streamRepository/api/createStream.ts +4 -1
- package/src/streamRepository/api/editStream.ts +51 -0
- package/src/streamRepository/api/index.ts +1 -0
- package/src/streamRepository/api/updateStream.ts +8 -1
- package/src/streamRepository/events/index.ts +2 -0
- package/src/streamRepository/events/onStreamViewerBanned.ts +58 -0
- package/src/streamRepository/events/onStreamViewerUnbanned.ts +47 -0
- package/src/streamRepository/internalApi/getLiveChat.ts +59 -0
- package/src/streamRepository/internalApi/getStream.ts +3 -3
- package/src/streamRepository/observers/getStreamById.ts +2 -0
- package/src/streamRepository/observers/getStreams/GetStreamsLiveCollectionController.ts +5 -1
- package/src/utils/linkedObject/channelLinkedObject.ts +3 -0
- package/src/utils/linkedObject/postLinkedObject.ts +25 -6
- package/src/utils/linkedObject/streamLinkedObject.ts +4 -0
- package/src/utils/postTypePredicate.ts +20 -7
- package/dist/channelRepository/events/onChannelMuted.d.ts +0 -2
- package/dist/channelRepository/events/onChannelMuted.d.ts.map +0 -1
- package/dist/fileRepository/api/uploadClip.d.ts +0 -17
- package/dist/fileRepository/api/uploadClip.d.ts.map +0 -1
- package/dist/postRepository/api/createClipPost.d.ts +0 -32
- package/dist/postRepository/api/createClipPost.d.ts.map +0 -1
- package/src/channelRepository/events/onChannelMuted.ts +0 -39
- package/src/fileRepository/api/uploadClip.ts +0 -71
- package/src/postRepository/api/createClipPost.ts +0 -62
|
@@ -43,7 +43,7 @@ export const queryPosts = async (
|
|
|
43
43
|
// API-FIX: parameters should be querystring. (1)
|
|
44
44
|
// API-FIX: backend should answer Amity.Response (2)
|
|
45
45
|
// const { data } = await client.http.get<Amity.Response<Amity.PagedResponse<Amity.PostPayload>>>(
|
|
46
|
-
const { data } = await client.http.get<Amity.PostPayload & Amity.Pagination>(`/api/
|
|
46
|
+
const { data } = await client.http.get<Amity.PostPayload & Amity.Pagination>(`/api/v4/posts`, {
|
|
47
47
|
params: {
|
|
48
48
|
...params,
|
|
49
49
|
isDeleted: inferIsDeleted(includeDeleted),
|
|
@@ -23,7 +23,7 @@ export class PostPaginationController extends PaginationController<
|
|
|
23
23
|
const options = token ? { ...baseOptions, token } : { ...baseOptions, limit };
|
|
24
24
|
|
|
25
25
|
const { data: queryResponse } = await this.http.get<Amity.PostPayload & Amity.Pagination>(
|
|
26
|
-
`/api/
|
|
26
|
+
`/api/v4/posts`,
|
|
27
27
|
{
|
|
28
28
|
params: {
|
|
29
29
|
...params,
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import { addPostSetting } from '~/communityRepository/utils';
|
|
2
2
|
import { updateMembershipStatus } from '~/communityRepository/utils/communityWithMembership';
|
|
3
|
+
import { isAmityLivestreamPost } from '~/utils/postTypePredicate';
|
|
4
|
+
|
|
5
|
+
const updateStreamReferences = (
|
|
6
|
+
streams: Amity.RawStream[],
|
|
7
|
+
streamId: string | undefined,
|
|
8
|
+
postId: string,
|
|
9
|
+
) => {
|
|
10
|
+
if (!streamId) return streams;
|
|
11
|
+
|
|
12
|
+
return streams.map(stream =>
|
|
13
|
+
stream.streamId === streamId
|
|
14
|
+
? {
|
|
15
|
+
...stream,
|
|
16
|
+
referenceType: 'post',
|
|
17
|
+
referenceId: postId,
|
|
18
|
+
postId,
|
|
19
|
+
}
|
|
20
|
+
: stream,
|
|
21
|
+
);
|
|
22
|
+
};
|
|
3
23
|
|
|
4
24
|
export const preparePostPayload = (payload: Amity.PostPayload): Amity.ProcessedPostPayload => {
|
|
5
|
-
const { posts: postsData, ...postPayload } = payload;
|
|
25
|
+
const { posts: postsData, postChildren, videoStreamings, ...postPayload } = payload;
|
|
6
26
|
|
|
7
27
|
// Unpack community payload by mapping payload field to postSetting value.
|
|
8
28
|
const communitiesWithPostSetting = addPostSetting({ communities: postPayload.communities });
|
|
@@ -24,18 +44,34 @@ export const preparePostPayload = (payload: Amity.PostPayload): Amity.ProcessedP
|
|
|
24
44
|
mappedCommunityUsers,
|
|
25
45
|
);
|
|
26
46
|
|
|
47
|
+
let mappedNewStream: Amity.RawStream[] = [];
|
|
48
|
+
|
|
27
49
|
// feed type
|
|
28
50
|
const posts = postsData.map(post => {
|
|
29
51
|
const feedType = postPayload.feeds.find(feed => feed.feedId === post.feedId)?.feedType;
|
|
52
|
+
const childPosts = payload.postChildren.filter(
|
|
53
|
+
children => children.parentPostId === post.postId,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
if (childPosts.length > 0 && isAmityLivestreamPost(childPosts[0])) {
|
|
57
|
+
mappedNewStream = updateStreamReferences(
|
|
58
|
+
videoStreamings,
|
|
59
|
+
childPosts[0].data?.streamId,
|
|
60
|
+
post.postId,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
30
63
|
|
|
31
64
|
return {
|
|
32
65
|
...post,
|
|
66
|
+
childPosts,
|
|
33
67
|
feedType,
|
|
34
68
|
};
|
|
35
69
|
});
|
|
36
70
|
|
|
37
71
|
return {
|
|
38
72
|
...postPayload,
|
|
73
|
+
postChildren,
|
|
74
|
+
videoStreamings: mappedNewStream,
|
|
39
75
|
posts,
|
|
40
76
|
communities: communityWithMembershipStatus,
|
|
41
77
|
communityUsers: mappedCommunityUsers,
|
|
@@ -21,7 +21,10 @@ import { LinkedObject } from '~/utils/linkedObject';
|
|
|
21
21
|
* @async
|
|
22
22
|
*/
|
|
23
23
|
export const createStream = async (
|
|
24
|
-
bundle: Pick<
|
|
24
|
+
bundle: Pick<
|
|
25
|
+
Amity.InternalStream,
|
|
26
|
+
'title' | 'thumbnailFileId' | 'description' | 'channelEnabled'
|
|
27
|
+
> & {
|
|
25
28
|
isSecure?: boolean;
|
|
26
29
|
},
|
|
27
30
|
): Promise<Amity.Cached<Amity.Stream>> => {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api';
|
|
2
|
+
|
|
3
|
+
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
4
|
+
import { LinkedObject } from '~/utils/linkedObject';
|
|
5
|
+
|
|
6
|
+
/* begin_public_function
|
|
7
|
+
id: stream.update
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* ```js
|
|
12
|
+
* import { StreamRepository } from '@amityco/ts-sdk'
|
|
13
|
+
* const updated = await StreamRepository.editStream(streamId, { title: 'foobar' })
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Updates an {@link Amity.Stream}
|
|
17
|
+
*
|
|
18
|
+
* @param streamId The ID of the {@link Amity.Stream} to edit
|
|
19
|
+
* @param patch The patch data to apply
|
|
20
|
+
* @returns the updated {@link Amity.Stream} object
|
|
21
|
+
*
|
|
22
|
+
* @category Stream API
|
|
23
|
+
* @async
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export const editStream = async (
|
|
27
|
+
streamId: Amity.Stream['streamId'],
|
|
28
|
+
patch: Patch<
|
|
29
|
+
Amity.Stream,
|
|
30
|
+
'title' | 'thumbnailFileId' | 'description' | 'metadata' | 'channelEnabled'
|
|
31
|
+
>,
|
|
32
|
+
): Promise<Amity.Cached<Amity.Stream>> => {
|
|
33
|
+
const client = getActiveClient();
|
|
34
|
+
client.log('stream/updateStream', streamId, patch);
|
|
35
|
+
|
|
36
|
+
const { data } = await client.http.put<Amity.StreamPayload>(
|
|
37
|
+
`/api/v3/video-streaming/${streamId}`,
|
|
38
|
+
patch,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const cachedAt = client.cache && Date.now();
|
|
42
|
+
if (client.cache) ingestInCache(data, { cachedAt });
|
|
43
|
+
|
|
44
|
+
const { videoStreamings } = data;
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
data: LinkedObject.stream(videoStreamings.find(stream => stream.streamId === streamId)!),
|
|
48
|
+
cachedAt,
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/* end_public_function */
|
|
@@ -7,6 +7,9 @@ import { LinkedObject } from '~/utils/linkedObject';
|
|
|
7
7
|
id: stream.update
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
|
+
* @deprecated this function is deprecated,
|
|
11
|
+
* please use {@link Amity.StreamRepository.editStream} instead.
|
|
12
|
+
*
|
|
10
13
|
* ```js
|
|
11
14
|
* import { updateStream } from '@amityco/ts-sdk'
|
|
12
15
|
* const updated = await updateStream(streamId, { title: 'foobar' })
|
|
@@ -21,9 +24,13 @@ import { LinkedObject } from '~/utils/linkedObject';
|
|
|
21
24
|
* @category Stream API
|
|
22
25
|
* @async
|
|
23
26
|
*/
|
|
27
|
+
|
|
24
28
|
export const updateStream = async (
|
|
25
29
|
streamId: Amity.Stream['streamId'],
|
|
26
|
-
patch: Patch<
|
|
30
|
+
patch: Patch<
|
|
31
|
+
Amity.Stream,
|
|
32
|
+
'title' | 'thumbnailFileId' | 'description' | 'metadata' | 'channelEnabled'
|
|
33
|
+
>,
|
|
27
34
|
): Promise<Amity.Cached<Amity.Stream>> => {
|
|
28
35
|
const client = getActiveClient();
|
|
29
36
|
client.log('stream/updateStream', streamId, patch);
|
|
@@ -3,3 +3,5 @@ export { onStreamStopped } from './onStreamStopped';
|
|
|
3
3
|
export { onStreamRecorded } from './onStreamRecorded';
|
|
4
4
|
export { onStreamFlagged } from './onStreamFlagged';
|
|
5
5
|
export { onStreamTerminated } from './onStreamTerminated';
|
|
6
|
+
export { onStreamViewerBanned } from './onStreamViewerBanned';
|
|
7
|
+
export { onStreamViewerUnbanned } from './onStreamViewerUnbanned';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api';
|
|
2
|
+
import { createEventSubscriber } from '~/core/events';
|
|
3
|
+
import { mergeInCache, pullFromCache, queryCache } from '~/cache/api';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ```js
|
|
7
|
+
* import { onStreamViewerBanned } from '@amityco/ts-sdk'
|
|
8
|
+
* const dispose = onStreamViewerBanned(stream => {
|
|
9
|
+
* // ...
|
|
10
|
+
* })
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Fired when a user in channel linked to stream has been banned
|
|
14
|
+
*
|
|
15
|
+
* @param callback The function to call when the event was fired
|
|
16
|
+
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
17
|
+
*
|
|
18
|
+
* @category Stream Events
|
|
19
|
+
*/
|
|
20
|
+
export const onStreamViewerBanned = (
|
|
21
|
+
callback: Amity.Listener<Amity.InternalStream>,
|
|
22
|
+
): Amity.Unsubscriber => {
|
|
23
|
+
const client = getActiveClient();
|
|
24
|
+
|
|
25
|
+
const filter = (payloads: Amity.StreamViewerBanPayload) => {
|
|
26
|
+
payloads.forEach(streamBanned => {
|
|
27
|
+
mergeInCache(['stream', 'get', streamBanned.streamId], { watcherUrl: null });
|
|
28
|
+
|
|
29
|
+
// Update isDeleted = true in banned user's messages
|
|
30
|
+
const messageCache = queryCache<Amity.InternalMessage>(['message', 'get'])?.filter(
|
|
31
|
+
// Check if creator id and user id are internal or external id
|
|
32
|
+
({ data }) => data.creatorId === streamBanned.userId,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Update isDeleted for each relavant messages
|
|
36
|
+
messageCache?.forEach(message => {
|
|
37
|
+
mergeInCache(message.key, { isDeleted: true });
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const stream = pullFromCache<Amity.InternalStream>([
|
|
42
|
+
'stream',
|
|
43
|
+
'get',
|
|
44
|
+
payloads[0].streamId,
|
|
45
|
+
])?.data;
|
|
46
|
+
|
|
47
|
+
if (!stream) return;
|
|
48
|
+
|
|
49
|
+
callback(stream);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return createEventSubscriber(
|
|
53
|
+
client,
|
|
54
|
+
'stream/onStreamViewerDidBan',
|
|
55
|
+
'video-streaming.viewerDidBan',
|
|
56
|
+
filter,
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api';
|
|
2
|
+
import { createEventSubscriber } from '~/core/events';
|
|
3
|
+
import { mergeInCache, pullFromCache } from '~/cache/api';
|
|
4
|
+
import { getStream } from '../internalApi/getStream';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ```js
|
|
8
|
+
* import { onStreamViewerUnbanned } from '@amityco/ts-sdk'
|
|
9
|
+
* const dispose = onStreamViewerBanned(stream => {
|
|
10
|
+
* // ...
|
|
11
|
+
* })
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Fired when a user in channel linked to stream has been unbanned
|
|
15
|
+
*
|
|
16
|
+
* @param callback The function to call when the event was fired
|
|
17
|
+
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
18
|
+
*
|
|
19
|
+
* @category Stream Events
|
|
20
|
+
*/
|
|
21
|
+
export const onStreamViewerUnbanned = (
|
|
22
|
+
callback: Amity.Listener<Amity.InternalStream>,
|
|
23
|
+
): Amity.Unsubscriber => {
|
|
24
|
+
const client = getActiveClient();
|
|
25
|
+
|
|
26
|
+
const filter = async (payloads: Amity.StreamViewerUnbanPayload) => {
|
|
27
|
+
// Get new stream object to restore stream watcherUrl in cache
|
|
28
|
+
await Promise.all(payloads.map(({ streamId }) => getStream(streamId)));
|
|
29
|
+
|
|
30
|
+
const stream = pullFromCache<Amity.InternalStream>([
|
|
31
|
+
'stream',
|
|
32
|
+
'get',
|
|
33
|
+
payloads[0].streamId,
|
|
34
|
+
])?.data;
|
|
35
|
+
|
|
36
|
+
if (!stream) return;
|
|
37
|
+
|
|
38
|
+
callback(stream);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return createEventSubscriber(
|
|
42
|
+
client,
|
|
43
|
+
'stream/onStreamViewerDidUnban',
|
|
44
|
+
'video-streaming.viewerDidUnban',
|
|
45
|
+
filter,
|
|
46
|
+
);
|
|
47
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api/activeClient';
|
|
2
|
+
import { mergeInCache, pullFromCache } from '~/cache/api';
|
|
3
|
+
import { createChannel } from '~/channelRepository/api/createChannel';
|
|
4
|
+
import { channelLinkedObject } from '~/utils/linkedObject/channelLinkedObject';
|
|
5
|
+
import { getChannel } from '~/channelRepository/internalApi/getChannel';
|
|
6
|
+
import { constructChannelObject } from '~/channelRepository/utils/constructChannelObject';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ```js
|
|
10
|
+
* import { getStream } from '@amityco/ts-sdk'
|
|
11
|
+
* const stream = await getStream('foobar')
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Fetches a {@link Amity.Channel} object linked with a current stream
|
|
15
|
+
*
|
|
16
|
+
* @param stream {@link Amity.Stream} that has linked live channel
|
|
17
|
+
* @returns the associated {@link Amity.Channel<'live'>} object
|
|
18
|
+
*
|
|
19
|
+
* @category Stream API
|
|
20
|
+
* @async
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const getLiveChat = async (
|
|
24
|
+
stream: Amity.InternalStream,
|
|
25
|
+
): Promise<Amity.Channel<'live'> | undefined> => {
|
|
26
|
+
const client = getActiveClient();
|
|
27
|
+
client.log('stream/getLiveChat', stream.streamId);
|
|
28
|
+
|
|
29
|
+
if (stream.channelId) {
|
|
30
|
+
const channel = pullFromCache<Amity.StaticInternalChannel>([
|
|
31
|
+
'channel',
|
|
32
|
+
'get',
|
|
33
|
+
stream.channelId,
|
|
34
|
+
])?.data;
|
|
35
|
+
|
|
36
|
+
if (channel) return channelLinkedObject(constructChannelObject(channel));
|
|
37
|
+
|
|
38
|
+
const { data } = await getChannel(stream.channelId);
|
|
39
|
+
return channelLinkedObject(constructChannelObject(data));
|
|
40
|
+
}
|
|
41
|
+
// No Channel ID
|
|
42
|
+
// streamer: create a new live channel
|
|
43
|
+
if (stream.userId === client.userId) {
|
|
44
|
+
const { data: channel } = await createChannel({
|
|
45
|
+
type: 'live',
|
|
46
|
+
postId: stream.referenceId,
|
|
47
|
+
videoStreamId: stream.streamId,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Update channelId to stream object in cache
|
|
51
|
+
mergeInCache(['stream', 'get', stream.streamId], {
|
|
52
|
+
channelId: channel.channelId,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return channel;
|
|
56
|
+
}
|
|
57
|
+
// watcher: return undefined
|
|
58
|
+
return undefined;
|
|
59
|
+
};
|
|
@@ -22,7 +22,7 @@ import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
|
22
22
|
*/
|
|
23
23
|
export const getStream = async (
|
|
24
24
|
streamId: Amity.Stream['streamId'],
|
|
25
|
-
): Promise<Amity.Cached<Amity.
|
|
25
|
+
): Promise<Amity.Cached<Amity.InternalStream>> => {
|
|
26
26
|
const client = getActiveClient();
|
|
27
27
|
client.log('stream/getStream', streamId);
|
|
28
28
|
|
|
@@ -57,13 +57,13 @@ export const getStream = async (
|
|
|
57
57
|
*/
|
|
58
58
|
getStream.locally = (
|
|
59
59
|
streamId: Amity.Stream['streamId'],
|
|
60
|
-
): Amity.Cached<Amity.
|
|
60
|
+
): Amity.Cached<Amity.InternalStream> | undefined => {
|
|
61
61
|
const client = getActiveClient();
|
|
62
62
|
client.log('stream/getStream', streamId);
|
|
63
63
|
|
|
64
64
|
if (!client.cache) return;
|
|
65
65
|
|
|
66
|
-
const cached = pullFromCache<Amity.
|
|
66
|
+
const cached = pullFromCache<Amity.InternalStream>(['stream', 'get', streamId]);
|
|
67
67
|
|
|
68
68
|
if (!cached) return;
|
|
69
69
|
|
|
@@ -8,6 +8,7 @@ import { onStreamTerminated } from '~/streamRepository/events/onStreamTerminated
|
|
|
8
8
|
import { LinkedObject } from '~/utils/linkedObject';
|
|
9
9
|
import { getStream as _getStream } from '../internalApi/getStream';
|
|
10
10
|
import { onStreamRecorded, onStreamStarted, onStreamStopped } from '../events';
|
|
11
|
+
import { onStreamViewerBanned } from '../events/onStreamViewerBanned';
|
|
11
12
|
|
|
12
13
|
/* begin_public_function
|
|
13
14
|
id: stream.get
|
|
@@ -45,6 +46,7 @@ export const getStreamById = (
|
|
|
45
46
|
onStreamStopped,
|
|
46
47
|
onStreamFlagged,
|
|
47
48
|
onStreamTerminated,
|
|
49
|
+
onStreamViewerBanned,
|
|
48
50
|
]);
|
|
49
51
|
};
|
|
50
52
|
/* end_public_function */
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
} from '~/streamRepository/events';
|
|
13
13
|
import { GetStreamsPageController } from '~/streamRepository/observers/getStreams/GetStreamsPageController';
|
|
14
14
|
import { GetStreamsQueryStreamController } from '~/streamRepository/observers/getStreams/GetStreamsQueryStreamController';
|
|
15
|
+
import { onStreamViewerBanned } from '~/streamRepository/events/onStreamViewerBanned';
|
|
16
|
+
import { onStreamViewerUnbanned } from '~/streamRepository/events/onStreamViewerUnbanned';
|
|
15
17
|
|
|
16
18
|
export class GetStreamsLiveCollectionController extends LiveCollectionController<
|
|
17
19
|
'stream',
|
|
@@ -77,6 +79,8 @@ export class GetStreamsLiveCollectionController extends LiveCollectionController
|
|
|
77
79
|
{ fn: onStreamStopped, action: 'onStreamStopped' },
|
|
78
80
|
{ fn: onStreamFlagged, action: 'onStreamFlagged' },
|
|
79
81
|
{ fn: onStreamTerminated, action: 'onStreamTerminated' },
|
|
82
|
+
{ fn: onStreamViewerBanned, action: 'onStreamViewerBanned' },
|
|
83
|
+
{ fn: onStreamViewerUnbanned, action: 'onStreamViewerUnbanned' },
|
|
80
84
|
]);
|
|
81
85
|
}
|
|
82
86
|
|
|
@@ -102,7 +106,7 @@ export class GetStreamsLiveCollectionController extends LiveCollectionController
|
|
|
102
106
|
this.queryStreamController.appendToQueryStream(response, direction, refresh);
|
|
103
107
|
}
|
|
104
108
|
|
|
105
|
-
private applyFilter = (data: Amity.
|
|
109
|
+
private applyFilter = (data: Amity.Stream[]): Amity.Stream[] => {
|
|
106
110
|
let streams = filterByPropEquality(data, 'isDeleted', this.query.isDeleted);
|
|
107
111
|
|
|
108
112
|
streams = streams.sort(
|
|
@@ -2,6 +2,7 @@ import { markAsRead } from '~/channelRepository/internalApi/markAsRead';
|
|
|
2
2
|
import { shallowClone } from '../shallowClone';
|
|
3
3
|
import { queryCache } from '~/cache/api';
|
|
4
4
|
import { channelMemberLinkedObject } from './channelMemberLinkedObject';
|
|
5
|
+
import { getMyMembership } from '~/channelRepository/observers/getMyMembership';
|
|
5
6
|
|
|
6
7
|
export const channelLinkedObject = (channel: Amity.InternalChannel): Amity.Channel => {
|
|
7
8
|
let previewMembers: Amity.Membership<'channel'>[] = [];
|
|
@@ -23,5 +24,7 @@ export const channelLinkedObject = (channel: Amity.InternalChannel): Amity.Chann
|
|
|
23
24
|
return shallowClone(channel, {
|
|
24
25
|
markAsRead: () => markAsRead(channel.channelInternalId),
|
|
25
26
|
previewMembers,
|
|
27
|
+
myMembership: (callback: Amity.LiveObjectCallback<Amity.Membership<'channel'> | undefined>) =>
|
|
28
|
+
getMyMembership(channel.channelId, callback),
|
|
26
29
|
});
|
|
27
30
|
};
|
|
@@ -3,16 +3,22 @@ import { commentLinkedObject } from '~/utils/linkedObject/commentLinkedObject';
|
|
|
3
3
|
import AnalyticsEngine from '../../analytic/service/analytic/AnalyticsEngine';
|
|
4
4
|
import { userLinkedObject } from './userLinkedObject';
|
|
5
5
|
import {
|
|
6
|
-
isAmityClipPost,
|
|
7
6
|
isAmityFilePost,
|
|
8
7
|
isAmityImagePost,
|
|
8
|
+
isAmityLivestreamPost,
|
|
9
|
+
isAmityPollPost,
|
|
9
10
|
isAmityVideoPost,
|
|
10
11
|
} from '../postTypePredicate';
|
|
12
|
+
import { streamLinkedObject } from './streamLinkedObject';
|
|
13
|
+
import { isNonNullable } from '..';
|
|
11
14
|
|
|
12
15
|
export const postLinkedObject = (post: Amity.InternalPost): Amity.Post => {
|
|
13
16
|
return {
|
|
14
17
|
...post,
|
|
15
|
-
|
|
18
|
+
childrenPosts: post.children
|
|
19
|
+
.map(childPost => pullFromCache<Amity.InternalPost>(['post', 'get', childPost])?.data)
|
|
20
|
+
.filter(isNonNullable)
|
|
21
|
+
.map(postLinkedObject),
|
|
16
22
|
analytics: {
|
|
17
23
|
markAsViewed: () => {
|
|
18
24
|
const analyticsEngineInstance = AnalyticsEngine.getInstance();
|
|
@@ -70,10 +76,23 @@ export const postLinkedObject = (post: Amity.InternalPost): Amity.Post => {
|
|
|
70
76
|
: undefined;
|
|
71
77
|
},
|
|
72
78
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
getLivestreamInfo(): Amity.Stream | undefined {
|
|
80
|
+
if (!isAmityLivestreamPost(post)) return;
|
|
81
|
+
const cache = pullFromCache<Amity.InternalStream>([
|
|
82
|
+
'stream',
|
|
83
|
+
'get',
|
|
84
|
+
post?.data?.streamId,
|
|
85
|
+
])?.data;
|
|
86
|
+
if (!cache) return;
|
|
87
|
+
|
|
88
|
+
return streamLinkedObject(cache);
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
getPollInfo(): Amity.Poll | undefined {
|
|
92
|
+
if (!isAmityPollPost(post)) return;
|
|
93
|
+
const cache = pullFromCache<Amity.Poll>(['poll', 'get', post?.data?.pollId])?.data;
|
|
94
|
+
if (!cache) return;
|
|
95
|
+
return cache;
|
|
77
96
|
},
|
|
78
97
|
};
|
|
79
98
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { pullFromCache } from '~/cache/api';
|
|
2
|
+
import { getLiveChat as _getLiveChat } from '~/streamRepository/internalApi/getLiveChat';
|
|
2
3
|
|
|
3
4
|
export const streamLinkedObject = (stream: Amity.InternalStream): Amity.Stream => {
|
|
4
5
|
return {
|
|
@@ -18,5 +19,8 @@ export const streamLinkedObject = (stream: Amity.InternalStream): Amity.Stream =
|
|
|
18
19
|
get user() {
|
|
19
20
|
return pullFromCache<Amity.User>(['user', 'get', stream.userId])?.data;
|
|
20
21
|
},
|
|
22
|
+
getLiveChat: () => _getLiveChat(stream),
|
|
23
|
+
isBanned: !stream.watcherUrl,
|
|
24
|
+
watcherUrl: null,
|
|
21
25
|
};
|
|
22
26
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export function isAmityImagePost(post
|
|
1
|
+
export function isAmityImagePost(post?: Amity.InternalPost): post is Amity.Post<'image'> {
|
|
2
2
|
return !!(
|
|
3
|
+
post &&
|
|
3
4
|
post.data &&
|
|
4
5
|
typeof post.data !== 'string' &&
|
|
5
6
|
'fileId' in post.data &&
|
|
@@ -7,8 +8,9 @@ export function isAmityImagePost(post: Amity.InternalPost): post is Amity.Post<'
|
|
|
7
8
|
);
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
export function isAmityFilePost(post
|
|
11
|
+
export function isAmityFilePost(post?: Amity.InternalPost): post is Amity.Post<'file'> {
|
|
11
12
|
return !!(
|
|
13
|
+
post &&
|
|
12
14
|
post.data &&
|
|
13
15
|
typeof post.data !== 'string' &&
|
|
14
16
|
'fileId' in post.data &&
|
|
@@ -16,8 +18,9 @@ export function isAmityFilePost(post: Amity.InternalPost): post is Amity.Post<'f
|
|
|
16
18
|
);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
export function isAmityVideoPost(post
|
|
21
|
+
export function isAmityVideoPost(post?: Amity.InternalPost): post is Amity.Post<'video'> {
|
|
20
22
|
return !!(
|
|
23
|
+
post &&
|
|
21
24
|
post.data &&
|
|
22
25
|
typeof post.data !== 'string' &&
|
|
23
26
|
'videoFileId' in post.data &&
|
|
@@ -26,12 +29,22 @@ export function isAmityVideoPost(post: Amity.InternalPost): post is Amity.Post<'
|
|
|
26
29
|
);
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
export function
|
|
32
|
+
export function isAmityLivestreamPost(post?: Amity.InternalPost): post is Amity.Post<'liveStream'> {
|
|
30
33
|
return !!(
|
|
34
|
+
post &&
|
|
31
35
|
post.data &&
|
|
32
36
|
typeof post.data !== 'string' &&
|
|
33
|
-
'
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
'streamId' in post.data &&
|
|
38
|
+
post.dataType === 'liveStream'
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function isAmityPollPost(post?: Amity.InternalPost): post is Amity.Post<'poll'> {
|
|
43
|
+
return !!(
|
|
44
|
+
post &&
|
|
45
|
+
post.data &&
|
|
46
|
+
typeof post.data !== 'string' &&
|
|
47
|
+
'pollId' in post.data &&
|
|
48
|
+
post.dataType === 'poll'
|
|
36
49
|
);
|
|
37
50
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"onChannelMuted.d.ts","sourceRoot":"","sources":["../../../src/channelRepository/events/onChannelMuted.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,cAAc,aAAc,MAAM,QAAQ,CAAC,MAAM,qBAAqB,CAAC,eAgBnF,CAAC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ```js
|
|
3
|
-
* import { FileRepository } from '@amityco/ts-sdk'
|
|
4
|
-
* const created = await FileRepository.uploadClip(formData)
|
|
5
|
-
* ```
|
|
6
|
-
*
|
|
7
|
-
* Creates an {@link Amity.File}
|
|
8
|
-
*
|
|
9
|
-
* @param formData The data necessary to create a new {@link Amity.File}
|
|
10
|
-
* @param onProgress The callback to track the upload progress
|
|
11
|
-
* @returns The newly created {@link Amity.File}
|
|
12
|
-
*
|
|
13
|
-
* @category File API
|
|
14
|
-
* @async
|
|
15
|
-
*/
|
|
16
|
-
export declare const uploadClip: (formData: FormData, feedType?: Amity.ContentFeedType, onProgress?: ((percent: number) => void) | undefined) => Promise<Amity.Cached<Amity.File<'clip'>[]>>;
|
|
17
|
-
//# sourceMappingURL=uploadClip.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"uploadClip.d.ts","sourceRoot":"","sources":["../../../src/fileRepository/api/uploadClip.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,UAAU,aACX,QAAQ,aACP,MAAM,eAAe,0BACT,MAAM,KAAK,IAAI,kBACrC,QAAQ,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CA2C5C,CAAC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ```js
|
|
3
|
-
* import { PostRepository } from '@amityco/ts-sdk'
|
|
4
|
-
* const created = await PostRepository.createClipPost({
|
|
5
|
-
* targetType: 'user',
|
|
6
|
-
* targetId: 'foobar',
|
|
7
|
-
* dataType: 'clip',
|
|
8
|
-
* data: { text: 'hello world' },
|
|
9
|
-
* attachments: [{ type: 'clip', fileId: 'fileId123', displayMode: 'fill', isMuted: false }]
|
|
10
|
-
* }))
|
|
11
|
-
* ```
|
|
12
|
-
*
|
|
13
|
-
* Creates an {@link Amity.Post}
|
|
14
|
-
*
|
|
15
|
-
* @param bundle The data necessary to create a new {@link Amity.Post}
|
|
16
|
-
* @returns The newly created {@link Amity.Post}
|
|
17
|
-
*
|
|
18
|
-
* @category Post API
|
|
19
|
-
* @async
|
|
20
|
-
*/
|
|
21
|
-
export declare const createClipPost: <T extends string>(bundle: Pick<Amity.Post<T>, "targetType" | "targetId"> & Partial<Pick<Amity.Post<T>, "metadata" | "tags" | "mentionees">> & {
|
|
22
|
-
data: {
|
|
23
|
-
[k: string]: any;
|
|
24
|
-
};
|
|
25
|
-
attachments: {
|
|
26
|
-
type: T;
|
|
27
|
-
fileId: Amity.File['fileId'];
|
|
28
|
-
displayMode?: Amity.ClipDisplayMode | undefined;
|
|
29
|
-
isMuted?: boolean | undefined;
|
|
30
|
-
}[];
|
|
31
|
-
}) => Promise<Amity.Cached<Amity.Post>>;
|
|
32
|
-
//# sourceMappingURL=createClipPost.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createClipPost.d.ts","sourceRoot":"","sources":["../../../src/postRepository/api/createClipPost.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,cAAc;;;;;;gBAMX,UAAU,CAAC,QAAQ,CAAC;;;;MAKjC,QAAQ,MAAM,MAAM,CAAC,MAAM,IAAI,CAAC,CAmBlC,CAAC"}
|