mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-27 16:59:39 -05:00
Compare commits
1 Commits
develop-1.
...
1.3.1-Rele
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
407f51fa73 |
@@ -47,23 +47,11 @@ public class TikTokCommentEvent extends TikTokHeaderEvent {
|
||||
|
||||
public TikTokCommentEvent(WebcastChatMessage msg) {
|
||||
super(msg.getCommon());
|
||||
user = User.map(msg.getUser(), msg.getUserIdentity());
|
||||
user = User.map(msg.getUser(),msg.getUserIdentity());
|
||||
text = msg.getContent();
|
||||
visibleToSender = msg.getVisibleToSender();
|
||||
getUserLanguage = msg.getContentLanguage();
|
||||
mentionedUser = User.map(msg.getAtUser());
|
||||
pictures = msg.getEmotesListList().stream().map(e -> Picture.map(e.getEmote().getImage())).toList();
|
||||
}
|
||||
|
||||
|
||||
public static TikTokCommentEvent of(String userName, String message) {
|
||||
var builder = WebcastChatMessage.newBuilder();
|
||||
builder.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
|
||||
.setNickname(userName)
|
||||
.build());
|
||||
builder.setContentLanguage("en");
|
||||
builder.setVisibleToSender(true);
|
||||
builder.setContent(message);
|
||||
return new TikTokCommentEvent(builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,10 @@ import lombok.Getter;
|
||||
*/
|
||||
@Getter
|
||||
@EventMeta(eventType = EventType.Message)
|
||||
public class TikTokSubscribeEvent extends TikTokHeaderEvent {
|
||||
public class TikTokSubscribeEvent extends TikTokHeaderEvent
|
||||
{
|
||||
private final User user;
|
||||
|
||||
|
||||
public TikTokSubscribeEvent(WebcastMemberMessage msg) {
|
||||
super(msg.getCommon());
|
||||
user = User.map(msg.getUser());
|
||||
@@ -52,11 +52,4 @@ public class TikTokSubscribeEvent extends TikTokHeaderEvent {
|
||||
user.addAttribute(UserAttribute.Subscriber);
|
||||
}
|
||||
|
||||
public static TikTokSubscribeEvent of(String userName) {
|
||||
return new TikTokSubscribeEvent(WebcastMemberMessage.newBuilder()
|
||||
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
|
||||
.setNickname(userName)
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
package io.github.jwdeveloper.tiktok.data.events.gift;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.annotations.*;
|
||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||
import io.github.jwdeveloper.tiktok.data.models.gifts.*;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||
@@ -33,7 +32,7 @@ import lombok.Getter;
|
||||
/**
|
||||
* Triggered every time gift is sent
|
||||
*
|
||||
* @see GiftComboStateType it has 3 states
|
||||
* @see GiftSendType it has 3 states
|
||||
*
|
||||
* <p>Example when user sends gift with combo</p>
|
||||
* <p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
||||
@@ -46,21 +45,10 @@ import lombok.Getter;
|
||||
@EventMeta(eventType = EventType.Message)
|
||||
@Getter
|
||||
public class TikTokGiftComboEvent extends TikTokGiftEvent {
|
||||
private final GiftComboStateType comboState;
|
||||
private final GiftSendType comboState;
|
||||
|
||||
public TikTokGiftComboEvent(Gift gift, User host, WebcastGiftMessage msg, GiftComboStateType comboState) {
|
||||
public TikTokGiftComboEvent(Gift gift, User host, WebcastGiftMessage msg, GiftSendType comboState) {
|
||||
super(gift, host, msg);
|
||||
this.comboState = comboState;
|
||||
}
|
||||
|
||||
public static TikTokGiftComboEvent of(Gift gift, int combo, GiftComboStateType comboState) {
|
||||
return new TikTokGiftComboEvent(
|
||||
gift,
|
||||
new User(0L, "Test", new Picture("")),
|
||||
WebcastGiftMessage
|
||||
.newBuilder()
|
||||
.setComboCount(combo)
|
||||
.build(),
|
||||
comboState);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ package io.github.jwdeveloper.tiktok.data.events.gift;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.annotations.*;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||
import io.github.jwdeveloper.tiktok.data.models.gifts.*;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||
@@ -56,20 +55,4 @@ public class TikTokGiftEvent extends TikTokHeaderEvent {
|
||||
}
|
||||
combo = msg.getComboCount();
|
||||
}
|
||||
|
||||
public TikTokGiftEvent(Gift gift) {
|
||||
this.gift = gift;
|
||||
user = new User(0L, "sender", new Picture(""));
|
||||
toUser = new User(0L, "receiver", new Picture(""));
|
||||
combo = 1;
|
||||
}
|
||||
|
||||
|
||||
public static TikTokGiftEvent of(Gift gift) {
|
||||
return new TikTokGiftEvent(gift);
|
||||
}
|
||||
|
||||
public static TikTokGiftEvent of(String name, int id, int diamonds) {
|
||||
return TikTokGiftEvent.of(new Gift(id, name, diamonds, ""));
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,8 @@ package io.github.jwdeveloper.tiktok.data.events.social;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage;
|
||||
import lombok.Value;
|
||||
|
||||
@@ -47,12 +45,4 @@ public class TikTokFollowEvent extends TikTokHeaderEvent
|
||||
totalFollowers = msg.getFollowCount();
|
||||
}
|
||||
|
||||
public static TikTokFollowEvent of(String userName)
|
||||
{
|
||||
return new TikTokFollowEvent(WebcastSocialMessage.newBuilder()
|
||||
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
|
||||
.setNickname(userName)
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage;
|
||||
import lombok.Getter;
|
||||
@@ -48,13 +47,4 @@ public class TikTokJoinEvent extends TikTokHeaderEvent {
|
||||
user = User.map(msg.getUser());
|
||||
totalUsers = msg.getMemberCount();
|
||||
}
|
||||
|
||||
public static TikTokJoinEvent of(String userName)
|
||||
{
|
||||
return new TikTokJoinEvent(WebcastMemberMessage.newBuilder()
|
||||
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
|
||||
.setNickname(userName)
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,15 +57,4 @@ public class TikTokLikeEvent extends TikTokHeaderEvent
|
||||
likes = msg.getCount();
|
||||
totalLikes = msg.getTotal();
|
||||
}
|
||||
|
||||
public static TikTokLikeEvent of(String userName, int likes)
|
||||
{
|
||||
return new TikTokLikeEvent(WebcastLikeMessage.newBuilder()
|
||||
.setCount(likes)
|
||||
.setTotal(likes)
|
||||
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
|
||||
.setNickname(userName)
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,16 +22,17 @@
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.data.models.gifts;
|
||||
|
||||
//TODO it should be called GiftComboStateType
|
||||
public enum GiftComboStateType {
|
||||
public enum GiftSendType
|
||||
{
|
||||
Finished,
|
||||
Begin,
|
||||
Active;
|
||||
|
||||
public static GiftComboStateType fromNumber(long number) {
|
||||
public static GiftSendType fromNumber(long number)
|
||||
{
|
||||
return switch ((int) number) {
|
||||
case 1, 2, 4 -> GiftComboStateType.Active;
|
||||
default -> GiftComboStateType.Finished;
|
||||
case 1, 2, 4 -> GiftSendType.Active;
|
||||
default -> GiftSendType.Finished;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,6 @@ public class LiveData {
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public static class Response {
|
||||
private String json;
|
||||
private LiveStatus liveStatus;
|
||||
@@ -46,11 +45,6 @@ public class LiveData {
|
||||
private boolean ageRestricted;
|
||||
private User host;
|
||||
private LiveType liveType;
|
||||
public Response() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public enum LiveStatus {
|
||||
|
||||
@@ -35,20 +35,10 @@ public class LiveClientSettings {
|
||||
|
||||
|
||||
/**
|
||||
* TODO: give better description
|
||||
* <p>
|
||||
* sets client in the offline mode, so it do not connects to TikTok servers
|
||||
* it makes sense to use it when you are testing client with your custom events
|
||||
*/
|
||||
private boolean offline;
|
||||
|
||||
/**
|
||||
* TODO: give better description
|
||||
* <p>
|
||||
* Determines if gifts data is downloaded before TikTokLive starts,
|
||||
* when `false` then client.giftManager() does not contain initial gifts
|
||||
*/
|
||||
private boolean fetchGifts = true;
|
||||
private boolean fetchGifts;
|
||||
|
||||
/**
|
||||
* ISO-Language for Client
|
||||
@@ -86,13 +76,14 @@ public class LiveClientSettings {
|
||||
private HttpClientSettings httpSettings;
|
||||
|
||||
/**
|
||||
* Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
|
||||
* documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages
|
||||
* Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
|
||||
* documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages
|
||||
*/
|
||||
private String sessionId;
|
||||
|
||||
/**
|
||||
* Optional: By default roomID is fetched before connect to live, but you can set it manually
|
||||
*
|
||||
*/
|
||||
private String roomId;
|
||||
|
||||
@@ -101,7 +92,8 @@ public class LiveClientSettings {
|
||||
*/
|
||||
private String apiKey;
|
||||
|
||||
public static LiveClientSettings createDefault() {
|
||||
public static LiveClientSettings createDefault()
|
||||
{
|
||||
var httpSettings = new HttpClientSettings();
|
||||
httpSettings.getParams().putAll(DefaultClientParams());
|
||||
httpSettings.getHeaders().putAll(DefaultRequestHeaders());
|
||||
@@ -174,6 +166,4 @@ public class LiveClientSettings {
|
||||
headers.put("Accept-Language", "en-US,en; q=0.9");
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -61,8 +61,6 @@ public interface LiveClient {
|
||||
*/
|
||||
void publishEvent(TikTokEvent event);
|
||||
|
||||
void publishMessage(String base64);
|
||||
|
||||
/**
|
||||
* Get information about gifts
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,6 @@ import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.LiveData;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.*;
|
||||
import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
|
||||
import io.github.jwdeveloper.tiktok.listener.ListenersManager;
|
||||
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
||||
import io.github.jwdeveloper.tiktok.live.GiftsManager;
|
||||
@@ -49,7 +48,7 @@ import java.util.logging.Logger;
|
||||
|
||||
public class TikTokLiveClient implements LiveClient {
|
||||
private final TikTokRoomInfo liveRoomInfo;
|
||||
private final LiveHttpClient httpClient;
|
||||
private final TikTokLiveHttpClient httpClient;
|
||||
private final SocketClient webSocketClient;
|
||||
private final TikTokLiveEventHandler tikTokEventHandler;
|
||||
private final LiveClientSettings clientSettings;
|
||||
@@ -59,7 +58,7 @@ public class TikTokLiveClient implements LiveClient {
|
||||
|
||||
public TikTokLiveClient(GiftsManager giftsManager,
|
||||
TikTokRoomInfo tikTokLiveMeta,
|
||||
LiveHttpClient tiktokHttpClient,
|
||||
TikTokLiveHttpClient tiktokHttpClient,
|
||||
SocketClient webSocketClient,
|
||||
TikTokLiveEventHandler tikTokEventHandler,
|
||||
LiveClientSettings clientSettings,
|
||||
|
||||
@@ -45,7 +45,6 @@ import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||
import io.github.jwdeveloper.tiktok.mappers.handlers.*;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.*;
|
||||
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient;
|
||||
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketOfflineClient;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -55,7 +54,7 @@ import java.util.logging.Logger;
|
||||
public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
|
||||
protected final LiveClientSettings clientSettings;
|
||||
protected final TikTokLiveEventHandler eventHandler;
|
||||
protected final TikTokLiveEventHandler tikTokEventHandler;
|
||||
protected final List<TikTokEventListener> listeners;
|
||||
protected Consumer<TikTokMapper> onCustomMappings;
|
||||
protected Logger logger;
|
||||
@@ -64,7 +63,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
public TikTokLiveClientBuilder(String userName) {
|
||||
this.clientSettings = LiveClientSettings.createDefault();
|
||||
this.clientSettings.setHostName(userName);
|
||||
this.eventHandler = new TikTokLiveEventHandler();
|
||||
this.tikTokEventHandler = new TikTokLiveEventHandler();
|
||||
this.listeners = new ArrayList<>();
|
||||
this.onCustomMappings = (e) -> {
|
||||
};
|
||||
@@ -110,30 +109,27 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
var tiktokRoomInfo = new TikTokRoomInfo();
|
||||
tiktokRoomInfo.setHostName(clientSettings.getHostName());
|
||||
|
||||
var listenerManager = new TikTokListenersManager(listeners, eventHandler);
|
||||
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
||||
|
||||
var httpClientFactory = new HttpClientFactory(clientSettings);
|
||||
var tikTokLiveHttpClient = new TikTokLiveHttpClient(httpClientFactory, clientSettings);
|
||||
|
||||
var liveHttpClient = clientSettings.isOffline() ?
|
||||
new TikTokLiveHttpOfflineClient() :
|
||||
new TikTokLiveHttpClient(httpClientFactory, clientSettings);
|
||||
|
||||
var eventsMapper = createMapper(giftsManager, tiktokRoomInfo);
|
||||
var messageHandler = new TikTokLiveMessageHandler(eventHandler, eventsMapper);
|
||||
var messageHandler = new TikTokLiveMessageHandler(tikTokEventHandler, eventsMapper);
|
||||
|
||||
var webSocketClient = clientSettings.isOffline() ?
|
||||
new TikTokWebSocketOfflineClient(eventHandler) :
|
||||
new TikTokWebSocketClient(
|
||||
clientSettings,
|
||||
messageHandler,
|
||||
eventHandler);
|
||||
|
||||
var webSocketClient = new TikTokWebSocketClient(
|
||||
clientSettings,
|
||||
messageHandler,
|
||||
tikTokEventHandler);
|
||||
|
||||
return new TikTokLiveClient(
|
||||
giftsManager,
|
||||
tiktokRoomInfo,
|
||||
liveHttpClient,
|
||||
tikTokLiveHttpClient,
|
||||
webSocketClient,
|
||||
eventHandler,
|
||||
tikTokEventHandler,
|
||||
clientSettings,
|
||||
listenerManager,
|
||||
logger);
|
||||
@@ -239,255 +235,255 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onUnhandledSocial(EventConsumer<TikTokUnhandledSocialEvent> event) {
|
||||
eventHandler.subscribe(TikTokUnhandledSocialEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokUnhandledSocialEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LiveClientBuilder onChest(EventConsumer<TikTokChestEvent> event) {
|
||||
eventHandler.subscribe(TikTokChestEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokChestEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLinkMicFanTicket(EventConsumer<TikTokLinkMicFanTicketEvent> event) {
|
||||
eventHandler.subscribe(TikTokLinkMicFanTicketEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLinkMicFanTicketEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onEnvelope(EventConsumer<TikTokEnvelopeEvent> event) {
|
||||
eventHandler.subscribe(TikTokEnvelopeEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokEnvelopeEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onShop(EventConsumer<TikTokShopEvent> event) {
|
||||
eventHandler.subscribe(TikTokShopEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokShopEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onDetect(EventConsumer<TikTokDetectEvent> event) {
|
||||
eventHandler.subscribe(TikTokDetectEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokDetectEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLinkLayer(EventConsumer<TikTokLinkLayerEvent> event) {
|
||||
eventHandler.subscribe(TikTokLinkLayerEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLinkLayerEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onConnected(EventConsumer<TikTokConnectedEvent> event) {
|
||||
eventHandler.subscribe(TikTokConnectedEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokConnectedEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onPreConnection(EventConsumer<TikTokPreConnectionEvent> event) {
|
||||
eventHandler.subscribe(TikTokPreConnectionEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokPreConnectionEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onCaption(EventConsumer<TikTokCaptionEvent> event) {
|
||||
eventHandler.subscribe(TikTokCaptionEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokCaptionEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onQuestion(EventConsumer<TikTokQuestionEvent> event) {
|
||||
eventHandler.subscribe(TikTokQuestionEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokQuestionEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onRoomPin(EventConsumer<TikTokRoomPinEvent> event) {
|
||||
eventHandler.subscribe(TikTokRoomPinEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokRoomPinEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends TikTokEvent> LiveClientBuilder onEvent(Class<E> eventClass, EventConsumer<E> event) {
|
||||
eventHandler.subscribe(eventClass, event);
|
||||
tikTokEventHandler.subscribe(eventClass, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokLiveClientBuilder onRoomInfo(EventConsumer<TikTokRoomInfoEvent> event) {
|
||||
eventHandler.subscribe(TikTokRoomInfoEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokRoomInfoEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLivePaused(EventConsumer<TikTokLivePausedEvent> event) {
|
||||
eventHandler.subscribe(TikTokLivePausedEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLivePausedEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokLiveClientBuilder onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> event) {
|
||||
eventHandler.subscribe(TikTokLiveUnpausedEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLiveUnpausedEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLike(EventConsumer<TikTokLikeEvent> event) {
|
||||
eventHandler.subscribe(TikTokLikeEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLikeEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLink(EventConsumer<TikTokLinkEvent> event) {
|
||||
eventHandler.subscribe(TikTokLinkEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLinkEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onBarrage(EventConsumer<TikTokBarrageEvent> event) {
|
||||
eventHandler.subscribe(TikTokBarrageEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokBarrageEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onGift(EventConsumer<TikTokGiftEvent> event) {
|
||||
eventHandler.subscribe(TikTokGiftEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokGiftEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onGiftCombo(EventConsumer<TikTokGiftComboEvent> event) {
|
||||
eventHandler.subscribe(TikTokGiftComboEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokGiftComboEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLinkMicArmies(EventConsumer<TikTokLinkMicArmiesEvent> event) {
|
||||
eventHandler.subscribe(TikTokLinkMicArmiesEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLinkMicArmiesEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onEmote(EventConsumer<TikTokEmoteEvent> event) {
|
||||
eventHandler.subscribe(TikTokEmoteEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokEmoteEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onUnauthorizedMember(EventConsumer<TikTokUnauthorizedMemberEvent> event) {
|
||||
eventHandler.subscribe(TikTokUnauthorizedMemberEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokUnauthorizedMemberEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onInRoomBanner(EventConsumer<TikTokInRoomBannerEvent> event) {
|
||||
eventHandler.subscribe(TikTokInRoomBannerEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokInRoomBannerEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLinkMicMethod(EventConsumer<TikTokLinkMicMethodEvent> event) {
|
||||
eventHandler.subscribe(TikTokLinkMicMethodEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLinkMicMethodEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onSubscribe(EventConsumer<TikTokSubscribeEvent> event) {
|
||||
eventHandler.subscribe(TikTokSubscribeEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokSubscribeEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onPoll(EventConsumer<TikTokPollEvent> event) {
|
||||
eventHandler.subscribe(TikTokPollEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokPollEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onFollow(EventConsumer<TikTokFollowEvent> event) {
|
||||
eventHandler.subscribe(TikTokFollowEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokFollowEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onComment(EventConsumer<TikTokCommentEvent> event) {
|
||||
eventHandler.subscribe(TikTokCommentEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokCommentEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveClientBuilder onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action) {
|
||||
eventHandler.subscribe(TikTokHttpResponseEvent.class, action);
|
||||
tikTokEventHandler.subscribe(TikTokHttpResponseEvent.class, action);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onGoalUpdate(EventConsumer<TikTokGoalUpdateEvent> event) {
|
||||
eventHandler.subscribe(TikTokGoalUpdateEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokGoalUpdateEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onRankUpdate(EventConsumer<TikTokRankUpdateEvent> event) {
|
||||
eventHandler.subscribe(TikTokRankUpdateEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokRankUpdateEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onIMDelete(EventConsumer<TikTokIMDeleteEvent> event) {
|
||||
eventHandler.subscribe(TikTokIMDeleteEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokIMDeleteEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLiveEnded(EventConsumer<TikTokLiveEndedEvent> event) {
|
||||
eventHandler.subscribe(TikTokLiveEndedEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLiveEndedEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onError(EventConsumer<TikTokErrorEvent> event) {
|
||||
eventHandler.subscribe(TikTokErrorEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokErrorEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onJoin(EventConsumer<TikTokJoinEvent> event) {
|
||||
eventHandler.subscribe(TikTokJoinEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokJoinEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onRankText(EventConsumer<TikTokRankTextEvent> event) {
|
||||
eventHandler.subscribe(TikTokRankTextEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokRankTextEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onShare(EventConsumer<TikTokShareEvent> event) {
|
||||
eventHandler.subscribe(TikTokShareEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokShareEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onUnhandledMember(EventConsumer<TikTokUnhandledMemberEvent> event) {
|
||||
eventHandler.subscribe(TikTokUnhandledMemberEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokUnhandledMemberEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onSubNotify(EventConsumer<TikTokSubNotifyEvent> event) {
|
||||
eventHandler.subscribe(TikTokSubNotifyEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokSubNotifyEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLinkMicBattle(EventConsumer<TikTokLinkMicBattleEvent> event) {
|
||||
eventHandler.subscribe(TikTokLinkMicBattleEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokLinkMicBattleEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onDisconnected(EventConsumer<TikTokDisconnectedEvent> event) {
|
||||
eventHandler.subscribe(TikTokDisconnectedEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokDisconnectedEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onUnhandledControl(EventConsumer<TikTokUnhandledControlEvent> event) {
|
||||
eventHandler.subscribe(TikTokUnhandledControlEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokUnhandledControlEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onEvent(EventConsumer<TikTokEvent> event) {
|
||||
eventHandler.subscribe(TikTokEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokLiveClientBuilder onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> event) {
|
||||
eventHandler.subscribe(TikTokWebsocketResponseEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokWebsocketResponseEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokLiveClientBuilder onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> event) {
|
||||
eventHandler.subscribe(TikTokWebsocketMessageEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokWebsocketMessageEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokLiveClientBuilder onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> event) {
|
||||
eventHandler.subscribe(TikTokWebsocketUnhandledMessageEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokWebsocketUnhandledMessageEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokLiveClientBuilder onReconnecting(EventConsumer<TikTokReconnectingEvent> event) {
|
||||
eventHandler.subscribe(TikTokReconnectingEvent.class, event);
|
||||
tikTokEventHandler.subscribe(TikTokReconnectingEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package io.github.jwdeveloper.tiktok;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.GiftsData;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.LiveData;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
||||
import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
public class TikTokLiveHttpOfflineClient implements LiveHttpClient {
|
||||
@Override
|
||||
public GiftsData.Response fetchGiftsData() {
|
||||
return new GiftsData.Response("", List.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) {
|
||||
return new LiveUserData.Response("", LiveUserData.UserStatus.Live, "offline_room_id", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveData.Response fetchLiveData(LiveData.Request request) {
|
||||
return new LiveData.Response("",
|
||||
LiveData.LiveStatus.HostOnline,
|
||||
"offline live",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
new User(0L, "offline user", new Picture("")),
|
||||
LiveData.LiveType.SOLO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request) {
|
||||
return new LiveConnectionData.Response("",
|
||||
URI.create("https://example.live"),
|
||||
WebcastResponse.newBuilder().build());
|
||||
}
|
||||
}
|
||||
@@ -58,40 +58,40 @@ public class TikTokGiftEventHandler {
|
||||
|
||||
public List<TikTokEvent> handleGift(WebcastGiftMessage currentMessage) {
|
||||
var userId = currentMessage.getUser().getId();
|
||||
var currentType = GiftComboStateType.fromNumber(currentMessage.getSendType());
|
||||
var currentType = GiftSendType.fromNumber(currentMessage.getSendType());
|
||||
var containsPreviousMessage = giftsMessages.containsKey(userId);
|
||||
|
||||
|
||||
//If gift is not streakable just return onGift event
|
||||
if (currentMessage.getGift().getType() != 1) {
|
||||
var comboEvent = getGiftComboEvent(currentMessage, GiftComboStateType.Finished);
|
||||
var comboEvent = getGiftComboEvent(currentMessage, GiftSendType.Finished);
|
||||
var giftEvent = getGiftEvent(currentMessage);
|
||||
return List.of(comboEvent, giftEvent);
|
||||
}
|
||||
|
||||
if (!containsPreviousMessage) {
|
||||
if (currentType == GiftComboStateType.Finished) {
|
||||
if (currentType == GiftSendType.Finished) {
|
||||
return List.of(getGiftEvent(currentMessage));
|
||||
} else {
|
||||
giftsMessages.put(userId, currentMessage);
|
||||
return List.of(getGiftComboEvent(currentMessage, GiftComboStateType.Begin));
|
||||
return List.of(getGiftComboEvent(currentMessage, GiftSendType.Begin));
|
||||
}
|
||||
}
|
||||
|
||||
var previousMessage = giftsMessages.get(userId);
|
||||
var previousType = GiftComboStateType.fromNumber(previousMessage.getSendType());
|
||||
if (currentType == GiftComboStateType.Active &&
|
||||
previousType == GiftComboStateType.Active) {
|
||||
var previousType = GiftSendType.fromNumber(previousMessage.getSendType());
|
||||
if (currentType == GiftSendType.Active &&
|
||||
previousType == GiftSendType.Active) {
|
||||
giftsMessages.put(userId, currentMessage);
|
||||
return List.of(getGiftComboEvent(currentMessage, GiftComboStateType.Active));
|
||||
return List.of(getGiftComboEvent(currentMessage, GiftSendType.Active));
|
||||
}
|
||||
|
||||
|
||||
if (currentType == GiftComboStateType.Finished &&
|
||||
previousType == GiftComboStateType.Active) {
|
||||
if (currentType == GiftSendType.Finished &&
|
||||
previousType == GiftSendType.Active) {
|
||||
giftsMessages.clear();
|
||||
return List.of(
|
||||
getGiftComboEvent(currentMessage, GiftComboStateType.Finished),
|
||||
getGiftComboEvent(currentMessage, GiftSendType.Finished),
|
||||
getGiftEvent(currentMessage));
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public class TikTokGiftEventHandler {
|
||||
return new TikTokGiftEvent(gift, tikTokRoomInfo.getHost(), message);
|
||||
}
|
||||
|
||||
private TikTokGiftEvent getGiftComboEvent(WebcastGiftMessage message, GiftComboStateType state) {
|
||||
private TikTokGiftEvent getGiftComboEvent(WebcastGiftMessage message, GiftSendType state) {
|
||||
var gift = getGiftObject(message);
|
||||
return new TikTokGiftComboEvent(gift, tikTokRoomInfo.getHost(), message, state);
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package io.github.jwdeveloper.tiktok.websocket;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokConnectedEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||
|
||||
public class TikTokWebSocketOfflineClient implements SocketClient {
|
||||
|
||||
private final TikTokLiveEventHandler handler;
|
||||
private LiveClient liveClient;
|
||||
|
||||
public TikTokWebSocketOfflineClient(TikTokLiveEventHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(LiveConnectionData.Response webcastResponse, LiveClient tikTokLiveClient) {
|
||||
liveClient = tikTokLiveClient;
|
||||
handler.publish(liveClient, new TikTokConnectedEvent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (liveClient == null) {
|
||||
return;
|
||||
}
|
||||
handler.publish(liveClient, new TikTokDisconnectedEvent());
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftComboStateType;
|
||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager;
|
||||
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.messages.data.GiftStruct;
|
||||
@@ -40,6 +40,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@@ -98,9 +99,9 @@ class TikTokGiftEventHandlerTest {
|
||||
Assertions.assertEquals(2, result3.size());
|
||||
var event3 = (TikTokGiftComboEvent) result3.get(0);
|
||||
|
||||
Assertions.assertEquals(GiftComboStateType.Begin, event1.getComboState());
|
||||
Assertions.assertEquals(GiftComboStateType.Active, event2.getComboState());
|
||||
Assertions.assertEquals(GiftComboStateType.Finished, event3.getComboState());
|
||||
Assertions.assertEquals(GiftSendType.Begin, event1.getComboState());
|
||||
Assertions.assertEquals(GiftSendType.Active, event2.getComboState());
|
||||
Assertions.assertEquals(GiftSendType.Finished, event3.getComboState());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class ChatMessageExample {
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
var roomData = TikTokLive.requests()
|
||||
.fetchLiveData("X");
|
||||
|
||||
var gifts = TikTokLive.requests().fetchGiftsData();
|
||||
|
||||
|
||||
var user = TikTokLive.requests()
|
||||
.fetchLiveUserData("mark");
|
||||
|
||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||
.configure(clientSettings ->
|
||||
{
|
||||
clientSettings.setPrintToConsole(true);
|
||||
clientSettings.getHttpSettings().setTimeout(Duration.ofSeconds(21));
|
||||
})
|
||||
.onComment((liveClient, event) ->
|
||||
{
|
||||
System.out.println("Chat message: " + event.getUser().getName() + " " + event.getText());
|
||||
})
|
||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info(event.getMessage().getMethod());
|
||||
}).buildAndConnect();
|
||||
}
|
||||
}
|
||||
@@ -40,11 +40,12 @@ public class CollectorExample {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
var collector = TikTokLiveCollector.useMongo(settings ->
|
||||
var collector = TikTokLiveCollector.use(settings ->
|
||||
{
|
||||
settings.setConnectionUrl("mongodb+srv://" + mongoUser + ":" + mongoPassword + "@" + mongoDatabase + "/?retryWrites=true&w=majority");
|
||||
settings.setDatabaseName("tiktok");
|
||||
});
|
||||
collector.connect();
|
||||
collector.connectDatabase();
|
||||
|
||||
var users = List.of("tehila_723", "dino123597", "domaxyzx", "dash4214", "obserwacje_live");
|
||||
Map<String, Object> additionalDataFields = Map.of("sessionTag", "ExampleTag");
|
||||
@@ -70,6 +71,6 @@ public class CollectorExample {
|
||||
}
|
||||
|
||||
System.in.read();
|
||||
collector.disconnect();
|
||||
collector.disconnectDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class CustomEventExample {
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
TikTokLive.newClient(ConnectionExample.TIKTOK_HOSTNAME)
|
||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||
.configure(clientSettings ->
|
||||
{
|
||||
clientSettings.setPrintToConsole(true);
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
package io.github.jwdeveloper.tiktok;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokSubNotifyEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokFollowEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftComboStateType;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||
|
||||
public class Events_And_Gifts_Testing_Example {
|
||||
public static void main(String[] args) {
|
||||
LiveClient client = TikTokLive.newClient(ConnectionExample.TIKTOK_HOSTNAME)
|
||||
.configure(liveClientSettings ->
|
||||
{
|
||||
liveClientSettings.setOffline(true);
|
||||
liveClientSettings.setPrintToConsole(true);
|
||||
})
|
||||
.onConnected((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("Connected");
|
||||
})
|
||||
.onDisconnected((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("Disconnected");
|
||||
})
|
||||
.onGiftCombo((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("New fake combo Gift: " + event.getGift());
|
||||
})
|
||||
.onGift((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("New fake Gift: " + event.getGift());
|
||||
})
|
||||
.build();
|
||||
|
||||
var gifts = TikTokLive.gifts();
|
||||
var roseGift = gifts.getByName("Rose");
|
||||
|
||||
var fakeGift = TikTokGiftEvent.of(roseGift);
|
||||
var fakeComboGift = TikTokGiftComboEvent.of(roseGift, 12, GiftComboStateType.Begin);
|
||||
|
||||
var fakeMessage = TikTokCommentEvent.of("Mark", "Hello world");
|
||||
|
||||
var fakeSubscriber = TikTokSubscribeEvent.of("Mark");
|
||||
var fakeFollow = TikTokFollowEvent.of("Mark");
|
||||
var fakeLike = TikTokLikeEvent.of("Mark", 12);
|
||||
var fakeJoin = TikTokJoinEvent.of("Mark");
|
||||
|
||||
client.connect();
|
||||
|
||||
client.publishEvent(fakeGift);
|
||||
client.publishEvent(fakeComboGift);
|
||||
client.publishEvent(fakeMessage);
|
||||
client.publishEvent(fakeSubscriber);
|
||||
client.publishEvent(fakeFollow);
|
||||
client.publishEvent(fakeLike);
|
||||
client.publishEvent(fakeJoin);
|
||||
|
||||
client.disconnect();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class ListenerExample
|
||||
showLogo();
|
||||
CustomListener customListener = new CustomListener();
|
||||
|
||||
TikTokLive.newClient(ConnectionExample.TIKTOK_HOSTNAME)
|
||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||
.addListener(customListener)
|
||||
.buildAndConnect();
|
||||
System.in.read();
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.net.Proxy;
|
||||
|
||||
public class ProxyExample {
|
||||
public static void main(String[] args) throws Exception {
|
||||
TikTokLive.newClient(ConnectionExample.TIKTOK_HOSTNAME)
|
||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||
.configure(clientSettings -> {
|
||||
clientSettings.setPrintToConsole(true);
|
||||
clientSettings.getHttpSettings().configureProxy(proxySettings -> {
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class ConnectionExample {
|
||||
public class SimpleExample {
|
||||
public static String TIKTOK_HOSTNAME = "kvadromama_marina1";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
@@ -40,10 +40,10 @@ public class ConnectionExample {
|
||||
|
||||
var gifts = TikTokLive.gifts();
|
||||
|
||||
TikTokLive.newClient(ConnectionExample.TIKTOK_HOSTNAME)
|
||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||
.configure(clientSettings ->
|
||||
{
|
||||
clientSettings.setHostName(ConnectionExample.TIKTOK_HOSTNAME); // This method is useful in case you want change hostname later
|
||||
clientSettings.setHostName(SimpleExample.TIKTOK_HOSTNAME); // This method is useful in case you want change hostname later
|
||||
clientSettings.setClientLanguage("en"); // Language
|
||||
clientSettings.setLogLevel(Level.ALL); // Log level
|
||||
clientSettings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF
|
||||
62
Tools-EventsCollector/pom.xml
Normal file
62
Tools-EventsCollector/pom.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>TikTokLiveJava</artifactId>
|
||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||
<version>1.3.0-Release</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>Tools-EventsCollector</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
<maven.compiler.target>16</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.34.0</version> <!-- Use the latest version available -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jdbi</groupId>
|
||||
<artifactId>jdbi3-core</artifactId>
|
||||
<version>3.23.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.googlecode.protobuf-java-format</groupId>
|
||||
<artifactId>protobuf-java-format</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jdbi</groupId>
|
||||
<artifactId>jdbi3-sqlobject</artifactId>
|
||||
<version>3.23.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.32</version> <!-- Use the latest version available -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||
<artifactId>Client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||
<artifactId>Tools-ReadmeGenerator</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokDataCollectorBuilder;
|
||||
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollectorBuilder;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.TikTokDataTesterBuilder;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTesterBuilder;
|
||||
|
||||
public class TikTokLiveTools
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param databaseName dataCollector use sql-lite database to store message
|
||||
* if database not exits it creates new one
|
||||
* @return
|
||||
*/
|
||||
public static DataCollectorBuilder createCollector(String databaseName)
|
||||
{
|
||||
return new TikTokDataCollectorBuilder(databaseName);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param databaseName dataTester will read messages for database
|
||||
* before using dataTester, use dataCollector to create database
|
||||
* if database not exits exception will be thrown
|
||||
* @return
|
||||
*/
|
||||
public static DataTesterBuilder createTester(String databaseName)
|
||||
{
|
||||
return new TikTokDataTesterBuilder(databaseName);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns browser application that collects and display Events, Messages, WebcastResponses
|
||||
* in online web editor so it's easier to read and analyze data structures
|
||||
* @return
|
||||
*/
|
||||
public static void createWebViewer()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.collector.api;
|
||||
|
||||
public interface DataCollector {
|
||||
|
||||
void connect();
|
||||
|
||||
|
||||
void disconnect();
|
||||
|
||||
void disconnect(boolean keepDatabase);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.collector.api;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface DataCollectorBuilder extends DataFilters<DataCollectorBuilder> {
|
||||
DataCollectorBuilder setOutputPath(String path);
|
||||
DataCollectorBuilder setSessionTag(String sessionTimestamp);
|
||||
|
||||
DataCollectorBuilder setDatabase(TikTokDatabase database);
|
||||
|
||||
DataCollectorBuilder configureLiveClient(Consumer<LiveClientBuilder> consumer);
|
||||
|
||||
DataCollectorBuilder addUser(String user);
|
||||
|
||||
DataCollector buildAndRun();
|
||||
|
||||
DataCollector build();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.collector.api;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
|
||||
public interface DataFilters<T> {
|
||||
T addMessageFilter(Class<? extends com.google.protobuf.GeneratedMessageV3> message);
|
||||
|
||||
T addMessageFilter(String message);
|
||||
|
||||
T addEventFilter(Class<? extends TikTokEvent> event);
|
||||
|
||||
T addEventFilter(String event);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.collector.api;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Data
|
||||
public class TikTokDataCollectorModel {
|
||||
private List<String> users;
|
||||
private String outputPath;
|
||||
private String outputName;
|
||||
private Set<String> eventsFilter;
|
||||
private Set<String> messagesFilter;
|
||||
private String sessionTag ="";
|
||||
private Consumer<LiveClientBuilder> onConfigureLiveClient;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.github.jwdeveloper.tiktok.FilesUtility;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MessagesManager {
|
||||
|
||||
@Getter
|
||||
Map<String, Queue<MessageData>> messages;
|
||||
String outputName;
|
||||
|
||||
int limit = 20;
|
||||
public MessagesManager(String outputName) {
|
||||
this.messages = new TreeMap<>();
|
||||
this.outputName = outputName;
|
||||
load();
|
||||
}
|
||||
|
||||
public void addMessage(Logger logger, String host, WebcastResponse.Message message) {
|
||||
var name = message.getMethod();
|
||||
var payload = message.getPayload().toByteArray();
|
||||
var base64 = Base64.getEncoder().encodeToString(payload);
|
||||
|
||||
if (!messages.containsKey(name)) {
|
||||
logger.info("New Message found! " + name);
|
||||
messages.put(name, new LinkedList<>());
|
||||
}
|
||||
|
||||
var queue = messages.get(name);
|
||||
if (queue.size() > limit) {
|
||||
queue.remove();
|
||||
}
|
||||
|
||||
queue.add(new MessageData(base64, host, LocalDateTime.now().toString()));
|
||||
save();
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
return JsonUtil.toJson(messages);
|
||||
}
|
||||
|
||||
public void load() {
|
||||
var file = new File(path());
|
||||
Type type = new TypeToken<Map<String, Queue<MessageData>>>() {}.getType();
|
||||
|
||||
if (file.exists()) {
|
||||
var content = FilesUtility.loadFileContent(path());
|
||||
var gson = new GsonBuilder().create();
|
||||
messages = gson.fromJson(content,type);
|
||||
}
|
||||
}
|
||||
|
||||
public void save() {
|
||||
|
||||
FilesUtility.saveFile(path(), toJson());
|
||||
}
|
||||
|
||||
public String path() {
|
||||
return Paths.get("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\Tools-EventsCollector\\src\\main\\resources", outputName + ".json").toString();
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class MessageData {
|
||||
String eventData;
|
||||
String uniqueId;
|
||||
String ts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||
|
||||
public class TikTokClientFactory {
|
||||
private final MessagesManager messageCollector;
|
||||
private final TikTokDatabase tikTokDatabase;
|
||||
|
||||
public TikTokClientFactory(MessagesManager messageCollector, TikTokDatabase tikTokDatabase) {
|
||||
this.messageCollector = messageCollector;
|
||||
this.tikTokDatabase = tikTokDatabase;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.TikTokLive;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketMessageEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollector;
|
||||
import io.github.jwdeveloper.tiktok.tools.collector.api.TikTokDataCollectorModel;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.ExceptionInfoModel;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokErrorModel;
|
||||
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
public class TikTokDataCollector implements DataCollector {
|
||||
private final TikTokDataCollectorModel dataCollectorModel;
|
||||
private final TikTokDatabase tikTokDatabase;
|
||||
private final List<LiveClient> tiktokClients;
|
||||
|
||||
public TikTokDataCollector(TikTokDataCollectorModel dataCollectorModel, TikTokDatabase tikTokDatabase) {
|
||||
this.dataCollectorModel = dataCollectorModel;
|
||||
this.tikTokDatabase = tikTokDatabase;
|
||||
this.tiktokClients = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
try {
|
||||
if (!tikTokDatabase.isConnected()) {
|
||||
tikTokDatabase.connect();
|
||||
}
|
||||
for (var user : dataCollectorModel.getUsers()) {
|
||||
var client = createLiveClient(user);
|
||||
tiktokClients.add(client);
|
||||
client.connectAsync();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to start tiktok connector", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void disconnect() {
|
||||
disconnect(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(boolean keepDatabase) {
|
||||
try {
|
||||
for (var client : tiktokClients) {
|
||||
client.disconnect();
|
||||
}
|
||||
if (!keepDatabase) {
|
||||
tikTokDatabase.close();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to stop tiktok connector", e);
|
||||
}
|
||||
}
|
||||
|
||||
public LiveClient createLiveClient(String tiktokUser) {
|
||||
var builder = TikTokLive.newClient(tiktokUser);
|
||||
builder.onConnected((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("Connected to " + liveClient.getRoomInfo().getHostName());
|
||||
})
|
||||
.onDisconnected((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("Disconnected " + liveClient.getRoomInfo().getHostName());
|
||||
})
|
||||
.onWebsocketResponse(this::handleResponseAndMessages)
|
||||
.onWebsocketMessage(this::handleMappedEvent)
|
||||
.onHttpResponse((liveClient, event) ->
|
||||
{
|
||||
var data = createHttpResponseData(event, tiktokUser);
|
||||
tikTokDatabase.insertData(data);
|
||||
})
|
||||
.onError(this::handleError);
|
||||
dataCollectorModel.getOnConfigureLiveClient().accept(builder);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void handleResponseAndMessages(LiveClient client, TikTokWebsocketResponseEvent event) {
|
||||
var responseData = createResponseData(event.getResponse(), client.getRoomInfo().getHostName());
|
||||
tikTokDatabase.insertData(responseData);
|
||||
|
||||
var filter = dataCollectorModel.getMessagesFilter();
|
||||
for (var message : event.getResponse().getMessagesList()) {
|
||||
if (filter.isEmpty()) {
|
||||
var data = createMessageData(message, client.getRoomInfo().getHostName());
|
||||
tikTokDatabase.insertData(data);
|
||||
continue;
|
||||
}
|
||||
if (!filter.contains(message.getMethod())) {
|
||||
continue;
|
||||
}
|
||||
var data = createMessageData(message, client.getRoomInfo().getHostName());
|
||||
tikTokDatabase.insertData(data);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMappedEvent(LiveClient client, TikTokWebsocketMessageEvent messageEvent) {
|
||||
var event = messageEvent.getEvent();
|
||||
var eventName = event.getClass().getSimpleName();
|
||||
|
||||
var filter = dataCollectorModel.getEventsFilter();
|
||||
|
||||
if (filter.isEmpty()) {
|
||||
var data = createEventData(event, client.getRoomInfo().getHostName());
|
||||
tikTokDatabase.insertData(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!filter.contains(eventName)) {
|
||||
return;
|
||||
}
|
||||
var data = createEventData(event, client.getRoomInfo().getHostName());
|
||||
tikTokDatabase.insertData(data);
|
||||
}
|
||||
|
||||
private void handleError(LiveClient client, TikTokErrorEvent event) {
|
||||
var exception = event.getException();
|
||||
var userName = client.getRoomInfo().getHostName();
|
||||
var exceptionContent = ExceptionInfoModel.getStackTraceAsString(exception);
|
||||
var errorModel = new TikTokErrorModel();
|
||||
if (exception instanceof TikTokLiveMessageException ex) {
|
||||
errorModel.setHostName(userName);
|
||||
errorModel.setErrorName(ex.messageMethod());
|
||||
errorModel.setErrorType("error-message");
|
||||
errorModel.setExceptionContent(exceptionContent);
|
||||
errorModel.setMessage(ex.messageToBase64());
|
||||
errorModel.setResponse(ex.webcastResponseToBase64());
|
||||
} else {
|
||||
errorModel.setHostName(userName);
|
||||
errorModel.setErrorName(exception.getClass().getSimpleName());
|
||||
errorModel.setErrorType("error-system");
|
||||
errorModel.setExceptionContent(exceptionContent);
|
||||
errorModel.setMessage("");
|
||||
errorModel.setResponse("");
|
||||
}
|
||||
|
||||
|
||||
tikTokDatabase.insertError(errorModel);
|
||||
client.getLogger().info("ERROR: " + errorModel.getErrorName());
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
private TikTokDataTable createHttpResponseData(TikTokHttpResponseEvent response, String tiktokUser) {
|
||||
var base64 = JsonUtil.toJson(response);
|
||||
var data = new TikTokDataTable();
|
||||
data.setSessionTag(dataCollectorModel.getSessionTag());
|
||||
data.setTiktokUser(tiktokUser);
|
||||
data.setDataType("response");
|
||||
data.setDataTypeName("Http");
|
||||
data.setContent(base64);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
private TikTokDataTable createResponseData(WebcastResponse response, String tiktokUser) {
|
||||
var base64 = Base64.getEncoder().encodeToString(response.toByteArray());
|
||||
var data = new TikTokDataTable();
|
||||
data.setSessionTag(dataCollectorModel.getSessionTag());
|
||||
data.setTiktokUser(tiktokUser);
|
||||
data.setDataType("response");
|
||||
data.setDataTypeName("WebcastResponse");
|
||||
data.setContent(base64);
|
||||
return data;
|
||||
}
|
||||
|
||||
private TikTokDataTable createMessageData(WebcastResponse.Message message, String tiktokUser) {
|
||||
var base64 = Base64.getEncoder().encodeToString(message.getPayload().toByteArray());
|
||||
var data = new TikTokDataTable();
|
||||
data.setSessionTag(dataCollectorModel.getSessionTag());
|
||||
data.setTiktokUser(tiktokUser);
|
||||
data.setDataType("message");
|
||||
data.setDataTypeName(message.getMethod());
|
||||
data.setContent(base64);
|
||||
return data;
|
||||
}
|
||||
|
||||
private TikTokDataTable createEventData(TikTokEvent event, String tiktokUser) {
|
||||
var base64 = JsonUtil.toJson(event);
|
||||
var data = new TikTokDataTable();
|
||||
data.setSessionTag(dataCollectorModel.getSessionTag());
|
||||
data.setTiktokUser(tiktokUser);
|
||||
data.setDataType("event");
|
||||
data.setDataTypeName(event.getClass().getSimpleName());
|
||||
data.setContent(base64);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
||||
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollectorBuilder;
|
||||
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollector;
|
||||
import io.github.jwdeveloper.tiktok.tools.collector.api.TikTokDataCollectorModel;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TikTokDataCollectorBuilder implements DataCollectorBuilder {
|
||||
|
||||
|
||||
TikTokDataCollectorModel dataModel;
|
||||
|
||||
TikTokDatabase database;
|
||||
|
||||
public TikTokDataCollectorBuilder(String outputName) {
|
||||
|
||||
dataModel = new TikTokDataCollectorModel();
|
||||
dataModel.setOutputName(outputName);
|
||||
dataModel.setUsers(new ArrayList<>());
|
||||
dataModel.setEventsFilter(new HashSet<>());
|
||||
dataModel.setMessagesFilter(new HashSet<>());
|
||||
dataModel.setOutputPath("...");
|
||||
dataModel.setOnConfigureLiveClient((e) -> {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCollectorBuilder addUser(String user) {
|
||||
dataModel.getUsers().add(user);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokDataCollectorBuilder addMessageFilter(Class<? extends GeneratedMessageV3> message) {
|
||||
dataModel.getMessagesFilter().add(message.getSimpleName());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokDataCollectorBuilder addMessageFilter(String message) {
|
||||
dataModel.getMessagesFilter().add(message);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokDataCollectorBuilder addEventFilter(Class<? extends TikTokEvent> event) {
|
||||
dataModel.getEventsFilter().add(event.getSimpleName());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokDataCollectorBuilder addEventFilter(String event) {
|
||||
dataModel.getEventsFilter().add(event);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataCollectorBuilder setOutputPath(String path) {
|
||||
dataModel.setOutputPath(path);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCollectorBuilder setSessionTag(String sessionTimestamp) {
|
||||
dataModel.setSessionTag(sessionTimestamp);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCollectorBuilder setDatabase(TikTokDatabase database)
|
||||
{
|
||||
this.database =database;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCollectorBuilder configureLiveClient(Consumer<LiveClientBuilder> consumer) {
|
||||
dataModel.setOnConfigureLiveClient(consumer);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataCollector buildAndRun() {
|
||||
|
||||
var collector = build();
|
||||
collector.connect();
|
||||
return collector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCollector build() {
|
||||
|
||||
if (dataModel.getSessionTag().isEmpty()) {
|
||||
dataModel.setSessionTag(UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
if(database == null)
|
||||
{
|
||||
database = new TikTokDatabase(dataModel.getOutputName());
|
||||
}
|
||||
var dataCollector = new TikTokDataCollector(dataModel, database);
|
||||
return dataCollector;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.db;
|
||||
|
||||
public class SqlConsts
|
||||
{
|
||||
|
||||
public static String CREATE_DATA_TABLE = """
|
||||
CREATE TABLE IF NOT EXISTS TikTokData (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sessionTag TEXT,
|
||||
tiktokUser TEXT,
|
||||
dataType TEXT,
|
||||
dataTypeName TEXT,
|
||||
content TEXT,
|
||||
createdAt TEXT
|
||||
);
|
||||
""";
|
||||
|
||||
public static String CREATE_ERROR_TABLE = """
|
||||
CREATE TABLE IF NOT EXISTS TikTokErrorModel (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
hostName VARCHAR(255),
|
||||
errorName VARCHAR(255),
|
||||
errorType VARCHAR(255),
|
||||
exceptionContent TEXT,
|
||||
message TEXT,
|
||||
response TEXT,
|
||||
createdAt DATETIME
|
||||
);
|
||||
""";
|
||||
|
||||
public static String CREATE_RESPONSE_MODEL = """
|
||||
CREATE TABLE IF NOT EXISTS TikTokResponseModel (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
hostName TEXT,
|
||||
response TEXT,
|
||||
createdAt TEXT
|
||||
);
|
||||
""";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.db;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
||||
import org.jdbi.v3.sqlobject.customizer.Bind;
|
||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlQuery;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RegisterBeanMapper(TikTokDataTable.class)
|
||||
public interface TikTokDataTableDAO {
|
||||
String query = """
|
||||
INSERT INTO TikTokData (sessionTag, tiktokUser, dataType, dataTypeName, content, createdAt) VALUES (:sessionTag, :tiktokUser, :dataType, :dataTypeName, :content, :createdAt)
|
||||
""";
|
||||
|
||||
@SqlUpdate(query)
|
||||
void insertData(@BindBean TikTokDataTable data);
|
||||
|
||||
@SqlQuery("SELECT * FROM TikTokData WHERE sessionTag = :sessionTag")
|
||||
List<TikTokDataTable> selectBySession(@Bind("sessionTag") String sessionTag);
|
||||
|
||||
@SqlQuery("SELECT * FROM TikTokData WHERE dataType = :dataType AND sessionTag = :sessionTag AND tiktokUser = :tiktokUser")
|
||||
List<TikTokDataTable> selectSessionData(@Bind("dataType") String dataType,
|
||||
@Bind("sessionTag") String sessionTag,
|
||||
@Bind("tiktokUser") String user);
|
||||
|
||||
@SqlQuery("SELECT * FROM TikTokData WHERE sessionTag = :sessionTag AND tiktokUser = :tiktokUser AND dataType = \"response\"")
|
||||
List<TikTokDataTable> selectResponces(@Bind("sessionTag") String sessionTag, @Bind("tiktokUser") String user);
|
||||
|
||||
@SqlQuery("SELECT * FROM TikTokData WHERE sessionTag = :sessionTag AND tiktokUser = :tiktokUser AND dataType = \"event\"")
|
||||
List<TikTokDataTable> selectBySessionEvents(@Bind("sessionTag") String sessionTag, @Bind("tiktokUser") String userName);
|
||||
|
||||
@SqlQuery("SELECT * FROM TikTokData WHERE sessionTag = :sessionTag AND tiktokUser = :tiktokUser AND dataType = \"message\"")
|
||||
List<TikTokDataTable> selectBySessionMessages(@Bind("sessionTag") String sessionTag, @Bind("tiktokUser") String userName);
|
||||
|
||||
|
||||
@SqlQuery("SELECT tiktokUser FROM TikTokData GROUP BY tiktokUser")
|
||||
List<String> getUsers();
|
||||
|
||||
|
||||
@SqlQuery("SELECT sessionTag FROM TikTokData WHERE tiktokUser = :tiktokUser GROUP BY sessionTag")
|
||||
List<String> getSessionTagByUser(@Bind("tiktokUser") String tiktokUser);
|
||||
|
||||
String groupByDataTypeNameQuery = """
|
||||
SELECT dataTypeName, COUNT(*) as count
|
||||
FROM TikTokData
|
||||
WHERE dataType = 'message' AND sessionTag = :sessionTag AND tiktokUser = :userName
|
||||
GROUP BY dataTypeName
|
||||
""";
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.db;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokErrorModel;
|
||||
import lombok.Getter;
|
||||
import org.jdbi.v3.core.Jdbi;
|
||||
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
|
||||
import org.sqlite.SQLiteConfig;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class TikTokDatabase {
|
||||
private final String database;
|
||||
|
||||
private TikTokErrorModelDAO errorTable;
|
||||
|
||||
@Getter
|
||||
private TikTokDataTableDAO dataTableDAO;
|
||||
|
||||
private Connection connection;
|
||||
|
||||
|
||||
public TikTokDatabase(String database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
public boolean isConnected()
|
||||
{
|
||||
return connection != null;
|
||||
}
|
||||
|
||||
public void connect() throws SQLException {
|
||||
var jdbcUrl = "jdbc:sqlite:" + database + ".db";
|
||||
var config = new SQLiteConfig();
|
||||
config.setEncoding(SQLiteConfig.Encoding.UTF8);
|
||||
connection = DriverManager.getConnection(jdbcUrl, config.toProperties());
|
||||
var jdbi = Jdbi.create(jdbcUrl).installPlugin(new SqlObjectPlugin());
|
||||
jdbi.useHandle(handle -> {
|
||||
handle.execute(SqlConsts.CREATE_DATA_TABLE);
|
||||
handle.execute(SqlConsts.CREATE_ERROR_TABLE);
|
||||
});
|
||||
dataTableDAO = jdbi.onDemand(TikTokDataTableDAO.class);
|
||||
errorTable = jdbi.onDemand(TikTokErrorModelDAO.class);
|
||||
}
|
||||
|
||||
public void close() throws SQLException {
|
||||
connection.close();
|
||||
}
|
||||
|
||||
public void insertData(TikTokDataTable tikTokDataTable) {
|
||||
tikTokDataTable.setCreatedAt(getTime());
|
||||
dataTableDAO.insertData(tikTokDataTable);
|
||||
}
|
||||
|
||||
public List<TikTokDataTable> getSessionResponces(String sessionTag, String userName) {
|
||||
return dataTableDAO.selectResponces(sessionTag, userName);
|
||||
}
|
||||
|
||||
public List<String> getDataNames(String dataType, String sessionTag, String userName) {
|
||||
|
||||
try {
|
||||
var sb = new StringBuilder();
|
||||
sb.append("""
|
||||
SELECT dataTypeName, COUNT(*) as count
|
||||
FROM TikTokData
|
||||
""");
|
||||
sb.append(" WHERE dataType = \""+dataType+"\" ");
|
||||
sb.append(" AND tiktokUser = \"" + userName + "\" ");
|
||||
sb.append(" AND sessionTag = \"" + sessionTag + "\" ");
|
||||
sb.append("GROUP BY dataTypeName");
|
||||
var statement = connection.prepareStatement(sb.toString());
|
||||
var resultSet = statement.executeQuery();
|
||||
List<String> dataTypeCounts = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
var dataTypeName = resultSet.getString("dataTypeName");
|
||||
dataTypeCounts.add(dataTypeName);
|
||||
}
|
||||
|
||||
resultSet.close();
|
||||
statement.close();
|
||||
|
||||
return dataTypeCounts;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return List.of("error");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<TikTokDataTable> getSessionMessages(String sessionTag, String userName, int count) {
|
||||
return dataTableDAO.selectBySessionMessages(sessionTag, userName);
|
||||
}
|
||||
|
||||
public void insertError(TikTokErrorModel message) {
|
||||
message.setCreatedAt(getTime());
|
||||
errorTable.insertTikTokMessage(message);
|
||||
}
|
||||
|
||||
|
||||
public List<TikTokErrorModel> selectErrors() {
|
||||
return errorTable.selectErrors();
|
||||
}
|
||||
|
||||
private String getTime() {
|
||||
return new SimpleDateFormat("dd:MM:yyyy HH:mm:ss.SSS").format(new Date());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.db;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokErrorModel;
|
||||
|
||||
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlQuery;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@RegisterBeanMapper(TikTokErrorModel.class)
|
||||
public interface TikTokErrorModelDAO
|
||||
{
|
||||
@SqlUpdate("INSERT INTO TikTokErrorModel (hostName, errorName, errorType, exceptionContent, message, response, createdAt) " +
|
||||
"VALUES (:hostName, :errorName, :errorType, :exceptionContent, :message, :response, :createdAt)")
|
||||
void insertTikTokMessage(@BindBean TikTokErrorModel message);
|
||||
|
||||
@SqlQuery("SELECT * FROM TikTokErrorModel")
|
||||
List<TikTokErrorModel> selectErrors();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
public class ExceptionInfoModel
|
||||
{
|
||||
private String message;
|
||||
private String stackTrace;
|
||||
|
||||
public ExceptionInfoModel(Throwable throwable) {
|
||||
this.message = throwable.getMessage();
|
||||
this.stackTrace = getStackTraceAsString(throwable);
|
||||
}
|
||||
|
||||
public static String getStackTraceAsString(Throwable throwable) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
throwable.printStackTrace(pw);
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
// Getters for message and stackTrace
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getStackTrace() {
|
||||
return stackTrace;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TikTokDataTable
|
||||
{
|
||||
private Integer id;
|
||||
|
||||
private String sessionTag;
|
||||
|
||||
private String tiktokUser;
|
||||
|
||||
private String dataType;
|
||||
|
||||
private String dataTypeName;
|
||||
|
||||
private String content;
|
||||
|
||||
private String createdAt;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TikTokErrorModel
|
||||
{
|
||||
private Integer id;
|
||||
|
||||
private String hostName;
|
||||
|
||||
private String errorName;
|
||||
|
||||
private String errorType;
|
||||
|
||||
private String exceptionContent;
|
||||
|
||||
private String message;
|
||||
|
||||
private String response;
|
||||
|
||||
private String createdAt;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.TikTokLiveMock;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.LiveClientMock;
|
||||
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
|
||||
public class RunJsonTester {
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
var messages = getMessages();
|
||||
var client =(LiveClientMock) TikTokLiveMock.create()
|
||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.append("Unhandled Message! " );
|
||||
sb.append(event.getData().getMethod());
|
||||
sb.append("\n");
|
||||
sb.append(MessageUtil.getContent(event.getData()));
|
||||
|
||||
|
||||
// liveClient.getLogger().info(sb.toString());
|
||||
}).
|
||||
onGift((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("Gift event: "+event.toJson());
|
||||
})
|
||||
.onGiftCombo((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("GiftCombo event"+event.toJson());
|
||||
})
|
||||
.onError((liveClient, event) ->
|
||||
{
|
||||
event.getException().printStackTrace();
|
||||
})
|
||||
.build();
|
||||
for(var msg : messages.entrySet())
|
||||
{
|
||||
for(var content : msg.getValue())
|
||||
{
|
||||
client.publishMessage(msg.getKey(),content);
|
||||
}
|
||||
}
|
||||
client.connect();
|
||||
}
|
||||
|
||||
|
||||
private static Map<String, List<String>> getMessages() throws IOException {
|
||||
var path = "C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\Tools-EventsCollector\\src\\main\\resources\\log.json";
|
||||
var jsonElement = JsonParser.parseReader(new FileReader(path, Charset.defaultCharset()));
|
||||
|
||||
var res = new HashMap<String, List<String>>();
|
||||
if (jsonElement.isJsonObject()) {
|
||||
var jsonObject = jsonElement.getAsJsonObject();
|
||||
var keys = jsonObject.keySet();
|
||||
for (String key : keys) {
|
||||
var messages = jsonObject.get(key).getAsJsonArray();
|
||||
for (var msg : messages) {
|
||||
var data = msg.getAsJsonObject().get("eventData").getAsString();
|
||||
res.computeIfAbsent(key, s -> new ArrayList<>()).add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTester;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTesterModel;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.TikTokLiveMock;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.LiveClientMock;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class TikTokDataTester implements DataTester {
|
||||
private DataTesterModel model;
|
||||
|
||||
private LiveClientMock client;
|
||||
|
||||
private Queue<TikTokDataTable> data;
|
||||
|
||||
private TikTokDatabase database;
|
||||
|
||||
public TikTokDataTester(DataTesterModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
|
||||
try {
|
||||
database = new TikTokDatabase(model.getDatabaseName());
|
||||
database.connect();
|
||||
var mockBuilder = TikTokLiveMock.create();
|
||||
model.getBuilderConsumer().accept(mockBuilder);
|
||||
client = mockBuilder.build();
|
||||
var respocnes = database.getSessionResponces(model.getSessionTag(), model.getUser());
|
||||
data = new LinkedList<>(respocnes);
|
||||
client.connect();
|
||||
while (!data.isEmpty()) {
|
||||
nextResponse();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error while running tester", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nextResponse() {
|
||||
try {
|
||||
var responce = data.poll();
|
||||
client.publishResponse(responce.getContent());
|
||||
Thread.sleep(1);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to run response!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
|
||||
try {
|
||||
client.disconnect();
|
||||
database.close();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTester;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTesterBuilder;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTesterModel;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TikTokDataTesterBuilder implements DataTesterBuilder {
|
||||
private final DataTesterModel model;
|
||||
|
||||
public TikTokDataTesterBuilder(String databaseName) {
|
||||
this.model = new DataTesterModel();
|
||||
this.model.setDatabaseName(databaseName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTesterBuilder setSessionTag(String sessionTag) {
|
||||
model.setSessionTag(sessionTag);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTesterBuilder setUser(String user) {
|
||||
model.setUser(user);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTesterBuilder configureLiveClient(Consumer<LiveClientBuilder> builderConsumer) {
|
||||
model.setBuilderConsumer(builderConsumer);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTester build() {
|
||||
return new TikTokDataTester(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTester buildAndRun()
|
||||
{
|
||||
var tester = build();
|
||||
tester.connect();
|
||||
return tester;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester.api;
|
||||
|
||||
public interface DataTester
|
||||
{
|
||||
void connect();
|
||||
|
||||
void nextResponse();
|
||||
|
||||
void disconnect();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester.api;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface DataTesterBuilder {
|
||||
|
||||
DataTesterBuilder setSessionTag(String sessionTag);
|
||||
|
||||
DataTesterBuilder setUser(String user);
|
||||
|
||||
DataTesterBuilder configureLiveClient(Consumer<LiveClientBuilder> builderConsumer);
|
||||
|
||||
DataTester build();
|
||||
|
||||
DataTester buildAndRun();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester.api;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Data
|
||||
public class DataTesterModel {
|
||||
|
||||
|
||||
String databaseName;
|
||||
String sessionTag;
|
||||
String user;
|
||||
Consumer<LiveClientBuilder> builderConsumer = (a) -> {
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester.mockClient;
|
||||
|
||||
public class TikTokLiveMock
|
||||
{
|
||||
public static TikTokMockBuilder create(String host)
|
||||
{
|
||||
return new TikTokMockBuilder(host);
|
||||
}
|
||||
|
||||
public static TikTokMockBuilder create()
|
||||
{
|
||||
return create("MockHostName");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester.mockClient;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveMessageHandler;
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveHttpClient;
|
||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager;
|
||||
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.LiveClientMock;
|
||||
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.WebsocketClientMock;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
|
||||
public class TikTokMockBuilder extends TikTokLiveClientBuilder {
|
||||
|
||||
Stack<WebcastResponse> responses;
|
||||
|
||||
public TikTokMockBuilder(String userName) {
|
||||
super(userName);
|
||||
responses = new Stack<>();
|
||||
|
||||
}
|
||||
|
||||
public TikTokMockBuilder addResponse(String value) {
|
||||
var bytes = Base64.getDecoder().decode(value);
|
||||
return addResponse(bytes);
|
||||
}
|
||||
|
||||
public TikTokMockBuilder addResponses(List<String> values) {
|
||||
for (var value : values) {
|
||||
try {
|
||||
addResponse(value);
|
||||
} catch (Exception e) {
|
||||
throw new TikTokLiveException(value, e);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokMockBuilder addResponse(byte[] bytes) {
|
||||
try {
|
||||
var response = WebcastResponse.parseFrom(bytes);
|
||||
return addResponse(response);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to parse response from bytes", e);
|
||||
}
|
||||
}
|
||||
|
||||
public TikTokMockBuilder addResponse(WebcastResponse message) {
|
||||
responses.push(message);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LiveClientMock build() {
|
||||
validate();
|
||||
|
||||
var tiktokRoomInfo = new TikTokRoomInfo();
|
||||
tiktokRoomInfo.setHostName(clientSettings.getHostName());
|
||||
|
||||
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
||||
var mapper = createMapper(new TikTokGiftsManager(List.of()), tiktokRoomInfo);
|
||||
var handler = new TikTokLiveMessageHandler(tikTokEventHandler, mapper);
|
||||
var webSocketClient = new WebsocketClientMock(logger, responses, handler);
|
||||
|
||||
return new LiveClientMock(tiktokRoomInfo,
|
||||
new TikTokLiveHttpClient(),
|
||||
webSocketClient,
|
||||
tikTokEventHandler,
|
||||
clientSettings,
|
||||
listenerManager,
|
||||
logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveClientMock buildAndConnect() {
|
||||
var client = build();
|
||||
client.connect();
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveHttpClient;
|
||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager;
|
||||
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class LiveClientMock extends TikTokLiveClient {
|
||||
|
||||
private final WebsocketClientMock websocketClientMock;
|
||||
|
||||
public LiveClientMock(
|
||||
TikTokRoomInfo tikTokLiveMeta,
|
||||
TikTokLiveHttpClient httpClient,
|
||||
WebsocketClientMock webSocketClient,
|
||||
TikTokLiveEventHandler tikTokEventHandler,
|
||||
LiveClientSettings clientSettings,
|
||||
TikTokListenersManager listenersManager,
|
||||
Logger logger) {
|
||||
super(
|
||||
new TikTokGiftsManager(List.of()),
|
||||
tikTokLiveMeta,
|
||||
httpClient,
|
||||
webSocketClient,
|
||||
tikTokEventHandler,
|
||||
clientSettings,
|
||||
listenersManager,
|
||||
logger);
|
||||
this.websocketClientMock = webSocketClient;
|
||||
websocketClientMock.setClient(this);
|
||||
}
|
||||
|
||||
|
||||
public void publishMessage(String type, String base64) {
|
||||
websocketClientMock.addMessage(type, base64);
|
||||
}
|
||||
|
||||
public void publishMessage(Class<?> clazz, String base64) {
|
||||
websocketClientMock.addMessage(clazz.getSimpleName(), base64);
|
||||
}
|
||||
|
||||
public void publishResponse(String value) {
|
||||
websocketClientMock.addResponse(value);
|
||||
}
|
||||
|
||||
public void publishResponse(byte[] bytes) {
|
||||
websocketClientMock.addResponse(bytes);
|
||||
}
|
||||
|
||||
public void publishResponse(WebcastResponse message) {
|
||||
websocketClientMock.addResponse(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveMessageHandler;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
import io.github.jwdeveloper.tiktok.websocket.SocketClient;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
public class WebsocketClientMock implements SocketClient {
|
||||
Logger logger;
|
||||
Stack<WebcastResponse> responses;
|
||||
Stack<MsgStruct> messages;
|
||||
TikTokLiveMessageHandler messageHandler;
|
||||
|
||||
LiveClient client;
|
||||
|
||||
Thread thread;
|
||||
|
||||
private boolean isRunning;
|
||||
|
||||
public void setClient(LiveClientMock liveClientMock) {
|
||||
this.client = liveClientMock;
|
||||
}
|
||||
|
||||
@Value
|
||||
public static class MsgStruct {
|
||||
String messageType;
|
||||
byte[] messageValue;
|
||||
}
|
||||
|
||||
public WebsocketClientMock(Logger logger, Stack<WebcastResponse> responses, TikTokLiveMessageHandler messageHandler) {
|
||||
this.logger = logger;
|
||||
this.responses = responses;
|
||||
this.messageHandler = messageHandler;
|
||||
messages = new Stack<>();
|
||||
}
|
||||
|
||||
public WebsocketClientMock addMessage(String type, String value) {
|
||||
var bytes = Base64.getDecoder().decode(value);
|
||||
messages.push(new MsgStruct(type, bytes));
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebsocketClientMock addResponse(String value) {
|
||||
var bytes = Base64.getDecoder().decode(value);
|
||||
return addResponse(bytes);
|
||||
}
|
||||
|
||||
public WebsocketClientMock addResponse(byte[] bytes) {
|
||||
try {
|
||||
var response = WebcastResponse.parseFrom(bytes);
|
||||
return addResponse(response);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to parse response from bytes", e);
|
||||
}
|
||||
}
|
||||
|
||||
public WebsocketClientMock addResponse(WebcastResponse message) {
|
||||
responses.push(message);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void start(LiveConnectionData.Response webcastResponse, LiveClient tikTokLiveClient) {
|
||||
logger.info("Running message: " + responses.size());
|
||||
|
||||
|
||||
thread = new Thread(() ->
|
||||
{
|
||||
|
||||
while (isRunning)
|
||||
{
|
||||
while (!responses.isEmpty()) {
|
||||
var response = responses.pop();
|
||||
messageHandler.handle(client, response);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
isRunning = true;
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
isRunning = false;
|
||||
thread.interrupt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.tools.util;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
|
||||
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||
import io.github.jwdeveloper.tiktok.utils.ProtocolUtils;
|
||||
|
||||
public class MessageUtil {
|
||||
public static String getContent(WebcastResponse.Message message) {
|
||||
try {
|
||||
var methodName = message.getMethod();
|
||||
var inputClazz = Class.forName("io.github.jwdeveloper.tiktok.messages.webcast." + methodName);
|
||||
var parseMethod = inputClazz.getDeclaredMethod("parseFrom", ByteString.class);
|
||||
var webcastObject = parseMethod.invoke(null, message.getPayload());
|
||||
return JsonUtil.messageToJson(webcastObject);
|
||||
} catch (Exception ex) {
|
||||
|
||||
return ConsoleColors.RED + "Can not find mapper for " + message.getMethod();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getContent(String messageName, byte[] bytes) {
|
||||
try {
|
||||
|
||||
var inputClazz = Class.forName("io.github.jwdeveloper.tiktok.messages.webcast." + messageName);
|
||||
var parseMethod = inputClazz.getDeclaredMethod("parseFrom", byte[].class);
|
||||
var deserialized = parseMethod.invoke(null, bytes);
|
||||
|
||||
return JsonUtil.messageToJson(deserialized);
|
||||
} catch (Exception ex) {
|
||||
var sb = new StringBuilder();
|
||||
sb.append("Can not find protocol-buffer file message representation for " + messageName);
|
||||
sb.append("\n");
|
||||
var structure = ProtocolUtils.getProtocolBufferStructure(bytes);
|
||||
var json =structure.toJson();
|
||||
sb.append(json);
|
||||
//String jsonString = JsonFormat.printToString(protobufData);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
4344
Tools-EventsCollector/src/main/resources/ab.json
Normal file
4344
Tools-EventsCollector/src/main/resources/ab.json
Normal file
File diff suppressed because one or more lines are too long
1452
Tools-EventsCollector/src/main/resources/dupa.json
Normal file
1452
Tools-EventsCollector/src/main/resources/dupa.json
Normal file
File diff suppressed because one or more lines are too long
1416
Tools-EventsCollector/src/main/resources/giftsCollector.json
Normal file
1416
Tools-EventsCollector/src/main/resources/giftsCollector.json
Normal file
File diff suppressed because one or more lines are too long
264
Tools-EventsCollector/src/main/resources/jw.json
Normal file
264
Tools-EventsCollector/src/main/resources/jw.json
Normal file
@@ -0,0 +1,264 @@
|
||||
{
|
||||
"RoomMessage": [
|
||||
{
|
||||
"eventData": "CioKDVN5c3RlbU1lc3NhZ2UQmofs1NO1z8sXGKGW59iz55WpZSDxhpnNvDESuQFXZWxjb21lIHRvIFRpa1RvayBMSVZFISBIYXZlIGZ1biBpbnRlcmFjdGluZyB3aXRoIHRoZSBMSVZFIGNyZWF0b3IgYW5kIG90aGVyIHZpZXdlcnMgaW4gcmVhbCB0aW1lIGFuZCByZW1lbWJlciB0byBjcmVhdGUgYSBzYWZlIHZpZXdpbmcgZXhwZXJpZW5jZSBieSBmb2xsb3dpbmcgb3VyIENvbW11bml0eSBHdWlkZWxpbmVzLjgB",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:06:35.153694400"
|
||||
},
|
||||
{
|
||||
"eventData": "CioKDVN5c3RlbU1lc3NhZ2UQjPTq1re3z8sXGKGW59iz55WpZSCI5ZzNvDESuQFXZWxjb21lIHRvIFRpa1RvayBMSVZFISBIYXZlIGZ1biBpbnRlcmFjdGluZyB3aXRoIHRoZSBMSVZFIGNyZWF0b3IgYW5kIG90aGVyIHZpZXdlcnMgaW4gcmVhbCB0aW1lIGFuZCByZW1lbWJlciB0byBjcmVhdGUgYSBzYWZlIHZpZXdpbmcgZXhwZXJpZW5jZSBieSBmb2xsb3dpbmcgb3VyIENvbW11bml0eSBHdWlkZWxpbmVzLjgB",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:07:36.360859900"
|
||||
},
|
||||
{
|
||||
"eventData": "CioKDVN5c3RlbU1lc3NhZ2UQocTpm8nCz8sXGKGW59iz55WpZSDSkrTNvDESuQFXZWxjb21lIHRvIFRpa1RvayBMSVZFISBIYXZlIGZ1biBpbnRlcmFjdGluZyB3aXRoIHRoZSBMSVZFIGNyZWF0b3IgYW5kIG90aGVyIHZpZXdlcnMgaW4gcmVhbCB0aW1lIGFuZCByZW1lbWJlciB0byBjcmVhdGUgYSBzYWZlIHZpZXdpbmcgZXhwZXJpZW5jZSBieSBmb2xsb3dpbmcgb3VyIENvbW11bml0eSBHdWlkZWxpbmVzLjgB",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:13:58.969658600"
|
||||
},
|
||||
{
|
||||
"eventData": "CioKDVN5c3RlbU1lc3NhZ2UQ8a6h9abiz8sXGKGW59iz55WpZSDS2PbNvDESuQFXZWxjb21lIHRvIFRpa1RvayBMSVZFISBIYXZlIGZ1biBpbnRlcmFjdGluZyB3aXRoIHRoZSBMSVZFIGNyZWF0b3IgYW5kIG90aGVyIHZpZXdlcnMgaW4gcmVhbCB0aW1lIGFuZCByZW1lbWJlciB0byBjcmVhdGUgYSBzYWZlIHZpZXdpbmcgZXhwZXJpZW5jZSBieSBmb2xsb3dpbmcgb3VyIENvbW11bml0eSBHdWlkZWxpbmVzLjgB",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:32:09.427463"
|
||||
}
|
||||
],
|
||||
"WebcastChatMessage": [
|
||||
{
|
||||
"eventData": "ClAKEldlYmNhc3RDaGF0TWVzc2FnZRCglqWQ1+2VqWUYoZbn2LPnlallIMjgmc28MTABSAJQAnoIdXNlYXN0MmGwAQG4AQLAAQLIAerYmc28MRKdCgiFiKX0gI2FlmAaF/CfkoAgUG9yYSB1bWllcmHEhyDwn5KASvgFCrYBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9dklLVGljWFYwZEdmZmdNa0QzYzJvU1BEJTJGbjAlM0QKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Nk1YbjZlellUMzRxVWNzdU1xUTFHMTBRMWVZJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTgxNEpPdU9DOGR5b1RkOVNWOU5CN1I2UmI2NCUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YRTNLaDI1QnlzMERVJTJGJTJGVWtyZWQlMkJMWnVCeFUlM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMVKOAwrCAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfnRwbHYtdGlrdG9reC1jb21wcmVzc19xdWFsaXR5XzMwOjcyOjcyLndlYnA/eC1leHBpcmVzPTE2OTk5MTY0MDAmeC1zaWduYXR1cmU9Q1RLNlJMNnVlTkpSelI5dHBLSjVGM0FvdHBJJTNECsYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2t4LWNvbXByZXNzX3F1YWxpdHlfMzA6NzI6NzIuanBlZz94LWV4cGlyZXM9MTY5OTkxNjQwMCZ4LXNpZ25hdHVyZT1IVG0lMkY3WEFMQTJzSlklMkJIMWp0MTN6QUdGc00wJTNEsgEGCIQFEKgVugEAggIAsgINZG9zdGF3Y2F2aWRlb/ICTE1TNHdMakFCQUFBQXFrRnQtRUpmRzRESFV1WXltUUJzU19qNmRyVWl5dFozM3RFTXlidWFHRi1pWHo3X1dZSXBfakQ0cElDVk1qd2QaA2FzZHICemiSAQIwAZoBFAoOdXNlcl90eXBlX3J1bGUQoMIemgEYChFjb21tdW5pdHktZmxhZ2dlZBDZt9oBmgEaCg5jb21tZW50YXRvcl9pZBCFiKX0gI2FlmCaARIKB2RlZmF1bHQQ8LqSkbvBggOaARAKC2RlZmF1bHRfYXBwEJBOmgERCgZyYW5rVjMQ4/2WkbvBggOaARoKD3R0cF9ydWxlX3JlcmFuaxDw5/SVu8GCA5oBGgoOdGltZXN0YW1wX2Rlc2MQkMWV28rtzq4BmgE1Cip0aWtjYXN0X2NvbW11bml0eV9jb21tZW50XzE4ODY2X3Y3X3I2NTUwNjkQkdSYkbvBggOaAToKL3Rpa2Nhc3RfY29tbXVuaXR5X2NvbW1lbnRfMTg4NjZfdjdfcjY1NTA2OV9kZXNjEO7S95W7wYIDmgEaCg9pZGNfcnVsZV9yZXJhbmsQ8Jv+qLvBggOaARYKC3YxM19yNzEyMDg4EPCb/qi7wYIDmgEWCgt2MTJfcjcwMjA3NRDwm/6ou8GCA5oBFgoLdjEzX3I3NjUxNjYQ8Jv+qLvBggOaARYKC3YxM19yNzY1MTY3EPCb/qi7wYIDmgEWCgt2MTNfcjc2NTE2ORDwm/6ou8GCA5oBFgoLdjEzX3I3NjcxMjIQ8Jv+qLvBggOaARYKC3YxM19yNzcwODA0EPCb/qi7wYIDmgEWCgt2MTNfcjc3MDgwNRDwm/6ou8GCA5oBFgoLdjEzX3I3NzA4MDYQ8Jv+qLvBggOaARYKC3YxM19yNzcwODA3EPCb/qi7wYIDmgEWCgt2MTNfcjc3MDgwOBDwm/6ou8GCA5oBFgoLdjEzX3I3NzA4MTAQ8Jv+qLvBggOaARoKD2lkY19ydWxlX3JlcmFuaxDwm/6ou8GCA6IBAQA=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:06:47.126429700"
|
||||
},
|
||||
{
|
||||
"eventData": "ClAKEldlYmNhc3RDaGF0TWVzc2FnZRCglqWQ1+2VqWUYoZbn2LPnlallIMjgmc28MTABSAJQAnoIdXNlYXN0MmGwAQG4AQLAAQLIAerYmc28MRKdCgiFiKX0gI2FlmAaF/CfkoAgUG9yYSB1bWllcmHEhyDwn5KASvgFCrYBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9dklLVGljWFYwZEdmZmdNa0QzYzJvU1BEJTJGbjAlM0QKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Nk1YbjZlellUMzRxVWNzdU1xUTFHMTBRMWVZJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTgxNEpPdU9DOGR5b1RkOVNWOU5CN1I2UmI2NCUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YRTNLaDI1QnlzMERVJTJGJTJGVWtyZWQlMkJMWnVCeFUlM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMVKOAwrCAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfnRwbHYtdGlrdG9reC1jb21wcmVzc19xdWFsaXR5XzMwOjcyOjcyLndlYnA/eC1leHBpcmVzPTE2OTk5MTY0MDAmeC1zaWduYXR1cmU9Q1RLNlJMNnVlTkpSelI5dHBLSjVGM0FvdHBJJTNECsYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2t4LWNvbXByZXNzX3F1YWxpdHlfMzA6NzI6NzIuanBlZz94LWV4cGlyZXM9MTY5OTkxNjQwMCZ4LXNpZ25hdHVyZT1IVG0lMkY3WEFMQTJzSlklMkJIMWp0MTN6QUdGc00wJTNEsgEGCIQFEKgVugEAggIAsgINZG9zdGF3Y2F2aWRlb/ICTE1TNHdMakFCQUFBQXFrRnQtRUpmRzRESFV1WXltUUJzU19qNmRyVWl5dFozM3RFTXlidWFHRi1pWHo3X1dZSXBfakQ0cElDVk1qd2QaA2FzZHICemiSAQIwAZoBFAoOdXNlcl90eXBlX3J1bGUQoMIemgEYChFjb21tdW5pdHktZmxhZ2dlZBDZt9oBmgEaCg5jb21tZW50YXRvcl9pZBCFiKX0gI2FlmCaARIKB2RlZmF1bHQQ8LqSkbvBggOaARAKC2RlZmF1bHRfYXBwEJBOmgERCgZyYW5rVjMQ4/2WkbvBggOaARoKD3R0cF9ydWxlX3JlcmFuaxDw5/SVu8GCA5oBGgoOdGltZXN0YW1wX2Rlc2MQkMWV28rtzq4BmgE1Cip0aWtjYXN0X2NvbW11bml0eV9jb21tZW50XzE4ODY2X3Y3X3I2NTUwNjkQkdSYkbvBggOaAToKL3Rpa2Nhc3RfY29tbXVuaXR5X2NvbW1lbnRfMTg4NjZfdjdfcjY1NTA2OV9kZXNjEO7S95W7wYIDmgEaCg9pZGNfcnVsZV9yZXJhbmsQ8Jv+qLvBggOaARYKC3YxM19yNzEyMDg4EPCb/qi7wYIDmgEWCgt2MTJfcjcwMjA3NRDwm/6ou8GCA5oBFgoLdjEzX3I3NjUxNjYQ8Jv+qLvBggOaARYKC3YxM19yNzY1MTY3EPCb/qi7wYIDmgEWCgt2MTNfcjc2NTE2ORDwm/6ou8GCA5oBFgoLdjEzX3I3NjcxMjIQ8Jv+qLvBggOaARYKC3YxM19yNzcwODA0EPCb/qi7wYIDmgEWCgt2MTNfcjc3MDgwNRDwm/6ou8GCA5oBFgoLdjEzX3I3NzA4MDYQ8Jv+qLvBggOaARYKC3YxM19yNzcwODA3EPCb/qi7wYIDmgEWCgt2MTNfcjc3MDgwOBDwm/6ou8GCA5oBFgoLdjEzX3I3NzA4MTAQ8Jv+qLvBggOaARoKD2lkY19ydWxlX3JlcmFuaxDwm/6ou8GCA6IBAQA=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:07:36.364450900"
|
||||
},
|
||||
{
|
||||
"eventData": "ClAKEldlYmNhc3RDaGF0TWVzc2FnZRCglp7Ix/SVqWUYoZbn2LPnlallIOvxm828MTABSAJQAnoIdXNlYXN0MmGwAQK4AQLAAQLIAfPqm828MRKVCgiFiMi2nP/V4l0aDG5vdGlmaWNhdGlvbkr+BQq6AWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzgzOTE5MWFlZDIzMzRjMTgyMTI1Y2M0YTAzMzA0Y2NhfnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPSUyQmRnaCUyRmxmVDNmUm4zZWZtQjMlMkZCSXU0NHJXUSUzRAqoAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzgzOTE5MWFlZDIzMzRjMTgyMTI1Y2M0YTAzMzA0Y2NhfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1XRkNLeXMyTVAyMlclMkZGR0lRdzFCMHpIQ1l6RSUzRAqqAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzgzOTE5MWFlZDIzMzRjMTgyMTI1Y2M0YTAzMzA0Y2NhfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT0lMkZITVJNaEFYQ3lFbXZkbyUyRnB6aVRDNjQ0c2hNJTNECqgBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODM5MTkxYWVkMjMzNGMxODIxMjVjYzRhMDMzMDRjY2F+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPWt2V3FUWmFOclBsTSUyRkVlV2hKakJ5TzkxUG5nJTNEEjwxMDB4MTAwL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODM5MTkxYWVkMjMzNGMxODIxMjVjYzRhMDMzMDRjY2FSjAMKwgFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC84MzkxOTFhZWQyMzM0YzE4MjEyNWNjNGEwMzMwNGNjYX50cGx2LXRpa3Rva3gtY29tcHJlc3NfcXVhbGl0eV8zMDo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNjk5OTE2NDAwJngtc2lnbmF0dXJlPU5vMWN2RXB2Yno1QXFtTnZmQzh1ZDl0d3hKTSUzRArEAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzgzOTE5MWFlZDIzMzRjMTgyMTI1Y2M0YTAzMzA0Y2NhfnRwbHYtdGlrdG9reC1jb21wcmVzc19xdWFsaXR5XzMwOjcyOjcyLmpwZWc/eC1leHBpcmVzPTE2OTk5MTY0MDAmeC1zaWduYXR1cmU9eEduYkFuVUFFckZKUzFTcW1OME5vJTJGOUVRM1UlM0SyAQgI3QwQ1BEYAboBAIICALICCm5pZXRvcGVyejDyAkxNUzR3TGpBQkFBQUF6emlzM0d0blI4bUJsVEIwQjZCY3RDVHBEd0NrMV9lc1hLckJTZkZOVTRCM0hkYXVESEkxUzl6QTM4TGR0cklWGgVzaWVtYXICcGySAQIgAZoBFAoOdXNlcl90eXBlX3J1bGUQwJoMmgEXChFjb21tdW5pdHktZmxhZ2dlZBCorRqaARoKDmNvbW1lbnRhdG9yX2lkEIWIyLac/9XiXZoBEgoHZGVmYXVsdBDg2uShu8GCA5oBEAoLZGVmYXVsdF9hcHAQkE6aAREKBnJhbmtWMxDjsaCku8GCA5oBGgoPdHRwX3J1bGVfcmVyYW5rEMiPx6a7wYIDmgEaCg50aW1lc3RhbXBfZGVzYxC4ncPKyu3OrgGaATUKKnRpa2Nhc3RfY29tbXVuaXR5X2NvbW1lbnRfMTg4NjZfdjdfcjY1NTA2ORDhz6Wku8GCA5oBOgovdGlrY2FzdF9jb21tdW5pdHlfY29tbWVudF8xODg2Nl92N19yNjU1MDY5X2Rlc2MQn7/9qLvBggOaARoKD2lkY19ydWxlX3JlcmFuaxDIw9C5u8GCA5oBFgoLdjEzX3I3MTIwODgQyMPQubvBggOaARYKC3YxMl9yNzAyMDc1EMjD0Lm7wYIDmgEWCgt2MTNfcjc2NTE2NhDIw9C5u8GCA5oBFgoLdjEzX3I3NjUxNjcQyMPQubvBggOaARYKC3YxM19yNzY1MTY5EMjD0Lm7wYIDmgEWCgt2MTNfcjc2NzEyMhDIw9C5u8GCA5oBFgoLdjEzX3I3NzA4MDQQyMPQubvBggOaARYKC3YxM19yNzcwODA1EMjD0Lm7wYIDmgEWCgt2MTNfcjc3MDgwNhDIw9C5u8GCA5oBFgoLdjEzX3I3NzA4MDcQyMPQubvBggOaARYKC3YxM19yNzcwODA4EMjD0Lm7wYIDmgEWCgt2MTNfcjc3MDgxMBDIw9C5u8GCA5oBGgoPaWRjX3J1bGVfcmVyYW5rEMjD0Lm7wYIDogEBAA==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:07:36.364951"
|
||||
},
|
||||
{
|
||||
"eventData": "ClAKEldlYmNhc3RDaGF0TWVzc2FnZRChlqfexJ+WqWUYoZbn2LPnlallINPCsc28MTABSAJQAnoIdXNlYXN0MmGwAQG4AQLAAQLIAcy+sc28MRKfCgiFiKX0gI2FlmAaF/CfkoAgUG9yYSB1bWllcmHEhyDwn5KASvoFCrgBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9eWRWc0c3JTJCYTRUbU9XRXFPSGd6JTJCQmVRU1k2YyUzRAqmAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT02TVhuNmV6WVQzNHFVY3N1TXFRMUcxMFExZVklM0QKpgFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9ODE0Sk91T0M4ZHlvVGQ5U1Y5TkI3UjZSYjY0JTNECqwBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVhFM0toMjVCeXMwRFUlMkYlMkZVa3JlZCUyQkxadUJ4VSUzRBI8MTAweDEwMC90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxUo4DCsIBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2t4LWNvbXByZXNzX3F1YWxpdHlfMzA6NzI6NzIud2VicD94LWV4cGlyZXM9MTY5OTkxNjQwMCZ4LXNpZ25hdHVyZT1DVEs2Ukw2dWVOSlJ6Ujl0cEtKNUYzQW90cEklM0QKxgFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX50cGx2LXRpa3Rva3gtY29tcHJlc3NfcXVhbGl0eV8zMDo3Mjo3Mi5qcGVnP3gtZXhwaXJlcz0xNjk5OTE2NDAwJngtc2lnbmF0dXJlPUhUbSUyRjdYQUxBMnNKWSUyQkgxanQxM3pBR0ZzTTAlM0SyAQYIhAUQqBW6AQCCAgCyAg1kb3N0YXdjYXZpZGVv8gJMTVM0d0xqQUJBQUFBcWtGdC1FSmZHNERIVXVZeW1RQnNTX2o2ZHJVaXl0WjMzdEVNeWJ1YUdGLWlYejdfV1lJcF9qRDRwSUNWTWp3ZBoDYXNkcgJ6aJIBAjABmgEUCg51c2VyX3R5cGVfcnVsZRCgwh6aARgKEWNvbW11bml0eS1mbGFnZ2VkENm32gGaARoKDmNvbW1lbnRhdG9yX2lkEIWIpfSAjYWWYJoBEgoHZGVmYXVsdBCwxunKvMGCA5oBEAoLZGVmYXVsdF9hcHAQkE6aAREKBnJhbmtWMxDj2JLLvMGCA5oBGgoPdHRwX3J1bGVfcmVyYW5rEJj7y8+8wYIDmgEaCg50aW1lc3RhbXBfZGVzYxDosb6hye3OrgGaATUKKnRpa2Nhc3RfY29tbXVuaXR5X2NvbW1lbnRfMTg4NjZfdjdfcjY1NTA2ORCRr5TLvMGCA5oBOgovdGlrY2FzdF9jb21tdW5pdHlfY29tbWVudF8xODg2Nl92N19yNjU1MDY5X2Rlc2MQ7q3zz7zBggOaARoKD2lkY19ydWxlX3JlcmFuaxCYr9XivMGCA5oBFgoLdjEzX3I3MTIwODgQmK/V4rzBggOaARYKC3YxMl9yNzAyMDc1EJiv1eK8wYIDmgEWCgt2MTNfcjc2NTE2NhCYr9XivMGCA5oBFgoLdjEzX3I3NjUxNjcQmK/V4rzBggOaARYKC3YxM19yNzY1MTY5EJiv1eK8wYIDmgEWCgt2MTNfcjc2NzEyMhCYr9XivMGCA5oBFgoLdjEzX3I3NzA4MDQQmK/V4rzBggOaARYKC3YxM19yNzcwODA1EJiv1eK8wYIDmgEWCgt2MTNfcjc3MDgwNhCYr9XivMGCA5oBFgoLdjEzX3I3NzA4MDcQmK/V4rzBggOaARYKC3YxM19yNzcwODA4EJiv1eK8wYIDmgEWCgt2MTNfcjc3MDgxMBCYr9XivMGCA5oBGgoPaWRjX3J1bGVfcmVyYW5rEJiv1eK8wYIDogEBAA==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:13:58.973166900"
|
||||
},
|
||||
{
|
||||
"eventData": "ClAKEldlYmNhc3RDaGF0TWVzc2FnZRChlt6SlaOWqWUYoZbn2LPnlallIMLsss28MTABSAJQAnoIdXNlYXN0MmGwAQG4AQLAAQLIAY7pss28MRKZCgiFiKX0gI2FlmAaF/CfkoAgUG9yYSB1bWllcmHEhyDwn5KASvQFCrYBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9dklLVGljWFYwZEdmZmdNa0QzYzJvU1BEJTJGbjAlM0QKpgFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9ODE0Sk91T0M4ZHlvVGQ5U1Y5TkI3UjZSYjY0JTNECqYBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTZNWG42ZXpZVDM0cVVjc3VNcVExRzEwUTFlWSUzRAqoAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YTll0ZU5yaXVjcjJSeGZDVEdZR1JHJTJGNXZTYyUzRBI8MTAweDEwMC90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxUo4DCsIBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2t4LWNvbXByZXNzX3F1YWxpdHlfMzA6NzI6NzIud2VicD94LWV4cGlyZXM9MTY5OTkxNjQwMCZ4LXNpZ25hdHVyZT1DVEs2Ukw2dWVOSlJ6Ujl0cEtKNUYzQW90cEklM0QKxgFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX50cGx2LXRpa3Rva3gtY29tcHJlc3NfcXVhbGl0eV8zMDo3Mjo3Mi5qcGVnP3gtZXhwaXJlcz0xNjk5OTE2NDAwJngtc2lnbmF0dXJlPUhUbSUyRjdYQUxBMnNKWSUyQkgxanQxM3pBR0ZzTTAlM0SyAQYIhAUQqBW6AQCCAgCyAg1kb3N0YXdjYXZpZGVv8gJMTVM0d0xqQUJBQUFBcWtGdC1FSmZHNERIVXVZeW1RQnNTX2o2ZHJVaXl0WjMzdEVNeWJ1YUdGLWlYejdfV1lJcF9qRDRwSUNWTWp3ZBoDYXNkcgJ6aJIBAjABmgEUCg51c2VyX3R5cGVfcnVsZRCgwh6aARgKEWNvbW11bml0eS1mbGFnZ2VkENm32gGaARoKDmNvbW1lbnRhdG9yX2lkEIWIpfSAjYWWYJoBEgoHZGVmYXVsdBCY3pnVvMGCA5oBEAoLZGVmYXVsdF9hcHAQkE6aAREKBnJhbmtWMxDj37nZvMGCA5oBGgoPdHRwX3J1bGVfcmVyYW5rEICT/Nm8wYIDmgEaCg50aW1lc3RhbXBfZGVzYxCAmo6Xye3OrgGaATUKKnRpa2Nhc3RfY29tbXVuaXR5X2NvbW1lbnRfMTg4NjZfdjdfcjY1NTA2ORCRtrvZvMGCA5oBOgovdGlrY2FzdF9jb21tdW5pdHlfY29tbWVudF8xODg2Nl92N19yNjU1MDY5X2Rlc2MQ7rSa3rzBggOaARoKD2lkY19ydWxlX3JlcmFuaxCAx4XtvMGCA5oBFgoLdjEzX3I3MTIwODgQgMeF7bzBggOaARYKC3YxMl9yNzAyMDc1EIDHhe28wYIDmgEWCgt2MTNfcjc2NTE2NhCAx4XtvMGCA5oBFgoLdjEzX3I3NjUxNjcQgMeF7bzBggOaARYKC3YxM19yNzY1MTY5EIDHhe28wYIDmgEWCgt2MTNfcjc2NzEyMhCAx4XtvMGCA5oBFgoLdjEzX3I3NzA4MDQQgMeF7bzBggOaARYKC3YxM19yNzcwODA1EIDHhe28wYIDmgEWCgt2MTNfcjc3MDgwNhCAx4XtvMGCA5oBFgoLdjEzX3I3NzA4MDcQgMeF7bzBggOaARYKC3YxM19yNzcwODA4EIDHhe28wYIDmgEWCgt2MTNfcjc3MDgxMBCAx4XtvMGCA5oBGgoPaWRjX3J1bGVfcmVyYW5rEIDHhe28wYIDogEBAA==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:13:58.974165"
|
||||
},
|
||||
{
|
||||
"eventData": "ClAKEldlYmNhc3RDaGF0TWVzc2FnZRCglq+yx6aWqWUYoZbn2LPnlallIIPXtM28MTABSAJQAnoIdXNlYXN0MmGwAQK4AQLAAQLIAa7StM28MRKdCgiFiKX0gI2FlmAaF/CfkoAgUG9yYSB1bWllcmHEhyDwn5KASvgFCrYBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9dklLVGljWFYwZEdmZmdNa0QzYzJvU1BEJTJGbjAlM0QKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Nk1YbjZlellUMzRxVWNzdU1xUTFHMTBRMWVZJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTgxNEpPdU9DOGR5b1RkOVNWOU5CN1I2UmI2NCUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YRTNLaDI1QnlzMERVJTJGJTJGVWtyZWQlMkJMWnVCeFUlM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMVKOAwrCAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfnRwbHYtdGlrdG9reC1jb21wcmVzc19xdWFsaXR5XzMwOjcyOjcyLndlYnA/eC1leHBpcmVzPTE2OTk5MTY0MDAmeC1zaWduYXR1cmU9Q1RLNlJMNnVlTkpSelI5dHBLSjVGM0FvdHBJJTNECsYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2t4LWNvbXByZXNzX3F1YWxpdHlfMzA6NzI6NzIuanBlZz94LWV4cGlyZXM9MTY5OTkxNjQwMCZ4LXNpZ25hdHVyZT1IVG0lMkY3WEFMQTJzSlklMkJIMWp0MTN6QUdGc00wJTNEsgEGCIQFEKgVugEAggIAsgINZG9zdGF3Y2F2aWRlb/ICTE1TNHdMakFCQUFBQXFrRnQtRUpmRzRESFV1WXltUUJzU19qNmRyVWl5dFozM3RFTXlidWFHRi1pWHo3X1dZSXBfakQ0cElDVk1qd2QaCGFkYXNkYXNkcgJ0cpIBAjABmgEUCg51c2VyX3R5cGVfcnVsZRCgwh6aARgKEWNvbW11bml0eS1mbGFnZ2VkEPzApwOaARoKDmNvbW1lbnRhdG9yX2lkEIWIpfSAjYWWYJoBEgoHZGVmYXVsdBCIjsPjvMGCA5oBEAoLZGVmYXVsdF9hcHAQkE6aAREKBnJhbmtWMxDj5uDnvMGCA5oBGgoPdHRwX3J1bGVfcmVyYW5rEIi7pei8wYIDmgEaCg50aW1lc3RhbXBfZGVzYxD48eSIye3OrgGaATUKKnRpa2Nhc3RfY29tbXVuaXR5X2NvbW1lbnRfMTg4NjZfdjdfcjY1NTA2ORCam+PnvMGCA5oBOgovdGlrY2FzdF9jb21tdW5pdHlfY29tbWVudF8xODg2Nl92N19yNjU1MDY5X2Rlc2MQ5d3A7LzBggOaARoKD2lkY19ydWxlX3JlcmFuaxCI7677vMGCA5oBFgoLdjEzX3I3MTIwODgQiO+u+7zBggOaARYKC3YxMl9yNzAyMDc1EIjvrvu8wYIDmgEWCgt2MTNfcjc2NTE2NhCI7677vMGCA5oBFgoLdjEzX3I3NjUxNjcQiO+u+7zBggOaARYKC3YxM19yNzY1MTY5EIjvrvu8wYIDmgEWCgt2MTNfcjc2NzEyMhCI7677vMGCA5oBFgoLdjEzX3I3NzA4MDQQiO+u+7zBggOaARYKC3YxM19yNzcwODA1EIjvrvu8wYIDmgEWCgt2MTNfcjc3MDgwNhCI7677vMGCA5oBFgoLdjEzX3I3NzA4MDcQiO+u+7zBggOaARYKC3YxM19yNzcwODA4EIjvrvu8wYIDmgEWCgt2MTNfcjc3MDgxMBCI7677vMGCA5oBGgoPaWRjX3J1bGVfcmVyYW5rEPD2rvu8wYIDogEBAA==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:14:07.736142"
|
||||
},
|
||||
{
|
||||
"eventData": "ClAKEldlYmNhc3RDaGF0TWVzc2FnZRChlqWizKeWqWUYoZbn2LPnlallIN7Htc28MTABSAJQAnoIdXNlYXN0MmGwAQK4AQLAAQLIAafEtc28MRKdCgiFiKX0gI2FlmAaF/CfkoAgUG9yYSB1bWllcmHEhyDwn5KASvgFCrYBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9dklLVGljWFYwZEdmZmdNa0QzYzJvU1BEJTJGbjAlM0QKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Nk1YbjZlellUMzRxVWNzdU1xUTFHMTBRMWVZJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTgxNEpPdU9DOGR5b1RkOVNWOU5CN1I2UmI2NCUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YRTNLaDI1QnlzMERVJTJGJTJGVWtyZWQlMkJMWnVCeFUlM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMVKOAwrCAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfnRwbHYtdGlrdG9reC1jb21wcmVzc19xdWFsaXR5XzMwOjcyOjcyLndlYnA/eC1leHBpcmVzPTE2OTk5MTY0MDAmeC1zaWduYXR1cmU9Q1RLNlJMNnVlTkpSelI5dHBLSjVGM0FvdHBJJTNECsYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+dHBsdi10aWt0b2t4LWNvbXByZXNzX3F1YWxpdHlfMzA6NzI6NzIuanBlZz94LWV4cGlyZXM9MTY5OTkxNjQwMCZ4LXNpZ25hdHVyZT1IVG0lMkY3WEFMQTJzSlklMkJIMWp0MTN6QUdGc00wJTNEsgEGCIQFEKgVugEAggIAsgINZG9zdGF3Y2F2aWRlb/ICTE1TNHdMakFCQUFBQXFrRnQtRUpmRzRESFV1WXltUUJzU19qNmRyVWl5dFozM3RFTXlidWFHRi1pWHo3X1dZSXBfakQ0cElDVk1qd2QaA2FzZHICemiSAQIwAZoBFAoOdXNlcl90eXBlX3J1bGUQoMIemgEYChFjb21tdW5pdHktZmxhZ2dlZBDZt9oBmgEaCg5jb21tZW50YXRvcl9pZBCFiKX0gI2FlmCaARIKB2RlZmF1bHQQ+K2z6rzBggOaARAKC2RlZmF1bHRfYXBwEJBOmgERCgZyYW5rVjMQ45PD7LzBggOaARoKD3R0cF9ydWxlX3JlcmFuaxDg4pXvvMGCA5oBGgoOdGltZXN0YW1wX2Rlc2MQoMr0gcntzq4BmgE1Cip0aWtjYXN0X2NvbW11bml0eV9jb21tZW50XzE4ODY2X3Y3X3I2NTUwNjkQkerE7LzBggOaAToKL3Rpa2Nhc3RfY29tbXVuaXR5X2NvbW1lbnRfMTg4NjZfdjdfcjY1NTA2OV9kZXNjEO7oo/G8wYIDmgEaCg9pZGNfcnVsZV9yZXJhbmsQ4Jafgr3BggOaARYKC3YxM19yNzEyMDg4EOCWn4K9wYIDmgEWCgt2MTJfcjcwMjA3NRDglp+CvcGCA5oBFgoLdjEzX3I3NjUxNjYQ4Jafgr3BggOaARYKC3YxM19yNzY1MTY3EOCWn4K9wYIDmgEWCgt2MTNfcjc2NTE2ORDglp+CvcGCA5oBFgoLdjEzX3I3NjcxMjIQ4Jafgr3BggOaARYKC3YxM19yNzcwODA0EOCWn4K9wYIDmgEWCgt2MTNfcjc3MDgwNRDglp+CvcGCA5oBFgoLdjEzX3I3NzA4MDYQ4Jafgr3BggOaARYKC3YxM19yNzcwODA3EOCWn4K9wYIDmgEWCgt2MTNfcjc3MDgwOBDglp+CvcGCA5oBFgoLdjEzX3I3NzA4MTAQ4Jafgr3BggOaARoKD2lkY19ydWxlX3JlcmFuaxDglp+CvcGCA6IBAQA=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:14:22.037528800"
|
||||
}
|
||||
],
|
||||
"WebcastLiveIntroMessage": [
|
||||
{
|
||||
"eventData": "CiMKF1dlYmNhc3RMaXZlSW50cm9NZXNzYWdlEKGWofjy+rWEZRChlqH48vq1hGUYASIJR3JhbSB3IE1DKrcFCIWIpfSAjYWWYBoX8J+SgCBQb3JhIHVtaWVyYcSHIPCfkoBKvwQKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Nk1YbjZlellUMzRxVWNzdU1xUTFHMTBRMWVZJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTgxNEpPdU9DOGR5b1RkOVNWOU5CN1I2UmI2NCUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YRTNLaDI1QnlzMERVJTJGJTJGVWtyZWQlMkJMWnVCeFUlM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMYICAPICTE1TNHdMakFCQUFBQXFrRnQtRUpmRzRESFV1WXltUUJzU19qNmRyVWl5dFozM3RFTXlidWFHRi1pWHo3X1dZSXBfakQ0cElDVk1qd2QwAToeCAKqARkIAhIPcG1fbXRfaG9zdGxhYmVsGgRIb3N0QgJlbg==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:06:35.159195800"
|
||||
},
|
||||
{
|
||||
"eventData": "CiMKF1dlYmNhc3RMaXZlSW50cm9NZXNzYWdlEKGWofjy+rWEZRChlqH48vq1hGUYASIJR3JhbSB3IE1DKrcFCIWIpfSAjYWWYBoX8J+SgCBQb3JhIHVtaWVyYcSHIPCfkoBKvwQKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Nk1YbjZlellUMzRxVWNzdU1xUTFHMTBRMWVZJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTgxNEpPdU9DOGR5b1RkOVNWOU5CN1I2UmI2NCUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YRTNLaDI1QnlzMERVJTJGJTJGVWtyZWQlMkJMWnVCeFUlM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMYICAPICTE1TNHdMakFCQUFBQXFrRnQtRUpmRzRESFV1WXltUUJzU19qNmRyVWl5dFozM3RFTXlidWFHRi1pWHo3X1dZSXBfakQ0cElDVk1qd2QwAToeCAKqARkIAhIPcG1fbXRfaG9zdGxhYmVsGgRIb3N0QgJlbg==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:07:36.363450600"
|
||||
},
|
||||
{
|
||||
"eventData": "CiMKF1dlYmNhc3RMaXZlSW50cm9NZXNzYWdlEKGWofjy+rWEZRChlqH48vq1hGUYASIJR3JhbSB3IE1DKrcFCIWIpfSAjYWWYBoX8J+SgCBQb3JhIHVtaWVyYcSHIPCfkoBKvwQKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Nk1YbjZlellUMzRxVWNzdU1xUTFHMTBRMWVZJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTgxNEpPdU9DOGR5b1RkOVNWOU5CN1I2UmI2NCUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YRTNLaDI1QnlzMERVJTJGJTJGVWtyZWQlMkJMWnVCeFUlM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMYICAPICTE1TNHdMakFCQUFBQXFrRnQtRUpmRzRESFV1WXltUUJzU19qNmRyVWl5dFozM3RFTXlidWFHRi1pWHo3X1dZSXBfakQ0cElDVk1qd2QwAToeCAKqARkIAhIPcG1fbXRfaG9zdGxhYmVsGgRIb3N0QgJlbg==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:13:58.972664900"
|
||||
},
|
||||
{
|
||||
"eventData": "CiMKF1dlYmNhc3RMaXZlSW50cm9NZXNzYWdlEKGWofjy+rWEZRChlqH48vq1hGUYASIJR3JhbSB3IE1DKrcFCIWIpfSAjYWWYBoX8J+SgCBQb3JhIHVtaWVyYcSHIPCfkoBKvwQKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Nk1YbjZlellUMzRxVWNzdU1xUTFHMTBRMWVZJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvYzJjYzgwOGQ5YmJjYTlmNTVjMzM4NzQwZDIyYzM0MjF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTgxNEpPdU9DOGR5b1RkOVNWOU5CN1I2UmI2NCUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4L2MyY2M4MDhkOWJiY2E5ZjU1YzMzODc0MGQyMmMzNDIxfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YRTNLaDI1QnlzMERVJTJGJTJGVWtyZWQlMkJMWnVCeFUlM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC9jMmNjODA4ZDliYmNhOWY1NWMzMzg3NDBkMjJjMzQyMYICAPICTE1TNHdMakFCQUFBQXFrRnQtRUpmRzRESFV1WXltUUJzU19qNmRyVWl5dFozM3RFTXlidWFHRi1pWHo3X1dZSXBfakQ0cElDVk1qd2QwAToeCAKqARkIAhIPcG1fbXRfaG9zdGxhYmVsGgRIb3N0QgJlbg==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:32:09.430963500"
|
||||
}
|
||||
],
|
||||
"WebcastRoomUserSeqMessage": [
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZafuvz/lallGKGW59iz55WpZSDshp/NvDESogQSnQQIoIidor7Iw/BkGgVBbGVrc0qPAwqnAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SWpFYno1WnBmbVJxOUI0TXBnNWQxOVhNclRjJTNECqkBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1yVFlybXNoeElXdzVOWGh4Smk3JTJGSm5FbjF2OCUzRBI3MTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MLoBAIICAKgCAbICCWFsZWtzODQ1OfICTE1TNHdMakFCQUFBQUQ0WVIwS1MxRVhfNlU3Z1k0aGoyVzlaMTItVUhtYXZ4a2lQR2ItV0lIYzFzbnZyYnd5V2lvSXY3NVg1VzRlVEqiQBM3MjY5MTA2OTU4MzA4MTY0NjQwGAESngUSmQUIhoiO8qqbjuBiGgttYW5pdG91MTIyMUqDBAqZAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YWCUyQnZlV3p1b1gyT01LbUpQRmNpSjV1T0NWYyUzRAqbAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1CUDJDUnd4JTJGM3VUJTJGVHlpUkRycTIzakY1c09zJTNECpcBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPU14ekJvbWpDRWM0RGJNeVdud3N1dWtjYXFFayUzRBItMTAweDEwMC9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0ugEAggIAqAIBsgILbWFuaXRvdTEyMjHyAkxNUzR3TGpBQkFBQUFDUlhtN2d5WHpqdnJOVzhiQVgwMWRIYjRQQ0JmcHBoUUJsTFlsN3QzaVYzNjN6Qi1mOXY2djZJMVByX2UtSjNxokATNzExNTc0OTkyMzEyMzA2OTk1OBgCGAI4AQ==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:08:13.650764700"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZaf2OeClqllGKGW59iz55WpZSDStaDNvDESogQSnQQIoIidor7Iw/BkGgVBbGVrc0qPAwqnAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SWpFYno1WnBmbVJxOUI0TXBnNWQxOVhNclRjJTNECqkBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1yVFlybXNoeElXdzVOWGh4Smk3JTJGSm5FbjF2OCUzRBI3MTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MLoBAIICAKgCAbICCWFsZWtzODQ1OfICTE1TNHdMakFCQUFBQUQ0WVIwS1MxRVhfNlU3Z1k0aGoyVzlaMTItVUhtYXZ4a2lQR2ItV0lIYzFzbnZyYnd5V2lvSXY3NVg1VzRlVEqiQBM3MjY5MTA2OTU4MzA4MTY0NjQwGAEYATgC",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:08:36.238853400"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZavypSElqllGKGW59iz55WpZSCJi6HNvDESogQSnQQIoIidor7Iw/BkGgVBbGVrc0qPAwqnAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SWpFYno1WnBmbVJxOUI0TXBnNWQxOVhNclRjJTNECqkBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1yVFlybXNoeElXdzVOWGh4Smk3JTJGSm5FbjF2OCUzRBI3MTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MLoBAIICAKgCAbICCWFsZWtzODQ1OfICTE1TNHdMakFCQUFBQUQ0WVIwS1MxRVhfNlU3Z1k0aGoyVzlaMTItVUhtYXZ4a2lQR2ItV0lIYzFzbnZyYnd5V2lvSXY3NVg1VzRlVEqiQBM3MjY5MTA2OTU4MzA4MTY0NjQwGAEYATgC",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:08:46.700698300"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZabh4KFlqllGKGW59iz55WpZSC1wKHNvDESogQSnQQIoIidor7Iw/BkGgVBbGVrc0qPAwqnAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SWpFYno1WnBmbVJxOUI0TXBnNWQxOVhNclRjJTNECqkBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1yVFlybXNoeElXdzVOWGh4Smk3JTJGSm5FbjF2OCUzRBI3MTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MLoBAIICAKgCAbICCWFsZWtzODQ1OfICTE1TNHdMakFCQUFBQUQ0WVIwS1MxRVhfNlU3Z1k0aGoyVzlaMTItVUhtYXZ4a2lQR2ItV0lIYzFzbnZyYnd5V2lvSXY3NVg1VzRlVEqiQBM3MjY5MTA2OTU4MzA4MTY0NjQwGAEYATgD",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:08:53.950839200"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJaq0vC6l6llGKGW59iz55WpZSD/p/rNvDEYATgK",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:33:08.727200600"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZaTwq67l6llGKGW59iz55WpZSCzw/rNvDEYATgL",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:33:11.956418700"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJaYnoa8l6llGKGW59iz55WpZSDG7/rNvDEYAjgM",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:33:17.383803400"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZanrPO9l6llGKGW59iz55WpZSCU5PvNvDEYATgM",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:33:32.712808600"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJah8LnJl6llGKGW59iz55WpZSCks4HOvDES0QQSzAQIhoiJ4Nqz7rtjGglkb21pbmlrNTRKtQMKtQFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWdpc28vZGQzNjI3ZTVlYTRmMTIzYzk5YjgwMDczZmQyM2JhYmF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTQzTmhEU3h4cExKVlNPYmpWOWNUakVQJTJCR25vJTNECrUBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1naXNvL2RkMzYyN2U1ZWE0ZjEyM2M5OWI4MDA3M2ZkMjNiYWJhfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1XZkxXRm5ha0EzWjc0a3hIa1N3Zm9IRmVTJTJGSSUzRBJDMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZ2lzby9kZDM2MjdlNWVhNGYxMjNjOTliODAwNzNmZDIzYmFiYboBAIICAKgCAbICDmRvbWluaWt3YXNpbHVr8gJMTVM0d0xqQUJBQUFBaVpaMlpDQl94TjZlYUJwc0wyLU9xMy1yRTdmajV5ZkRWTnotZmZUUmUyWnlLd3dMdlh2ajF2all5RnJ6WXBzN6JAEzcxNjc0MDE0MTg4MzAyNjczOTgYARgCOA0=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:35:05.042649"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJa7+vLPl6llGKGW59iz55WpZSDEyITOvDES2gQS1QQIhoirsOTthPleGhBCcmFqYW4gb2tvbmVyIFhESroDCrgBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC85NWYwNzg0ZDljMGQ0ZGY1ZTI2YzRmNWNjNzU3YmVjNn5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9em1nSEN4OXVSZXNYQ1hWaDZoZEJQJTJGMCUyRldMQSUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvOTVmMDc4NGQ5YzBkNGRmNWUyNmM0ZjVjYzc1N2JlYzZ+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVJWQjNYM0N3Y1VDMkFJejIlMkZ3cFVqRDBhbjVNJTNEEkQxMDB4MTAwL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC85NWYwNzg0ZDljMGQ0ZGY1ZTI2YzRmNWNjNzU3YmVjNroBAIICAKgCAbICC2FudGVrMTI0NTcx8gJMTVM0d0xqQUJBQUFBM3M2akdBak5wbzFFdTdnWnV0Y3FPZWhIMkFzdGdYOWQwcFBJWHFYSG9KTnRDX29BcTJ5ZXNsb2tVVEpaazBUSKJAEzY4NDE1NTIxNDgyNzE2NDU3MDIYARgCOA4=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:35:56.425306600"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZbtiITbl6llGKGW59iz55WpZSDw/4nOvDEYATgO",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:37:25.577177500"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJaKs9fsl6llGKGW59iz55WpZSCa0ZLOvDESxgQSwQQIgICw8vjIy/wDGgTwn6ugSrgDCrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC8yMzYwZjk3ODViYWI3ZjFlMjBhYTMwYjZlMzA4M2E3Nn5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9RnFGTERxVWE0V0dLYUklMkJYc0Q3RklWQ3dsYkUlM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzIzNjBmOTc4NWJhYjdmMWUyMGFhMzBiNmUzMDgzYTc2fmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1idEFla3VPR1NmJTJCZ282RFFwU05GNDNFM3lnUSUzRBJEMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvMjM2MGY5Nzg1YmFiN2YxZTIwYWEzMGI2ZTMwODNhNza6AQCCAgCoAgGyAgYxanVsYWfyAkxNUzR3TGpBQkFBQUFydEh0azg5SV9HWTktUlZQc3E3VmtDV2s3SDJ4WmJLUVpoWmEwY2o0a3RxWE5uVHhhQm0zNENwV1FvWWxwT251okASMjg2MzEwOTM2MTc5NjM4MjcyGAEYATgO",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:39:46.883152900"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZbI6NLtl6llGKGW59iz55WpZSCqipPOvDEYATgP",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:39:54.132292500"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJaukoXzl6llGKGW59iz55WpZSDt25XOvDESxQQSwAQIhoimzuOSnqdiGgNPTE9KtgMKtAFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2Q5MTFhNjkxNDk3ZmUzM2M5MmQwOTUxNGVlOTBhYjkwfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1SYlZHdjVReHdwWW4zUDE2VW5lMlRJTG9wOTAlM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2Q5MTFhNjkxNDk3ZmUzM2M5MmQwOTUxNGVlOTBhYjkwfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1uN3FjRm1HYUsyTyUyQnFsNXBiNmF5VDc4eG4ybyUzRBJEMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZDkxMWE2OTE0OTdmZTMzYzkyZDA5NTE0ZWU5MGFiOTC6AQCCAgCoAgGyAgdvbG9fdjEy8gJMTVM0d0xqQUJBQUFBalFUeHpRcEZXS0RNaHdDQ3QtWWpIQ1dIM3gxRlI4UW82bm4yVkNyRjFKZlVacTFEcnZNclF4Y0VRUF9lWnAzRaJAEzcwODM3MzE4NTA1MTAzMDQyNjIYARgCOBA=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:40:37.563873900"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZaS0rvzl6llGKGW59iz55WpZSC89pXOvDEYATgQ",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:40:40.781947100"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJaSot/9l6llGKGW59iz55WpZSCe+JrOvDESzwUSygUIhoDrtqn685FcGgNlbG9KvQQKpgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC82OTJiODk3YmEzYzUwNTNiMzEyNWFmZTMxY2E5YTRkYn5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9akdJc1VBbGxESmNmbWkwaHVzME9PNHVhT0xRJTNECqYBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvNjkyYjg5N2JhM2M1MDUzYjMxMjVhZmUzMWNhOWE0ZGJ+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUdsMTh0V0tCeXA1NUVBNU1oQ1Nhd0pIaVF3dyUzRAqqAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzY5MmI4OTdiYTNjNTA1M2IzMTI1YWZlMzFjYTlhNGRifmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1JWUo1ZVVabEJnN0MlMkZEVk1pbkttbCUyRno0MDFJJTNEEjwxMDB4MTAwL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvNjkyYjg5N2JhM2M1MDUzYjMxMjVhZmUzMWNhOWE0ZGK6AQCCAgCoAgGyAgpyYW5kb21tZW1q8gJMTVM0d0xqQUJBQUFBWlZsSldueTFLQ0l6T1c2bW4xcmZBOG0yNHhLd2VKRXlHS2g4SDFVclFnZ2hoTm1zaXZxTTV4Y21nSm14ZEFuY6JAEzY2MzkzNzg3NzkwNTUyNDMyNzAYARgCOBE=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:42:03.040632200"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJbMro3+l6llGKGW59iz55WpZSCskJvOvDEYATgR",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:42:06.280761800"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoZbzooKEmKllGKGW59iz55WpZSD0/p3OvDES1QQS0AQIhoiD8tXni7lfGgZUb21zb25KuAMKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2IwYWI2N2Q4OGFhN2JhMDBmY2RlZGU5YjNlNmQxNWE0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1hREYlMkJrb2tQQ0dKRjV5cDVTTnJCNVA3MjlJOCUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvYjBhYjY3ZDg4YWE3YmEwMGZjZGVkZTliM2U2ZDE1YTR+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTYxZ0Y3VFFVSUpqWDYlMkJ6aHRJcVpjOUdRUXlBJTNEEkQxMDB4MTAwL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9iMGFiNjdkODhhYTdiYTAwZmNkZWRlOWIzZTZkMTVhNLoBAIICAKgCAbICEnVzZXIxNzA4ODEwNzM0MDUwMvICTE1TNHdMakFCQUFBQXY4T1B0OWlNaFkzSWFFTlJoZThjOXE2RkdDOFg5cDJMbmhmSnZWSm5HOWlWelZ6VnhtUnlDUi1wZFNOaFFVV1aiQBM2ODc3NjExNTIxNTY4OTgyMDIyGAEYAjgS",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:42:52.821875300"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJbr0sSEmKllGKGW59iz55WpZSDwn57OvDEYATgS",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:42:57.643174900"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJaQheGVmKllGKGW59iz55WpZSDv1abOvDESyQQSxAQImoji2K2D5aVkGgEuSrYDCrQBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kY2IzZjYyYTg4NzFlZWY2OWViZTdjZDFiZGQ1YzM1OX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9cDdqVExCMFNvUEhJeWxta3dRMVE0eXBsOTZZJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kY2IzZjYyYTg4NzFlZWY2OWViZTdjZDFiZGQ1YzM1OX5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9RHIlMkZmRVYzMm5jdnB5dXFoRTJxcVZ5WUpQTE0lM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2RjYjNmNjJhODg3MWVlZjY5ZWJlN2NkMWJkZDVjMzU5ugEAggIAqAIBsgINbGl0dGxlX2JveTAyMvICTE1TNHdMakFCQUFBQXc1TWtxMWxMazNvQ2ZidGVobnk0SlY1UkJfR3k5V3pYT3RaVmRrcVhXZXVoUzNRcjZycXBSdEtkazE5am1pcnOiQBM3MjI3MDMyODcwMTExOTcwMzMwGAEYATgS",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:45:15.031268700"
|
||||
},
|
||||
{
|
||||
"eventData": "CjYKGVdlYmNhc3RSb29tVXNlclNlcU1lc3NhZ2UQoJauqP6VmKllGKGW59iz55WpZSDe5KbOvDEYATgT",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:45:17.450676400"
|
||||
}
|
||||
],
|
||||
"WebcastMemberMessage": [
|
||||
{
|
||||
"eventData": "CtgGChRXZWJjYXN0TWVtYmVyTWVzc2FnZRChlrumyf6VqWUYoZbn2LPnlallILC4ns28MTABQpUGChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMi2gUICxIMCgcjOENFN0ZGIJADqgHGBQrDBQigiJ2ivsjD8GQaBUFsZWtzSscECrUBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUdnVUhmTHhYeVpLTkNwa2IwTkt4aERPQU5RMCUzRAqnAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SWpFYno1WnBmbVJxOUI0TXBnNWQxOVhNclRjJTNECqkBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1yVFlybXNoeElXdzVOWGh4Smk3JTJGSm5FbjF2OCUzRBI3MTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MLIBBAgaEAO6AQCCAgCyAglhbGVrczg0NTnyAkxNUzR3TGpBQkFBQUFENFlSMEtTMUVYXzZVN2dZNGhqMlc5WjEyLVVIbWF2eGtpUEdiLVdJSGMxc252cmJ3eVdpb0l2NzVYNVc0ZVRKSAFQAbABArgBAcABARLDBQigiJ2ivsjD8GQaBUFsZWtzSscECrUBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUdnVUhmTHhYeVpLTkNwa2IwTkt4aERPQU5RMCUzRAqnAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SWpFYno1WnBmbVJxOUI0TXBnNWQxOVhNclRjJTNECqkBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1yVFlybXNoeElXdzVOWGh4Smk3JTJGSm5FbjF2OCUzRBI3MTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI2OTEwNzQ4Nzk4NTg2MDY0MLIBBAgaEAO6AQCCAgCyAglhbGVrczg0NTnyAkxNUzR3TGpBQkFBQUFENFlSMEtTMUVYXzZVN2dZNGhqMlc5WjEyLVVIbWF2eGtpUEdiLVdJSGMxc252cmJ3eVdpb0l2NzVYNVc0ZVRKGAFQAZIBlQYKFWxpdmVfcm9vbV9lbnRlcl90b2FzdBIPezA6dXNlcn0gam9pbmVkGg4KCSNiOGZmZmZmZiCQAyLaBQgLEgwKByM4Q0U3RkYgkAOqAcYFCsMFCKCInaK+yMPwZBoFQWxla3NKxwQKtQFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzcyNjkxMDc0ODc5ODU4NjA2NDB+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9R2dVSGZMeFh5WktOQ3BrYjBOS3hoRE9BTlEwJTNECqcBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1JakViejVacGZtUnE5QjRNcGc1ZDE5WE1yVGMlM0QKqQFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzcyNjkxMDc0ODc5ODU4NjA2NDB+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPXJUWXJtc2h4SVd3NU5YaHhKaTclMkZKbkVuMXY4JTNEEjcxMDB4MTAwL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83MjY5MTA3NDg3OTg1ODYwNjQwsgEECBoQA7oBAIICALICCWFsZWtzODQ1OfICTE1TNHdMakFCQUFBQUQ0WVIwS1MxRVhfNlU3Z1k0aGoyVzlaMTItVUhtYXZ4a2lQR2ItV0lIYzFzbnZyYnd5V2lvSXY3NVg1VzRlVEqaARZob21lcGFnZV9ob3QtbGl2ZV9jZWxs",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:08:03.396935200"
|
||||
},
|
||||
{
|
||||
"eventData": "CsoHChRXZWJjYXN0TWVtYmVyTWVzc2FnZRChlsfK8v+VqWUYoZbn2LPnlallIJ+Ln828MTABQocHChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMizAYICxIMCgcjOENFN0ZGIJADqgG4Bgq1BgiGiI7yqpuO4GIaC21hbml0b3UxMjIxSq8FCqkBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SUQlMkJvMVJHJTJCdkpPbENQWGNjUHQ1RkZCUUs1cyUzRAqZAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YWCUyQnZlV3p1b1gyT01LbUpQRmNpSjV1T0NWYyUzRAqbAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1CUDJDUnd4JTJGM3VUJTJGVHlpUkRycTIzakY1c09zJTNECpcBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPU14ekJvbWpDRWM0RGJNeVdud3N1dWtjYXFFayUzRBItMTAweDEwMC9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0sgEGCAcQChgBugEAggIAsgILbWFuaXRvdTEyMjHyAkxNUzR3TGpBQkFBQUFDUlhtN2d5WHpqdnJOVzhiQVgwMWRIYjRQQ0JmcHBoUUJsTFlsN3QzaVYzNjN6Qi1mOXY2djZJMVByX2UtSjNxSAFQAbABArgBAcABARK1BgiGiI7yqpuO4GIaC21hbml0b3UxMjIxSq8FCqkBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SUQlMkJvMVJHJTJCdkpPbENQWGNjUHQ1RkZCUUs1cyUzRAqZAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YWCUyQnZlV3p1b1gyT01LbUpQRmNpSjV1T0NWYyUzRAqbAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1CUDJDUnd4JTJGM3VUJTJGVHlpUkRycTIzakY1c09zJTNECpcBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPU14ekJvbWpDRWM0RGJNeVdud3N1dWtjYXFFayUzRBItMTAweDEwMC9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0sgEGCAcQChgBugEAggIAsgILbWFuaXRvdTEyMjHyAkxNUzR3TGpBQkFBQUFDUlhtN2d5WHpqdnJOVzhiQVgwMWRIYjRQQ0JmcHBoUUJsTFlsN3QzaVYzNjN6Qi1mOXY2djZJMVByX2UtSjNxGAJQAZIBhwcKFWxpdmVfcm9vbV9lbnRlcl90b2FzdBIPezA6dXNlcn0gam9pbmVkGg4KCSNiOGZmZmZmZiCQAyLMBggLEgwKByM4Q0U3RkYgkAOqAbgGCrUGCIaIjvKqm47gYhoLbWFuaXRvdTEyMjFKrwUKqQFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1JRCUyQm8xUkclMkJ2Sk9sQ1BYY2NQdDVGRkJRSzVzJTNECpkBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVhYJTJCdmVXenVvWDJPTUttSlBGY2lKNXVPQ1ZjJTNECpsBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUJQMkNSd3glMkYzdVQlMkZUeWlSRHJxMjNqRjVzT3MlM0QKlwFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9TXh6Qm9takNFYzREYk15V253c3V1a2NhcUVrJTNEEi0xMDB4MTAwL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTSyAQYIBxAKGAG6AQCCAgCyAgttYW5pdG91MTIyMfICTE1TNHdMakFCQUFBQUNSWG03Z3lYemp2ck5XOGJBWDAxZEhiNFBDQmZwcGhRQmxMWWw3dDNpVjM2M3pCLWY5djZ2NkkxUHJfZS1KM3GaAQlwdXNoLXB1c2iiAQVjbGljaw==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:08:13.651263600"
|
||||
},
|
||||
{
|
||||
"eventData": "CpwIChRXZWJjYXN0TWVtYmVyTWVzc2FnZRCglsOaiYSWqWUYoZbn2LPnlallIOuPoc28MTABQtkHChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMingcICxIMCgcjOENFN0ZGIJADqgGKBwqHBwiGiKyWl8PO8mIaBnBvbGFuZEqEBgq6AWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzJlODYzYTY5NTUwMjY1OGM5NTc3M2MxNWZmYjU5MGJjfnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTRNQ2hwNlBQRlUlMkIwJTJCNHhQUzBtJTJGY2hLU2ZCVSUzRAqsAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzJlODYzYTY5NTUwMjY1OGM5NTc3M2MxNWZmYjU5MGJjfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1IWVFuJTJCMUV4Zkw1QmglMkIyU0hQbUM4TEolMkZoZnclM0QKrAFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC8yZTg2M2E2OTU1MDI2NThjOTU3NzNjMTVmZmI1OTBiY35jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9M01rSllpVE5iVVFyR2dOZSUyRiUyQnZhJTJGZ1FQN3ZJJTNECqgBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvMmU4NjNhNjk1NTAyNjU4Yzk1NzczYzE1ZmZiNTkwYmN+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVJuemRyWkQlMkJCZVVUenpUellWSGRoSURsb3lZJTNEEjwxMDB4MTAwL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvMmU4NjNhNjk1NTAyNjU4Yzk1NzczYzE1ZmZiNTkwYmOyAQcI8QwQDxgBugEAggIAsgIMYW50b25pa3Vyenlu8gJMTVM0d0xqQUJBQUFBd3lVV0FUT2RHNC1QdUYtenhhbFdoLUZzVE1YVzVScGpINzJJLUhtUjVYbzQ2OWVSTm15WFp5SDhLS2FvR1FVRkgBUAKwAQG4AQHAAQEShwcIhoislpfDzvJiGgZwb2xhbmRKhAYKugFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC8yZTg2M2E2OTU1MDI2NThjOTU3NzNjMTVmZmI1OTBiY350cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT00TUNocDZQUEZVJTJCMCUyQjR4UFMwbSUyRmNoS1NmQlUlM0QKrAFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC8yZTg2M2E2OTU1MDI2NThjOTU3NzNjMTVmZmI1OTBiY35jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SFlRbiUyQjFFeGZMNUJoJTJCMlNIUG1DOExKJTJGaGZ3JTNECqwBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvMmU4NjNhNjk1NTAyNjU4Yzk1NzczYzE1ZmZiNTkwYmN+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTNNa0pZaVROYlVRckdnTmUlMkYlMkJ2YSUyRmdRUDd2SSUzRAqoAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzJlODYzYTY5NTUwMjY1OGM5NTc3M2MxNWZmYjU5MGJjfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1SbnpkclpEJTJCQmVVVHp6VHpZVkhkaElEbG95WSUzRBI8MTAweDEwMC90b3MtbWFsaXZhLWF2dC0wMDY4LzJlODYzYTY5NTUwMjY1OGM5NTc3M2MxNWZmYjU5MGJjsgEHCPEMEA8YAboBAIICALICDGFudG9uaWt1cnp5bvICTE1TNHdMakFCQUFBQXd5VVdBVE9kRzQtUHVGLXp4YWxXaC1Gc1RNWFc1UnBqSDcySS1IbVI1WG80NjllUk5teVhaeUg4S0thb0dRVUYYAlABkgHZBwoVbGl2ZV9yb29tX2VudGVyX3RvYXN0Eg97MDp1c2VyfSBqb2luZWQaDgoJI2I4ZmZmZmZmIJADIp4HCAsSDAoHIzhDRTdGRiCQA6oBigcKhwcIhoislpfDzvJiGgZwb2xhbmRKhAYKugFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC8yZTg2M2E2OTU1MDI2NThjOTU3NzNjMTVmZmI1OTBiY350cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT00TUNocDZQUEZVJTJCMCUyQjR4UFMwbSUyRmNoS1NmQlUlM0QKrAFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC8yZTg2M2E2OTU1MDI2NThjOTU3NzNjMTVmZmI1OTBiY35jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SFlRbiUyQjFFeGZMNUJoJTJCMlNIUG1DOExKJTJGaGZ3JTNECqwBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvMmU4NjNhNjk1NTAyNjU4Yzk1NzczYzE1ZmZiNTkwYmN+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTNNa0pZaVROYlVRckdnTmUlMkYlMkJ2YSUyRmdRUDd2SSUzRAqoAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzJlODYzYTY5NTUwMjY1OGM5NTc3M2MxNWZmYjU5MGJjfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1SbnpkclpEJTJCQmVVVHp6VHpZVkhkaElEbG95WSUzRBI8MTAweDEwMC90b3MtbWFsaXZhLWF2dC0wMDY4LzJlODYzYTY5NTUwMjY1OGM5NTc3M2MxNWZmYjU5MGJjsgEHCPEMEA8YAboBAIICALICDGFudG9uaWt1cnp5bvICTE1TNHdMakFCQUFBQXd5VVdBVE9kRzQtUHVGLXp4YWxXaC1Gc1RNWFc1UnBqSDcySS1IbVI1WG80NjllUk5teVhaeUg4S0thb0dRVUaaARVpbm5lcl9wdXNoLWlubmVyX3B1c2iiAQVjbGljaw==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:08:47.493168800"
|
||||
},
|
||||
{
|
||||
"eventData": "CuIGChRXZWJjYXN0TWVtYmVyTWVzc2FnZRCglqbQ8LqXqWUYoZbn2LPnlallIM6r+s28MTABQp8GChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMi5AUICxIMCgcjOENFN0ZGIJADqgHQBQrNBQiFiJeU282M42EaCUxlbnVzaWExMUrLBAq3AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI5OTM0NjUxNDEwNTU5Nzk4NX50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1jYW5ZZTNZU3h1em9GNXVHbHJUV25lU3clMkJMRSUzRAqnAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI5OTM0NjUxNDEwNTU5Nzk4NX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9UlBzcEVkREtVMmFWTVlDWlRpSVR2QkRpSlprJTNECqsBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83Mjk5MzQ2NTE0MTA1NTk3OTg1fmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1KeGw4Y29DcHhlSXZja3o3MWFSbHl0eHAlMkYlMkY4JTNEEjcxMDB4MTAwL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC83Mjk5MzQ2NTE0MTA1NTk3OTg1sgEECAsQA7oBAIICALICC2p1c3R5bmFzeXN68gJMTVM0d0xqQUJBQUFBcXJWQkViS1RTWXVFZmVJeE5PSGx6WjhYLXVseDNIYVJYZnJZbmFtYl85Y1pOdW44R295ZWJFSXI4c2phRnE0dEgBUAKwAQG4AQHAAQESzQUIhYiXlNvNjONhGglMZW51c2lhMTFKywQKtwFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzcyOTkzNDY1MTQxMDU1OTc5ODV+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Y2FuWWUzWVN4dXpvRjV1R2xyVFduZVN3JTJCTEUlM0QKpwFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzcyOTkzNDY1MTQxMDU1OTc5ODV+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVJQc3BFZERLVTJhVk1ZQ1pUaUlUdkJEaUpaayUzRAqrAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI5OTM0NjUxNDEwNTU5Nzk4NX5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SnhsOGNvQ3B4ZUl2Y2t6NzFhUmx5dHhwJTJGJTJGOCUzRBI3MTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI5OTM0NjUxNDEwNTU5Nzk4NbIBBAgLEAO6AQCCAgCyAgtqdXN0eW5hc3lzevICTE1TNHdMakFCQUFBQXFyVkJFYktUU1l1RWZlSXhOT0hselo4WC11bHgzSGFSWGZyWW5hbWJfOWNaTnVuOEdveWViRUlyOHNqYUZxNHQYAlABkgGfBgoVbGl2ZV9yb29tX2VudGVyX3RvYXN0Eg97MDp1c2VyfSBqb2luZWQaDgoJI2I4ZmZmZmZmIJADIuQFCAsSDAoHIzhDRTdGRiCQA6oB0AUKzQUIhYiXlNvNjONhGglMZW51c2lhMTFKywQKtwFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzcyOTkzNDY1MTQxMDU1OTc5ODV+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9Y2FuWWUzWVN4dXpvRjV1R2xyVFduZVN3JTJCTEUlM0QKpwFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzcyOTkzNDY1MTQxMDU1OTc5ODV+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVJQc3BFZERLVTJhVk1ZQ1pUaUlUdkJEaUpaayUzRAqrAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI5OTM0NjUxNDEwNTU5Nzk4NX5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SnhsOGNvQ3B4ZUl2Y2t6NzFhUmx5dHhwJTJGJTJGOCUzRBI3MTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNzI5OTM0NjUxNDEwNTU5Nzk4NbIBBAgLEAO6AQCCAgCyAgtqdXN0eW5hc3lzevICTE1TNHdMakFCQUFBQXFyVkJFYktUU1l1RWZlSXhOT0hselo4WC11bHgzSGFSWGZyWW5hbWJfOWNaTnVuOEdveWViRUlyOHNqYUZxNHSaARNsaXZlX2VuZC1saXZlX2NvdmVyogEFY2xpY2s=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:33:09.521317400"
|
||||
},
|
||||
{
|
||||
"eventData": "CukHChRXZWJjYXN0TWVtYmVyTWVzc2FnZRChlsyE97uXqWUYoZbn2LPnlallIK3z+s28MTABQqYHChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMi6wYICxIMCgcjOENFN0ZGIJADqgHXBgrUBgiGiMS6yfvm6l0aJ/CfpKbigI3imYLvuI/wn6Sm4oCN4pmC77iP8J+kpuKAjeKZgu+4j0qvBQqpAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUlEJTJCbzFSRyUyQnZKT2xDUFhjY1B0NUZGQlFLNXMlM0QKmwFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9QlAyQ1J3eCUyRjN1VCUyRlR5aVJEcnEyM2pGNXNPcyUzRAqZAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1YWCUyQnZlV3p1b1gyT01LbUpQRmNpSjV1T0NWYyUzRAqXAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS9tdXNpY2FsbHktbWFsaXZhLW9iai8xNTk0ODA1MjU4MjE2NDU0fmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1HbGh4d3A3WjY0b2VLU1ZpcEFzbTk5ZU1RajAlM0QSLTEwMHgxMDAvbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NLIBBQiLARBjugEAggIAsgIPc2lrZS55b3UudG91Z2h08gJMTVM0d0xqQUJBQUFBTWhrZ1JtcWxNNlhQeW1LSEZHOEU0OVVUMXFEV2RzVUxRdG45bHh2VjhDS1ZhczZKaHhWeHhDOGdIaU4xWm10aEgBUAKwAQG4AQHAAQES1AYIhojEusn75updGifwn6Sm4oCN4pmC77iP8J+kpuKAjeKZgu+4j/CfpKbigI3imYLvuI9KrwUKqQFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1JRCUyQm8xUkclMkJ2Sk9sQ1BYY2NQdDVGRkJRSzVzJTNECpsBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUJQMkNSd3glMkYzdVQlMkZUeWlSRHJxMjNqRjVzT3MlM0QKmQFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9WFglMkJ2ZVd6dW9YMk9NS21KUEZjaUo1dU9DVmMlM0QKlwFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9R2xoeHdwN1o2NG9lS1NWaXBBc205OWVNUWowJTNEEi0xMDB4MTAwL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTSyAQUIiwEQY7oBAIICALICD3Npa2UueW91LnRvdWdodPICTE1TNHdMakFCQUFBQU1oa2dSbXFsTTZYUHltS0hGRzhFNDlVVDFxRFdkc1VMUXRuOWx4dlY4Q0tWYXM2Smh4Vnh4QzhnSGlOMVptdGgYAlABkgGmBwoVbGl2ZV9yb29tX2VudGVyX3RvYXN0Eg97MDp1c2VyfSBqb2luZWQaDgoJI2I4ZmZmZmZmIJADIusGCAsSDAoHIzhDRTdGRiCQA6oB1wYK1AYIhojEusn75updGifwn6Sm4oCN4pmC77iP8J+kpuKAjeKZgu+4j/CfpKbigI3imYLvuI9KrwUKqQFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1JRCUyQm8xUkclMkJ2Sk9sQ1BYY2NQdDVGRkJRSzVzJTNECpsBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTR+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUJQMkNSd3glMkYzdVQlMkZUeWlSRHJxMjNqRjVzT3MlM0QKmQFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9WFglMkJ2ZVd6dW9YMk9NS21KUEZjaUo1dU9DVmMlM0QKlwFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vbXVzaWNhbGx5LW1hbGl2YS1vYmovMTU5NDgwNTI1ODIxNjQ1NH5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9R2xoeHdwN1o2NG9lS1NWaXBBc205OWVNUWowJTNEEi0xMDB4MTAwL211c2ljYWxseS1tYWxpdmEtb2JqLzE1OTQ4MDUyNTgyMTY0NTSyAQUIiwEQY7oBAIICALICD3Npa2UueW91LnRvdWdodPICTE1TNHdMakFCQUFBQU1oa2dSbXFsTTZYUHltS0hGRzhFNDlVVDFxRFdkc1VMUXRuOWx4dlY4Q0tWYXM2Smh4Vnh4QzhnSGlOMVptdGiaARVsaXZlX21lcmdlLWxpdmVfY292ZXKiAQRkcmF3",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:33:18.203136100"
|
||||
},
|
||||
{
|
||||
"eventData": "CpkHChRXZWJjYXN0TWVtYmVyTWVzc2FnZRChltn8pMmXqWUYoZbn2LPnlallIIK0gc68MTABQtYGChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMimwYICxIMCgcjOENFN0ZGIJADqgGHBgqEBgiGiIng2rPuu2MaCWRvbWluaWs1NEr9BArFAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZ2lzby9kZDM2MjdlNWVhNGYxMjNjOTliODAwNzNmZDIzYmFiYX50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1hJTJCdmp3VWc1JTJCRkg4NGpwT1dFMDFIb3FMVGdZJTNECrUBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1naXNvL2RkMzYyN2U1ZWE0ZjEyM2M5OWI4MDA3M2ZkMjNiYWJhfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT00M05oRFN4eHBMSlZTT2JqVjljVGpFUCUyQkdubyUzRAq1AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZ2lzby9kZDM2MjdlNWVhNGYxMjNjOTliODAwNzNmZDIzYmFiYX5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9V2ZMV0ZuYWtBM1o3NGt4SGtTd2ZvSEZlUyUyRkklM0QSQzEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWdpc28vZGQzNjI3ZTVlYTRmMTIzYzk5YjgwMDczZmQyM2JhYmGyAQYIZRA7GAG6AQCCAgCyAg5kb21pbmlrd2FzaWx1a/ICTE1TNHdMakFCQUFBQWlaWjJaQ0JfeE42ZWFCcHNMMi1PcTMtckU3Zmo1eWZEVk56LWZmVFJlMlp5S3d3THZYdmoxdmpZeUZyellwczdIAVACsAEBuAEBwAEBEoQGCIaIieDas+67YxoJZG9taW5pazU0Sv0ECsUBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1naXNvL2RkMzYyN2U1ZWE0ZjEyM2M5OWI4MDA3M2ZkMjNiYWJhfnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPWElMkJ2andVZzUlMkJGSDg0anBPV0UwMUhvcUxUZ1klM0QKtQFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWdpc28vZGQzNjI3ZTVlYTRmMTIzYzk5YjgwMDczZmQyM2JhYmF+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTQzTmhEU3h4cExKVlNPYmpWOWNUakVQJTJCR25vJTNECrUBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1naXNvL2RkMzYyN2U1ZWE0ZjEyM2M5OWI4MDA3M2ZkMjNiYWJhfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1XZkxXRm5ha0EzWjc0a3hIa1N3Zm9IRmVTJTJGSSUzRBJDMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZ2lzby9kZDM2MjdlNWVhNGYxMjNjOTliODAwNzNmZDIzYmFiYbIBBghlEDsYAboBAIICALICDmRvbWluaWt3YXNpbHVr8gJMTVM0d0xqQUJBQUFBaVpaMlpDQl94TjZlYUJwc0wyLU9xMy1yRTdmajV5ZkRWTnotZmZUUmUyWnlLd3dMdlh2ajF2all5RnJ6WXBzNxgCUAGSAdYGChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMimwYICxIMCgcjOENFN0ZGIJADqgGHBgqEBgiGiIng2rPuu2MaCWRvbWluaWs1NEr9BArFAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZ2lzby9kZDM2MjdlNWVhNGYxMjNjOTliODAwNzNmZDIzYmFiYX50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1hJTJCdmp3VWc1JTJCRkg4NGpwT1dFMDFIb3FMVGdZJTNECrUBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1naXNvL2RkMzYyN2U1ZWE0ZjEyM2M5OWI4MDA3M2ZkMjNiYWJhfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT00M05oRFN4eHBMSlZTT2JqVjljVGpFUCUyQkdubyUzRAq1AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZ2lzby9kZDM2MjdlNWVhNGYxMjNjOTliODAwNzNmZDIzYmFiYX5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9V2ZMV0ZuYWtBM1o3NGt4SGtTd2ZvSEZlUyUyRkklM0QSQzEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWdpc28vZGQzNjI3ZTVlYTRmMTIzYzk5YjgwMDczZmQyM2JhYmGyAQYIZRA7GAG6AQCCAgCyAg5kb21pbmlrd2FzaWx1a/ICTE1TNHdMakFCQUFBQWlaWjJaQ0JfeE42ZWFCcHNMMi1PcTMtckU3Zmo1eWZEVk56LWZmVFJlMlp5S3d3THZYdmoxdmpZeUZyellwczeaARZob21lcGFnZV9ob3QtbGl2ZV9jZWxs",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:35:05.044148700"
|
||||
},
|
||||
{
|
||||
"eventData": "CqIHChRXZWJjYXN0TWVtYmVyTWVzc2FnZRChlpaS8c+XqWUYoZbn2LPnlallIKrMhM68MTABQt8GChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMipAYICxIMCgcjOENFN0ZGIJADqgGQBgqNBgiGiKuw5O2E+V4aEEJyYWphbiBva29uZXIgWERKgwUKxgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzk1ZjA3ODRkOWMwZDRkZjVlMjZjNGY1Y2M3NTdiZWM2fnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTNseVhFJTJGNWtVa0Npdlhab1YlMkZlS2lSeXliVGMlM0QKuAFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzk1ZjA3ODRkOWMwZDRkZjVlMjZjNGY1Y2M3NTdiZWM2fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT16bWdIQ3g5dVJlc1hDWFZoNmhkQlAlMkYwJTJGV0xBJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC85NWYwNzg0ZDljMGQ0ZGY1ZTI2YzRmNWNjNzU3YmVjNn5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9UlZCM1gzQ3djVUMyQUl6MiUyRndwVWpEMGFuNU0lM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzk1ZjA3ODRkOWMwZDRkZjVlMjZjNGY1Y2M3NTdiZWM2sgEFCKkBEEe6AQCCAgCyAgthbnRlazEyNDU3MfICTE1TNHdMakFCQUFBQTNzNmpHQWpOcG8xRXU3Z1p1dGNxT2VoSDJBc3RnWDlkMHBQSVhxWEhvSk50Q19vQXEyeWVzbG9rVVRKWmswVEhIAVACsAEBuAEBwAEBEo0GCIaIq7Dk7YT5XhoQQnJhamFuIG9rb25lciBYREqDBQrGAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvOTVmMDc4NGQ5YzBkNGRmNWUyNmM0ZjVjYzc1N2JlYzZ+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9M2x5WEUlMkY1a1VrQ2l2WFpvViUyRmVLaVJ5eWJUYyUzRAq4AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvOTVmMDc4NGQ5YzBkNGRmNWUyNmM0ZjVjYzc1N2JlYzZ+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPXptZ0hDeDl1UmVzWENYVmg2aGRCUCUyRjAlMkZXTEElM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzk1ZjA3ODRkOWMwZDRkZjVlMjZjNGY1Y2M3NTdiZWM2fmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1SVkIzWDNDd2NVQzJBSXoyJTJGd3BVakQwYW41TSUzRBJEMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvOTVmMDc4NGQ5YzBkNGRmNWUyNmM0ZjVjYzc1N2JlYzayAQUIqQEQR7oBAIICALICC2FudGVrMTI0NTcx8gJMTVM0d0xqQUJBQUFBM3M2akdBak5wbzFFdTdnWnV0Y3FPZWhIMkFzdGdYOWQwcFBJWHFYSG9KTnRDX29BcTJ5ZXNsb2tVVEpaazBUSBgCUAGSAd8GChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMipAYICxIMCgcjOENFN0ZGIJADqgGQBgqNBgiGiKuw5O2E+V4aEEJyYWphbiBva29uZXIgWERKgwUKxgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzk1ZjA3ODRkOWMwZDRkZjVlMjZjNGY1Y2M3NTdiZWM2fnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTNseVhFJTJGNWtVa0Npdlhab1YlMkZlS2lSeXliVGMlM0QKuAFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzk1ZjA3ODRkOWMwZDRkZjVlMjZjNGY1Y2M3NTdiZWM2fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT16bWdIQ3g5dVJlc1hDWFZoNmhkQlAlMkYwJTJGV0xBJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC85NWYwNzg0ZDljMGQ0ZGY1ZTI2YzRmNWNjNzU3YmVjNn5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9UlZCM1gzQ3djVUMyQUl6MiUyRndwVWpEMGFuNU0lM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzk1ZjA3ODRkOWMwZDRkZjVlMjZjNGY1Y2M3NTdiZWM2sgEFCKkBEEe6AQCCAgCyAgthbnRlazEyNDU3MfICTE1TNHdMakFCQUFBQTNzNmpHQWpOcG8xRXU3Z1p1dGNxT2VoSDJBc3RnWDlkMHBQSVhxWEhvSk50Q19vQXEyeWVzbG9rVVRKWmswVEiaARdzZWFyY2hfcmVzdWx0LWxpdmVfY2VsbA==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:35:57.223255400"
|
||||
},
|
||||
{
|
||||
"eventData": "CooHChRXZWJjYXN0TWVtYmVyTWVzc2FnZRCgls2G0+yXqWUYoZbn2LPnlallINXUks68MTABQscGChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMijAYICxIMCgcjOENFN0ZGIJADqgH4BQr1BQiAgLDy+MjL/AMaBPCfq6BK/QQKwgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzIzNjBmOTc4NWJhYjdmMWUyMGFhMzBiNmUzMDgzYTc2fnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPWJiSTlobVJlZzVsOE1zSkcwTzl3MDJIc2YyUSUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvMjM2MGY5Nzg1YmFiN2YxZTIwYWEzMGI2ZTMwODNhNzZ+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUZxRkxEcVVhNFdHS2FJJTJCWHNEN0ZJVkN3bGJFJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC8yMzYwZjk3ODViYWI3ZjFlMjBhYTMwYjZlMzA4M2E3Nn5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9YnRBZWt1T0dTZiUyQmdvNkRRcFNORjQzRTN5Z1ElM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzIzNjBmOTc4NWJhYjdmMWUyMGFhMzBiNmUzMDgzYTc2sgEECDgQc7oBAIICALICBjFqdWxhZ/ICTE1TNHdMakFCQUFBQXJ0SHRrODlJX0dZOS1SVlBzcTdWa0NXazdIMnhaYktRWmhaYTBjajRrdHFYTm5UeGFCbTM0Q3BXUW9ZbHBPbnVIAVACsAEBuAEBwAEBEvUFCICAsPL4yMv8AxoE8J+roEr9BArCAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvMjM2MGY5Nzg1YmFiN2YxZTIwYWEzMGI2ZTMwODNhNzZ+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9YmJJOWhtUmVnNWw4TXNKRzBPOXcwMkhzZjJRJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC8yMzYwZjk3ODViYWI3ZjFlMjBhYTMwYjZlMzA4M2E3Nn5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9RnFGTERxVWE0V0dLYUklMkJYc0Q3RklWQ3dsYkUlM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzIzNjBmOTc4NWJhYjdmMWUyMGFhMzBiNmUzMDgzYTc2fmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1idEFla3VPR1NmJTJCZ282RFFwU05GNDNFM3lnUSUzRBJEMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvMjM2MGY5Nzg1YmFiN2YxZTIwYWEzMGI2ZTMwODNhNzayAQQIOBBzugEAggIAsgIGMWp1bGFn8gJMTVM0d0xqQUJBQUFBcnRIdGs4OUlfR1k5LVJWUHNxN1ZrQ1drN0gyeFpiS1FaaFphMGNqNGt0cVhOblR4YUJtMzRDcFdRb1lscE9udRgCUAGSAccGChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMijAYICxIMCgcjOENFN0ZGIJADqgH4BQr1BQiAgLDy+MjL/AMaBPCfq6BK/QQKwgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzIzNjBmOTc4NWJhYjdmMWUyMGFhMzBiNmUzMDgzYTc2fnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPWJiSTlobVJlZzVsOE1zSkcwTzl3MDJIc2YyUSUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvMjM2MGY5Nzg1YmFiN2YxZTIwYWEzMGI2ZTMwODNhNzZ+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUZxRkxEcVVhNFdHS2FJJTJCWHNEN0ZJVkN3bGJFJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC8yMzYwZjk3ODViYWI3ZjFlMjBhYTMwYjZlMzA4M2E3Nn5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9YnRBZWt1T0dTZiUyQmdvNkRRcFNORjQzRTN5Z1ElM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzIzNjBmOTc4NWJhYjdmMWUyMGFhMzBiNmUzMDgzYTc2sgEECDgQc7oBAIICALICBjFqdWxhZ/ICTE1TNHdMakFCQUFBQXJ0SHRrODlJX0dZOS1SVlBzcTdWa0NXazdIMnhaYktRWmhaYTBjajRrdHFYTm5UeGFCbTM0Q3BXUW9ZbHBPbnWaARZob21lcGFnZV9ob3QtbGl2ZV9jZWxs",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:39:47.676401600"
|
||||
},
|
||||
{
|
||||
"eventData": "Co4HChRXZWJjYXN0TWVtYmVyTWVzc2FnZRChlrmo+vKXqWUYoZbn2LPnlallIIfelc68MTABQssGChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMikAYICxIMCgcjOENFN0ZGIJADqgH8BQr5BQiGiKbO45Kep2IaA09MT0r/BArGAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZDkxMWE2OTE0OTdmZTMzYzkyZDA5NTE0ZWU5MGFiOTB+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9bXlwMzBkJTJCUzNCRmRPZm4xV1ElMkZpbXA4WGdrMCUzRAq0AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZDkxMWE2OTE0OTdmZTMzYzkyZDA5NTE0ZWU5MGFiOTB+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVJiVkd2NVF4d3BZbjNQMTZVbmUyVElMb3A5MCUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZDkxMWE2OTE0OTdmZTMzYzkyZDA5NTE0ZWU5MGFiOTB+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPW43cWNGbUdhSzJPJTJCcWw1cGI2YXlUNzh4bjJvJTNEEkQxMDB4MTAwL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kOTExYTY5MTQ5N2ZlMzNjOTJkMDk1MTRlZTkwYWI5MLIBBgjUExDJBroBAIICALICB29sb192MTLyAkxNUzR3TGpBQkFBQUFqUVR4elFwRldLRE1od0NDdC1ZakhDV0gzeDFGUjhRbzZubjJWQ3JGMUpmVVpxMURydk1yUXhjRVFQX2VacDNFSAFQArABAbgBAcABARL5BQiGiKbO45Kep2IaA09MT0r/BArGAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZDkxMWE2OTE0OTdmZTMzYzkyZDA5NTE0ZWU5MGFiOTB+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9bXlwMzBkJTJCUzNCRmRPZm4xV1ElMkZpbXA4WGdrMCUzRAq0AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZDkxMWE2OTE0OTdmZTMzYzkyZDA5NTE0ZWU5MGFiOTB+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVJiVkd2NVF4d3BZbjNQMTZVbmUyVElMb3A5MCUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZDkxMWE2OTE0OTdmZTMzYzkyZDA5NTE0ZWU5MGFiOTB+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPW43cWNGbUdhSzJPJTJCcWw1cGI2YXlUNzh4bjJvJTNEEkQxMDB4MTAwL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kOTExYTY5MTQ5N2ZlMzNjOTJkMDk1MTRlZTkwYWI5MLIBBgjUExDJBroBAIICALICB29sb192MTLyAkxNUzR3TGpBQkFBQUFqUVR4elFwRldLRE1od0NDdC1ZakhDV0gzeDFGUjhRbzZubjJWQ3JGMUpmVVpxMURydk1yUXhjRVFQX2VacDNFGAJQAZIBywYKFWxpdmVfcm9vbV9lbnRlcl90b2FzdBIPezA6dXNlcn0gam9pbmVkGg4KCSNiOGZmZmZmZiCQAyKQBggLEgwKByM4Q0U3RkYgkAOqAfwFCvkFCIaIps7jkp6nYhoDT0xPSv8ECsYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kOTExYTY5MTQ5N2ZlMzNjOTJkMDk1MTRlZTkwYWI5MH50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1teXAzMGQlMkJTM0JGZE9mbjFXUSUyRmltcDhYZ2swJTNECrQBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kOTExYTY5MTQ5N2ZlMzNjOTJkMDk1MTRlZTkwYWI5MH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9UmJWR3Y1UXh3cFluM1AxNlVuZTJUSUxvcDkwJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kOTExYTY5MTQ5N2ZlMzNjOTJkMDk1MTRlZTkwYWI5MH5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9bjdxY0ZtR2FLMk8lMkJxbDVwYjZheVQ3OHhuMm8lM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2Q5MTFhNjkxNDk3ZmUzM2M5MmQwOTUxNGVlOTBhYjkwsgEGCNQTEMkGugEAggIAsgIHb2xvX3YxMvICTE1TNHdMakFCQUFBQWpRVHh6UXBGV0tETWh3Q0N0LVlqSENXSDN4MUZSOFFvNm5uMlZDckYxSmZVWnExRHJ2TXJReGNFUVBfZVpwM0WaARlnZW5lcmFsX3NlYXJjaC12aWRlb19oZWFkogEFY2xpY2s=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:40:37.565374200"
|
||||
},
|
||||
{
|
||||
"eventData": "CoQIChRXZWJjYXN0TWVtYmVyTWVzc2FnZRCglpuE1f2XqWUYoZbn2LPnlallIJn6ms68MTABQsEHChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMihgcICxIMCgcjOENFN0ZGIJADqgHyBgrvBgiGgOu2qfrzkVwaA2Vsb0r2BQq2AWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzY5MmI4OTdiYTNjNTA1M2IzMTI1YWZlMzFjYTlhNGRifnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPVYzM1ozJTJGRDFjcFBMbkI5Y3QxbHgyRVYxaXRjJTNECqYBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvNjkyYjg5N2JhM2M1MDUzYjMxMjVhZmUzMWNhOWE0ZGJ+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPWpHSXNVQWxsREpjZm1pMGh1czBPTzR1YU9MUSUzRAqmAWh0dHBzOi8vcDE2LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzY5MmI4OTdiYTNjNTA1M2IzMTI1YWZlMzFjYTlhNGRifmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1HbDE4dFdLQnlwNTVFQTVNaENTYXdKSGlRd3clM0QKqgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC82OTJiODk3YmEzYzUwNTNiMzEyNWFmZTMxY2E5YTRkYn5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9SVlKNWVVWmxCZzdDJTJGRFZNaW5LbWwlMkZ6NDAxSSUzRBI8MTAweDEwMC90b3MtbWFsaXZhLWF2dC0wMDY4LzY5MmI4OTdiYTNjNTA1M2IzMTI1YWZlMzFjYTlhNGRisgECEAO6AQCCAgCyAgpyYW5kb21tZW1q8gJMTVM0d0xqQUJBQUFBWlZsSldueTFLQ0l6T1c2bW4xcmZBOG0yNHhLd2VKRXlHS2g4SDFVclFnZ2hoTm1zaXZxTTV4Y21nSm14ZEFuY0gBUAKwAQG4AQHAAQES7wYIhoDrtqn685FcGgNlbG9K9gUKtgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC82OTJiODk3YmEzYzUwNTNiMzEyNWFmZTMxY2E5YTRkYn50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1WMzNaMyUyRkQxY3BQTG5COWN0MWx4MkVWMWl0YyUzRAqmAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzY5MmI4OTdiYTNjNTA1M2IzMTI1YWZlMzFjYTlhNGRifmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1qR0lzVUFsbERKY2ZtaTBodXMwT080dWFPTFElM0QKpgFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC82OTJiODk3YmEzYzUwNTNiMzEyNWFmZTMxY2E5YTRkYn5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9R2wxOHRXS0J5cDU1RUE1TWhDU2F3SkhpUXd3JTNECqoBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvNjkyYjg5N2JhM2M1MDUzYjMxMjVhZmUzMWNhOWE0ZGJ+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUlZSjVlVVpsQmc3QyUyRkRWTWluS21sJTJGejQwMUklM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC82OTJiODk3YmEzYzUwNTNiMzEyNWFmZTMxY2E5YTRkYrIBAhADugEAggIAsgIKcmFuZG9tbWVtavICTE1TNHdMakFCQUFBQVpWbEpXbnkxS0NJek9XNm1uMXJmQThtMjR4S3dlSkV5R0toOEgxVXJRZ2doaE5tc2l2cU01eGNtZ0pteGRBbmMYAlABkgHBBwoVbGl2ZV9yb29tX2VudGVyX3RvYXN0Eg97MDp1c2VyfSBqb2luZWQaDgoJI2I4ZmZmZmZmIJADIoYHCAsSDAoHIzhDRTdGRiCQA6oB8gYK7wYIhoDrtqn685FcGgNlbG9K9gUKtgFodHRwczovL3A3Ny1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC82OTJiODk3YmEzYzUwNTNiMzEyNWFmZTMxY2E5YTRkYn50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1WMzNaMyUyRkQxY3BQTG5COWN0MWx4MkVWMWl0YyUzRAqmAWh0dHBzOi8vcDc3LXNpZ24tdmEudGlrdG9rY2RuLmNvbS90b3MtbWFsaXZhLWF2dC0wMDY4LzY5MmI4OTdiYTNjNTA1M2IzMTI1YWZlMzFjYTlhNGRifmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1qR0lzVUFsbERKY2ZtaTBodXMwT080dWFPTFElM0QKpgFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC82OTJiODk3YmEzYzUwNTNiMzEyNWFmZTMxY2E5YTRkYn5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9R2wxOHRXS0J5cDU1RUE1TWhDU2F3SkhpUXd3JTNECqoBaHR0cHM6Ly9wNzctc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvNjkyYjg5N2JhM2M1MDUzYjMxMjVhZmUzMWNhOWE0ZGJ+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPUlZSjVlVVpsQmc3QyUyRkRWTWluS21sJTJGejQwMUklM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC82OTJiODk3YmEzYzUwNTNiMzEyNWFmZTMxY2E5YTRkYrIBAhADugEAggIAsgIKcmFuZG9tbWVtavICTE1TNHdMakFCQUFBQVpWbEpXbnkxS0NJek9XNm1uMXJmQThtMjR4S3dlSkV5R0toOEgxVXJRZ2doaE5tc2l2cU01eGNtZ0pteGRBbmOaARZob21lcGFnZV9ob3QtbGl2ZV9jZWxs",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:42:03.041132700"
|
||||
},
|
||||
{
|
||||
"eventData": "CqAHChRXZWJjYXN0TWVtYmVyTWVzc2FnZRCglp+O8oOYqWUYoZbn2LPnlallIPqCns68MTABQt0GChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMiogYICxIMCgcjOENFN0ZGIJADqgGOBgqLBgiGiIPy1eeLuV8aBlRvbXNvbkqFBQrKAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvYjBhYjY3ZDg4YWE3YmEwMGZjZGVkZTliM2U2ZDE1YTR+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9VGo3JTJCblhBeiUyRndEdSUyQm1iblhyaHBlWFNXJTJCajAlM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2IwYWI2N2Q4OGFhN2JhMDBmY2RlZGU5YjNlNmQxNWE0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1hREYlMkJrb2tQQ0dKRjV5cDVTTnJCNVA3MjlJOCUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvYjBhYjY3ZDg4YWE3YmEwMGZjZGVkZTliM2U2ZDE1YTR+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTYxZ0Y3VFFVSUpqWDYlMkJ6aHRJcVpjOUdRUXlBJTNEEkQxMDB4MTAwL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9iMGFiNjdkODhhYTdiYTAwZmNkZWRlOWIzZTZkMTVhNLIBBAhDEBC6AQCCAgCyAhJ1c2VyMTcwODgxMDczNDA1MDLyAkxNUzR3TGpBQkFBQUF2OE9QdDlpTWhZM0lhRU5SaGU4YzlxNkZHQzhYOXAyTG5oZkp2VkpuRzlpVnpWelZ4bVJ5Q1ItcGRTTmhRVVdWSAFQArABAbgBAcABARKLBgiGiIPy1eeLuV8aBlRvbXNvbkqFBQrKAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvYjBhYjY3ZDg4YWE3YmEwMGZjZGVkZTliM2U2ZDE1YTR+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9VGo3JTJCblhBeiUyRndEdSUyQm1iblhyaHBlWFNXJTJCajAlM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2IwYWI2N2Q4OGFhN2JhMDBmY2RlZGU5YjNlNmQxNWE0fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1hREYlMkJrb2tQQ0dKRjV5cDVTTnJCNVA3MjlJOCUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvYjBhYjY3ZDg4YWE3YmEwMGZjZGVkZTliM2U2ZDE1YTR+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPTYxZ0Y3VFFVSUpqWDYlMkJ6aHRJcVpjOUdRUXlBJTNEEkQxMDB4MTAwL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9iMGFiNjdkODhhYTdiYTAwZmNkZWRlOWIzZTZkMTVhNLIBBAhDEBC6AQCCAgCyAhJ1c2VyMTcwODgxMDczNDA1MDLyAkxNUzR3TGpBQkFBQUF2OE9QdDlpTWhZM0lhRU5SaGU4YzlxNkZHQzhYOXAyTG5oZkp2VkpuRzlpVnpWelZ4bVJ5Q1ItcGRTTmhRVVdWGAJQAZIB3QYKFWxpdmVfcm9vbV9lbnRlcl90b2FzdBIPezA6dXNlcn0gam9pbmVkGg4KCSNiOGZmZmZmZiCQAyKiBggLEgwKByM4Q0U3RkYgkAOqAY4GCosGCIaIg/LV54u5XxoGVG9tc29uSoUFCsoBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9iMGFiNjdkODhhYTdiYTAwZmNkZWRlOWIzZTZkMTVhNH50cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1UajclMkJuWEF6JTJGd0R1JTJCbWJuWHJocGVYU1clMkJqMCUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvYjBhYjY3ZDg4YWE3YmEwMGZjZGVkZTliM2U2ZDE1YTR+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPWFERiUyQmtva1BDR0pGNXlwNVNOckI1UDcyOUk4JTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9iMGFiNjdkODhhYTdiYTAwZmNkZWRlOWIzZTZkMTVhNH5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9NjFnRjdUUVVJSmpYNiUyQnpodElxWmM5R1FReUElM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2IwYWI2N2Q4OGFhN2JhMDBmY2RlZGU5YjNlNmQxNWE0sgEECEMQELoBAIICALICEnVzZXIxNzA4ODEwNzM0MDUwMvICTE1TNHdMakFCQUFBQXY4T1B0OWlNaFkzSWFFTlJoZThjOXE2RkdDOFg5cDJMbmhmSnZWSm5HOWlWelZ6VnhtUnlDUi1wZFNOaFFVV1aaARZob21lcGFnZV9ob3QtbGl2ZV9jZWxs",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:42:53.616185700"
|
||||
},
|
||||
{
|
||||
"eventData": "Co4HChRXZWJjYXN0TWVtYmVyTWVzc2FnZRCglonZ0JWYqWUYoZbn2LPnlallIJbZps68MTABQssGChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMikAYICxIMCgcjOENFN0ZGIJADqgH8BQr5BQiaiOLYrYPlpWQaAS5K/QQKxAFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2RjYjNmNjJhODg3MWVlZjY5ZWJlN2NkMWJkZDVjMzU5fnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPWlHSFByTnludTh3aTJNUSUyRmZBV1JQREc0ZURRJTNECrQBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kY2IzZjYyYTg4NzFlZWY2OWViZTdjZDFiZGQ1YzM1OX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9cDdqVExCMFNvUEhJeWxta3dRMVE0eXBsOTZZJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kY2IzZjYyYTg4NzFlZWY2OWViZTdjZDFiZGQ1YzM1OX5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9RHIlMkZmRVYzMm5jdnB5dXFoRTJxcVZ5WUpQTE0lM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2RjYjNmNjJhODg3MWVlZjY5ZWJlN2NkMWJkZDVjMzU5sgEECBEQWLoBAIICALICDWxpdHRsZV9ib3kwMjLyAkxNUzR3TGpBQkFBQUF3NU1rcTFsTGszb0NmYnRlaG55NEpWNVJCX0d5OVd6WE90WlZka3FYV2V1aFMzUXI2cnFwUnRLZGsxOWptaXJzSAFQArABAbgBAcABARL5BQiaiOLYrYPlpWQaAS5K/QQKxAFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2RjYjNmNjJhODg3MWVlZjY5ZWJlN2NkMWJkZDVjMzU5fnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNzAwMDY3NjAwJngtc2lnbmF0dXJlPWlHSFByTnludTh3aTJNUSUyRmZBV1JQREc0ZURRJTNECrQBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kY2IzZjYyYTg4NzFlZWY2OWViZTdjZDFiZGQ1YzM1OX5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9cDdqVExCMFNvUEhJeWxta3dRMVE0eXBsOTZZJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC9kY2IzZjYyYTg4NzFlZWY2OWViZTdjZDFiZGQ1YzM1OX5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9RHIlMkZmRVYzMm5jdnB5dXFoRTJxcVZ5WUpQTE0lM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2RjYjNmNjJhODg3MWVlZjY5ZWJlN2NkMWJkZDVjMzU5sgEECBEQWLoBAIICALICDWxpdHRsZV9ib3kwMjLyAkxNUzR3TGpBQkFBQUF3NU1rcTFsTGszb0NmYnRlaG55NEpWNVJCX0d5OVd6WE90WlZka3FYV2V1aFMzUXI2cnFwUnRLZGsxOWptaXJzGAJQAZIBywYKFWxpdmVfcm9vbV9lbnRlcl90b2FzdBIPezA6dXNlcn0gam9pbmVkGg4KCSNiOGZmZmZmZiCQAyKQBggLEgwKByM4Q0U3RkYgkAOqAfwFCvkFCJqI4titg+WlZBoBLkr9BArEAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZGNiM2Y2MmE4ODcxZWVmNjllYmU3Y2QxYmRkNWMzNTl+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE3MDAwNjc2MDAmeC1zaWduYXR1cmU9aUdIUHJOeW51OHdpMk1RJTJGZkFXUlBERzRlRFElM0QKtAFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2RjYjNmNjJhODg3MWVlZjY5ZWJlN2NkMWJkZDVjMzU5fmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1wN2pUTEIwU29QSEl5bG1rd1ExUTR5cGw5NlklM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwL2RjYjNmNjJhODg3MWVlZjY5ZWJlN2NkMWJkZDVjMzU5fmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTcwMDA2NzYwMCZ4LXNpZ25hdHVyZT1EciUyRmZFVjMybmN2cHl1cWhFMnFxVnlZSlBMTSUzRBJEMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvZGNiM2Y2MmE4ODcxZWVmNjllYmU3Y2QxYmRkNWMzNTmyAQQIERBYugEAggIAsgINbGl0dGxlX2JveTAyMvICTE1TNHdMakFCQUFBQXc1TWtxMWxMazNvQ2ZidGVobnk0SlY1UkJfR3k5V3pYT3RaVmRrcVhXZXVoUzNRcjZycXBSdEtkazE5am1pcnOaARVsaXZlX21lcmdlLWxpdmVfY292ZXKiAQRkcmF3",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:45:15.827938300"
|
||||
}
|
||||
],
|
||||
"WebcastControlMessage": [
|
||||
{
|
||||
"eventData": "CjQKFVdlYmNhc3RDb250cm9sTWVzc2FnZRCglq+Gv7yWqWUYoZbn2LPnlallINDPvM28MTABEAEiAA==",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:16:17.730662700"
|
||||
},
|
||||
{
|
||||
"eventData": "CjQKFVdlYmNhc3RDb250cm9sTWVzc2FnZRCgluru472WqWUYoZbn2LPnlallIJujvc28MTABEAI=",
|
||||
"uniqueId": "dostawcavideo",
|
||||
"ts": "2023-11-13T18:16:28.978931500"
|
||||
}
|
||||
]
|
||||
}
|
||||
1111
Tools-EventsCollector/src/main/resources/link.json
Normal file
1111
Tools-EventsCollector/src/main/resources/link.json
Normal file
File diff suppressed because one or more lines are too long
4389
Tools-EventsCollector/src/main/resources/log.json
Normal file
4389
Tools-EventsCollector/src/main/resources/log.json
Normal file
File diff suppressed because one or more lines are too long
1247
Tools-EventsCollector/src/main/resources/web.json
Normal file
1247
Tools-EventsCollector/src/main/resources/web.json
Normal file
File diff suppressed because one or more lines are too long
4389
Tools-EventsCollector/target/classes/log.json
Normal file
4389
Tools-EventsCollector/target/classes/log.json
Normal file
File diff suppressed because one or more lines are too long
35
Tools-EventsWebViewer/pom.xml
Normal file
35
Tools-EventsWebViewer/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>TikTokLiveJava</artifactId>
|
||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||
<version>1.3.0-Release</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>Tools-EventsWebViewer</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.javalin</groupId>
|
||||
<artifactId>javalin</artifactId>
|
||||
<version>5.6.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>2.0.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||
<artifactId>Tools-EventsCollector</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.webviewer;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||
import io.github.jwdeveloper.tiktok.webviewer.handlers.TikTokHandler;
|
||||
import io.github.jwdeveloper.tiktok.webviewer.services.TikTokCollectorService;
|
||||
import io.github.jwdeveloper.tiktok.webviewer.services.TikTokDatabaseService;
|
||||
import io.javalin.Javalin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws SQLException
|
||||
{
|
||||
var settings = new Settings();
|
||||
settings.setUserName("szalonamoniaxx");
|
||||
settings.setSessionTag("battle");
|
||||
settings.setDbName("db-battle");
|
||||
settings.setPort(8002);
|
||||
|
||||
var db = new TikTokDatabase(settings.getDbName());
|
||||
db.connect();
|
||||
|
||||
var service = new TikTokDatabaseService(db);
|
||||
var collectorService = new TikTokCollectorService(settings, db);
|
||||
var handler = new TikTokHandler(service, settings, collectorService);
|
||||
// var manager = new TikTokManager(service);
|
||||
var app = Javalin.create(config ->
|
||||
{
|
||||
config.plugins.enableCors(corsContainer ->
|
||||
{
|
||||
corsContainer.add(corsPluginConfig ->
|
||||
{
|
||||
corsPluginConfig.allowHost("http://localhost:5500");
|
||||
});
|
||||
});
|
||||
config.staticFiles.add("/public");
|
||||
}).start(settings.getPort());
|
||||
|
||||
app.get("/tiktok/status", handler::connectionStatus);
|
||||
app.get("/tiktok/connect", handler::connect);
|
||||
app.get("/tiktok/disconnect", handler::disconnect);
|
||||
|
||||
app.get("/tiktok/data/pages", handler::getDataPages);
|
||||
app.get("/tiktok/data/names", handler::getDataNames);
|
||||
app.get("/tiktok/data", handler::getData);
|
||||
|
||||
app.get("/tiktok/update", handler::updateSearch);
|
||||
app.get("/tiktok/sessions", handler::getUserSessionTags);
|
||||
app.get("/tiktok/users", handler::getUsers);
|
||||
app.get("/tiktok/data-types", handler::getDataTypes);
|
||||
}
|
||||
}
|
||||
@@ -20,14 +20,17 @@
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.api.settings;
|
||||
package io.github.jwdeveloper.tiktok.webviewer;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
public class FileDataCollectorSettings {
|
||||
public class Settings
|
||||
{
|
||||
|
||||
private File parentFile;
|
||||
}
|
||||
private int port;
|
||||
private String dbName;
|
||||
private String userName;
|
||||
private String sessionTag;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.webviewer;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.TikTokLiveTools;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ToolsExamples {
|
||||
|
||||
private static final String tiktokUser = "k.peaks";
|
||||
|
||||
private static final String db = "a";
|
||||
|
||||
private static final String sessionTag = "a";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
// runCollector();
|
||||
runCollector();
|
||||
//runTester();
|
||||
System.in.read();
|
||||
}
|
||||
|
||||
/*
|
||||
WebcastLinkMicArmies
|
||||
WebcastLinkMicBattle
|
||||
*/
|
||||
//WebcastLinkMicArmies battle data?
|
||||
//WebcastLinkMicBattlePunishFinish end of battle?
|
||||
//WebcastLinkLayerMessage send after end of battle
|
||||
// send after LinkLayer -> WebcastLinkMessage
|
||||
|
||||
private static void runCollector() {
|
||||
TikTokLiveTools.createCollector(db)
|
||||
.addUser(tiktokUser)
|
||||
.setSessionTag(sessionTag)
|
||||
.configureLiveClient(liveClientBuilder ->
|
||||
{
|
||||
liveClientBuilder.configure(clientSettings ->
|
||||
{
|
||||
clientSettings.setPrintToConsole(true);
|
||||
})
|
||||
.onComment((liveClient, event) ->
|
||||
{
|
||||
System.out.println("Chat message: " + event.getUser().getName() + " " + event.getText());
|
||||
})
|
||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info(event.getMessage().getMethod());
|
||||
});
|
||||
liveClientBuilder.onConnected((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("Connected");
|
||||
});
|
||||
}).buildAndRun();
|
||||
}
|
||||
|
||||
private static void runTester() {
|
||||
TikTokLiveTools.createTester(db)
|
||||
.setSessionTag(sessionTag)
|
||||
.setUser(tiktokUser)
|
||||
.configureLiveClient(liveClientBuilder ->
|
||||
{
|
||||
liveClientBuilder.onError((liveClient, event) ->
|
||||
{
|
||||
event.getException().printStackTrace();
|
||||
;
|
||||
});
|
||||
|
||||
liveClientBuilder.onWebsocketResponse((liveClient, event) ->
|
||||
{
|
||||
System.out.println("Response =====================================");
|
||||
for (var msg : event.getResponse().getMessagesList()) {
|
||||
System.out.println("Message -> " + msg.getMethod());
|
||||
}
|
||||
});
|
||||
liveClientBuilder.onEvent((liveClient, event) ->
|
||||
{
|
||||
System.out.println("Event -> " + event.getClass().getSimpleName());
|
||||
});
|
||||
})
|
||||
.buildAndRun();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.webviewer.handlers;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import io.github.jwdeveloper.tiktok.webviewer.Settings;
|
||||
import io.github.jwdeveloper.tiktok.webviewer.services.TikTokCollectorService;
|
||||
import io.github.jwdeveloper.tiktok.webviewer.services.TikTokDatabaseService;
|
||||
import io.javalin.http.Context;
|
||||
import lombok.Value;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class TikTokHandler {
|
||||
private final TikTokDatabaseService databaseService;
|
||||
private final Settings settings;
|
||||
private final TikTokCollectorService collectorService;
|
||||
|
||||
public TikTokHandler(TikTokDatabaseService databaseService,
|
||||
Settings settings,
|
||||
TikTokCollectorService collectorService) {
|
||||
this.databaseService = databaseService;
|
||||
this.settings = settings;
|
||||
this.collectorService = collectorService;
|
||||
}
|
||||
|
||||
|
||||
public void connect(Context context) {
|
||||
var name = context.queryParam("name");
|
||||
var sessionTag = context.queryParam("session");
|
||||
System.out.println("Session tag" + sessionTag);
|
||||
collectorService.start(name, sessionTag);
|
||||
settings.setUserName(name);
|
||||
context.status(200);
|
||||
}
|
||||
|
||||
public void connectionStatus(Context context) {
|
||||
var isWorking = collectorService.isRunning();
|
||||
var result = getGson().toJson(isWorking);
|
||||
context.result(result);
|
||||
context.status(200);
|
||||
}
|
||||
|
||||
public void disconnect(Context context) {
|
||||
|
||||
collectorService.stop();
|
||||
context.status(200);
|
||||
}
|
||||
|
||||
|
||||
public void getUsers(Context context) {
|
||||
var users = databaseService.getUsers();
|
||||
var result = getGson().toJson(users);
|
||||
context.result(result);
|
||||
context.status(200);
|
||||
}
|
||||
|
||||
public void getUserSessionTags(Context context) {
|
||||
var dataType = context.queryParam("user");
|
||||
var sessionsTags = databaseService.getSessionTag(dataType);
|
||||
|
||||
var result = getGson().toJson(sessionsTags);
|
||||
context.result(result);
|
||||
context.status(200);
|
||||
}
|
||||
|
||||
public void getDataTypes(Context context) {
|
||||
var result = getGson().toJson(List.of("event", "message", "response"));
|
||||
context.result(result);
|
||||
context.status(200);
|
||||
}
|
||||
|
||||
|
||||
public void updateSearch(Context context) {
|
||||
var userName = context.queryParam("user");
|
||||
var sessionTag = context.queryParam("session");
|
||||
|
||||
settings.setUserName(userName);
|
||||
settings.setSessionTag(sessionTag);
|
||||
context.status(200);
|
||||
}
|
||||
|
||||
|
||||
public void getDataNames(Context context) {
|
||||
var dataType = context.queryParam("type");
|
||||
var dataNames = databaseService.getDataNames(dataType, settings.getUserName(), settings.getSessionTag());
|
||||
var gson = getGson();
|
||||
|
||||
|
||||
var result = gson.toJson(dataNames);
|
||||
context.result(result);
|
||||
context.status(200);
|
||||
}
|
||||
|
||||
public void getData(Context context) {
|
||||
var page = context.queryParam("page");
|
||||
var dataType = context.queryParam("type");
|
||||
var dataName = context.queryParam("name");
|
||||
if (page == null) {
|
||||
page = "0";
|
||||
}
|
||||
|
||||
|
||||
var asProto = context.queryParam("asProto");
|
||||
var asJson = asProto == null;
|
||||
var dto = new TikTokDatabaseService.DatabaseDataDto(dataType, dataName, settings.getUserName(), settings.getSessionTag(), asJson);
|
||||
var result = databaseService.getData(dto);
|
||||
var content = result.get(Integer.parseInt(page));
|
||||
|
||||
var response = new MessageDto(content, "", dataName);
|
||||
var gson = getGson();
|
||||
context.result(gson.toJson(response));
|
||||
}
|
||||
|
||||
public void getDataPages(Context context) throws InvalidProtocolBufferException {
|
||||
var dataType = context.queryParam("type");
|
||||
var dataName = context.queryParam("name");
|
||||
|
||||
var asJson = true;
|
||||
var dto = new TikTokDatabaseService.DatabaseDataDto(dataType, dataName, settings.getUserName(), settings.getSessionTag(), asJson);
|
||||
var result = databaseService.getData(dto);
|
||||
var counter = new AtomicInteger(-1);
|
||||
var pages = result.stream().map(e ->
|
||||
{
|
||||
return "http://localhost:" + settings.getPort() + "/tiktok/data?type=" + dataType + "&page=" + counter.incrementAndGet() + "&name=" + dataName;
|
||||
}).toList();
|
||||
|
||||
var response = new PagesDto(dataName, counter.get(), pages);
|
||||
var gson = getGson();
|
||||
context.result(gson.toJson(response));
|
||||
}
|
||||
|
||||
|
||||
public Gson getGson() {
|
||||
return new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
|
||||
}
|
||||
|
||||
|
||||
@Value
|
||||
public class PagesDto {
|
||||
String eventName;
|
||||
int pages;
|
||||
List<String> links;
|
||||
}
|
||||
|
||||
|
||||
@Value
|
||||
public class MessageDto {
|
||||
String content;
|
||||
String base64;
|
||||
String eventName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.webviewer.services;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.tools.TikTokLiveTools;
|
||||
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollector;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||
import io.github.jwdeveloper.tiktok.webviewer.Settings;
|
||||
|
||||
public class TikTokCollectorService {
|
||||
private final Settings settings;
|
||||
private final TikTokDatabase database;
|
||||
|
||||
private boolean isConnected = false;
|
||||
|
||||
private DataCollector collector;
|
||||
|
||||
public TikTokCollectorService(Settings settings, TikTokDatabase database) {
|
||||
this.settings = settings;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
public void start(String user, String sessionTag) {
|
||||
stop();
|
||||
collector = createClient(user, sessionTag);
|
||||
|
||||
collector.connect();
|
||||
}
|
||||
|
||||
public boolean isRunning()
|
||||
{
|
||||
if(collector == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (collector != null) {
|
||||
collector.disconnect(true);
|
||||
}
|
||||
isConnected =false;
|
||||
collector = null;
|
||||
try {
|
||||
database.close();
|
||||
database.connect();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private DataCollector createClient(String user, String sessionTag) {
|
||||
return TikTokLiveTools.createCollector("dupa")
|
||||
.addUser(user)
|
||||
.setSessionTag(sessionTag)
|
||||
.setDatabase(database)
|
||||
.configureLiveClient(liveClientBuilder ->
|
||||
{
|
||||
liveClientBuilder.configure(clientSettings ->
|
||||
{
|
||||
clientSettings.setPrintToConsole(true);
|
||||
});
|
||||
|
||||
liveClientBuilder.onWebsocketResponse((liveClient, event) ->
|
||||
{
|
||||
for (var msg : event.getResponse().getMessagesList()) {
|
||||
System.out.println(msg.getMethod());
|
||||
}
|
||||
});
|
||||
liveClientBuilder.onDisconnected((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("Disconnected");
|
||||
isConnected = false;
|
||||
});
|
||||
liveClientBuilder.onError((liveClient, event) ->
|
||||
{
|
||||
event.getException().printStackTrace();
|
||||
});
|
||||
liveClientBuilder.onConnected((liveClient, event) ->
|
||||
{
|
||||
liveClient.getLogger().info("Connected");
|
||||
isConnected = true;
|
||||
});
|
||||
}).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.webviewer.services;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDataTableDAO;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
|
||||
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||
import io.github.jwdeveloper.tiktok.utils.ProtocolUtils;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
public class TikTokDatabaseService {
|
||||
public TikTokDatabase tikTokDatabase;
|
||||
private TikTokDataTableDAO table;
|
||||
|
||||
|
||||
public record DatabaseDataDto(String dataType, String dataName, String user, String sessionTag, boolean asJson) {
|
||||
}
|
||||
|
||||
|
||||
public TikTokDatabaseService(TikTokDatabase databaseName) {
|
||||
tikTokDatabase = databaseName;
|
||||
table = tikTokDatabase.getDataTableDAO();
|
||||
}
|
||||
|
||||
public List<String> getUsers() {
|
||||
return table.getUsers();
|
||||
}
|
||||
|
||||
public List<String> getSessionTag(String user) {
|
||||
return table.getSessionTagByUser(user);
|
||||
}
|
||||
|
||||
public List<String> getDataNames(String dataType, String user, String sessionTag) {
|
||||
|
||||
return tikTokDatabase.getDataNames(dataType, sessionTag, user);
|
||||
}
|
||||
|
||||
public List<String> getData(DatabaseDataDto dataDto) {
|
||||
var data = tikTokDatabase.getDataTableDAO().selectSessionData(dataDto.dataType(), dataDto.sessionTag(), dataDto.user());
|
||||
switch (dataDto.dataType()) {
|
||||
case "message" -> {
|
||||
return getMessages(dataDto.dataName(), data, dataDto.asJson);
|
||||
}
|
||||
case "event" -> {
|
||||
return getEvents(dataDto.dataName(), data);
|
||||
}
|
||||
case "response" -> {
|
||||
return getResponse(data,dataDto.dataName());
|
||||
}
|
||||
}
|
||||
return List.of("unknown dataType");
|
||||
}
|
||||
|
||||
|
||||
private List<String> getMessages(String messageName, List<TikTokDataTable> data, boolean asJson) {
|
||||
|
||||
var messages = data.stream()
|
||||
.filter(e -> e.getDataTypeName().equals(messageName))
|
||||
.map(e ->
|
||||
{
|
||||
|
||||
try {
|
||||
var bytes = Base64.getDecoder().decode(e.getContent());
|
||||
if (asJson == false) {
|
||||
return ProtocolUtils.getProtocolBufferStructure(bytes).toJson();
|
||||
}
|
||||
var parsedMessage = MessageUtil.getContent(messageName, bytes);
|
||||
return parsedMessage;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
|
||||
})
|
||||
.toList();
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
private List<String> getResponse(List<TikTokDataTable> data,String dataTypeName)
|
||||
{
|
||||
var messages = data.stream()
|
||||
.filter(e -> e.getDataTypeName().equals(dataTypeName))
|
||||
.map(e ->
|
||||
{
|
||||
if(e.getDataTypeName().equals("Http"))
|
||||
{
|
||||
return e.getContent();
|
||||
}
|
||||
try
|
||||
{
|
||||
var bytes = Base64.getDecoder().decode(e.getContent());
|
||||
var parsedMessage = WebcastResponse.parseFrom(bytes);
|
||||
var json = JsonUtil.toJson(parsedMessage);
|
||||
return json;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return "error";
|
||||
}
|
||||
|
||||
})
|
||||
.toList();
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
private List<String> getEvents(String dataName, List<TikTokDataTable> data) {
|
||||
var messages = data.stream()
|
||||
.filter(e -> e.getDataTypeName().equals(dataName))
|
||||
.map(TikTokDataTable::getContent)
|
||||
.toList();
|
||||
|
||||
return messages;
|
||||
}
|
||||
}
|
||||
3655
Tools-EventsWebViewer/src/main/resources/WebcastLog2.json
Normal file
3655
Tools-EventsWebViewer/src/main/resources/WebcastLog2.json
Normal file
File diff suppressed because one or more lines are too long
135
Tools-EventsWebViewer/src/main/resources/public/index.css
Normal file
135
Tools-EventsWebViewer/src/main/resources/public/index.css
Normal file
@@ -0,0 +1,135 @@
|
||||
body, html {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
color: whitesmoke;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.connect-btn
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
.dropdown
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
.dropdown-toggle
|
||||
{
|
||||
background-color: #2c2c2c;
|
||||
border-color: #2c2c2c;
|
||||
width: 100%;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.btn-primary
|
||||
{
|
||||
background-color: #2c2c2c;
|
||||
border-color: #2c2c2c;
|
||||
}
|
||||
.btn-primary:hover
|
||||
{
|
||||
background-color: #474747;
|
||||
border-color: #474747;
|
||||
}
|
||||
.margin
|
||||
{
|
||||
margin-top: 2em;
|
||||
}
|
||||
.form
|
||||
{
|
||||
|
||||
padding: 1em;
|
||||
|
||||
border-bottom: 2px solid #676767
|
||||
}
|
||||
.form-label
|
||||
{
|
||||
color: whitesmoke;
|
||||
}
|
||||
.editor-parent
|
||||
{
|
||||
height: 2000px;
|
||||
}
|
||||
.editor-container
|
||||
{
|
||||
resize: vertical;
|
||||
overflow: auto;
|
||||
}
|
||||
.list-group-item:hover
|
||||
{
|
||||
background-color: #474747;
|
||||
color: azure;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.list-group-item
|
||||
{
|
||||
background-color: #2c2c2c;
|
||||
color: azure;
|
||||
border-color: #252424;
|
||||
}
|
||||
.margin-left
|
||||
{
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
.content {
|
||||
flex-grow: 1; /* Takes up the remaining space */
|
||||
display: flex;
|
||||
}
|
||||
.col-md-10, .col-md-2 {
|
||||
padding: 0; /* Remove default padding */
|
||||
height: 100%;
|
||||
}
|
||||
.scrollable-element {
|
||||
|
||||
overflow-y: scroll; /* Enable vertical scrollbar */
|
||||
/* Other styles as needed */
|
||||
scrollbar-width: thin;
|
||||
height: 800px;
|
||||
scrollbar-color: #275c9c #000000; /* thumb and track color */
|
||||
}
|
||||
.dropdown-menu
|
||||
{
|
||||
width: 100%;
|
||||
background-color: #414040;
|
||||
color: whitesmoke;
|
||||
}
|
||||
.dropdown-item
|
||||
{
|
||||
-webkit-user-select: none; /* For webkit browsers */
|
||||
-moz-user-select: none; /* For Firefox */
|
||||
-ms-user-select: none; /* For Microsoft browsers */
|
||||
user-select: none; /* Standard syntax */
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
.dropdown-item:hover
|
||||
{
|
||||
background-color: #696868;
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
.dropdown-item:hover
|
||||
{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 10px; /* Set width of the scrollbar */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #1e1e23; /* Track color */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #123054; /* Thumb color */
|
||||
border-radius: 5px; /* Rounded corners */
|
||||
}
|
||||
136
Tools-EventsWebViewer/src/main/resources/public/index.html
Normal file
136
Tools-EventsWebViewer/src/main/resources/public/index.html
Normal file
@@ -0,0 +1,136 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
|
||||
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js"
|
||||
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
|
||||
crossorigin="anonymous"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js"
|
||||
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js" type="text/javascript"
|
||||
charset="utf-8"></script>
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/editor/editor.main.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/loader.min.js"></script>
|
||||
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/editor/editor.main.css">
|
||||
<link rel="stylesheet" , href="index.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/loader.min.js"></script>
|
||||
<script>
|
||||
require.config({
|
||||
paths: {'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs'}
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
var editor;
|
||||
var editor2;
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
editor = monaco.editor.create(document.getElementById('editor'), {
|
||||
value: [
|
||||
'Hello world!',
|
||||
].join('\n'),
|
||||
language: 'json',
|
||||
theme: 'vs-dark',
|
||||
automaticLayout: true
|
||||
});
|
||||
|
||||
editor2 = monaco.editor.create(document.getElementById('editor2'), {
|
||||
value: [
|
||||
'Hello world!',
|
||||
].join('\n'),
|
||||
language: 'json',
|
||||
theme: 'vs-dark',
|
||||
automaticLayout: true
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body class="container-fluid bg-dark">
|
||||
|
||||
|
||||
<div class="row ">
|
||||
<div class="col-2 ">
|
||||
<div class="form margin">
|
||||
<h5 >Data collector</h5>
|
||||
<div class="form-group ">
|
||||
<label for="name" class="form-label">TikTok username</label>
|
||||
<input type="text" id="name" class="form-control">
|
||||
</div>
|
||||
<div class="form-group ">
|
||||
<label class="form-label">SessionTag</label>
|
||||
<input type="text" id="sessionTag" class="form-control">
|
||||
</div>
|
||||
<button id="connectionButton" type="button" class="btn btn-primary mt-3 connect-btn">Connect </button>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="dropdown mt-3" id="usersDropDown">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" id="usersDropDownButton"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
User
|
||||
</button>
|
||||
<div id="userDropdownContent" class="dropdown-menu" aria-labelledby="usersDropDownButton">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dropdown mt-3" id="sessionTagDropDown">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" id="sessionTagDropDownButton"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
SessionTag
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="sessionTagDropDownButton">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dropdown mt-3" id="dataTypeDropDown">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Data Type
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<ul id="dataList" class="list-group scrollable-element">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-10 margin">
|
||||
<nav aria-label="Page navigation example">
|
||||
<ul id="pages" class="pagination">
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="row editor-parent">
|
||||
<div class="col-6 editor-container" id="editor"></div>
|
||||
<div class="col-6 editor-container" id="editor2"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="index.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
205
Tools-EventsWebViewer/src/main/resources/public/index.js
Normal file
205
Tools-EventsWebViewer/src/main/resources/public/index.js
Normal file
@@ -0,0 +1,205 @@
|
||||
var dataType = "messages"
|
||||
var connected = false;
|
||||
var paginationIndex = 0;
|
||||
var maxPages = 10;
|
||||
var pages = [];
|
||||
var userName = "";
|
||||
|
||||
var port = 8002;
|
||||
var baseUrl = `http://localhost:${port}`
|
||||
|
||||
var data =
|
||||
{
|
||||
dataType: "event",
|
||||
dataName: "",
|
||||
user: "",
|
||||
sessionTag: "",
|
||||
page: 0,
|
||||
|
||||
collector:
|
||||
{
|
||||
connected: false,
|
||||
user: "",
|
||||
sessionTag: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dropDown("usersDropDown", () => `${baseUrl}/tiktok/users`, async (e) => {
|
||||
data.user = e;
|
||||
update();
|
||||
|
||||
})
|
||||
|
||||
dropDown("dataTypeDropDown", () => `${baseUrl}/tiktok/data-types`, async (e) => {
|
||||
data.dataType = e;
|
||||
update();
|
||||
})
|
||||
|
||||
dropDown("sessionTagDropDown", () => `${baseUrl}/tiktok/sessions?user=${data.user}`, async (e) => {
|
||||
data.sessionTag = e;
|
||||
update();
|
||||
})
|
||||
|
||||
|
||||
function update() {
|
||||
new Promise(async function (resolve, reject) {
|
||||
await updateAsync();
|
||||
resolve(true);
|
||||
});
|
||||
}
|
||||
|
||||
async function updateAsync() {
|
||||
console.log("Updating", data);
|
||||
await updateConnectionButton()
|
||||
await updateDataNamesList(async (dataName) => {
|
||||
data.dataName = dataName;
|
||||
data.page = 0;
|
||||
await updateContent(`${baseUrl}/tiktok/data?name=${data.dataName}&type=${data.dataType}&page=${data.page}`);
|
||||
await updatePagination(async (page, link) => {
|
||||
data.page = page;
|
||||
await updateContent(link)
|
||||
});
|
||||
});
|
||||
await fetch(`${baseUrl}/tiktok/update?user=${data.user}&session=${data.sessionTag}`);
|
||||
}
|
||||
|
||||
async function updatePagination(onSelect) {
|
||||
let response = await fetch(`${baseUrl}/tiktok/data/pages?name=${data.dataName}&type=${data.dataType}`);
|
||||
let json = await response.text();
|
||||
let object = JSON.parse(json);
|
||||
let pages = object.links;
|
||||
$("#pages").empty();
|
||||
let page = 0;
|
||||
$.each(pages, function (index, element) {
|
||||
|
||||
let currentPage = page;
|
||||
page++;
|
||||
let content = $('<button>', {
|
||||
class: 'btn btn-primary margin-left',
|
||||
text: index
|
||||
}).click(async function () {
|
||||
|
||||
await onSelect(currentPage, element);
|
||||
});
|
||||
$("#pages").append(content);
|
||||
});
|
||||
}
|
||||
|
||||
async function updateContent(link) {
|
||||
console.log("updating content", data)
|
||||
let response = await fetch(link);
|
||||
let json = await response.text();
|
||||
console.log(link)
|
||||
let root = JSON.parse(json);
|
||||
editor.setValue(root.content);
|
||||
$("#editor2").hide()
|
||||
if (data.dataType === 'message') {
|
||||
console.log("sending proto version")
|
||||
let response2 = await fetch(`${link}&asProto=true`);
|
||||
let json2 = await response2.text();
|
||||
let root2 = JSON.parse(json2);
|
||||
editor2.setValue(root2.content);
|
||||
$("#editor2").show()
|
||||
}
|
||||
|
||||
if (data.dataType === 'response' && data.dataName === 'Http') {
|
||||
|
||||
var content = JSON.parse(root.content);
|
||||
var body = JSON.parse(content.request.body)
|
||||
var asJson = JSON.stringify(body, null, 2)
|
||||
editor2.setValue(asJson);
|
||||
$("#editor2").show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function updateDataNamesList(onSelect) {
|
||||
let response = await fetch(`${baseUrl}/tiktok/data/names?type=${data.dataType}`);
|
||||
let json = await response.text();
|
||||
let responce = JSON.parse(json);
|
||||
let element = $("#dataList");
|
||||
console.log(responce)
|
||||
element.empty();
|
||||
$.each(responce, function (index, dataName) {
|
||||
let listItem = $('<li>', {
|
||||
class: 'list-group-item',
|
||||
text: dataName
|
||||
}).click(async function () {
|
||||
onSelect(dataName)
|
||||
});
|
||||
element.append(listItem);
|
||||
});
|
||||
}
|
||||
|
||||
function dropDown(elementId, onUrl, onSelect) {
|
||||
let dropDown = $("#" + elementId);
|
||||
dropDown.on('show.bs.dropdown', async function (e, b) {
|
||||
let response = await fetch(onUrl());
|
||||
let json = await response.text();
|
||||
let values = JSON.parse(json);
|
||||
let optionsElement = dropDown.find("div")
|
||||
optionsElement.empty();
|
||||
let displayElement = dropDown.find("button")
|
||||
for (let value of values) {
|
||||
let dropDownItem = $('<p>', {
|
||||
class: 'dropdown-item',
|
||||
text: value
|
||||
}).click(async function () {
|
||||
displayElement.text(value)
|
||||
onSelect(value)
|
||||
});
|
||||
optionsElement.append(dropDownItem)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
new Promise(async (a, b) => {
|
||||
await updateConnectionButton()
|
||||
});
|
||||
}, 1000)
|
||||
|
||||
|
||||
$("#connectionButton").on('click', async (a) => {
|
||||
|
||||
if (!data.collector.connected) {
|
||||
console.log("connecting")
|
||||
await connect()
|
||||
} else {
|
||||
console.log("disconnecting")
|
||||
await disconnect()
|
||||
}
|
||||
});
|
||||
|
||||
async function updateConnectionButton() {
|
||||
let button = $("#connectionButton");
|
||||
let response = await fetch(`${baseUrl}/tiktok/status`);
|
||||
let json = await response.text();
|
||||
let values = JSON.parse(json);
|
||||
console.log(values)
|
||||
data.collector.connected = values;
|
||||
if (data.collector.connected) {
|
||||
button.text("disconnect");
|
||||
} else {
|
||||
button.text("connect");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function connect() {
|
||||
let name = document.getElementById('name').value;
|
||||
let session = document.getElementById('sessionTag').value;
|
||||
data.collector.name = name
|
||||
data.collector.sessionTag = session
|
||||
|
||||
let response = await fetch(`${baseUrl}/tiktok/connect?name=${data.collector.name}&session=${data.collector.sessionTag}`);
|
||||
let greeting = await response.text();
|
||||
}
|
||||
|
||||
async function disconnect() {
|
||||
let response = await fetch(`${baseUrl}/tiktok/disconnect`);
|
||||
let greeting = await response.text();
|
||||
}
|
||||
|
||||
update()
|
||||
@@ -22,34 +22,19 @@
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.extension.collector;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.FileDataCollectorSettings;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.mongo.MongoDataCollectorSettings;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.impl.*;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.impl.storages.FileStorage;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.impl.storages.MongoStorage;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.LiveDataCollector;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.data.LiveDataCollectorSettings;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.impl.TikTokLiveDataCollector;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class TikTokLiveCollector
|
||||
{
|
||||
|
||||
public static DataCollector useMongo(Consumer<MongoDataCollectorSettings> consumer) {
|
||||
var settings = new MongoDataCollectorSettings();
|
||||
public static TikTokLiveDataCollector use(Consumer<LiveDataCollectorSettings> consumer)
|
||||
{
|
||||
var settings = new LiveDataCollectorSettings();
|
||||
consumer.accept(settings);
|
||||
|
||||
var storage = new MongoStorage(settings);
|
||||
return new DataCollector(storage);
|
||||
return new TikTokLiveDataCollector(settings);
|
||||
}
|
||||
|
||||
public static DataCollector useFile(Consumer<FileDataCollectorSettings> consumer) {
|
||||
var settings = new FileDataCollectorSettings();
|
||||
consumer.accept(settings);
|
||||
|
||||
var storage = new FileStorage(settings);
|
||||
return new DataCollector(storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.api;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
public interface Storage {
|
||||
void connect();
|
||||
|
||||
void disconnect();
|
||||
|
||||
void insert(Document document);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.api.settings;
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.api.data;
|
||||
|
||||
import lombok.Data;
|
||||
import org.bson.Document;
|
||||
@@ -10,4 +10,4 @@ import java.util.function.Function;
|
||||
public class CollectorListenerSettings {
|
||||
private Map<String, Object> extraFields;
|
||||
private Function<Document, Boolean> filter;
|
||||
}
|
||||
}
|
||||
@@ -20,25 +20,29 @@
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.api.settings.mongo;
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.api.data;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Data
|
||||
public class MongoDataCollectorSettings {
|
||||
public class LiveDataCollectorSettings {
|
||||
|
||||
@Setter
|
||||
private String connectionUrl;
|
||||
|
||||
private String databaseName = "tiktok";
|
||||
private String databaseName;
|
||||
|
||||
private String collectionName = "data";
|
||||
private String sessionTag;
|
||||
|
||||
public void connectionBuilder(Consumer<MongoDBConnectionStringBuilder> consumer) {
|
||||
|
||||
public void setConnectionUrl(String connectionUrl) {
|
||||
this.connectionUrl = connectionUrl;
|
||||
}
|
||||
|
||||
public void setConnectionUrl(Consumer<MongoDBConnectionStringBuilder> consumer) {
|
||||
var builder = new MongoDBConnectionStringBuilder();
|
||||
consumer.accept(builder);
|
||||
connectionUrl = builder.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,21 +20,36 @@
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.api.settings.mongo;
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.api.data;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
public class MongoDBConnectionStringBuilder {
|
||||
private String username;
|
||||
private String password;
|
||||
private String database;
|
||||
private String cluster;
|
||||
|
||||
public MongoDBConnectionStringBuilder setUsername(String username) {
|
||||
this.username = username;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MongoDBConnectionStringBuilder setPassword(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MongoDBConnectionStringBuilder setDatabase(String database) {
|
||||
this.database = database;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MongoDBConnectionStringBuilder setCluster(String cluster) {
|
||||
this.cluster = cluster;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String build() {
|
||||
return String.format("mongodb+srv://%s:%s@%s/%s?retryWrites=true&w=majority",
|
||||
username, password, cluster, database);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.impl;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.CollectorListenerSettings;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class DataCollector {
|
||||
|
||||
private final Storage storage;
|
||||
|
||||
public DataCollector(Storage storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
storage.connect();
|
||||
}
|
||||
public void disconnect() {
|
||||
storage.disconnect();
|
||||
}
|
||||
|
||||
public DataCollectorListener newListener() {
|
||||
return newListener(Map.of());
|
||||
}
|
||||
|
||||
public DataCollectorListener newListener(Map<String, Object> additionalFields) {
|
||||
return newListener(additionalFields, (e) -> true);
|
||||
}
|
||||
|
||||
public DataCollectorListener newListener(Map<String, Object> additionalFields,
|
||||
Function<Document, Boolean> filter) {
|
||||
var settings = new CollectorListenerSettings();
|
||||
settings.setExtraFields(additionalFields);
|
||||
settings.setFilter(filter);
|
||||
return new DataCollectorListener(storage, settings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.impl;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.ServerApi;
|
||||
import com.mongodb.ServerApiVersion;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.model.Indexes;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.data.CollectorListenerSettings;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.data.LiveDataCollectorSettings;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class TikTokLiveDataCollector {
|
||||
|
||||
private final LiveDataCollectorSettings settings;
|
||||
private MongoClient mongoClient;
|
||||
private MongoDatabase database;
|
||||
private MongoCollection<Document> collection;
|
||||
|
||||
public TikTokLiveDataCollector(LiveDataCollectorSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
|
||||
public void connectDatabase() {
|
||||
var serverApi = ServerApi.builder()
|
||||
.version(ServerApiVersion.V1)
|
||||
.build();
|
||||
var mongoSettings = MongoClientSettings.builder()
|
||||
.applyConnectionString(new ConnectionString(settings.getConnectionUrl()))
|
||||
.serverApi(serverApi)
|
||||
.build();
|
||||
|
||||
mongoClient = MongoClients.create(mongoSettings);
|
||||
database = mongoClient.getDatabase(settings.getDatabaseName());
|
||||
collection = database.getCollection("data");
|
||||
collection.createIndex(Indexes.hashed("session"));
|
||||
collection.createIndex(Indexes.hashed("dataType"));
|
||||
}
|
||||
|
||||
|
||||
public void disconnectDatabase() {
|
||||
mongoClient.close();
|
||||
}
|
||||
|
||||
public TikTokLiveDataCollectorListener newListener() {
|
||||
return newListener(Map.of());
|
||||
}
|
||||
|
||||
public TikTokLiveDataCollectorListener newListener(Map<String, Object> additionalFields) {
|
||||
return newListener(additionalFields, (e)->true);
|
||||
}
|
||||
|
||||
public TikTokLiveDataCollectorListener newListener(Map<String, Object> additionalFields,
|
||||
Function<Document, Boolean> filter) {
|
||||
var settings = new CollectorListenerSettings();
|
||||
settings.setExtraFields(additionalFields);
|
||||
settings.setFilter(filter);
|
||||
return new TikTokLiveDataCollectorListener(collection, settings);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.impl;
|
||||
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
@@ -7,8 +8,7 @@ import io.github.jwdeveloper.tiktok.data.events.control.TikTokConnectingEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.LiveDataCollector;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.CollectorListenerSettings;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.data.CollectorListenerSettings;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||
@@ -19,15 +19,15 @@ import java.io.StringWriter;
|
||||
import java.util.Base64;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DataCollectorListener implements LiveDataCollector {
|
||||
public class TikTokLiveDataCollectorListener implements LiveDataCollector {
|
||||
|
||||
private final Storage storage;
|
||||
private final MongoCollection<Document> collection;
|
||||
private final CollectorListenerSettings settings;
|
||||
private String sessionId;
|
||||
private String userName;
|
||||
|
||||
public DataCollectorListener(Storage collection, CollectorListenerSettings settings) {
|
||||
this.storage = collection;
|
||||
public TikTokLiveDataCollectorListener(MongoCollection<Document> collection, CollectorListenerSettings settings) {
|
||||
this.collection = collection;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,10 @@ public class DataCollectorListener implements LiveDataCollector {
|
||||
@TikTokEventObserver
|
||||
private void onResponse(LiveClient liveClient, TikTokWebsocketResponseEvent event) {
|
||||
includeResponse(liveClient, event.getResponse());
|
||||
event.getResponse().getMessagesList().forEach(message -> includeMessage(liveClient, message));
|
||||
event.getResponse().getMessagesList().forEach(message ->
|
||||
{
|
||||
includeMessage(liveClient, message);
|
||||
});
|
||||
}
|
||||
|
||||
@TikTokEventObserver
|
||||
@@ -100,7 +103,7 @@ public class DataCollectorListener implements LiveDataCollector {
|
||||
if (!settings.getFilter().apply(document)) {
|
||||
return;
|
||||
}
|
||||
storage.insert(document);
|
||||
collection.insertOne(document);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,4 +119,4 @@ public class DataCollectorListener implements LiveDataCollector {
|
||||
doc.append("content", content);
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.impl.storages;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.FileDataCollectorSettings;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
public class FileStorage implements Storage {
|
||||
|
||||
private final FileDataCollectorSettings settings;
|
||||
|
||||
public FileStorage(FileDataCollectorSettings fileDataCollectorSettings) {
|
||||
this.settings = fileDataCollectorSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Document document) {
|
||||
var fileName = document.get("dataType") + ":" + document.get("dataTypeName") + ".json";
|
||||
try {
|
||||
var file = new File(settings.getParentFile(), fileName);
|
||||
file.createNewFile();
|
||||
Files.writeString(file.toPath(), document.toJson(), StandardOpenOption.APPEND);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package io.github.jwdeveloper.tiktok.extension.collector.impl.storages;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.ServerApi;
|
||||
import com.mongodb.ServerApiVersion;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.model.Indexes;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
|
||||
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.mongo.MongoDataCollectorSettings;
|
||||
import org.bson.Document;
|
||||
|
||||
public class MongoStorage implements Storage {
|
||||
private MongoClient mongoClient;
|
||||
private MongoDatabase database;
|
||||
private MongoCollection<Document> collection;
|
||||
private final MongoDataCollectorSettings settings;
|
||||
|
||||
public MongoStorage(MongoDataCollectorSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
|
||||
var serverApi = ServerApi.builder()
|
||||
.version(ServerApiVersion.V1)
|
||||
.build();
|
||||
var mongoSettings = MongoClientSettings.builder()
|
||||
.applyConnectionString(new ConnectionString(settings.getConnectionUrl()))
|
||||
.serverApi(serverApi)
|
||||
.build();
|
||||
|
||||
mongoClient = MongoClients.create(mongoSettings);
|
||||
database = mongoClient.getDatabase(settings.getDatabaseName());
|
||||
collection = database.getCollection(settings.getCollectionName());
|
||||
collection.createIndex(Indexes.hashed("session"));
|
||||
collection.createIndex(Indexes.hashed("dataType"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
|
||||
if (mongoClient == null) {
|
||||
return;
|
||||
}
|
||||
mongoClient.close();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void insert(Document document) {
|
||||
collection.insertOne(document);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user