mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-27 16:59:39 -05:00
Compare commits
40 Commits
develop-1-
...
1.0.12-Rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81ac92fb33 | ||
|
|
34a78b5435 | ||
|
|
534cb7906d | ||
|
|
0bb8edfe5c | ||
|
|
4979c1b27a | ||
|
|
f7c8ffdaa5 | ||
|
|
c1fda687d3 | ||
|
|
05c49c4545 | ||
|
|
7d36f36cee | ||
|
|
f8a716429d | ||
|
|
fee805f0ea | ||
|
|
1733102aff | ||
|
|
89f54d5976 | ||
|
|
39055b5f3a | ||
|
|
cd9e9ead85 | ||
|
|
5a2d2d23f0 | ||
|
|
3eed982d6b | ||
|
|
385560de3a | ||
|
|
2e37b6627b | ||
|
|
c4f0d63b43 | ||
|
|
15550ed703 | ||
|
|
c7d84218f2 | ||
|
|
1ecd192539 | ||
|
|
d6c0d50ac3 | ||
|
|
b4997da0a8 | ||
|
|
82990665b8 | ||
|
|
155b47977d | ||
|
|
3e262773a4 | ||
|
|
89fbeb848b | ||
|
|
aa99c5929b | ||
|
|
4dd866c6cc | ||
|
|
0d384f0fdc | ||
|
|
4f3ec1c6d9 | ||
|
|
31075e5f09 | ||
|
|
33a3f7afb8 | ||
|
|
6c888c5d5b | ||
|
|
214aa3b1ff | ||
|
|
3f2c9083d5 | ||
|
|
450014759c | ||
|
|
790f568244 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,10 +1,10 @@
|
|||||||
backend-infrastructure/.aws-sam
|
backend-infrastructure/.aws-sam
|
||||||
|
|
||||||
# Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode
|
# Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode
|
||||||
|
*.db
|
||||||
### Linux ###
|
### Linux ###
|
||||||
*~
|
*~
|
||||||
|
.db
|
||||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
.fuse_hidden*
|
.fuse_hidden*
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.11-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>API</artifactId>
|
<artifactId>API</artifactId>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class ClientSettings {
|
|||||||
* Whether to print Logs to Console
|
* Whether to print Logs to Console
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private boolean printToConsole;
|
private boolean printToConsole = true;
|
||||||
/**
|
/**
|
||||||
* LoggingLevel for Logs
|
* LoggingLevel for Logs
|
||||||
*/
|
*/
|
||||||
@@ -64,7 +64,7 @@ public class ClientSettings {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional: Use it if you need to change TikTok live hostname in builder
|
* Optional: Use it if you need to change TikTok live hostname in builder
|
||||||
*/
|
*/
|
||||||
private String hostName;
|
private String hostName;
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface TikTokEventHandler
|
public @interface TikTokEventObserver
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -47,11 +47,11 @@ public class TikTokCommentEvent extends TikTokHeaderEvent {
|
|||||||
|
|
||||||
public TikTokCommentEvent(WebcastChatMessage msg) {
|
public TikTokCommentEvent(WebcastChatMessage msg) {
|
||||||
super(msg.getCommon());
|
super(msg.getCommon());
|
||||||
user = User.map(msg.getUser());
|
user = User.map(msg.getUser(),msg.getUserIdentity());
|
||||||
text = msg.getContent();
|
text = msg.getContent();
|
||||||
visibleToSender = msg.getVisibleToSender();
|
visibleToSender = msg.getVisibleToSender();
|
||||||
getUserLanguage = msg.getContentLanguage();
|
getUserLanguage = msg.getContentLanguage();
|
||||||
mentionedUser = User.map(msg.getAtUser(),msg.getUserIdentity());
|
mentionedUser = User.map(msg.getAtUser());
|
||||||
pictures = msg.getEmotesListList().stream().map(e -> Picture.map(e.getEmote().getImage())).toList();
|
pictures = msg.getEmotesListList().stream().map(e -> Picture.map(e.getEmote().getImage())).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
|||||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ import lombok.Getter;
|
|||||||
* <p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
* <p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||||
* <p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
* <p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||||
* <p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
* <p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
||||||
*
|
* <p>
|
||||||
* Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
* Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||||
*/
|
*/
|
||||||
@EventMeta(eventType = EventType.Message)
|
@EventMeta(eventType = EventType.Message)
|
||||||
@@ -48,8 +49,8 @@ import lombok.Getter;
|
|||||||
public class TikTokGiftComboEvent extends TikTokGiftEvent {
|
public class TikTokGiftComboEvent extends TikTokGiftEvent {
|
||||||
private final GiftSendType comboState;
|
private final GiftSendType comboState;
|
||||||
|
|
||||||
public TikTokGiftComboEvent(Gift gift, WebcastGiftMessage msg, GiftSendType comboState) {
|
public TikTokGiftComboEvent(Gift gift, User host, WebcastGiftMessage msg, GiftSendType comboState) {
|
||||||
super(gift, msg);
|
super(gift, host, msg);
|
||||||
this.comboState = comboState;
|
this.comboState = comboState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,28 +26,38 @@ package io.github.jwdeveloper.tiktok.data.events.gift;
|
|||||||
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
|
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.Gift;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/*
|
|
||||||
|
/**
|
||||||
* Triggered when user sends gifts that has
|
* Triggered when user sends gifts that has
|
||||||
* no combo (most of expensive gifts)
|
* no combo (most of expensive gifts)
|
||||||
* or if combo has finished
|
* or if combo has finished
|
||||||
*/
|
*/
|
||||||
@EventMeta(eventType = EventType.Message)
|
@EventMeta(eventType = EventType.Message)
|
||||||
@Getter
|
@Getter
|
||||||
public class TikTokGiftEvent extends TikTokHeaderEvent {
|
public class TikTokGiftEvent extends TikTokHeaderEvent {
|
||||||
private final Gift gift;
|
private final Gift gift;
|
||||||
private final User user;
|
private final User user;
|
||||||
|
private final User toUser;
|
||||||
private final int combo;
|
private final int combo;
|
||||||
public TikTokGiftEvent(Gift gift, WebcastGiftMessage msg) {
|
|
||||||
|
public TikTokGiftEvent(Gift gift, User liveHost, WebcastGiftMessage msg) {
|
||||||
super(msg.getCommon());
|
super(msg.getCommon());
|
||||||
this.gift = gift;
|
this.gift = gift;
|
||||||
user = User.map(msg.getUser(), msg.getUserIdentity());
|
user = User.map(msg.getUser(), msg.getUserIdentity());
|
||||||
|
if (msg.getToUser().getNickname().isEmpty()) {
|
||||||
|
toUser = liveHost;
|
||||||
|
} else {
|
||||||
|
toUser = User.map(msg.getToUser());
|
||||||
|
}
|
||||||
combo = msg.getComboCount();
|
combo = msg.getComboCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.data.events.http;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.http.HttpData;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EventMeta(eventType = EventType.Debug)
|
||||||
|
public class TikTokHttpResponseEvent extends TikTokEvent
|
||||||
|
{
|
||||||
|
String url;
|
||||||
|
|
||||||
|
HttpData response;
|
||||||
|
|
||||||
|
HttpData request;
|
||||||
|
}
|
||||||
@@ -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.data.models.http;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class HttpData {
|
||||||
|
String url;
|
||||||
|
String method;
|
||||||
|
Map<String, List<String>> headers = new TreeMap<>();
|
||||||
|
Map<String, String> parameters = new TreeMap<>();
|
||||||
|
int status;
|
||||||
|
String body = "";
|
||||||
|
|
||||||
|
|
||||||
|
public static HttpData map(HttpRequest request) {
|
||||||
|
var data = new HttpData();
|
||||||
|
data.setUrl(request.uri().getPath());
|
||||||
|
data.setMethod(request.method());
|
||||||
|
data.setParameters(extractQueryParams(request.uri()));
|
||||||
|
data.setStatus(200);
|
||||||
|
if (request.bodyPublisher().isPresent()) {
|
||||||
|
data.setBody(request.bodyPublisher().get().toString());
|
||||||
|
}
|
||||||
|
data.setHeaders(Collections.unmodifiableMap(request.headers().map()));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpData map(HttpResponse<String> response) {
|
||||||
|
var data = new HttpData();
|
||||||
|
data.setUrl(response.uri().getPath());
|
||||||
|
data.setMethod(response.request().method());
|
||||||
|
data.setParameters(extractQueryParams(response.uri()));
|
||||||
|
data.setStatus(200);
|
||||||
|
data.setBody(response.body());
|
||||||
|
data.setHeaders(Collections.unmodifiableMap(response.headers().map()));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Map<String, String> extractQueryParams(URI uri) {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
String query = uri.getQuery();
|
||||||
|
if (query != null && !query.isEmpty()) {
|
||||||
|
for (String param : query.split("&")) {
|
||||||
|
String[] keyValue = param.split("=");
|
||||||
|
if (keyValue.length > 1) {
|
||||||
|
params.put(keyValue[0], keyValue[1]);
|
||||||
|
} else {
|
||||||
|
params.put(keyValue[0], ""); // Empty value for parameter without explicit value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.live;
|
package io.github.jwdeveloper.tiktok.live;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.listener.ListenersManager;
|
import io.github.jwdeveloper.tiktok.listener.ListenersManager;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
||||||
|
|
||||||
@@ -55,6 +56,11 @@ public interface LiveClient {
|
|||||||
void disconnect();
|
void disconnect();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use to manually invoke event
|
||||||
|
*/
|
||||||
|
void publishEvent(TikTokEvent event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information about gifts
|
* Get information about gifts
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
|||||||
import io.github.jwdeveloper.tiktok.data.events.*;
|
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
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.gift.TikTokGiftEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokFollowEvent;
|
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.TikTokJoinEvent;
|
||||||
@@ -39,61 +40,140 @@ import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandl
|
|||||||
public interface EventsBuilder<T> {
|
public interface EventsBuilder<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used to register own custom events
|
* Invoked whenever specified event is triggered
|
||||||
* @param eventClazz event class
|
*
|
||||||
* @param event action
|
* @param eventClass event class
|
||||||
|
* @param action action
|
||||||
*/
|
*/
|
||||||
<E extends TikTokEvent> T onCustomEvent(Class<E> eventClazz, EventConsumer<E> event);
|
<E extends TikTokEvent> T onEvent(Class<E> eventClass, EventConsumer<E> action);
|
||||||
|
|
||||||
T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> event);
|
|
||||||
|
|
||||||
T onComment(EventConsumer<TikTokCommentEvent> event);
|
|
||||||
|
|
||||||
T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> event);
|
|
||||||
|
|
||||||
T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> event);
|
|
||||||
|
|
||||||
T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> event);
|
|
||||||
|
|
||||||
|
|
||||||
T onGiftCombo(EventConsumer<TikTokGiftComboEvent> event);
|
/**
|
||||||
|
* Invoked whenever any event is triggered
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onEvent(EventConsumer<TikTokEvent> action);
|
||||||
|
|
||||||
T onGift(EventConsumer<TikTokGiftEvent> event);
|
/**
|
||||||
|
* Invoked when information about room (live) got updated such as viewer count, etc..
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> action);
|
||||||
|
|
||||||
T onQuestion(EventConsumer<TikTokQuestionEvent> event);
|
/**
|
||||||
|
* Invoked when someone send message to chat
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onComment(EventConsumer<TikTokCommentEvent> action);
|
||||||
|
|
||||||
T onSubscribe(EventConsumer<TikTokSubscribeEvent> event);
|
|
||||||
|
|
||||||
T onFollow(EventConsumer<TikTokFollowEvent> event);
|
/**
|
||||||
|
* Invoked when TikTokLiveJava makes http request and getting response
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action);
|
||||||
|
|
||||||
T onLike(EventConsumer<TikTokLikeEvent> event);
|
/**
|
||||||
|
* Invoked when TikTok protocolBuffer data "message" was successfully mapped to event
|
||||||
|
* events contains protocol-buffer "Message" and TikTokLiveJava "Event"
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> action);
|
||||||
|
|
||||||
T onEmote(EventConsumer<TikTokEmoteEvent> event);
|
/**
|
||||||
|
* Invoked when there was not found event mapper for TikTok protocolBuffer data "message"
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> action);
|
||||||
|
|
||||||
T onJoin(EventConsumer<TikTokJoinEvent> event);
|
/**
|
||||||
|
* Invoked every time TikTok sends protocolBuffer data to websocket
|
||||||
|
* Response contains list of messages that are later mapped to events
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> action);
|
||||||
|
|
||||||
T onShare(EventConsumer<TikTokShareEvent> event);
|
|
||||||
|
|
||||||
// T onChest(EventConsumer<TikTokChestEvent> event);
|
/**
|
||||||
|
* Invoked for gifts that has no combo, or when combo finishes
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onGift(EventConsumer<TikTokGiftEvent> action);
|
||||||
|
|
||||||
T onLivePaused(EventConsumer<TikTokLivePausedEvent> event);
|
/**
|
||||||
|
* Invoked for gifts that has combo options such as roses
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onGiftCombo(EventConsumer<TikTokGiftComboEvent> action);
|
||||||
|
|
||||||
T onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> event);
|
|
||||||
|
|
||||||
T onLiveEnded(EventConsumer<TikTokLiveEndedEvent> event);
|
T onQuestion(EventConsumer<TikTokQuestionEvent> action);
|
||||||
|
|
||||||
T onConnected(EventConsumer<TikTokConnectedEvent> event);
|
T onSubscribe(EventConsumer<TikTokSubscribeEvent> action);
|
||||||
|
|
||||||
T onReconnecting(EventConsumer<TikTokReconnectingEvent> event);
|
T onFollow(EventConsumer<TikTokFollowEvent> action);
|
||||||
|
|
||||||
T onDisconnected(EventConsumer<TikTokDisconnectedEvent> event);
|
T onLike(EventConsumer<TikTokLikeEvent> action);
|
||||||
|
|
||||||
T onError(EventConsumer<TikTokErrorEvent> event);
|
T onEmote(EventConsumer<TikTokEmoteEvent> action);
|
||||||
|
|
||||||
T onEvent(EventConsumer<TikTokEvent> event);
|
T onJoin(EventConsumer<TikTokJoinEvent> action);
|
||||||
|
|
||||||
|
T onShare(EventConsumer<TikTokShareEvent> action);
|
||||||
|
|
||||||
|
T onLivePaused(EventConsumer<TikTokLivePausedEvent> action);
|
||||||
|
|
||||||
|
T onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> action);
|
||||||
|
|
||||||
|
T onLiveEnded(EventConsumer<TikTokLiveEndedEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when client has been successfully connected to live
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onConnected(EventConsumer<TikTokConnectedEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when client tries to reconnect
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onReconnecting(EventConsumer<TikTokReconnectingEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when client disconnected
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onDisconnected(EventConsumer<TikTokDisconnectedEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when exception was throed inside client or event handler
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onError(EventConsumer<TikTokErrorEvent> action);
|
||||||
|
|
||||||
|
|
||||||
// TODO Figure out how those events works
|
// TODO Figure out how those events works
|
||||||
|
// T onChest(EventConsumer<TikTokChestEvent> event);
|
||||||
|
|
||||||
//T onLinkMicFanTicket(TikTokEventConsumer<TikTokLinkMicFanTicketEvent> event);
|
//T onLinkMicFanTicket(TikTokEventConsumer<TikTokLinkMicFanTicketEvent> event);
|
||||||
|
|
||||||
//T onEnvelope(TikTokEventConsumer<TikTokEnvelopeEvent> event);
|
//T onEnvelope(TikTokEventConsumer<TikTokEnvelopeEvent> event);
|
||||||
|
|||||||
@@ -1,73 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers;
|
package io.github.jwdeveloper.tiktok.mappers;
|
||||||
|
|
||||||
import com.google.protobuf.GeneratedMessageV3;
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public interface TikTokMapper {
|
public interface TikTokMapper {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when `sourceClass` is mapped,
|
* * if mapper is not found for messageName, TikTokLiveException is thrown
|
||||||
* input is bytes that are coming from TikTok in `sourceClass` packet
|
|
||||||
* output is TikTok event we want to create
|
|
||||||
* <p>
|
|
||||||
* bytesToEvent(WebcastGiftMessage.class, bytes ->
|
|
||||||
* {
|
|
||||||
* var giftMessage = WebcastGiftMessage.parseFrom(bytes);
|
|
||||||
* var giftName = giftMessage.getGift().getName();
|
|
||||||
* return new TikTokEvent(Gift.ROSE, giftMessage);
|
|
||||||
* })
|
|
||||||
*
|
*
|
||||||
* @param sourceClass protocol buffer webcast class
|
* @param messageName
|
||||||
* @param onMapping lambda function that is triggered on mapping. takes as input ProtocolBuffer object and as output TikTokEvent
|
* @return TikTokMapperModel
|
||||||
*/
|
*/
|
||||||
void bytesToEvent(Class<? extends GeneratedMessageV3> sourceClass, Function<byte[], TikTokEvent> onMapping);
|
TikTokMapperModel forMessage(String messageName);
|
||||||
|
|
||||||
void bytesToEvents(Class<? extends GeneratedMessageV3> sourceClass, Function<byte[], List<TikTokEvent>> onMapping);
|
TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName);
|
||||||
|
|
||||||
|
TikTokMapperModel forMessage(String mapperName, MappingAction<MappingResult> onMapping);
|
||||||
|
|
||||||
|
TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, MappingAction<MappingResult> onMapping);
|
||||||
|
|
||||||
|
TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, Function<byte[], TikTokEvent> onMapping);
|
||||||
|
|
||||||
|
TikTokMapperModel forAnyMessage();
|
||||||
|
|
||||||
|
|
||||||
/**
|
boolean isRegistered(String mapperName);
|
||||||
* In case you found some TikTok message that has not Webcast class use this method
|
|
||||||
*
|
|
||||||
* @param messageName Name of TikTok data event
|
|
||||||
* @param onMapping lambda function that is triggered on mapping. takes as input ProtocolBuffer object and as output TikTokEvent
|
|
||||||
*/
|
|
||||||
void bytesToEvent(String messageName, Function<byte[], TikTokEvent> onMapping);
|
|
||||||
|
|
||||||
void bytesToEvents(String messageName, Function<byte[], List<TikTokEvent>> onMapping);
|
<T extends GeneratedMessageV3> boolean isRegistered(Class<T> mapperName);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method can be used to override default mapping for
|
|
||||||
* certain TikTok incoming data message. For this example
|
|
||||||
* we are overriding WebcastGiftMessage and retuning CustomGiftEvent
|
|
||||||
* instead of TikTokGiftEvent
|
|
||||||
* <p>
|
|
||||||
* webcastObjectToEvent(WebcastGiftMessage.class, webcastGiftMessage ->
|
|
||||||
* {
|
|
||||||
* var giftName = webcastGiftMessage.getGift().getName();
|
|
||||||
* var user = webcastGiftMessage.getUser().getNickname();
|
|
||||||
* return new CustomGiftEvent(giftName, user);
|
|
||||||
* })
|
|
||||||
*
|
|
||||||
* @param sourceClass ProtocolBuffer class that represent incoming custom data, hint class should starts with Webcast prefix
|
|
||||||
* @param onMapping lambda function that is triggered on mapping. takes as input ProtocolBuffer object and as output TikTokEvent
|
|
||||||
*/
|
|
||||||
<T extends GeneratedMessageV3> void webcastObjectToEvent(Class<T> sourceClass, Function<T, TikTokEvent> onMapping);
|
|
||||||
|
|
||||||
<T extends GeneratedMessageV3> void webcastObjectToEvents(Class<T> sourceClass, Function<T, List<TikTokEvent>> onMapping);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered when `sourceClass` is mapped,
|
|
||||||
* looking for constructor in `outputClass` with one parameter that is of type `sourceClass`
|
|
||||||
* and created instance of object from this constructor
|
|
||||||
*
|
|
||||||
* @param sourceClass protocol buffer webcast class
|
|
||||||
* @param outputClass TikTok event class
|
|
||||||
*/
|
|
||||||
void webcastObjectToConstructor(Class<? extends GeneratedMessageV3> sourceClass, Class<? extends TikTokEvent> outputClass);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers;
|
||||||
|
|
||||||
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject;
|
||||||
|
|
||||||
|
public interface TikTokMapperHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes protocol buffer data bytes
|
||||||
|
* @param messageClass class that we want to serialize bytes to
|
||||||
|
* @param <T> @messageClass must be class that is made by protocol buffer
|
||||||
|
* @return object of type @messageClass
|
||||||
|
*/
|
||||||
|
<T extends GeneratedMessageV3> T bytesToWebcastObject(byte[] bytes, Class<T> messageClass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes protocol buffer data bytes
|
||||||
|
* @param messageName class that we want to serialize bytes to
|
||||||
|
* @return protocol buffer objects if class for @messageName has been found
|
||||||
|
* @throws TikTokMessageMappingException if there is no suitable class for messageName
|
||||||
|
*/
|
||||||
|
Object bytesToWebcastObject(byte[] bytes, String messageName);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param messageName checks wheaten TikTokLiveJava has class representation for certain protocol-buffer message name
|
||||||
|
* @return false if class is not found
|
||||||
|
*/
|
||||||
|
boolean isMessageHasProtoClass(String messageName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes protocol buffer data bytes
|
||||||
|
* @return tree structure of protocol buffer object
|
||||||
|
* @see ProtoBufferObject
|
||||||
|
*/
|
||||||
|
ProtoBufferObject bytesToProtoBufferStructure(byte[] bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts object to json
|
||||||
|
*
|
||||||
|
* @param obj any object
|
||||||
|
* @return pretty formatted json
|
||||||
|
*/
|
||||||
|
String toJson(Object obj);
|
||||||
|
}
|
||||||
@@ -20,24 +20,39 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
package io.github.jwdeveloper.tiktok.mappers;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
|
import io.github.jwdeveloper.tiktok.mappers.data.AfterMappingAction;
|
||||||
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
import org.jdbi.v3.sqlobject.statement.SqlQuery;
|
|
||||||
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
@RegisterBeanMapper(TikTokResponseModel.class)
|
public interface TikTokMapperModel {
|
||||||
public interface TikTokResponseModelDAO
|
|
||||||
{
|
|
||||||
@SqlUpdate("INSERT INTO TikTokResponseModel (hostName, response, createdAt) " +
|
|
||||||
"VALUES (:hostName, :response, :createdAt)")
|
|
||||||
void insert(@BindBean TikTokResponseModel message);
|
|
||||||
|
|
||||||
@SqlQuery("SELECT * FROM TikTokResponseModel")
|
/**
|
||||||
List<TikTokResponseModel> select();
|
* @return name of websocket message that this mapper is mapping from
|
||||||
|
*/
|
||||||
|
|
||||||
|
String getSourceMessageName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param action Input bytes from websocket, you can modify it and returns different bytes
|
||||||
|
*/
|
||||||
|
TikTokMapperModel onBeforeMapping(MappingAction<byte[]> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param action Input bytes from websocket. As output returns list of tiktok live events
|
||||||
|
*/
|
||||||
|
TikTokMapperModel onMapping(MappingAction<MappingResult> action);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param action You can modify output list of TikTokLive events
|
||||||
|
* @see AfterMappingAction
|
||||||
|
*/
|
||||||
|
TikTokMapperModel onAfterMapping(Function<MappingResult, List<TikTokEvent>> action);
|
||||||
}
|
}
|
||||||
@@ -20,17 +20,18 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
package io.github.jwdeveloper.tiktok.mappers.data;
|
||||||
|
|
||||||
public class TikTokMessageCollectorClient
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
{
|
|
||||||
public static TikTokMessagessCollectorBuilder create(String outputName)
|
|
||||||
{
|
|
||||||
return new TikTokMessagessCollectorBuilder(outputName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TikTokMessagessCollectorBuilder create(MessageCollector messageCollector, String outputName)
|
import java.util.List;
|
||||||
{
|
|
||||||
return new TikTokMessagessCollectorBuilder(messageCollector,outputName);
|
@FunctionalInterface
|
||||||
}
|
public interface AfterMappingAction {
|
||||||
|
/**
|
||||||
|
* @param source object that was used as source to create events
|
||||||
|
* @param events list of events prepared before, could be modified or changed
|
||||||
|
* @return list of events that will be invoked
|
||||||
|
*/
|
||||||
|
List<TikTokEvent> onAfterMapping(Object source, List<TikTokEvent> events);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers.data;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface MappingAction<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param inputBytes incoming bytes from TikTok server. The represents protocol buffer message that was send to client
|
||||||
|
* @param messageName name of protocol buffer message
|
||||||
|
* @param mapperHelper utils and helper methods that can be use to debbug/display/deserialize protocol buffer data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onMapping(byte[] inputBytes, String messageName, TikTokMapperHelper mapperHelper);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.mappers.data;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class MappingResult
|
||||||
|
{
|
||||||
|
|
||||||
|
Object source;
|
||||||
|
|
||||||
|
List<TikTokEvent> events;
|
||||||
|
|
||||||
|
String message;
|
||||||
|
|
||||||
|
public static MappingResult of(Object source) {
|
||||||
|
return new MappingResult(source, List.of(),"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MappingResult of(Object source, List<TikTokEvent> events) {
|
||||||
|
return new MappingResult(source, events,"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MappingResult of(Object source,TikTokEvent events) {
|
||||||
|
return new MappingResult(source, List.of(events),"");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ message Text {
|
|||||||
string stringValue = 11;
|
string stringValue = 11;
|
||||||
oneof textPieceType
|
oneof textPieceType
|
||||||
{
|
{
|
||||||
TextPieceUser userValue = 21;
|
TextPieceUser userValue = 21;
|
||||||
TextPieceGift giftValue = 22;
|
TextPieceGift giftValue = 22;
|
||||||
}
|
}
|
||||||
TextPiecePatternRef patternRefValue = 24;
|
TextPiecePatternRef patternRefValue = 24;
|
||||||
}
|
}
|
||||||
@@ -155,7 +155,7 @@ message BadgeStruct {
|
|||||||
|
|
||||||
message ProfileCardPanel {
|
message ProfileCardPanel {
|
||||||
bool useNewProfileCardStyle = 1;
|
bool useNewProfileCardStyle = 1;
|
||||||
// BadgeTextPosition badgeTextPosition = 2; // Enum
|
// BadgeTextPosition badgeTextPosition = 2; // Enum
|
||||||
ProjectionConfig projectionConfig = 3;
|
ProjectionConfig projectionConfig = 3;
|
||||||
ProfileContent profileContent = 4;
|
ProfileContent profileContent = 4;
|
||||||
}
|
}
|
||||||
@@ -1000,8 +1000,8 @@ message LinkerCreateContent {
|
|||||||
|
|
||||||
message LinkerEnterContent {
|
message LinkerEnterContent {
|
||||||
repeated User LinkedUsersList = 1;
|
repeated User LinkedUsersList = 1;
|
||||||
//LinkmicMultiLiveEnum AnchorMultiLiveEnum = 2;
|
// LinkmicMultiLiveEnum AnchorMultiLiveEnum = 2;
|
||||||
// Data.LinkmicUserSettingInfo AnchorSettingInfo = 3;
|
// Data.LinkmicUserSettingInfo AnchorSettingInfo = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkerInviteContent {
|
message LinkerInviteContent {
|
||||||
@@ -1018,15 +1018,15 @@ message LinkerInviteContent {
|
|||||||
//Data.LinkmicMultiLiveEnum AnchorMultiLiveEnum = 11;
|
//Data.LinkmicMultiLiveEnum AnchorMultiLiveEnum = 11;
|
||||||
//Data.LinkmicUserSettingInfo AnchorSettingInfo = 12;
|
//Data.LinkmicUserSettingInfo AnchorSettingInfo = 12;
|
||||||
string InviterLinkmicIdStr = 13;
|
string InviterLinkmicIdStr = 13;
|
||||||
// InviteTopHostInfo FromTopHostInfo = 16;
|
// InviteTopHostInfo FromTopHostInfo = 16;
|
||||||
int64 ActionId = 17;
|
int64 ActionId = 17;
|
||||||
// repeated LinkmicUserInfo LinkedUsersList = 18;
|
// repeated LinkmicUserInfo LinkedUsersList = 18;
|
||||||
// Data.PerceptionDialogInfo Dialog = 19;
|
// Data.PerceptionDialogInfo Dialog = 19;
|
||||||
// Data.PunishEventInfo PunishInfo = 20;
|
// Data.PunishEventInfo PunishInfo = 20;
|
||||||
int32 FromRoomAgeRestricted = 21;
|
int32 FromRoomAgeRestricted = 21;
|
||||||
// Data.Tag FromTag = 22;
|
// Data.Tag FromTag = 22;
|
||||||
// repeated Data.CohostABTestSetting AbTestSettingList = 23;
|
// repeated Data.CohostABTestSetting AbTestSettingList = 23;
|
||||||
// Data.LinkerInviteMessageExtra LinkerInviteMsgExtra = 101;
|
// Data.LinkerInviteMessageExtra LinkerInviteMsgExtra = 101;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkerKickOutContent {
|
message LinkerKickOutContent {
|
||||||
@@ -1046,17 +1046,17 @@ message LinkerLinkedListChangeContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message LinkerListChangeContent {
|
message LinkerListChangeContent {
|
||||||
repeated User LinkedUsersList = 1;
|
repeated LinkLayerListUser LinkedUsersList = 1;
|
||||||
repeated User AppliedUsersList = 2;
|
repeated LinkLayerListUser AppliedUsersList = 2;
|
||||||
repeated User ConnectingUsersList = 3;
|
repeated LinkLayerListUser ConnectingUsersList = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkerMediaChangeContent {
|
message LinkerMediaChangeContent {
|
||||||
// MicIdxOperation Op = 1;
|
// MicIdxOperation Op = 1;
|
||||||
int64 ToUserId = 2;
|
int64 ToUserId = 2;
|
||||||
int64 AnchorId = 3;
|
int64 AnchorId = 3;
|
||||||
int64 RoomId = 4;
|
int64 RoomId = 4;
|
||||||
// LinkerSceneType ChangeScene = 5;
|
// LinkerSceneType ChangeScene = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkerMicIdxUpdateContent {
|
message LinkerMicIdxUpdateContent {
|
||||||
@@ -1064,14 +1064,14 @@ message LinkerMicIdxUpdateContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message LinkerMicIdxUpdateInfo {
|
message LinkerMicIdxUpdateInfo {
|
||||||
// MicIdxOperation Op = 1;
|
// MicIdxOperation Op = 1;
|
||||||
int64 UserId = 2;
|
int64 UserId = 2;
|
||||||
int64 MicIdx = 3;
|
int64 MicIdx = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkerMuteContent {
|
message LinkerMuteContent {
|
||||||
int64 UserId = 1;
|
int64 UserId = 1;
|
||||||
// Data.MuteStatus Status = 2;
|
// Data.MuteStatus Status = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkerRandomMatchContent {
|
message LinkerRandomMatchContent {
|
||||||
@@ -1085,9 +1085,9 @@ message LinkerRandomMatchContent {
|
|||||||
message LinkerReplyContent {
|
message LinkerReplyContent {
|
||||||
int64 FromUserId = 1;
|
int64 FromUserId = 1;
|
||||||
int64 FromRoomId = 2;
|
int64 FromRoomId = 2;
|
||||||
// LinkmicInfo FromUserLinkmicInfo = 3;
|
// LinkmicInfo FromUserLinkmicInfo = 3;
|
||||||
int64 ToUserId = 4;
|
int64 ToUserId = 4;
|
||||||
// LinkmicInfo ToUserLinkmicInfo = 5;
|
// LinkmicInfo ToUserLinkmicInfo = 5;
|
||||||
int64 LinkType = 6;
|
int64 LinkType = 6;
|
||||||
int64 ReplyStatus = 7;
|
int64 ReplyStatus = 7;
|
||||||
LinkerSetting LinkerSetting = 8;
|
LinkerSetting LinkerSetting = 8;
|
||||||
@@ -1096,10 +1096,10 @@ message LinkerReplyContent {
|
|||||||
map<int64, string> RtcExtInfoMap = 11;
|
map<int64, string> RtcExtInfoMap = 11;
|
||||||
LinkerMicIdxUpdateInfo InviteeMicIdxUpdateInfo = 12;
|
LinkerMicIdxUpdateInfo InviteeMicIdxUpdateInfo = 12;
|
||||||
map<int64, int64> ApplierMicIdxInfoMap = 13;
|
map<int64, int64> ApplierMicIdxInfoMap = 13;
|
||||||
// Data.LinkmicMultiLiveEnum AnchorMultiLiveEnum = 14;
|
// Data.LinkmicMultiLiveEnum AnchorMultiLiveEnum = 14;
|
||||||
// Data.LinkmicUserSettingInfo AnchorSettingInfo = 15;
|
// Data.LinkmicUserSettingInfo AnchorSettingInfo = 15;
|
||||||
int64 ActionId = 16;
|
int64 ActionId = 16;
|
||||||
// repeated LinkmicUserInfo LinkedUsersList = 17;
|
// repeated LinkmicUserInfo LinkedUsersList = 17;
|
||||||
int64 SourceType = 18;
|
int64 SourceType = 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1124,9 +1124,394 @@ message LinkerUpdateUserContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message LinkerUpdateUserSettingContent {
|
message LinkerUpdateUserSettingContent {
|
||||||
// Data.LinkmicUserSettingInfo UpdateUserSettingInfo = 1;
|
// Data.LinkmicUserSettingInfo UpdateUserSettingInfo = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkerWaitingListChangeContent {
|
message LinkerWaitingListChangeContent {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message LinkmicUserSettingInfo {
|
||||||
|
int64 userId = 1;
|
||||||
|
int64 layout = 2; // @warning Enum not found, should be Layout
|
||||||
|
int64 fixMicNum = 3; // @warning Enum not found, should be FixMicNum
|
||||||
|
int64 allowRequestFromUser = 4; // @warning Enum not found, should be AllowRequestFromUser
|
||||||
|
int64 allowRequestFromFollowerOnly = 5; // @warning Enum not found, should be AllowRequestFromFollowerOnly
|
||||||
|
LinkmicApplierSortSetting applierSortSetting = 7; // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message Player {
|
||||||
|
int64 roomId = 1;
|
||||||
|
int64 userId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AllListUser {
|
||||||
|
repeated LinkLayerListUser linkedList = 2;
|
||||||
|
repeated LinkLayerListUser appliedList = 3;
|
||||||
|
repeated LinkLayerListUser invitedList = 4;
|
||||||
|
repeated LinkLayerListUser readyList = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinkLayerListUser {
|
||||||
|
User user = 1;
|
||||||
|
int64 linkmicId = 2;
|
||||||
|
Position pos = 3;
|
||||||
|
int64 linkedTimeNano = 4;
|
||||||
|
string appVersion = 5;
|
||||||
|
int64 magicNumber1 = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Position {
|
||||||
|
int32 type = 1;
|
||||||
|
LinkPosition link = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinkPosition {
|
||||||
|
int32 position = 1;
|
||||||
|
int32 opt = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GroupPlayer {
|
||||||
|
int64 channelId = 1;
|
||||||
|
User user = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DSLConfig {
|
||||||
|
int32 sceneVersion = 1;
|
||||||
|
string layoutId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GroupChannelAllUser {
|
||||||
|
int64 groupChannelId = 1;
|
||||||
|
repeated GroupChannelUser userList = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GroupChannelUser {
|
||||||
|
int64 channelId = 1;
|
||||||
|
GroupStatus status = 2; // Enum
|
||||||
|
TextType type = 3; // Enum
|
||||||
|
AllListUser allUser = 4;
|
||||||
|
int64 joinTime = 5;
|
||||||
|
int64 linkedTime = 6;
|
||||||
|
GroupPlayer ownerUser = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RTCExtraInfo {
|
||||||
|
RTCEngineConfig liveRtcEngineConfig = 1;
|
||||||
|
repeated RTCLiveVideoParam liveRtcVideoParamList = 2;
|
||||||
|
RTCBitrateMap rtcBitrateMap = 3;
|
||||||
|
int32 rtcFps = 4;
|
||||||
|
string rtcBusinessId = 8;
|
||||||
|
int32 interactClientType = 10;
|
||||||
|
|
||||||
|
message RTCEngineConfig {
|
||||||
|
string rtcAppId = 1;
|
||||||
|
string rtcUserId = 2;
|
||||||
|
string rtcToken = 3;
|
||||||
|
int64 rtcChannelId = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RTCLiveVideoParam {
|
||||||
|
int32 strategyId = 1;
|
||||||
|
RTCVideoParam params = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RTCVideoParam {
|
||||||
|
int32 width = 1;
|
||||||
|
int32 height = 2;
|
||||||
|
int32 fps = 3;
|
||||||
|
int32 bitrateKbps = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RTCBitrateMap {
|
||||||
|
int32 xx1 = 1;
|
||||||
|
int32 xx2 = 2;
|
||||||
|
int32 xx3 = 3;
|
||||||
|
int32 xx4 = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateChannelContent {
|
||||||
|
Player owner = 1;
|
||||||
|
string ownerLinkMicId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListChangeContent {
|
||||||
|
TextType type = 1; // Enum
|
||||||
|
AllListUser list = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MultiLiveContent {
|
||||||
|
InviteBizContent inviteBizContent = 2;
|
||||||
|
ReplyBizContent replyBizContent = 3;
|
||||||
|
PermitBizContent permitBizContent = 4;
|
||||||
|
KickOutBizContent kickOutBizContent = 6;
|
||||||
|
|
||||||
|
|
||||||
|
message InviteBizContent {
|
||||||
|
LinkmicUserSettingInfo anchorSettingInfo = 1;
|
||||||
|
int64 inviteSource = 2; // @warning Enum not found, should be InviteSource
|
||||||
|
User operatorUserInfo = 3;
|
||||||
|
int64 operatorLinkAdminType = 4; // @warning Enum not found, should be OperatorLinkAdminType
|
||||||
|
User inviteeUserInfo = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message ReplyBizContent {
|
||||||
|
int32 linkType = 1;
|
||||||
|
int32 isTurnOffInvitation = 2;
|
||||||
|
User replyUserInfo = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PermitBizContent {
|
||||||
|
LinkmicUserSettingInfo anchorSettingInfo = 1;
|
||||||
|
int64 expireTimestamp = 2;
|
||||||
|
User operatorUserInfo = 3;
|
||||||
|
int64 operatorLinkAdminType = 4; // @warning Enum not found, should be OperatorLinkAdminType
|
||||||
|
}
|
||||||
|
|
||||||
|
message KickOutBizContent {
|
||||||
|
User operatorUserInfo = 1;
|
||||||
|
int64 operatorLinkAdminType = 2; // @warning Enum not found, should be OperatorLinkAdminType
|
||||||
|
User kickPlayerUserInfo = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message InviteContent {
|
||||||
|
Player invitor = 1;
|
||||||
|
RTCExtraInfo inviteeRtcExtInfo = 2;
|
||||||
|
string invitorLinkMicId = 3;
|
||||||
|
string inviteeLinkMicId = 4;
|
||||||
|
bool isOwner = 5;
|
||||||
|
Position pos = 6;
|
||||||
|
DSLConfig dsl = 7;
|
||||||
|
User invitee = 8;
|
||||||
|
User operator = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @ApplyContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message ApplyContent {
|
||||||
|
Player applier = 1;
|
||||||
|
string applierLinkMicId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @PermitApplyContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message PermitApplyContent {
|
||||||
|
Player permiter = 1;
|
||||||
|
string permiterLinkMicId = 2;
|
||||||
|
Position applierPos = 3;
|
||||||
|
ReplyStatus replyStatus = 4; // Enum
|
||||||
|
DSLConfig dsl = 5;
|
||||||
|
User applier = 6;
|
||||||
|
User operator = 7;
|
||||||
|
string applierLinkMicId = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @ReplyInviteContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message ReplyInviteContent {
|
||||||
|
Player invitee = 1;
|
||||||
|
ReplyStatus replyStatus = 2; // Enum
|
||||||
|
string inviteeLinkMicId = 3;
|
||||||
|
Position inviteePos = 4;
|
||||||
|
Player inviteOperatorUser = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @KickOutContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message KickOutContent {
|
||||||
|
Player offliner = 1;
|
||||||
|
KickoutReason kickoutReason = 2; // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @CancelApplyContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message CancelApplyContent {
|
||||||
|
Player applier = 1;
|
||||||
|
string applierLinkMicId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @CancelInviteContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message CancelInviteContent {
|
||||||
|
Player invitor = 1;
|
||||||
|
string invitorLinkMicId = 2;
|
||||||
|
string inviteeLinkMicId = 3;
|
||||||
|
int64 inviteSeqId = 4;
|
||||||
|
Player invitee = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @LeaveContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message LeaveContent {
|
||||||
|
Player leaver = 1;
|
||||||
|
int64 leaveReason = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @FinishChannelContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message FinishChannelContent {
|
||||||
|
Player owner = 1;
|
||||||
|
int64 finishReason = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @JoinDirectContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message JoinDirectContent {
|
||||||
|
LinkLayerListUser joiner = 1;
|
||||||
|
AllListUser allUsers = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @LeaveJoinGroupContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message LeaveJoinGroupContent {
|
||||||
|
GroupPlayer operator = 1;
|
||||||
|
int64 groupChannelId = 2;
|
||||||
|
string leaveSource = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @PermitJoinGroupContent
|
||||||
|
// proto.webcast.im
|
||||||
|
message PermitJoinGroupContent {
|
||||||
|
GroupPlayer approver = 1;
|
||||||
|
AgreeStatus agreeStatus = 2; // Enum
|
||||||
|
TextType type = 3; // Enum
|
||||||
|
repeated RTCExtraInfo groupExtInfoList = 4;
|
||||||
|
GroupChannelAllUser groupUser = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @CancelJoinGroupContent
|
||||||
|
// proto.webcast.im
|
||||||
|
message CancelJoinGroupContent {
|
||||||
|
repeated GroupPlayer leaverList = 1;
|
||||||
|
GroupPlayer operator = 2;
|
||||||
|
TextType type = 3; // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message P2PGroupChangeContent {
|
||||||
|
repeated RTCExtraInfo groupExtInfoList = 1;
|
||||||
|
GroupChannelAllUser groupUser = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message BusinessContent {
|
||||||
|
int64 overLength = 1;
|
||||||
|
MultiLiveContent multiLiveContent = 100;
|
||||||
|
CohostContent cohostContent = 200;
|
||||||
|
|
||||||
|
message CohostContent {
|
||||||
|
JoinGroupBizContent joinGroupBizContent = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message JoinGroupBizContent {
|
||||||
|
int32 fromRoomAgeRestricted = 1;
|
||||||
|
Tag fromTag = 2;
|
||||||
|
PerceptionDialogInfo dialog = 3;
|
||||||
|
PunishEventInfo punishInfo = 4;
|
||||||
|
JoinGroupMessageExtra joinGroupMsgExtra = 101;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Tag {
|
||||||
|
int32 tagType = 1;
|
||||||
|
string tagValue = 2;
|
||||||
|
string tagText = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PerceptionDialogInfo {
|
||||||
|
int64 iconType = 1; // @warning Enum not found, should be IconType
|
||||||
|
Text title = 2;
|
||||||
|
Text subTitle = 3;
|
||||||
|
Text adviceActionText = 4;
|
||||||
|
Text defaultActionText = 5;
|
||||||
|
string violationDetailUrl = 6;
|
||||||
|
int32 scene = 7;
|
||||||
|
int64 targetUserId = 8;
|
||||||
|
int64 targetRoomId = 9;
|
||||||
|
int64 countDownTime = 10;
|
||||||
|
bool showFeedback = 11;
|
||||||
|
repeated PerceptionFeedbackOption feedbackOptionsList = 12;
|
||||||
|
int64 policyTip = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PerceptionFeedbackOption {
|
||||||
|
int64 id = 1;
|
||||||
|
string contentKey = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message JoinGroupMessageExtra {
|
||||||
|
int64 sourceType = 1;
|
||||||
|
RivalExtra extra = 2;
|
||||||
|
repeated RivalExtra otherUsersList = 3;
|
||||||
|
|
||||||
|
|
||||||
|
// @RivalExtra
|
||||||
|
// proto.webcast.im.JoinGroupMessageExtra
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message RivalExtra {
|
||||||
|
int64 userCount = 4;
|
||||||
|
Image avatarThumb = 5;
|
||||||
|
string displayId = 6;
|
||||||
|
AuthenticationInfo authenticationInfo = 7;
|
||||||
|
string nickname = 8;
|
||||||
|
int64 followStatus = 9;
|
||||||
|
Hashtag hashtag = 10;
|
||||||
|
TopHostInfo topHostInfo = 11;
|
||||||
|
int64 userId = 12;
|
||||||
|
bool isBestTeammate = 13;
|
||||||
|
|
||||||
|
message AuthenticationInfo {
|
||||||
|
string customVerify = 1;
|
||||||
|
string enterpriseVerifyReason = 2;
|
||||||
|
Image authenticationBadge = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message Hashtag {
|
||||||
|
int64 id = 1;
|
||||||
|
string title = 2;
|
||||||
|
Image image = 3;
|
||||||
|
HashtagNamespace namespace = 4; // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
message TopHostInfo {
|
||||||
|
string rankType = 1;
|
||||||
|
int64 topIndex = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message JoinGroupContent {
|
||||||
|
GroupChannelAllUser groupUser = 1;
|
||||||
|
GroupPlayer joinUser = 2;
|
||||||
|
TextType type = 3; // Enum
|
||||||
}
|
}
|
||||||
@@ -25,6 +25,85 @@ enum EmotePrivateType {
|
|||||||
EMOTE_PRIVATE_TYPE_SUB_WAVE = 1;
|
EMOTE_PRIVATE_TYPE_SUB_WAVE = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TextType {
|
||||||
|
DISPLAY_TEXT = 0;
|
||||||
|
CONTENT = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LinkmicApplierSortSetting {
|
||||||
|
LINKMIC_APPLIER_SORT_SETTING_NONE = 0;
|
||||||
|
LINKMIC_APPLIER_SORT_SETTING_BY_GIFT_SCORE = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum HashtagNamespace {
|
||||||
|
GLOBAL = 0;
|
||||||
|
GAMING = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AgreeStatus {
|
||||||
|
AGREE_UNKNOWN = 0;
|
||||||
|
AGREE = 1;
|
||||||
|
REJECT = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum KickoutReason {
|
||||||
|
KICKOUT_REASON_UNKNOWN = 0;
|
||||||
|
KICKOUT_REASON_FIRST_FRAME_TIMEOUT = 1;
|
||||||
|
KICKOUT_REASON_BY_HOST = 2;
|
||||||
|
KICKOUT_REASON_RTC_LOST_CONNECTION = 3;
|
||||||
|
KICKOUT_REASON_BY_PUNISH = 4;
|
||||||
|
KICKOUT_REASON_BY_ADMIN = 5;
|
||||||
|
KICKOUT_REASON_HOST_REMOVE_ALL_GUESTS = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum GroupStatus {
|
||||||
|
GROUP_STATUS_UNKNOWN = 0;
|
||||||
|
GROUP_STATUS_WAITING = 1;
|
||||||
|
GROUP_STATUS_LINKED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BusinessCase {
|
||||||
|
BUSINESS_NOT_SET = 0;
|
||||||
|
APPLY_BIZ_CONTENT = 1;
|
||||||
|
INVITE_BIZ_CONTENT = 2;
|
||||||
|
REPLY_BIZ_CONTENT = 3;
|
||||||
|
PERMIT_BIZ_CONTENT = 4;
|
||||||
|
JOIN_DIRECT_BIZ_CONTENT = 5;
|
||||||
|
KICK_OUT_BIZ_CONTENT = 6;
|
||||||
|
LIST_CHANGE_BIZ_CONTENT = 11;
|
||||||
|
MULTI_LIVE_CONTENT = 100;
|
||||||
|
COHOST_CONTENT = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ReplyStatus {
|
||||||
|
REPLY_STATUS_UNKNOWN = 0;
|
||||||
|
REPLY_STATUS_AGREE = 1;
|
||||||
|
REPLY_STATUS_REFUSE_PERSONALLY = 2;
|
||||||
|
REPLY_STATUS_REFUSE_TYPE_NOT_SUPPORT = 3;
|
||||||
|
REPLY_STATUS_REFUSE_PROCESSING_INVITATION = 4;
|
||||||
|
REPLY_STATUS_REFUSE_BY_TIMEOUT = 5;
|
||||||
|
REPLY_STATUS_REFUSE_EXCEPTION = 6;
|
||||||
|
REPLY_STATUS_REFUSE_SYSTEM_NOT_SUPPORTED = 7;
|
||||||
|
REPLY_STATUS_REFUSE_SUBTYPE_DIFFERENCE = 8;
|
||||||
|
REPLY_STATUS_REFUSE_IN_MICROOM = 9;
|
||||||
|
REPLY_STATUS_REFUSE_NOT_LOAD_PLUGIN = 10;
|
||||||
|
REPLY_STATUS_REFUSE_IN_MULTI_GUEST = 11;
|
||||||
|
REPLY_STATUS_REFUSE_PAUSE_LIVE = 12;
|
||||||
|
REPLY_STATUS_REFUSE_OPEN_CAMERA_DIALOG_SHOWING = 13;
|
||||||
|
REPLY_STATUS_REFUSE_DRAW_GUESSING = 14;
|
||||||
|
REPLY_STATUS_REFUSE_RANDOM_MATCHING = 15;
|
||||||
|
REPLY_STATUS_REFUSE_IN_MATCH_PROCESSING = 16;
|
||||||
|
REPLY_STATUS_REFUSE_IN_MICROOM_FOR_MULTI_COHOST = 17;
|
||||||
|
REPLY_STATUS_REFUSE_COHOST_FINISHED = 18;
|
||||||
|
REPLY_STATUS_REFUSE_NOT_CONNECTED = 19;
|
||||||
|
REPLY_STATUS_REFUSE_LINKMIC_FULL = 20;
|
||||||
|
REPLY_STATUS_REFUSE_ARC_INCOMPATIBLE = 21;
|
||||||
|
REPLY_STATUS_REFUSE_PROCESSING_OTHER_INVITE = 22;
|
||||||
|
REPLY_STATUS_REFUSE_PROCESSING_OTHER_APPLY = 23;
|
||||||
|
REPLY_STATUS_REFUSE_IN_ANCHOR_COHOST = 24;
|
||||||
|
REPLY_STATUS_REFUSE_TOPIC_PAIRING = 25;
|
||||||
|
}
|
||||||
|
|
||||||
enum SubscribeType {
|
enum SubscribeType {
|
||||||
SUBSCRIBETYPE_ONCE = 0;
|
SUBSCRIBETYPE_ONCE = 0;
|
||||||
@@ -136,4 +215,51 @@ enum EnvelopeDisplay
|
|||||||
EnvelopeDisplayUnknown = 0;
|
EnvelopeDisplayUnknown = 0;
|
||||||
EnvelopeDisplayNew = 1;
|
EnvelopeDisplayNew = 1;
|
||||||
EnvelopeDisplayHide = 2;
|
EnvelopeDisplayHide = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum CommonContentCase {
|
||||||
|
COMMON_CONTENT_NOT_SET = 0;
|
||||||
|
CREATE_CHANNEL_CONTENT = 100;
|
||||||
|
LIST_CHANGE_CONTENT = 102;
|
||||||
|
INVITE_CONTENT = 103;
|
||||||
|
APPLY_CONTENT = 104;
|
||||||
|
PERMIT_APPLY_CONTENT = 105;
|
||||||
|
REPLY_INVITE_CONTENT = 106;
|
||||||
|
KICK_OUT_CONTENT = 107;
|
||||||
|
CANCEL_APPLY_CONTENT = 108;
|
||||||
|
CANCEL_INVITE_CONTENT = 109;
|
||||||
|
LEAVE_CONTENT = 110;
|
||||||
|
FINISH_CONTENT = 111;
|
||||||
|
JOIN_DIRECT_CONTENT = 112;
|
||||||
|
JOIN_GROUP_CONTENT = 113;
|
||||||
|
PERMIT_GROUP_CONTENT = 114;
|
||||||
|
CANCEL_GROUP_CONTENT = 115;
|
||||||
|
LEAVE_GROUP_CONTENT = 116;
|
||||||
|
P2P_GROUP_CHANGE_CONTENT = 117;
|
||||||
|
GROUP_CHANGE_CONTENT = 118;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum MessageType {
|
||||||
|
MESSAGETYPE_SUBSUCCESS = 0;
|
||||||
|
MESSAGETYPE_ANCHORREMINDER = 1;
|
||||||
|
MESSAGETYPE_ENTERROOMEXPIRESOON = 2;
|
||||||
|
MESSAGETYPE_SUBGOALCREATETOANCHOR = 3;
|
||||||
|
MESSAGETYPE_SUBGOALCOMPLETETOAUDIENCE = 4;
|
||||||
|
MESSAGETYPE_SUBGOALCOMPLETETOANCHOR = 5;
|
||||||
|
MESSAGETYPE_SUBGIFTTIKTOK2USERNOTICE = 6;
|
||||||
|
MESSAGETYPE_SUBGIFTTIKTOK2ANCHORNOTICE = 7;
|
||||||
|
MESSAGETYPE_SUBGIFTTRECEIVESENDNOTICE = 8;
|
||||||
|
MESSAGETYPE_SUBGIFTSENDSUCCEEDROOMMESSAGE = 9;
|
||||||
|
MESSAGETYPE_SUBGIFTSENDSUCCEEDANCHORNOTICE = 10;
|
||||||
|
MESSAGETYPE_SUBGIFTLOWVERSIONUPGRADENOTICE = 11;
|
||||||
|
MESSAGETYPE_SUBGIFTUSERBUYAUTHNOTICE = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Scene {
|
||||||
|
SCENE_UNKNOWN = 0;
|
||||||
|
SCENE_CO_HOST = 2;
|
||||||
|
SCENE_MULTI_LIVE = 4;
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ message WebcastPushFrame {
|
|||||||
uint64 LogId = 2;
|
uint64 LogId = 2;
|
||||||
uint64 Service = 3;
|
uint64 Service = 3;
|
||||||
uint64 Method = 4;
|
uint64 Method = 4;
|
||||||
map<string,string> headers = 5;
|
map<string, string> headers = 5;
|
||||||
string PayloadEncoding = 6;
|
string PayloadEncoding = 6;
|
||||||
string PayloadType = 7;
|
string PayloadType = 7;
|
||||||
bytes Payload = 8;
|
bytes Payload = 8;
|
||||||
@@ -81,6 +81,13 @@ message WebcastGiftMessage {
|
|||||||
bool isFirstSent = 25;
|
bool isFirstSent = 25;
|
||||||
string orderId = 28;
|
string orderId = 28;
|
||||||
UserIdentity userIdentity = 32;
|
UserIdentity userIdentity = 32;
|
||||||
|
UserGiftReciever userGiftReciever = 23;
|
||||||
|
|
||||||
|
message UserGiftReciever
|
||||||
|
{
|
||||||
|
int64 userId = 1;
|
||||||
|
string deviceName = 10;
|
||||||
|
}
|
||||||
|
|
||||||
message GiftIMPriority {
|
message GiftIMPriority {
|
||||||
repeated int64 queueSizesList = 1;
|
repeated int64 queueSizesList = 1;
|
||||||
@@ -197,7 +204,7 @@ message WebcastChatMessage {
|
|||||||
int32 quickChatScene = 16;
|
int32 quickChatScene = 16;
|
||||||
int32 communityFlaggedStatus = 17;
|
int32 communityFlaggedStatus = 17;
|
||||||
UserIdentity UserIdentity = 18;
|
UserIdentity UserIdentity = 18;
|
||||||
map<int32,string> CommentQualityScores = 19;
|
map<int32, string> CommentQualityScores = 19;
|
||||||
|
|
||||||
// @EmoteWithIndex
|
// @EmoteWithIndex
|
||||||
// proto.webcast.im.ChatMessage
|
// proto.webcast.im.ChatMessage
|
||||||
@@ -277,14 +284,14 @@ message WebcastGoalUpdateMessage {
|
|||||||
int64 contributorId = 4;
|
int64 contributorId = 4;
|
||||||
Image contributorAvatar = 5;
|
Image contributorAvatar = 5;
|
||||||
string contributorDisplayId = 6;
|
string contributorDisplayId = 6;
|
||||||
// SubGoal contributeSubgoal = 7;
|
// SubGoal contributeSubgoal = 7;
|
||||||
int64 contributeCount = 9;
|
int64 contributeCount = 9;
|
||||||
int64 contributeScore = 10;
|
int64 contributeScore = 10;
|
||||||
int64 giftRepeatCount = 11;
|
int64 giftRepeatCount = 11;
|
||||||
string contributorIdStr = 12;
|
string contributorIdStr = 12;
|
||||||
bool pin = 13;
|
bool pin = 13;
|
||||||
bool unpin = 14;
|
bool unpin = 14;
|
||||||
// GoalPinInfo pinInfo = 15;
|
// GoalPinInfo pinInfo = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message related to Chat-moderation?
|
// Message related to Chat-moderation?
|
||||||
@@ -348,7 +355,7 @@ message WebcastSocialMessage {
|
|||||||
message WebcastSubNotifyMessage {
|
message WebcastSubNotifyMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
User user = 2;
|
User user = 2;
|
||||||
// ExhibitionType exhibitionType = 3; // Enum
|
// ExhibitionType exhibitionType = 3; // Enum
|
||||||
int64 subMonth = 4;
|
int64 subMonth = 4;
|
||||||
SubscribeType subscribeType = 5; // Enum
|
SubscribeType subscribeType = 5; // Enum
|
||||||
OldSubscribeStatus oldSubscribeStatus = 6; // Enum
|
OldSubscribeStatus oldSubscribeStatus = 6; // Enum
|
||||||
@@ -442,7 +449,7 @@ message WebcastMemberMessage {
|
|||||||
//@WebcastPollMessage
|
//@WebcastPollMessage
|
||||||
message WebcastPollMessage {
|
message WebcastPollMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
int32 messageType = 2;
|
MessageType messageType = 2;
|
||||||
int64 pollId = 3;
|
int64 pollId = 3;
|
||||||
PollStartContent startContent = 4;
|
PollStartContent startContent = 4;
|
||||||
PollEndContent endContent = 5;
|
PollEndContent endContent = 5;
|
||||||
@@ -507,6 +514,9 @@ message WebcastHourlyRankMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//<Battles>
|
||||||
|
|
||||||
//@WebcastLinkMicArmies
|
//@WebcastLinkMicArmies
|
||||||
message WebcastLinkMicArmies {
|
message WebcastLinkMicArmies {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
@@ -523,6 +533,45 @@ message WebcastLinkMicArmies {
|
|||||||
uint32 data4 = 12;
|
uint32 data4 = 12;
|
||||||
uint32 data5 = 13;
|
uint32 data5 = 13;
|
||||||
}
|
}
|
||||||
|
//@WebcastLinkMicBattlePunishFinish
|
||||||
|
message WebcastLinkMicBattlePunishFinish {
|
||||||
|
Common Header = 1;
|
||||||
|
uint64 Id1 = 2;
|
||||||
|
uint64 Timestamp = 3;
|
||||||
|
uint32 Data4 = 4;
|
||||||
|
uint64 Id2 = 5;
|
||||||
|
LinkMicBattlePunishFinishData Data6 = 6;
|
||||||
|
|
||||||
|
message LinkMicBattlePunishFinishData {
|
||||||
|
uint64 Id2 = 1; // Same as Id2 in outer object (loser?)
|
||||||
|
uint64 Timestamp = 2;
|
||||||
|
uint32 Data3 = 3;
|
||||||
|
uint64 Id1 = 4; // Same as Id1 in outer object (winner?)
|
||||||
|
uint32 Data5 = 5;
|
||||||
|
uint32 Data6 = 6;
|
||||||
|
uint32 Data8 = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@WebcastLinkmicBattleTaskMessage
|
||||||
|
message WebcastLinkmicBattleTaskMessage {
|
||||||
|
Common Header = 1;
|
||||||
|
uint32 Data2 = 2;
|
||||||
|
LinkmicBattleTaskData Data3 = 3;
|
||||||
|
LinkmicBattleTaskData2 Data5 = 5;
|
||||||
|
|
||||||
|
message LinkmicBattleTaskData {
|
||||||
|
BattleTaskData Data1 = 1;
|
||||||
|
}
|
||||||
|
message BattleTaskData {
|
||||||
|
uint32 Data1 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinkmicBattleTaskData2 {
|
||||||
|
uint32 Data1 = 1;
|
||||||
|
uint32 Data2 = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//@WebcastLinkMicBattle
|
//@WebcastLinkMicBattle
|
||||||
message WebcastLinkMicBattle {
|
message WebcastLinkMicBattle {
|
||||||
@@ -572,11 +621,10 @@ message WebcastLinkMicFanTicketMethod {
|
|||||||
Common common = 1;
|
Common common = 1;
|
||||||
FanTicketRoomNoticeContent FanTicketRoomNotice = 2;
|
FanTicketRoomNoticeContent FanTicketRoomNotice = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@WebcastLinkMicMethod
|
//@WebcastLinkMicMethod
|
||||||
message WebcastLinkMicMethod {
|
message WebcastLinkMicMethod {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
int64 messageType = 2;
|
MessageType messageType = 2;
|
||||||
string accessKey = 3;
|
string accessKey = 3;
|
||||||
int64 anchorLinkmicId = 4;
|
int64 anchorLinkmicId = 4;
|
||||||
int64 userId = 5;
|
int64 userId = 5;
|
||||||
@@ -590,6 +638,8 @@ message WebcastLinkMicMethod {
|
|||||||
int64 inviteUid = 13;
|
int64 inviteUid = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//<Battles>
|
||||||
|
|
||||||
//@WebcastLiveIntroMessage
|
//@WebcastLiveIntroMessage
|
||||||
message WebcastLiveIntroMessage {
|
message WebcastLiveIntroMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
@@ -610,7 +660,7 @@ message WebcastUnauthorizedMemberMessage {
|
|||||||
string nickName = 4;
|
string nickName = 4;
|
||||||
Text enterText = 5;
|
Text enterText = 5;
|
||||||
}
|
}
|
||||||
S
|
|
||||||
//@WebcastMsgDetectMessage
|
//@WebcastMsgDetectMessage
|
||||||
message WebcastMsgDetectMessage {
|
message WebcastMsgDetectMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
@@ -632,7 +682,7 @@ message WebcastMsgDetectMessage {
|
|||||||
bool detectP2PMsg = 3;
|
bool detectP2PMsg = 3;
|
||||||
bool detectRoomMsg = 4;
|
bool detectRoomMsg = 4;
|
||||||
bool httpOptimize = 5;
|
bool httpOptimize = 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@WebcastOecLiveShoppingMessage
|
//@WebcastOecLiveShoppingMessage
|
||||||
@@ -683,9 +733,9 @@ message WebcastSystemMessage {
|
|||||||
//@WebcastLinkMessage
|
//@WebcastLinkMessage
|
||||||
message WebcastLinkMessage {
|
message WebcastLinkMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
int64 MessageType = 2;
|
MessageType MessageType = 2;
|
||||||
int64 LinkerId = 3;
|
int64 LinkerId = 3;
|
||||||
int64 Scene = 4;
|
Scene Scene = 4;
|
||||||
LinkerInviteContent InviteContent = 5;
|
LinkerInviteContent InviteContent = 5;
|
||||||
LinkerReplyContent ReplyContent = 6;
|
LinkerReplyContent ReplyContent = 6;
|
||||||
LinkerCreateContent CreateContent = 7;
|
LinkerCreateContent CreateContent = 7;
|
||||||
@@ -702,24 +752,44 @@ message WebcastLinkMessage {
|
|||||||
LinkerUpdateUserSettingContent UpdateUserSettingContent = 18;
|
LinkerUpdateUserSettingContent UpdateUserSettingContent = 18;
|
||||||
LinkerMicIdxUpdateContent MicIdxUpdateContent = 19;
|
LinkerMicIdxUpdateContent MicIdxUpdateContent = 19;
|
||||||
LinkerListChangeContent ListChangeContent = 20;
|
LinkerListChangeContent ListChangeContent = 20;
|
||||||
// CohostListChangeContent CohostListChangeContent = 21;
|
// CohostListChangeContent CohostListChangeContent = 21;
|
||||||
LinkerMediaChangeContent MediaChangeContent = 22;
|
LinkerMediaChangeContent MediaChangeContent = 22;
|
||||||
LinkerAcceptNoticeContent ReplyAcceptNoticeContent = 23;
|
LinkerAcceptNoticeContent ReplyAcceptNoticeContent = 23;
|
||||||
LinkerSysKickOutContent SysKickOutContent = 101;
|
LinkerSysKickOutContent SysKickOutContent = 101;
|
||||||
// LinkmicUserToastContent UserToastContent = 102;
|
// LinkmicUserToastContent UserToastContent = 102;
|
||||||
string Extra = 200;
|
string Extra = 200;
|
||||||
int64 ExpireTimestamp = 201;
|
int64 ExpireTimestamp = 201;
|
||||||
string TransferExtra = 202;
|
string TransferExtra = 202;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@WebcastLinkLayerMessage
|
|
||||||
|
// @WebcastLinkLayerMessage
|
||||||
message WebcastLinkLayerMessage {
|
message WebcastLinkLayerMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
LinkLayerMessageType messageType = 2;
|
MessageType messageType = 2; // Enum
|
||||||
int64 channelId = 3;
|
int64 channelId = 3;
|
||||||
|
Scene scene = 4; // Enum
|
||||||
|
CreateChannelContent createChannelContent = 100;
|
||||||
|
ListChangeContent listChangeContent = 102;
|
||||||
|
InviteContent inviteContent = 103;
|
||||||
|
ApplyContent applyContent = 104;
|
||||||
|
PermitApplyContent permitApplyContent = 105;
|
||||||
|
ReplyInviteContent replyInviteContent = 106;
|
||||||
|
KickOutContent kickOutContent = 107;
|
||||||
|
CancelApplyContent cancelApplyContent = 108;
|
||||||
|
CancelInviteContent cancelInviteContent = 109;
|
||||||
|
LeaveContent leaveContent = 110;
|
||||||
|
FinishChannelContent finishContent = 111;
|
||||||
|
JoinDirectContent joinDirectContent = 112;
|
||||||
|
JoinGroupContent joinGroupContent = 113;
|
||||||
|
PermitJoinGroupContent permitGroupContent = 114;
|
||||||
|
CancelJoinGroupContent cancelGroupContent = 115;
|
||||||
|
LeaveJoinGroupContent leaveGroupContent = 116;
|
||||||
|
P2PGroupChangeContent p2pGroupChangeContent = 117;
|
||||||
|
BusinessContent businessContent = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @RoomVerifyMessage
|
||||||
message RoomVerifyMessage {
|
message RoomVerifyMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
int32 action = 2;
|
int32 action = 2;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.11-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -87,4 +87,5 @@ public class TikTokLive
|
|||||||
{
|
{
|
||||||
return new TikTokDataChecker().isHostNameValidAsync(hostName);
|
return new TikTokDataChecker().isHostNameValidAsync(hostName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ package io.github.jwdeveloper.tiktok;
|
|||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
||||||
@@ -189,4 +190,8 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
liveRoomInfo.setConnectionState(connectionState);
|
liveRoomInfo.setConnectionState(connectionState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void publishEvent(TikTokEvent event)
|
||||||
|
{
|
||||||
|
tikTokEventHandler.publish(this, event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
|||||||
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
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.gift.TikTokGiftEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
|
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomPinEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomPinEvent;
|
||||||
@@ -41,23 +42,25 @@ import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
|||||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandler;
|
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandler;
|
||||||
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokCommonEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokGiftEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokRoomInfoEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokSocialMediaEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper;
|
import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapperHelper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokCommonEventHandler;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokRoomInfoEventHandler;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokSocialMediaEventHandler;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.*;
|
import io.github.jwdeveloper.tiktok.messages.webcast.*;
|
||||||
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
|
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
|
||||||
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient;
|
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient;
|
||||||
@@ -88,12 +91,12 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public LiveClientBuilder onMapping(Consumer<TikTokMapper> onCustomMappings) {
|
public LiveClientBuilder onMapping(Consumer<TikTokMapper> onCustomMappings) {
|
||||||
this.onCustomMappings = onCustomMappings;
|
this.onCustomMappings = onCustomMappings;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TikTokLiveClientBuilder configure(Consumer<ClientSettings> onConfigure) {
|
public TikTokLiveClientBuilder configure(Consumer<ClientSettings> onConfigure) {
|
||||||
onConfigure.accept(clientSettings);
|
onConfigure.accept(clientSettings);
|
||||||
return this;
|
return this;
|
||||||
@@ -159,7 +162,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
|
|
||||||
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
||||||
var cookieJar = new TikTokCookieJar();
|
var cookieJar = new TikTokCookieJar();
|
||||||
var requestFactory = new TikTokHttpRequestFactory(cookieJar);
|
var requestFactory = new TikTokHttpRequestFactory(cookieJar, tikTokEventHandler);
|
||||||
var apiClient = new TikTokHttpClient(cookieJar, requestFactory);
|
var apiClient = new TikTokHttpClient(cookieJar, requestFactory);
|
||||||
var apiService = new TikTokApiService(apiClient, logger, clientSettings);
|
var apiService = new TikTokApiService(apiClient, logger, clientSettings);
|
||||||
var giftManager = new TikTokGiftManager(logger);
|
var giftManager = new TikTokGiftManager(logger);
|
||||||
@@ -167,7 +170,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
var messageHandler = new TikTokMessageHandler(tikTokEventHandler, eventsMapper);
|
var messageHandler = new TikTokMessageHandler(tikTokEventHandler, eventsMapper);
|
||||||
|
|
||||||
|
|
||||||
var webSocketClient = new TikTokWebSocketClient(logger,
|
var webSocketClient = new TikTokWebSocketClient(
|
||||||
cookieJar,
|
cookieJar,
|
||||||
clientSettings,
|
clientSettings,
|
||||||
messageHandler,
|
messageHandler,
|
||||||
@@ -185,56 +188,85 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
|
|
||||||
public TikTokLiveMapper createMapper(GiftManager giftManager, TikTokRoomInfo roomInfo) {
|
public TikTokLiveMapper createMapper(GiftManager giftManager, TikTokRoomInfo roomInfo) {
|
||||||
var eventMapper = new TikTokGenericEventMapper();
|
var eventMapper = new TikTokGenericEventMapper();
|
||||||
var mapper = new TikTokLiveMapper(eventMapper);
|
var mapper = new TikTokLiveMapper(new TikTokLiveMapperHelper(eventMapper));
|
||||||
|
|
||||||
//ConnectionEvents events
|
//ConnectionEvents events
|
||||||
var commonHandler = new TikTokCommonEventHandler();
|
var commonHandler = new TikTokCommonEventHandler();
|
||||||
var giftHandler = new TikTokGiftEventHandler(giftManager);
|
var giftHandler = new TikTokGiftEventHandler(giftManager, roomInfo);
|
||||||
var roomInfoHandler = new TikTokRoomInfoEventHandler(roomInfo);
|
var roomInfoHandler = new TikTokRoomInfoEventHandler(roomInfo);
|
||||||
var socialHandler = new TikTokSocialMediaEventHandler(roomInfo);
|
var socialHandler = new TikTokSocialMediaEventHandler(roomInfo);
|
||||||
|
|
||||||
mapper.bytesToEvent(WebcastControlMessage.class, commonHandler::handleWebcastControlMessage);
|
|
||||||
|
mapper.forMessage(WebcastControlMessage.class, commonHandler::handleWebcastControlMessage);
|
||||||
|
|
||||||
//Room status events
|
//Room status events
|
||||||
mapper.bytesToEvent(WebcastLiveIntroMessage.class, roomInfoHandler::handleIntro);
|
mapper.forMessage(WebcastLiveIntroMessage.class, roomInfoHandler::handleIntro);
|
||||||
mapper.bytesToEvent(WebcastRoomUserSeqMessage.class, roomInfoHandler::handleUserRanking);
|
mapper.forMessage(WebcastRoomUserSeqMessage.class, roomInfoHandler::handleUserRanking);
|
||||||
|
mapper.forMessage(WebcastCaptionMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastCaptionMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokCaptionEvent(messageObject));
|
||||||
|
});
|
||||||
|
|
||||||
mapper.webcastObjectToConstructor(WebcastCaptionMessage.class, TikTokCaptionEvent.class);
|
|
||||||
|
|
||||||
//User Interactions events
|
//User Interactions events
|
||||||
mapper.webcastObjectToConstructor(WebcastChatMessage.class, TikTokCommentEvent.class);
|
mapper.forMessage(WebcastChatMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
mapper.bytesToEvents(WebcastLikeMessage.class, roomInfoHandler::handleLike);
|
{
|
||||||
mapper.bytesToEvents(WebcastGiftMessage.class, giftHandler::handleGift);
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
|
||||||
mapper.bytesToEvent(WebcastSocialMessage.class, socialHandler::handle);
|
return MappingResult.of(messageObject, new TikTokCommentEvent(messageObject));
|
||||||
mapper.bytesToEvents(WebcastMemberMessage.class, roomInfoHandler::handleMemberMessage);
|
});
|
||||||
|
mapper.forMessage(WebcastSubNotifyMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastSubNotifyMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokSubscribeEvent(messageObject));
|
||||||
|
});
|
||||||
|
mapper.forMessage(WebcastEmoteChatMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastEmoteChatMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokEmoteEvent(messageObject));
|
||||||
|
});
|
||||||
|
mapper.forMessage(WebcastQuestionNewMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastQuestionNewMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokQuestionEvent(messageObject));
|
||||||
|
});
|
||||||
|
|
||||||
|
mapper.forMessage(WebcastLikeMessage.class, roomInfoHandler::handleLike);
|
||||||
|
mapper.forMessage(WebcastGiftMessage.class, giftHandler::handleGifts);
|
||||||
|
mapper.forMessage(WebcastSocialMessage.class, socialHandler::handle);
|
||||||
|
mapper.forMessage(WebcastMemberMessage.class, roomInfoHandler::handleMemberMessage);
|
||||||
|
|
||||||
|
|
||||||
//Host Interaction events
|
//Host Interaction events
|
||||||
mapper.bytesToEvent(WebcastPollMessage.class, commonHandler::handlePollEvent);
|
mapper.forMessage(WebcastPollMessage.class, commonHandler::handlePollEvent);
|
||||||
mapper.bytesToEvent(WebcastRoomPinMessage.class, commonHandler::handlePinMessage);
|
mapper.forMessage(WebcastRoomPinMessage.class, commonHandler::handlePinMessage);
|
||||||
mapper.webcastObjectToConstructor(WebcastGoalUpdateMessage.class, TikTokGoalUpdateEvent.class);
|
mapper.forMessage(WebcastChatMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokCommentEvent(messageObject));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
//LinkMic events
|
//LinkMic events
|
||||||
mapper.webcastObjectToConstructor(WebcastLinkMicBattle.class, TikTokLinkMicBattleEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastLinkMicBattle.class, TikTokLinkMicBattleEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastLinkMicArmies.class, TikTokLinkMicArmiesEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastLinkMicArmies.class, TikTokLinkMicArmiesEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastLinkMicMethod.class, TikTokLinkMicMethodEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastLinkMicMethod.class, TikTokLinkMicMethodEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastLinkMicFanTicketMethod.class, TikTokLinkMicFanTicketEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastLinkMicFanTicketMethod.class, TikTokLinkMicFanTicketEvent.class);
|
||||||
|
|
||||||
//Rank events
|
//Rank events
|
||||||
mapper.webcastObjectToConstructor(WebcastRankTextMessage.class, TikTokRankTextEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastRankTextMessage.class, TikTokRankTextEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastRankUpdateMessage.class, TikTokRankUpdateEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastRankUpdateMessage.class, TikTokRankUpdateEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastHourlyRankMessage.class, TikTokRankUpdateEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastHourlyRankMessage.class, TikTokRankUpdateEvent.class);
|
||||||
|
|
||||||
//Others events
|
//Others events
|
||||||
mapper.webcastObjectToConstructor(WebcastInRoomBannerMessage.class, TikTokInRoomBannerEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastInRoomBannerMessage.class, TikTokInRoomBannerEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastMsgDetectMessage.class, TikTokDetectEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastMsgDetectMessage.class, TikTokDetectEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastBarrageMessage.class, TikTokBarrageEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastBarrageMessage.class, TikTokBarrageEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastUnauthorizedMemberMessage.class, TikTokUnauthorizedMemberEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastUnauthorizedMemberMessage.class, TikTokUnauthorizedMemberEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastOecLiveShoppingMessage.class, TikTokShopEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastOecLiveShoppingMessage.class, TikTokShopEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastImDeleteMessage.class, TikTokIMDeleteEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastImDeleteMessage.class, TikTokIMDeleteEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastQuestionNewMessage.class, TikTokQuestionEvent.class);
|
// mapper.bytesToEvents(WebcastEnvelopeMessage.class, commonHandler::handleEnvelop);
|
||||||
mapper.bytesToEvents(WebcastEnvelopeMessage.class, commonHandler::handleEnvelop);
|
|
||||||
mapper.webcastObjectToConstructor(WebcastSubNotifyMessage.class, TikTokSubscribeEvent.class);
|
|
||||||
mapper.webcastObjectToConstructor(WebcastEmoteChatMessage.class, TikTokEmoteEvent.class);
|
|
||||||
|
|
||||||
onCustomMappings.accept(mapper);
|
onCustomMappings.accept(mapper);
|
||||||
return mapper;
|
return mapper;
|
||||||
@@ -315,8 +347,8 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <E extends TikTokEvent> LiveClientBuilder onCustomEvent(Class<E> eventClazz, EventConsumer<E> event) {
|
public <E extends TikTokEvent> LiveClientBuilder onEvent(Class<E> eventClass, EventConsumer<E> event) {
|
||||||
tikTokEventHandler.subscribe(eventClazz, event);
|
tikTokEventHandler.subscribe(eventClass, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,6 +448,12 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LiveClientBuilder onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action) {
|
||||||
|
tikTokEventHandler.subscribe(TikTokHttpResponseEvent.class, action);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onGoalUpdate(EventConsumer<TikTokGoalUpdateEvent> event) {
|
public TikTokLiveClientBuilder onGoalUpdate(EventConsumer<TikTokGoalUpdateEvent> event) {
|
||||||
tikTokEventHandler.subscribe(TikTokGoalUpdateEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokGoalUpdateEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class TikTokRoomInfo implements LiveRoomInfo {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getHostUser() {
|
public User getHostUser() {
|
||||||
return null;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRanking(List<RankingUser> rankingUsers) {
|
public void updateRanking(List<RankingUser> rankingUsers) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import io.github.jwdeveloper.tiktok.ClientSettings;
|
|||||||
import io.github.jwdeveloper.tiktok.Constants;
|
import io.github.jwdeveloper.tiktok.Constants;
|
||||||
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
|
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -54,7 +55,7 @@ public class TikTokDataChecker {
|
|||||||
|
|
||||||
public TikTokApiService getApiService() {
|
public TikTokApiService getApiService() {
|
||||||
var jar = new TikTokCookieJar();
|
var jar = new TikTokCookieJar();
|
||||||
var factory = new TikTokHttpRequestFactory(jar);
|
var factory = new TikTokHttpRequestFactory(jar,new TikTokEventObserver());
|
||||||
var client = new TikTokHttpClient(jar, factory);
|
var client = new TikTokHttpClient(jar, factory);
|
||||||
var settings = new ClientSettings();
|
var settings = new ClientSettings();
|
||||||
settings.setClientParameters(Constants.DefaultClientParams());
|
settings.setClientParameters(Constants.DefaultClientParams());
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ public class TikTokHttpClient {
|
|||||||
if (parameters == null) {
|
if (parameters == null) {
|
||||||
parameters = new HashMap<>();
|
parameters = new HashMap<>();
|
||||||
}
|
}
|
||||||
System.out.println("RomMID: "+parameters.get("room_id"));
|
|
||||||
var request = requestFactory.setQueries(parameters);
|
var request = requestFactory.setQueries(parameters);
|
||||||
return request.post(url);
|
return request.post(url);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ package io.github.jwdeveloper.tiktok.http;
|
|||||||
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.Constants;
|
import io.github.jwdeveloper.tiktok.Constants;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.http.HttpData;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
|
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
import java.net.CookieManager;
|
import java.net.CookieManager;
|
||||||
@@ -45,26 +48,27 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
private final Map<String, String> defaultHeaders;
|
private final Map<String, String> defaultHeaders;
|
||||||
private final TikTokCookieJar tikTokCookieJar;
|
private final TikTokCookieJar tikTokCookieJar;
|
||||||
private final HttpClient client;
|
private final HttpClient client;
|
||||||
|
private final TikTokEventObserver eventHandler;
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
public TikTokHttpRequestFactory(TikTokCookieJar tikTokCookieJar) {
|
public TikTokHttpRequestFactory(TikTokCookieJar tikTokCookieJar, TikTokEventObserver eventHandler) {
|
||||||
this.tikTokCookieJar = tikTokCookieJar;
|
this.tikTokCookieJar = tikTokCookieJar;
|
||||||
this.cookieManager = new CookieManager();
|
this.cookieManager = new CookieManager();
|
||||||
|
this.eventHandler = eventHandler;
|
||||||
defaultHeaders = Constants.DefaultRequestHeaders();
|
defaultHeaders = Constants.DefaultRequestHeaders();
|
||||||
client = HttpClient.newBuilder()
|
client = HttpClient.newBuilder()
|
||||||
.cookieHandler(cookieManager)
|
.cookieHandler(cookieManager)
|
||||||
.connectTimeout(Duration.ofSeconds(2))
|
.connectTimeout(Duration.ofSeconds(2))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String get(String url) {
|
public String get(String url) {
|
||||||
var uri = URI.create(url);
|
var uri = URI.create(url);
|
||||||
var requestBuilder = HttpRequest.newBuilder().GET();
|
var requestBuilder = HttpRequest.newBuilder().GET();
|
||||||
|
|
||||||
for (var header : defaultHeaders.entrySet())
|
for (var header : defaultHeaders.entrySet()) {
|
||||||
{
|
if (header.getKey().equals("Connection") || header.getKey().equals("Accept-Encoding")) {
|
||||||
if(header.getKey().equals("Connection") || header.getKey().equals("Accept-Encoding"))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
requestBuilder.setHeader(header.getKey(), header.getValue());
|
requestBuilder.setHeader(header.getKey(), header.getValue());
|
||||||
@@ -73,9 +77,7 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
var baseUri = uri.toString();
|
var baseUri = uri.toString();
|
||||||
var requestUri = URI.create(baseUri + "?" + query);
|
var requestUri = URI.create(baseUri + "?" + query);
|
||||||
requestBuilder.uri(requestUri);
|
requestBuilder.uri(requestUri);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
requestBuilder.uri(uri);
|
requestBuilder.uri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,15 +90,13 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
public String post(String url) {
|
public String post(String url) {
|
||||||
var uri = URI.create(url);
|
var uri = URI.create(url);
|
||||||
var request = HttpRequest.newBuilder().POST(HttpRequest.BodyPublishers.ofString(""));
|
var request = HttpRequest.newBuilder().POST(HttpRequest.BodyPublishers.ofString(""));
|
||||||
for (var header : defaultHeaders.entrySet())
|
for (var header : defaultHeaders.entrySet()) {
|
||||||
{
|
if (header.getKey().equals("Connection")) {
|
||||||
if(header.getKey().equals("Connection"))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
request.setHeader(header.getKey(), header.getValue());
|
request.setHeader(header.getKey(), header.getValue());
|
||||||
}
|
}
|
||||||
request.setHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8");
|
request.setHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||||
request.setHeader("Cookie", tikTokCookieJar.parseCookies());
|
request.setHeader("Cookie", tikTokCookieJar.parseCookies());
|
||||||
|
|
||||||
|
|
||||||
@@ -104,11 +104,8 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
var baseUri = uri.toString();
|
var baseUri = uri.toString();
|
||||||
var requestUri = URI.create(baseUri + "?" + query);
|
var requestUri = URI.create(baseUri + "?" + query);
|
||||||
request.uri(requestUri);
|
request.uri(requestUri);
|
||||||
System.out.println(requestUri.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return getContent(request.build());
|
return getContent(request.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +122,7 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
public TikTokHttpRequest setQueries(Map<String, Object> queries) {
|
public TikTokHttpRequest setQueries(Map<String, Object> queries) {
|
||||||
if (queries == null)
|
if (queries == null)
|
||||||
return this;
|
return this;
|
||||||
var testMap = new TreeMap<String,Object>(queries);
|
var testMap = new TreeMap<String, Object>(queries);
|
||||||
query = String.join("&", testMap.entrySet().stream().map(x ->
|
query = String.join("&", testMap.entrySet().stream().map(x ->
|
||||||
{
|
{
|
||||||
var key = x.getKey();
|
var key = x.getKey();
|
||||||
@@ -143,6 +140,9 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
|
|
||||||
private String getContent(HttpRequest request) throws Exception {
|
private String getContent(HttpRequest request) throws Exception {
|
||||||
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
|
||||||
|
var event = new TikTokHttpResponseEvent(response.uri().toString(), HttpData.map(response), HttpData.map(request));
|
||||||
|
eventHandler.publish(null, event);
|
||||||
if (response.statusCode() == 404) {
|
if (response.statusCode() == 404) {
|
||||||
throw new TikTokLiveRequestException("Request responded with 404 NOT_FOUND");
|
throw new TikTokLiveRequestException("Request responded with 404 NOT_FOUND");
|
||||||
}
|
}
|
||||||
@@ -155,8 +155,6 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
for (var cookie : cookies) {
|
for (var cookie : cookies) {
|
||||||
var split = cookie.split(";")[0].split("=");
|
var split = cookie.split(";")[0].split("=");
|
||||||
var uri = request.uri();
|
var uri = request.uri();
|
||||||
|
|
||||||
|
|
||||||
var key = split[0];
|
var key = split[0];
|
||||||
var value = split[1];
|
var value = split[1];
|
||||||
tikTokCookieJar.set(key, value);
|
tikTokCookieJar.set(key, value);
|
||||||
|
|||||||
@@ -23,11 +23,10 @@
|
|||||||
package io.github.jwdeveloper.tiktok.listener;
|
package io.github.jwdeveloper.tiktok.listener;
|
||||||
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.annotations.TikTokEventHandler;
|
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokEventListenerMethodException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokEventListenerMethodException;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
||||||
|
|
||||||
@@ -37,10 +36,10 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TikTokListenersManager implements ListenersManager {
|
public class TikTokListenersManager implements ListenersManager {
|
||||||
private final TikTokEventObserver eventObserver;
|
private final io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver eventObserver;
|
||||||
private final List<ListenerBindingModel> bindingModels;
|
private final List<ListenerBindingModel> bindingModels;
|
||||||
|
|
||||||
public TikTokListenersManager(List<TikTokEventListener> listeners, TikTokEventObserver tikTokEventHandler) {
|
public TikTokListenersManager(List<TikTokEventListener> listeners, io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver tikTokEventHandler) {
|
||||||
this.eventObserver = tikTokEventHandler;
|
this.eventObserver = tikTokEventHandler;
|
||||||
this.bindingModels = new ArrayList<>(listeners.size());
|
this.bindingModels = new ArrayList<>(listeners.size());
|
||||||
for (var listener : listeners) {
|
for (var listener : listeners) {
|
||||||
@@ -93,7 +92,7 @@ public class TikTokListenersManager implements ListenersManager {
|
|||||||
var clazz = listener.getClass();
|
var clazz = listener.getClass();
|
||||||
var methods = Arrays.stream(clazz.getDeclaredMethods()).filter(m ->
|
var methods = Arrays.stream(clazz.getDeclaredMethods()).filter(m ->
|
||||||
m.getParameterCount() == 2 &&
|
m.getParameterCount() == 2 &&
|
||||||
m.isAnnotationPresent(TikTokEventHandler.class)).toList();
|
m.isAnnotationPresent(TikTokEventObserver.class)).toList();
|
||||||
var eventsMap = new HashMap<Class<?>, List<EventConsumer<?>>>();
|
var eventsMap = new HashMap<Class<?>, List<EventConsumer<?>>>();
|
||||||
for (var method : methods) {
|
for (var method : methods) {
|
||||||
var eventClazz = method.getParameterTypes()[1];
|
var eventClazz = method.getParameterTypes()[1];
|
||||||
|
|||||||
@@ -1,8 +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.mappers;
|
package io.github.jwdeveloper.tiktok.mappers;
|
||||||
|
|
||||||
import com.google.protobuf.GeneratedMessageV3;
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokLive;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -10,79 +34,83 @@ import java.util.Map;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class TikTokLiveMapper implements TikTokMapper {
|
public class TikTokLiveMapper implements TikTokMapper {
|
||||||
private final Map<String, Function<byte[], List<TikTokEvent>>> mappers;
|
|
||||||
private final TikTokGenericEventMapper genericMapper;
|
|
||||||
|
|
||||||
public TikTokLiveMapper(TikTokGenericEventMapper genericMapper) {
|
private final Map<String, TikTokLiveMapperModel> mappers;
|
||||||
|
private final TikTokMapperHelper mapperUtils;
|
||||||
|
private final TikTokLiveMapperModel globalMapperModel;
|
||||||
|
|
||||||
|
public TikTokLiveMapper(TikTokMapperHelper mapperUtils) {
|
||||||
this.mappers = new HashMap<>();
|
this.mappers = new HashMap<>();
|
||||||
this.genericMapper = genericMapper;
|
this.mapperUtils = mapperUtils;
|
||||||
|
this.globalMapperModel = new TikTokLiveMapperModel("any message");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bytesToEvent(String messageName, Function<byte[], TikTokEvent> onMapping) {
|
public TikTokMapperModel forMessage(String messageName) {
|
||||||
mappers.put(messageName, messagePayload -> List.of(onMapping.apply(messagePayload)));
|
if (!isRegistered(messageName)) {
|
||||||
|
var model = new TikTokLiveMapperModel(messageName);
|
||||||
|
mappers.put(messageName, model);
|
||||||
|
}
|
||||||
|
return mappers.get(messageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bytesToEvents(String messageName, Function<byte[], List<TikTokEvent>> onMapping) {
|
public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName) {
|
||||||
mappers.put(messageName, onMapping::apply);
|
return forMessage(mapperName.getSimpleName());
|
||||||
}
|
|
||||||
|
|
||||||
public void bytesToEvent(Class<? extends GeneratedMessageV3> clazz, Function<byte[], TikTokEvent> onMapping) {
|
|
||||||
mappers.put(clazz.getSimpleName(), messagePayload -> List.of(onMapping.apply(messagePayload)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void bytesToEvents(Class<? extends GeneratedMessageV3> clazz, Function<byte[], List<TikTokEvent>> onMapping) {
|
|
||||||
mappers.put(clazz.getSimpleName(), onMapping::apply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void webcastObjectToConstructor(Class<? extends GeneratedMessageV3> sourceClass, Class<? extends TikTokEvent> outputClass) {
|
public TikTokMapperModel forMessage(String mapperName, MappingAction<MappingResult> onMapping) {
|
||||||
bytesToEvent(sourceClass, (e) -> genericMapper.mapToEvent(sourceClass, outputClass, e));
|
var model = forMessage(mapperName);
|
||||||
|
model.onMapping(onMapping);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, MappingAction<MappingResult> onMapping) {
|
||||||
|
var model = forMessage(mapperName);
|
||||||
|
model.onMapping(onMapping);
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends GeneratedMessageV3> void webcastObjectToEvent(Class<T> source, Function<T, TikTokEvent> onMapping) {
|
public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, Function<byte[], TikTokEvent> onMapping) {
|
||||||
bytesToEvent(source, (bytes) ->
|
return forMessage(mapperName, (inputBytes, messageName, mapperHelper) -> MappingResult.of(inputBytes, onMapping.apply(inputBytes)));
|
||||||
{
|
|
||||||
try {
|
|
||||||
var parsingMethod = genericMapper.getParsingMethod(source);
|
|
||||||
var sourceObject = parsingMethod.invoke(null, bytes);
|
|
||||||
var event = onMapping.apply((T) sourceObject);
|
|
||||||
return event;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new TikTokMessageMappingException(source, "can't find parsing method", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends GeneratedMessageV3> void webcastObjectToEvents(Class<T> source, Function<T, List<TikTokEvent>> onMapping) {
|
public TikTokMapperModel forAnyMessage() {
|
||||||
bytesToEvents(source, (bytes) ->
|
return globalMapperModel;
|
||||||
{
|
|
||||||
try {
|
|
||||||
var parsingMethod = genericMapper.getParsingMethod(source);
|
|
||||||
var sourceObject = parsingMethod.invoke(null, bytes);
|
|
||||||
var event = onMapping.apply((T) sourceObject);
|
|
||||||
return event;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new TikTokMessageMappingException(source, "can't find parsing method", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRegistered(String input) {
|
|
||||||
return mappers.containsKey(input);
|
public boolean isRegistered(String mapperName) {
|
||||||
|
return mappers.containsKey(mapperName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TikTokEvent> handleMapping(String input, byte[] bytes) {
|
public <T extends GeneratedMessageV3> boolean isRegistered(Class<T> mapperName) {
|
||||||
if (!isRegistered(input)) {
|
return mappers.containsKey(mapperName.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TikTokEvent> handleMapping(String messageName, byte[] bytes) {
|
||||||
|
if (!isRegistered(messageName)) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
var mapper = mappers.get(input);
|
var mapperModel = mappers.get(messageName);
|
||||||
var events = mapper.apply(bytes);
|
|
||||||
return events;
|
var inputBytes = mapperModel.getOnBeforeMapping().onMapping(bytes, messageName, mapperUtils);
|
||||||
|
var globalInputBytes = globalMapperModel.getOnBeforeMapping().onMapping(inputBytes, messageName, mapperUtils);
|
||||||
|
|
||||||
|
|
||||||
|
var mappingResult = mapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
|
||||||
|
|
||||||
|
if (mappingResult == null) {
|
||||||
|
mappingResult = globalMapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
var afterMappingResult = mapperModel.getOnAfterMapping().apply(mappingResult);
|
||||||
|
var globalAfterMappingResult = globalMapperModel.getOnAfterMapping().apply(MappingResult.of(mappingResult.getSource(), afterMappingResult));
|
||||||
|
return globalAfterMappingResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.mappers;
|
||||||
|
|
||||||
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.ProtocolUtils;
|
||||||
|
|
||||||
|
public class TikTokLiveMapperHelper implements TikTokMapperHelper {
|
||||||
|
private final TikTokGenericEventMapper genericMapper;
|
||||||
|
|
||||||
|
public TikTokLiveMapperHelper(TikTokGenericEventMapper genericMapper) {
|
||||||
|
this.genericMapper = genericMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends GeneratedMessageV3> T bytesToWebcastObject(byte[] bytes, Class<T> messageClass) {
|
||||||
|
try {
|
||||||
|
var parsingMethod = genericMapper.getParsingMethod(messageClass);
|
||||||
|
var sourceObject = parsingMethod.invoke(null, bytes);
|
||||||
|
return (T) sourceObject;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new TikTokMessageMappingException(messageClass, "can't find parsing method", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object bytesToWebcastObject(byte[] bytes, String messageName) {
|
||||||
|
try {
|
||||||
|
var packageName = "io.github.jwdeveloper.tiktok.messages.webcast." + messageName;
|
||||||
|
var clazz = Class.forName(packageName);
|
||||||
|
return bytesToWebcastObject(bytes, (Class<? extends GeneratedMessageV3>) clazz);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new TikTokMessageMappingException(messageName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMessageHasProtoClass(String messageName) {
|
||||||
|
try {
|
||||||
|
var packageName = "io.github.jwdeveloper.tiktok.messages.webcast." + messageName;
|
||||||
|
Class.forName(packageName);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProtoBufferObject bytesToProtoBufferStructure(byte[] bytes) {
|
||||||
|
return ProtocolUtils.getProtocolBufferStructure(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJson(Object obj) {
|
||||||
|
return JsonUtil.toJson(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TikTokLiveMapperModel implements TikTokMapperModel {
|
||||||
|
@Getter
|
||||||
|
private String sourceMessageName;
|
||||||
|
|
||||||
|
private MappingAction<byte[]> onBeforeMapping;
|
||||||
|
|
||||||
|
private MappingAction<MappingResult> onMapping;
|
||||||
|
|
||||||
|
private Function<MappingResult, List<TikTokEvent>> onAfterMapping;
|
||||||
|
|
||||||
|
public TikTokLiveMapperModel(String sourceMessageName, MappingAction onMapping) {
|
||||||
|
this.sourceMessageName = sourceMessageName;
|
||||||
|
this.onBeforeMapping = (inputBytes, mesasgeName, mapperHelper) -> inputBytes;
|
||||||
|
this.onMapping = onMapping;
|
||||||
|
this.onAfterMapping = MappingResult::getEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokLiveMapperModel(String sourceMessageName) {
|
||||||
|
this.sourceMessageName = sourceMessageName;
|
||||||
|
this.onBeforeMapping = (inputBytes, mesasgeName, mapperHelper) -> inputBytes;
|
||||||
|
this.onMapping = (inputBytes, mesasgeName, mapperHelper) -> MappingResult.of(inputBytes, List.of());
|
||||||
|
this.onAfterMapping = MappingResult::getEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokMapperModel onBeforeMapping(MappingAction<byte[]> action) {
|
||||||
|
this.onBeforeMapping = action;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokMapperModel onMapping(MappingAction<MappingResult> action) {
|
||||||
|
this.onMapping = action;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokMapperModel onAfterMapping(Function<MappingResult, List<TikTokEvent>> action) {
|
||||||
|
this.onAfterMapping = action;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
package io.github.jwdeveloper.tiktok.mappers.handlers;
|
||||||
|
|
||||||
public class TikTokChestEventHandler {
|
public class TikTokChestEventHandler {
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,26 @@
|
|||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
/*
|
||||||
|
* 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.mappers.handlers;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.*;
|
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
@@ -43,9 +65,9 @@ public class TikTokCommonEventHandler
|
|||||||
public TikTokEvent handlePollEvent(byte[] msg) {
|
public TikTokEvent handlePollEvent(byte[] msg) {
|
||||||
var poolMessage = WebcastPollMessage.parseFrom(msg);
|
var poolMessage = WebcastPollMessage.parseFrom(msg);
|
||||||
return switch (poolMessage.getMessageType()) {
|
return switch (poolMessage.getMessageType()) {
|
||||||
case 0 -> new TikTokPollStartEvent(poolMessage);
|
case MESSAGETYPE_SUBSUCCESS -> new TikTokPollStartEvent(poolMessage);
|
||||||
case 1 -> new TikTokPollEndEvent(poolMessage);
|
case MESSAGETYPE_ANCHORREMINDER -> new TikTokPollEndEvent(poolMessage);
|
||||||
case 2 -> new TikTokPollUpdateEvent(poolMessage);
|
case MESSAGETYPE_ENTERROOMEXPIRESOON -> new TikTokPollUpdateEvent(poolMessage);
|
||||||
default -> new TikTokPollEvent(poolMessage);
|
default -> new TikTokPollEvent(poolMessage);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -20,8 +20,9 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
package io.github.jwdeveloper.tiktok.mappers.handlers;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
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.gift.TikTokGiftEvent;
|
||||||
@@ -30,6 +31,8 @@ import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
|||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
@@ -41,16 +44,19 @@ import java.util.Map;
|
|||||||
public class TikTokGiftEventHandler {
|
public class TikTokGiftEventHandler {
|
||||||
private final GiftManager giftManager;
|
private final GiftManager giftManager;
|
||||||
private final Map<Long, WebcastGiftMessage> giftsMessages;
|
private final Map<Long, WebcastGiftMessage> giftsMessages;
|
||||||
|
private final TikTokRoomInfo tikTokRoomInfo;
|
||||||
|
|
||||||
public TikTokGiftEventHandler(GiftManager giftManager) {
|
public TikTokGiftEventHandler(GiftManager giftManager, TikTokRoomInfo tikTokRoomInfo) {
|
||||||
this.giftManager = giftManager;
|
this.giftManager = giftManager;
|
||||||
giftsMessages = new HashMap<>();
|
giftsMessages = new HashMap<>();
|
||||||
|
this.tikTokRoomInfo = tikTokRoomInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public List<TikTokEvent> handleGift(byte[] msg) {
|
public MappingResult handleGifts(byte[] msg, String name, TikTokMapperHelper helper) {
|
||||||
var currentMessage = WebcastGiftMessage.parseFrom(msg);
|
var currentMessage = WebcastGiftMessage.parseFrom(msg);
|
||||||
return handleGift(currentMessage);
|
var gifts = handleGift(currentMessage);
|
||||||
|
return MappingResult.of(currentMessage, gifts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TikTokEvent> handleGift(WebcastGiftMessage currentMessage) {
|
public List<TikTokEvent> handleGift(WebcastGiftMessage currentMessage) {
|
||||||
@@ -98,12 +104,12 @@ public class TikTokGiftEventHandler {
|
|||||||
|
|
||||||
private TikTokGiftEvent getGiftEvent(WebcastGiftMessage message) {
|
private TikTokGiftEvent getGiftEvent(WebcastGiftMessage message) {
|
||||||
var gift = getGiftObject(message);
|
var gift = getGiftObject(message);
|
||||||
return new TikTokGiftEvent(gift, message);
|
return new TikTokGiftEvent(gift, tikTokRoomInfo.getHost(), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TikTokGiftEvent getGiftComboEvent(WebcastGiftMessage message, GiftSendType state) {
|
private TikTokGiftEvent getGiftComboEvent(WebcastGiftMessage message, GiftSendType state) {
|
||||||
var gift = getGiftObject(message);
|
var gift = getGiftObject(message);
|
||||||
return new TikTokGiftComboEvent(gift, message, state);
|
return new TikTokGiftComboEvent(gift, tikTokRoomInfo.getHost(), message, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Gift getGiftObject(WebcastGiftMessage giftMessage) {
|
private Gift getGiftObject(WebcastGiftMessage giftMessage) {
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
package io.github.jwdeveloper.tiktok.mappers.handlers;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent;
|
||||||
@@ -31,6 +31,8 @@ import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
|||||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLiveIntroMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLiveIntroMessage;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage;
|
||||||
@@ -76,8 +78,7 @@ public class TikTokRoomInfoEventHandler {
|
|||||||
|
|
||||||
return handleRoomInfo(tikTokRoomInfo ->
|
return handleRoomInfo(tikTokRoomInfo ->
|
||||||
{
|
{
|
||||||
if(tikTokRoomInfo.getHost() == null)
|
if (tikTokRoomInfo.getHost() == null) {
|
||||||
{
|
|
||||||
tikTokRoomInfo.setHost(hostUser);
|
tikTokRoomInfo.setHost(hostUser);
|
||||||
}
|
}
|
||||||
tikTokRoomInfo.setLanguage(language);
|
tikTokRoomInfo.setLanguage(language);
|
||||||
@@ -85,7 +86,7 @@ public class TikTokRoomInfoEventHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public List<TikTokEvent> handleMemberMessage(byte[] msg) {
|
public MappingResult handleMemberMessage(byte[] msg, String name, TikTokMapperHelper helper) {
|
||||||
var message = WebcastMemberMessage.parseFrom(msg);
|
var message = WebcastMemberMessage.parseFrom(msg);
|
||||||
|
|
||||||
var event = switch (message.getAction()) {
|
var event = switch (message.getAction()) {
|
||||||
@@ -98,18 +99,17 @@ public class TikTokRoomInfoEventHandler {
|
|||||||
{
|
{
|
||||||
tikTokRoomInfo.setViewersCount(message.getMemberCount());
|
tikTokRoomInfo.setViewersCount(message.getMemberCount());
|
||||||
});
|
});
|
||||||
|
return MappingResult.of(message, List.of(event, roomInfoEvent));
|
||||||
return List.of(event, roomInfoEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public List<TikTokEvent> handleLike(byte[] msg)
|
public MappingResult handleLike(byte[] msg, String name, TikTokMapperHelper helper) {
|
||||||
{
|
|
||||||
var message = WebcastLikeMessage.parseFrom(msg);
|
var message = WebcastLikeMessage.parseFrom(msg);
|
||||||
var event = new TikTokLikeEvent(message);
|
var event = new TikTokLikeEvent(message);
|
||||||
var roomInfoEvent = this.handleRoomInfo(tikTokRoomInfo ->
|
var roomInfoEvent = this.handleRoomInfo(tikTokRoomInfo ->
|
||||||
{
|
{
|
||||||
tikTokRoomInfo.setLikesCount(event.getTotalLikes());
|
tikTokRoomInfo.setLikesCount(event.getTotalLikes());
|
||||||
});
|
});
|
||||||
return List.of(event, roomInfoEvent);
|
return MappingResult.of(message, List.of(event, roomInfoEvent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
package io.github.jwdeveloper.tiktok.mappers.handlers;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokUnhandledSocialEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokUnhandledSocialEvent;
|
||||||
@@ -39,7 +39,6 @@ import java.util.TreeMap;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class TikTokWebSocketClient implements SocketClient {
|
public class TikTokWebSocketClient implements SocketClient {
|
||||||
private final Logger logger;
|
|
||||||
private final ClientSettings clientSettings;
|
private final ClientSettings clientSettings;
|
||||||
private final TikTokCookieJar tikTokCookieJar;
|
private final TikTokCookieJar tikTokCookieJar;
|
||||||
private final TikTokMessageHandler messageHandler;
|
private final TikTokMessageHandler messageHandler;
|
||||||
@@ -48,12 +47,11 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
private TikTokWebSocketPingingTask pingingTask;
|
private TikTokWebSocketPingingTask pingingTask;
|
||||||
private boolean isConnected;
|
private boolean isConnected;
|
||||||
|
|
||||||
public TikTokWebSocketClient(Logger logger,
|
public TikTokWebSocketClient(
|
||||||
TikTokCookieJar tikTokCookieJar,
|
TikTokCookieJar tikTokCookieJar,
|
||||||
ClientSettings clientSettings,
|
ClientSettings clientSettings,
|
||||||
TikTokMessageHandler messageHandler,
|
TikTokMessageHandler messageHandler,
|
||||||
TikTokEventObserver tikTokEventHandler) {
|
TikTokEventObserver tikTokEventHandler) {
|
||||||
this.logger = logger;
|
|
||||||
this.tikTokCookieJar = tikTokCookieJar;
|
this.tikTokCookieJar = tikTokCookieJar;
|
||||||
this.clientSettings = clientSettings;
|
this.clientSettings = clientSettings;
|
||||||
this.messageHandler = messageHandler;
|
this.messageHandler = messageHandler;
|
||||||
|
|||||||
@@ -22,12 +22,13 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.handlers.events;
|
package io.github.jwdeveloper.tiktok.handlers.events;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
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.gift.TikTokGiftEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokGiftEventHandler;
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.GiftStruct;
|
import io.github.jwdeveloper.tiktok.messages.data.GiftStruct;
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.Image;
|
import io.github.jwdeveloper.tiktok.messages.data.Image;
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.User;
|
import io.github.jwdeveloper.tiktok.messages.data.User;
|
||||||
@@ -49,42 +50,43 @@ class TikTokGiftEventHandlerTest {
|
|||||||
@BeforeAll
|
@BeforeAll
|
||||||
public void before() {
|
public void before() {
|
||||||
var manager = new TikTokGiftManager(Logger.getLogger("x"));
|
var manager = new TikTokGiftManager(Logger.getLogger("x"));
|
||||||
|
var info = new TikTokRoomInfo();
|
||||||
|
info.setHost(new io.github.jwdeveloper.tiktok.data.models.users.User(123L, "test", new Picture("")));
|
||||||
manager.registerGift(123, "example", 123, new Picture("image.webp"));
|
manager.registerGift(123, "example", 123, new Picture("image.webp"));
|
||||||
handler = new TikTokGiftEventHandler(manager);
|
handler = new TikTokGiftEventHandler(manager, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleGifts() {
|
void shouldHandleGifts() {
|
||||||
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,false);
|
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1, false);
|
||||||
var result = handler.handleGift(message);
|
var result = handler.handleGift(message);
|
||||||
|
|
||||||
Assertions.assertEquals(2, result.size());
|
Assertions.assertEquals(2, result.size());
|
||||||
|
|
||||||
var event = (TikTokGiftEvent) result.get(0);
|
var event = (TikTokGiftEvent) result.get(0);
|
||||||
var gift = event.getGift();
|
var gift = event.getGift();
|
||||||
Assertions.assertEquals("image-new.png",gift.getPicture().getLink());
|
Assertions.assertEquals("image-new.png", gift.getPicture().getLink());
|
||||||
Assertions.assertEquals(123,gift.getId());
|
Assertions.assertEquals(123, gift.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleStrakableGift() {
|
void shouldHandleStrakableGift() {
|
||||||
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,true);
|
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1, true);
|
||||||
var result = handler.handleGift(message);
|
var result = handler.handleGift(message);
|
||||||
|
|
||||||
Assertions.assertEquals(1, result.size());
|
Assertions.assertEquals(1, result.size());
|
||||||
|
|
||||||
var event = (TikTokGiftEvent) result.get(0);
|
var event = (TikTokGiftEvent) result.get(0);
|
||||||
var gift = event.getGift();
|
var gift = event.getGift();
|
||||||
Assertions.assertEquals("image-new.png",gift.getPicture().getLink());
|
Assertions.assertEquals("image-new.png", gift.getPicture().getLink());
|
||||||
Assertions.assertEquals(123,gift.getId());
|
Assertions.assertEquals(123, gift.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleStrike()
|
void shouldHandleStrike() {
|
||||||
{
|
var message1 = getGiftMessage("example-new-name", 123, "image-new.png", 1, 1, true);
|
||||||
var message1 = getGiftMessage("example-new-name", 123, "image-new.png", 1, 1,true);
|
var message2 = getGiftMessage("example-new-name", 123, "image-new.png", 2, 1, true);
|
||||||
var message2 = getGiftMessage("example-new-name", 123, "image-new.png", 2, 1,true);
|
var message3 = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1, true);
|
||||||
var message3 = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,true);
|
|
||||||
|
|
||||||
var result1 = handler.handleGift(message1);
|
var result1 = handler.handleGift(message1);
|
||||||
var result2 = handler.handleGift(message2);
|
var result2 = handler.handleGift(message2);
|
||||||
@@ -96,9 +98,9 @@ class TikTokGiftEventHandlerTest {
|
|||||||
Assertions.assertEquals(2, result3.size());
|
Assertions.assertEquals(2, result3.size());
|
||||||
var event3 = (TikTokGiftComboEvent) result3.get(0);
|
var event3 = (TikTokGiftComboEvent) result3.get(0);
|
||||||
|
|
||||||
Assertions.assertEquals(GiftSendType.Begin,event1.getComboState());
|
Assertions.assertEquals(GiftSendType.Begin, event1.getComboState());
|
||||||
Assertions.assertEquals(GiftSendType.Active,event2.getComboState());
|
Assertions.assertEquals(GiftSendType.Active, event2.getComboState());
|
||||||
Assertions.assertEquals(GiftSendType.Finished,event3.getComboState());
|
Assertions.assertEquals(GiftSendType.Finished, event3.getComboState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -116,7 +118,7 @@ class TikTokGiftEventHandlerTest {
|
|||||||
giftBuilder.setId(giftId);
|
giftBuilder.setId(giftId);
|
||||||
giftBuilder.setName(giftName);
|
giftBuilder.setName(giftName);
|
||||||
giftBuilder.setImage(Image.newBuilder().addUrlList(giftImage).build());
|
giftBuilder.setImage(Image.newBuilder().addUrlList(giftImage).build());
|
||||||
giftBuilder.setType(streakable?1:0);
|
giftBuilder.setType(streakable ? 1 : 0);
|
||||||
userBuilder.setId(userId);
|
userBuilder.setId(userId);
|
||||||
|
|
||||||
builder.setGiftId(giftId);
|
builder.setGiftId(giftId);
|
||||||
@@ -127,5 +129,4 @@ class TikTokGiftEventHandlerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -22,12 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.listener;
|
package io.github.jwdeveloper.tiktok.listener;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.annotations.TikTokEventHandler;
|
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -42,12 +41,12 @@ import static org.mockito.Mockito.verify;
|
|||||||
|
|
||||||
class TikTokListenersManagerTest {
|
class TikTokListenersManagerTest {
|
||||||
|
|
||||||
private TikTokEventObserver eventObserver;
|
private io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver eventObserver;
|
||||||
private TikTokListenersManager tikTokListenersManager;
|
private TikTokListenersManager tikTokListenersManager;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
eventObserver = Mockito.mock(TikTokEventObserver.class);
|
eventObserver = Mockito.mock(io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver.class);
|
||||||
List<TikTokEventListener> listeners = new ArrayList<>();
|
List<TikTokEventListener> listeners = new ArrayList<>();
|
||||||
tikTokListenersManager = new TikTokListenersManager(listeners, eventObserver);
|
tikTokListenersManager = new TikTokListenersManager(listeners, eventObserver);
|
||||||
}
|
}
|
||||||
@@ -93,19 +92,19 @@ class TikTokListenersManagerTest {
|
|||||||
|
|
||||||
public static class TikTokEventListenerTest implements TikTokEventListener
|
public static class TikTokEventListenerTest implements TikTokEventListener
|
||||||
{
|
{
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onJoin(LiveClient client, TikTokJoinEvent joinEvent)
|
public void onJoin(LiveClient client, TikTokJoinEvent joinEvent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onGift(LiveClient client, TikTokGiftEvent giftMessageEvent)
|
public void onGift(LiveClient client, TikTokGiftEvent giftMessageEvent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onEvent(LiveClient client, TikTokEvent event)
|
public void onEvent(LiveClient client, TikTokEvent event)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.11-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
public class CustomEventExample {
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class CheapGiftEvent extends TikTokEvent {
|
||||||
|
Gift gift;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class ExpensiveGiftEvent extends TikTokEvent {
|
||||||
|
Gift gift;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||||
|
.onGift((liveClient, event) ->
|
||||||
|
{
|
||||||
|
if (event.getGift().getDiamondCost() > 100)
|
||||||
|
liveClient.publishEvent(new ExpensiveGiftEvent(event.getGift()));
|
||||||
|
else
|
||||||
|
liveClient.publishEvent(new CheapGiftEvent(event.getGift()));
|
||||||
|
})
|
||||||
|
.onEvent(CheapGiftEvent.class,(liveClient, event) ->
|
||||||
|
{
|
||||||
|
System.out.println("Thanks for cheap gift");
|
||||||
|
})
|
||||||
|
.onEvent(ExpensiveGiftEvent.class,(liveClient, event) ->
|
||||||
|
{
|
||||||
|
System.out.println("Thanks for expensive gift!");
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,54 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastChatMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastChatMessage;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
|
||||||
import io.github.jwdeveloper.tiktok.utils.ProtocolUtils;
|
|
||||||
|
|
||||||
public class CustomMappingExample {
|
public class CustomMappingExample {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
TikTokLive.newClient("vadimpyrography")
|
TikTokLive.newClient("saszareznikow")
|
||||||
.onCustomEvent(CustomChatEvent.class, (liveClient, event) ->
|
.onMapping(mapper ->
|
||||||
{
|
{
|
||||||
System.out.println("hello world!");
|
mapper.forMessage(WebcastChatMessage.class)
|
||||||
|
.onBeforeMapping((inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
System.out.println("===============================");
|
||||||
|
System.out.println("OnBefore mapping: " + messageName);
|
||||||
|
return inputBytes;
|
||||||
|
})
|
||||||
|
.onMapping((inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
System.out.println("onMapping mapping: " + messageName);
|
||||||
|
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
|
||||||
|
var language = message.getContentLanguage();
|
||||||
|
var userName = message.getUser().getNickname();
|
||||||
|
var content = message.getContent();
|
||||||
|
var event = new CustomChatEvent(language, userName, content);
|
||||||
|
return MappingResult.of(message, event);
|
||||||
|
})
|
||||||
|
.onAfterMapping(mappingResult ->
|
||||||
|
{
|
||||||
|
var source = mappingResult.getSource();
|
||||||
|
var events = mappingResult.getEvents();
|
||||||
|
System.out.println("onAfter mapping, " + source.getClass().getSimpleName() + " was mapped to " + events.size() + " events");
|
||||||
|
return events;
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
There might be cast that we don't have Webcast class for incoming message from TikTok
|
||||||
|
`mapperHelper.bytesToProtoBufferStructure` but you can still investigate message structure
|
||||||
|
by using helper methods
|
||||||
|
*/
|
||||||
|
mapper.forMessage("WebcastMemberMessage")
|
||||||
|
.onBeforeMapping((inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
if (mapperHelper.isMessageHasProtoClass(messageName)) {
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, messageName);
|
||||||
|
// System.out.println(mapperHelper.toJson(messageObject));
|
||||||
|
} else {
|
||||||
|
var structure = mapperHelper.bytesToProtoBufferStructure(inputBytes);
|
||||||
|
// System.out.println(structure.toJson());
|
||||||
|
}
|
||||||
|
return inputBytes;
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.onError((liveClient, event) ->
|
.onError((liveClient, event) ->
|
||||||
{
|
{
|
||||||
event.getException().printStackTrace();
|
event.getException().printStackTrace();
|
||||||
})
|
})
|
||||||
.onMapping(mapper ->
|
.buildAndConnect();
|
||||||
{
|
|
||||||
mapper.webcastObjectToEvent(WebcastChatMessage.class, chatMessage ->
|
|
||||||
{
|
|
||||||
var language = chatMessage.getContentLanguage();
|
|
||||||
var userName = chatMessage.getUser().getNickname();
|
|
||||||
var message = chatMessage.getContent();
|
|
||||||
return new CustomChatEvent(language, userName, message);
|
|
||||||
});
|
|
||||||
mapper.bytesToEvent("WebcastGiftMessage", bytes ->
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var event = WebcastGiftMessage.parseFrom(bytes);
|
|
||||||
return new TikTokGiftEvent(Gift.ROSA, event);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new TikTokMessageMappingException("unable to map gift message!", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mapper.bytesToEvent("WebcastMemberMessage",bytes ->
|
|
||||||
{
|
|
||||||
//displaying unknown messages from tiktok
|
|
||||||
var structure = ProtocolUtils.getProtocolBufferStructure(bytes);
|
|
||||||
System.out.println(structure.toJson());
|
|
||||||
return new TikTokErrorEvent(new RuntimeException("Message not implemented"));
|
|
||||||
});
|
|
||||||
}).buildAndConnect();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.annotations.TikTokEventHandler;
|
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
@@ -65,24 +65,24 @@ public class ListenerExample
|
|||||||
|
|
||||||
public static class CustomListener implements TikTokEventListener {
|
public static class CustomListener implements TikTokEventListener {
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
||||||
System.out.println(event.toString());
|
System.out.println(event.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
||||||
// event.getException().printStackTrace();
|
// event.getException().printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
||||||
var userName = event.getUser().getName();
|
var userName = event.getUser().getName();
|
||||||
var text = event.getText();
|
var text = event.getText();
|
||||||
liveClient.getLogger().info(userName + ": " + text);
|
liveClient.getLogger().info(userName + ": " + text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
||||||
var message = switch (event.getGift()) {
|
var message = switch (event.getGift()) {
|
||||||
case ROSE -> "Thanks :)";
|
case ROSE -> "Thanks :)";
|
||||||
@@ -95,7 +95,7 @@ public class ListenerExample
|
|||||||
liveClient.getLogger().info(message);
|
liveClient.getLogger().info(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
||||||
liveClient.getLogger().info(event.getClass().getSimpleName());
|
liveClient.getLogger().info(event.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -1,7 +1,6 @@
|
|||||||
<div align="center" >
|
<div align="center" >
|
||||||
<a target="blank" >
|
<a target="blank" >
|
||||||
<img src="https://raw.githubusercontent.com/jwdeveloper/TikTokLiveJava/develop-1_0_0/Tools-ReadmeGenerator/src/main/resources/logo.svg" width="15%" >
|
<img src="https://raw.githubusercontent.com/jwdeveloper/TikTokLiveJava/develop-1_0_0/Tools-ReadmeGenerator/src/main/resources/logo.svg" width="15%" >
|
||||||
</img>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div align="center" >
|
<div align="center" >
|
||||||
@@ -12,18 +11,15 @@
|
|||||||
<div align="center" >
|
<div align="center" >
|
||||||
<a href="https://jitpack.io/#jwdeveloper/TikTok-Live-Java" target="blank" >
|
<a href="https://jitpack.io/#jwdeveloper/TikTok-Live-Java" target="blank" >
|
||||||
<img src="https://jitpack.io/v/jwdeveloper/TikTok-Live-Java.svg" width="20%" >
|
<img src="https://jitpack.io/v/jwdeveloper/TikTok-Live-Java.svg" width="20%" >
|
||||||
</img>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<a href="https://discord.gg/e2XwPNTBBr" target="blank" >
|
<a href="https://discord.gg/e2XwPNTBBr" target="blank" >
|
||||||
<img src="https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white" >
|
<img src="https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white" >
|
||||||
</img>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a target="blank" >
|
<a target="blank" >
|
||||||
<img src="https://img.shields.io/badge/java-%23ED8B00.svg?style=for-the-badge&logo=openjdk&logoColor=white" >
|
<img src="https://img.shields.io/badge/java-%23ED8B00.svg?style=for-the-badge&logo=openjdk&logoColor=white" >
|
||||||
</img>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,6 +29,9 @@ A Java library inspired by [TikTokLive](https://github.com/isaackogan/TikTokLive
|
|||||||
The library includes a wrapper that connects to the WebCast service using just the username (`uniqueId`). This allows you to connect to your own live chat as well as the live chat of other streamers.
|
The library includes a wrapper that connects to the WebCast service using just the username (`uniqueId`). This allows you to connect to your own live chat as well as the live chat of other streamers.
|
||||||
No credentials are required. Events such as [Members Joining](#member), [Gifts](#gift), [Subscriptions](#subscribe), [Viewers](#roomuser), [Follows](#social), [Shares](#social), [Questions](#questionnew), [Likes](#like) and [Battles](#linkmicbattle) can be tracked.
|
No credentials are required. Events such as [Members Joining](#member), [Gifts](#gift), [Subscriptions](#subscribe), [Viewers](#roomuser), [Follows](#social), [Shares](#social), [Questions](#questionnew), [Likes](#like) and [Battles](#linkmicbattle) can be tracked.
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
[Library documentation for contributors](https://github.com/jwdeveloper/TikTokLiveJava/wiki)
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://www.youtube.com/watch?v=eerWGgUKc6c" align="right" target="blank"><img src="https://img.youtube.com/vi/eerWGgUKc6c/hqdefault.jpg" alt="IMAGE ALT TEXT" width="38%" align="right"></a>
|
<a href="https://www.youtube.com/watch?v=eerWGgUKc6c" align="right" target="blank"><img src="https://img.youtube.com/vi/eerWGgUKc6c/hqdefault.jpg" alt="IMAGE ALT TEXT" width="38%" align="right"></a>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,8 +54,9 @@ Do you prefer other programming languages?
|
|||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
1. Install the package via Maven
|
1. Install the package
|
||||||
|
|
||||||
|
Maven
|
||||||
```xml
|
```xml
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
@@ -69,12 +69,27 @@ Do you prefer other programming languages?
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||||
<artifactId>Client</artifactId>
|
<artifactId>Client</artifactId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.11-Release</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Gradle
|
||||||
|
```gradle
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'com.github.jwdeveloper.TikTok-Live-Java:Client:1.0.11-Release'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
2. Create your first chat connection
|
2. Create your first chat connection
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@@ -419,9 +434,9 @@ Triggered every time gift is sent
|
|||||||
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
||||||
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||||
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||||
<p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
<p>Combo: 12 -> comboState = GiftSendType.Finished</p>
|
||||||
|
|
||||||
Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
Remember if comboState is Finished both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.11-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,93 +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.tools.collector;
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLive;
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
|
||||||
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.users.User;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessageCollectorClient;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
public class RunCollector {
|
|
||||||
|
|
||||||
//https://protobuf-decoder.netlify.app/
|
|
||||||
//https://streamdps.com/tiktok-widgets/gifts/
|
|
||||||
|
|
||||||
//WebcastLinkMicBattleItemCard does streamer win battle?
|
|
||||||
|
|
||||||
public static void main(String[] args) throws SQLException, IOException {
|
|
||||||
|
|
||||||
TikTokMessageCollectorClient.create("giftsCollector")
|
|
||||||
//.addUser("crece.sara")
|
|
||||||
//.addUser("moniczkka")
|
|
||||||
.addUser("valeria.viral")
|
|
||||||
// .addUser("cbcgod")
|
|
||||||
// .addUser("psychotropnazywo")
|
|
||||||
// .addUser("accordionistka")
|
|
||||||
//.addEventFilter(WebcastGiftMessage.class)
|
|
||||||
.addOnBuilder(liveClientBuilder ->
|
|
||||||
{
|
|
||||||
liveClientBuilder.onGiftCombo((liveClient, event) ->
|
|
||||||
{
|
|
||||||
liveClient.getLogger().setLevel(Level.OFF);
|
|
||||||
var gifts = liveClient.getGiftManager().getGifts();
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append("GIFT COMBO User: " + event.getUser().getProfileName()+" ");
|
|
||||||
sb.append("Name: " + event.getGift().getName() + " ");
|
|
||||||
sb.append("Combo: " + event.getCombo() + " ");
|
|
||||||
sb.append("COST: " + event.getGift().getDiamondCost() + " ");
|
|
||||||
sb.append("STATE: " + event.getComboState() + " ");
|
|
||||||
System.out.println(sb.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
liveClientBuilder.onGift((liveClient, event) ->
|
|
||||||
{
|
|
||||||
liveClient.getLogger().setLevel(Level.OFF);
|
|
||||||
var gifts = liveClient.getGiftManager().getGifts();
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append("GIFT User: " + event.getUser().getProfileName()+" ");
|
|
||||||
sb.append("Name: " + event.getGift().getName() + " ");
|
|
||||||
sb.append("COST: " + event.getGift().getDiamondCost() + " ");
|
|
||||||
sb.append("Combo: " + event.getCombo() + " ");
|
|
||||||
System.out.println(sb.toString());
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.buildAndRun();
|
|
||||||
|
|
||||||
System.in.read();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -37,14 +37,14 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class MessageCollector {
|
public class MessagesManager {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
Map<String, Queue<MessageData>> messages;
|
Map<String, Queue<MessageData>> messages;
|
||||||
String outputName;
|
String outputName;
|
||||||
|
|
||||||
int limit = 20;
|
int limit = 20;
|
||||||
public MessageCollector(String outputName) {
|
public MessagesManager(String outputName) {
|
||||||
this.messages = new TreeMap<>();
|
this.messages = new TreeMap<>();
|
||||||
this.outputName = outputName;
|
this.outputName = outputName;
|
||||||
load();
|
load();
|
||||||
@@ -22,104 +22,16 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLive;
|
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.db.TikTokDatabase;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.ExceptionInfoModel;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
|
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class TikTokClientFactory {
|
public class TikTokClientFactory {
|
||||||
private final MessageCollector messageCollector;
|
private final MessagesManager messageCollector;
|
||||||
private final TikTokDatabase tikTokDatabase;
|
private final TikTokDatabase tikTokDatabase;
|
||||||
|
|
||||||
public TikTokClientFactory(MessageCollector messageCollector, TikTokDatabase tikTokDatabase) {
|
public TikTokClientFactory(MessagesManager messageCollector, TikTokDatabase tikTokDatabase) {
|
||||||
this.messageCollector = messageCollector;
|
this.messageCollector = messageCollector;
|
||||||
this.tikTokDatabase = tikTokDatabase;
|
this.tikTokDatabase = tikTokDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<LiveClient> runClientAsync(String tiktokUser, List<Class<?>> filters, Consumer<LiveClientBuilder> onBuilder) {
|
|
||||||
var builder = TikTokLive.newClient(tiktokUser);
|
|
||||||
var msgFilter = filters.stream().map(Class::getSimpleName).toList();
|
|
||||||
onBuilder.accept(builder);
|
|
||||||
return builder.onConnected((liveClient, event) ->
|
|
||||||
{
|
|
||||||
liveClient.getLogger().info("CONNECTED TO " + liveClient.getRoomInfo().getHostName());
|
|
||||||
})
|
|
||||||
.onWebsocketResponse((liveClient, event) ->
|
|
||||||
{
|
|
||||||
var response = Base64.getEncoder().encodeToString(event.getResponse().toByteArray());
|
|
||||||
|
|
||||||
var responseModel = new TikTokResponseModel();
|
|
||||||
responseModel.setResponse(response);
|
|
||||||
responseModel.setHostName(liveClient.getRoomInfo().getHostName());
|
|
||||||
tikTokDatabase.insertResponse(responseModel);
|
|
||||||
liveClient.getLogger().info("Response");
|
|
||||||
for (var message : event.getResponse().getMessagesList())
|
|
||||||
{
|
|
||||||
if(msgFilter.size() > 0 && !msgFilter.contains(message.getMethod()))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
messageCollector.addMessage(liveClient.getLogger(), liveClient.getRoomInfo().getHostName(), message);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.onWebsocketMessage((liveClient, event) ->
|
|
||||||
{
|
|
||||||
var eventName = event.getEvent().getClass().getSimpleName();
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (msgFilter.size() != 0 && !msgFilter.contains(event.getEvent().getClass())) {
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
var messageBinary = Base64.getEncoder().encodeToString(event.getMessage().toByteArray());
|
|
||||||
var model = new TikTokMessageModel();
|
|
||||||
model.setType("messsage");
|
|
||||||
model.setHostName(tiktokUser);
|
|
||||||
model.setEventName(eventName);
|
|
||||||
model.setMessage(messageBinary);
|
|
||||||
|
|
||||||
// tikTokDatabase.insertMessage(model);
|
|
||||||
// liveClient.getLogger().info("EVENT: [" + tiktokUser + "] " + eventName);
|
|
||||||
})
|
|
||||||
.onError((liveClient, event) ->
|
|
||||||
{
|
|
||||||
event.getException().printStackTrace();
|
|
||||||
var exception = event.getException();
|
|
||||||
var exceptionContent = ExceptionInfoModel.getStackTraceAsString(exception);
|
|
||||||
var errorModel = new TikTokErrorModel();
|
|
||||||
if (exception instanceof TikTokLiveMessageException ex) {
|
|
||||||
errorModel.setHostName(tiktokUser);
|
|
||||||
errorModel.setErrorName(ex.messageMethod());
|
|
||||||
errorModel.setErrorType("error-message");
|
|
||||||
errorModel.setExceptionContent(exceptionContent);
|
|
||||||
errorModel.setMessage(ex.messageToBase64());
|
|
||||||
errorModel.setResponse(ex.webcastResponseToBase64());
|
|
||||||
} else {
|
|
||||||
errorModel.setHostName(tiktokUser);
|
|
||||||
errorModel.setErrorName(exception.getClass().getSimpleName());
|
|
||||||
errorModel.setErrorType("error-system");
|
|
||||||
errorModel.setExceptionContent(exceptionContent);
|
|
||||||
errorModel.setMessage("");
|
|
||||||
errorModel.setResponse("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tikTokDatabase.insertError(errorModel);
|
|
||||||
liveClient.getLogger().info("ERROR: " + errorModel.getErrorName());
|
|
||||||
exception.printStackTrace();
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnectAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,99 +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.tools.collector.client;
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.db.TikTokDatabase;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class TikTokMessagessCollectorBuilder {
|
|
||||||
List<String> users;
|
|
||||||
String outputFileName;
|
|
||||||
List<Class<?>> filters;
|
|
||||||
Consumer<LiveClientBuilder> onBuilder;
|
|
||||||
List<LiveClient> tiktokclients;
|
|
||||||
|
|
||||||
MessageCollector messageCollector;
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder(String outputName) {
|
|
||||||
users = new ArrayList<>();
|
|
||||||
outputFileName = outputName;
|
|
||||||
filters = new ArrayList<>();
|
|
||||||
onBuilder = (e) -> {
|
|
||||||
};
|
|
||||||
tiktokclients = new ArrayList<>();
|
|
||||||
messageCollector = new MessageCollector(outputName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder(MessageCollector messageCollector, String outputFileName) {
|
|
||||||
this(outputFileName);
|
|
||||||
this.messageCollector = messageCollector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder setOutputName(String name) {
|
|
||||||
outputFileName = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder addOnBuilder(Consumer<LiveClientBuilder> consumer) {
|
|
||||||
onBuilder = consumer;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder addUser(String user) {
|
|
||||||
users.add(user);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder addEventFilter(Class<?> event) {
|
|
||||||
filters.add(event);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageCollector buildAndRun() throws SQLException {
|
|
||||||
var db = new TikTokDatabase(outputFileName);
|
|
||||||
db.init();
|
|
||||||
var factory = new TikTokClientFactory(messageCollector, db);
|
|
||||||
for (var user : users) {
|
|
||||||
var client = factory.runClientAsync(user,filters, onBuilder);
|
|
||||||
client.thenAccept(liveClient ->
|
|
||||||
{
|
|
||||||
tiktokclients.add(liveClient);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return messageCollector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
for (var client : tiktokclients) {
|
|
||||||
client.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +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.tools.collector.db;
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
|
|
||||||
import org.jdbi.v3.core.Jdbi;
|
|
||||||
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
|
|
||||||
|
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TikTokDatabase {
|
|
||||||
private final String database;
|
|
||||||
private TikTokMessageModelDAO messagesTable;
|
|
||||||
private TikTokErrorModelDAO errorTable;
|
|
||||||
private TikTokResponseModelDAO responseTable;
|
|
||||||
|
|
||||||
public TikTokDatabase(String database) {
|
|
||||||
this.database = database;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() throws SQLException {
|
|
||||||
var jdbcUrl = "jdbc:sqlite:" + database + ".db";
|
|
||||||
DriverManager.getConnection(jdbcUrl);
|
|
||||||
var jdbi = Jdbi.create(jdbcUrl)
|
|
||||||
.installPlugin(new SqlObjectPlugin());
|
|
||||||
jdbi.useHandle(handle -> {
|
|
||||||
handle.execute(SqlConsts.CREATE_MESSAGES_TABLE);
|
|
||||||
handle.execute(SqlConsts.CREATE_ERROR_TABLE);
|
|
||||||
handle.execute(SqlConsts.CREATE_RESPONSE_MODEL);
|
|
||||||
});
|
|
||||||
messagesTable = jdbi.onDemand(TikTokMessageModelDAO.class);
|
|
||||||
errorTable = jdbi.onDemand(TikTokErrorModelDAO.class);
|
|
||||||
responseTable = jdbi.onDemand(TikTokResponseModelDAO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insertMessage(TikTokMessageModel message) {
|
|
||||||
message.setCreatedAt(getTime());
|
|
||||||
messagesTable.insertTikTokMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insertError(TikTokErrorModel message) {
|
|
||||||
message.setCreatedAt(getTime());
|
|
||||||
errorTable.insertTikTokMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insertResponse(TikTokResponseModel message) {
|
|
||||||
message.setCreatedAt(getTime());
|
|
||||||
responseTable.insert(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TikTokErrorModel> selectErrors() {
|
|
||||||
return errorTable.selectErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TikTokMessageModel> selectMessages() {
|
|
||||||
return messagesTable.select();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TikTokResponseModel> selectResponces() {
|
|
||||||
return responseTable.select();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTime() {
|
|
||||||
return new SimpleDateFormat("dd:MM:yyyy HH:mm:ss.SSS").format(new Date());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +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.tools.collector.db;
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
|
||||||
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(TikTokMessageModel.class)
|
|
||||||
public interface TikTokMessageModelDAO
|
|
||||||
{
|
|
||||||
@SqlUpdate("INSERT INTO TikTokMessageModel (hostName, eventName,type, eventContent, createdAt) " +
|
|
||||||
"VALUES (:hostName, :eventName, :type, :eventContent, :createdAt)")
|
|
||||||
void insertTikTokMessage(@BindBean TikTokMessageModel message);
|
|
||||||
|
|
||||||
@SqlQuery("SELECT * FROM TikTokMessageModel")
|
|
||||||
List<TikTokMessageModel> select();
|
|
||||||
}
|
|
||||||
@@ -20,17 +20,19 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
package io.github.jwdeveloper.tiktok.tools.db;
|
||||||
|
|
||||||
public class SqlConsts
|
public class SqlConsts
|
||||||
{
|
{
|
||||||
public static String CREATE_MESSAGES_TABLE = """
|
|
||||||
CREATE TABLE IF NOT EXISTS TikTokMessageModel (
|
public static String CREATE_DATA_TABLE = """
|
||||||
|
CREATE TABLE IF NOT EXISTS TikTokData (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
hostName TEXT,
|
sessionTag TEXT,
|
||||||
type TEXT,
|
tiktokUser TEXT,
|
||||||
eventName TEXT,
|
dataType TEXT,
|
||||||
eventContent TEXT,
|
dataTypeName TEXT,
|
||||||
|
content TEXT,
|
||||||
createdAt 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
package io.github.jwdeveloper.tiktok.tools.db;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokErrorModel;
|
||||||
|
|
||||||
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
||||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
@@ -20,23 +20,24 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TikTokMessageModel
|
public class TikTokDataTable
|
||||||
{
|
{
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
private String hostName;
|
private String sessionTag;
|
||||||
|
|
||||||
private String eventName;
|
private String tiktokUser;
|
||||||
|
|
||||||
private String type;
|
private String dataType;
|
||||||
|
|
||||||
private String message;
|
private String dataTypeName;
|
||||||
|
|
||||||
|
private String content;
|
||||||
|
|
||||||
private String createdAt;
|
private String createdAt;
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -1,77 +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.tools.tester;
|
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.TikTokClientMock;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.db.TikTokDatabase;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
|
|
||||||
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
|
|
||||||
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
|
||||||
|
|
||||||
import java.util.logging.ConsoleHandler;
|
|
||||||
import java.util.logging.Formatter;
|
|
||||||
import java.util.logging.LogRecord;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
|
|
||||||
public class RunDbTester {
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
var db = new TikTokDatabase("test");
|
|
||||||
db.init();
|
|
||||||
|
|
||||||
var responses = db.selectResponces().stream().map(TikTokResponseModel::getResponse).toList();
|
|
||||||
var client = TikTokClientMock
|
|
||||||
.create()
|
|
||||||
.addResponses(responses)
|
|
||||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append("Unhandled Message! " );
|
|
||||||
sb.append(event.getData().getMethod());
|
|
||||||
sb.append(MessageUtil.getContent(event.getData()));
|
|
||||||
|
|
||||||
liveClient.getLogger().info(sb.toString());
|
|
||||||
})
|
|
||||||
.onWebsocketMessage((liveClient, event) ->
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append(event.getEvent().getClass().getSimpleName());
|
|
||||||
sb.append(event.getEvent().toJson());
|
|
||||||
liveClient.getLogger().fine(sb.toString());
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
|
||||||
client.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -23,8 +23,8 @@
|
|||||||
package io.github.jwdeveloper.tiktok.tools.tester;
|
package io.github.jwdeveloper.tiktok.tools.tester;
|
||||||
|
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.TikTokClientMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.TikTokLiveMock;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.mocks.LiveClientMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.LiveClientMock;
|
||||||
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
|
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
|
||||||
|
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
@@ -37,7 +37,7 @@ public class RunJsonTester {
|
|||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
var messages = getMessages();
|
var messages = getMessages();
|
||||||
var client =(LiveClientMock) TikTokClientMock.create()
|
var client =(LiveClientMock) TikTokLiveMock.create()
|
||||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
.onWebsocketUnhandledMessage((liveClient, event) ->
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|||||||
@@ -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) -> {
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient;
|
||||||
|
|
||||||
public class TikTokClientMock
|
public class TikTokLiveMock
|
||||||
{
|
{
|
||||||
public static TikTokMockBuilder create(String host)
|
public static TikTokMockBuilder create(String host)
|
||||||
{
|
{
|
||||||
@@ -20,25 +20,22 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
||||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||||
|
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandler;
|
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandler;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokGiftEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokRoomInfoEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokSocialMediaEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper;
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.mocks.ApiServiceMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.ApiServiceMock;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.mocks.LiveClientMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.LiveClientMock;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.mocks.WebsocketClientMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.WebsocketClientMock;
|
||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -96,7 +93,7 @@ public class TikTokMockBuilder extends TikTokLiveClientBuilder {
|
|||||||
|
|
||||||
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
||||||
var giftManager = new TikTokGiftManager(logger);
|
var giftManager = new TikTokGiftManager(logger);
|
||||||
var requestFactory = new TikTokHttpRequestFactory(cookie);
|
var requestFactory = new TikTokHttpRequestFactory(cookie, new TikTokEventObserver());
|
||||||
var apiClient = new TikTokHttpClient(cookie, requestFactory);
|
var apiClient = new TikTokHttpClient(cookie, requestFactory);
|
||||||
var apiService = new ApiServiceMock(apiClient, logger, clientSettings);
|
var apiService = new ApiServiceMock(apiClient, logger, clientSettings);
|
||||||
var mapper = createMapper(giftManager, tiktokRoomInfo);
|
var mapper = createMapper(giftManager, tiktokRoomInfo);
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient.mocks;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient.mocks;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||||
@@ -54,8 +54,11 @@ public class LiveClientMock extends TikTokLiveClient {
|
|||||||
listenersManager,
|
listenersManager,
|
||||||
logger);
|
logger);
|
||||||
this.websocketClientMock = webSocketClient;
|
this.websocketClientMock = webSocketClient;
|
||||||
|
websocketClientMock.setClient(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void publishMessage(String type, String base64) {
|
public void publishMessage(String type, String base64) {
|
||||||
websocketClientMock.addMessage(type, base64);
|
websocketClientMock.addMessage(type, base64);
|
||||||
}
|
}
|
||||||
@@ -75,5 +78,4 @@ public class LiveClientMock extends TikTokLiveClient {
|
|||||||
public void publishResponse(WebcastResponse message) {
|
public void publishResponse(WebcastResponse message) {
|
||||||
websocketClientMock.addResponse(message);
|
websocketClientMock.addResponse(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient.mocks;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
@@ -39,12 +39,19 @@ import java.util.logging.Logger;
|
|||||||
public class WebsocketClientMock implements SocketClient {
|
public class WebsocketClientMock implements SocketClient {
|
||||||
Logger logger;
|
Logger logger;
|
||||||
Stack<WebcastResponse> responses;
|
Stack<WebcastResponse> responses;
|
||||||
|
|
||||||
Stack<MsgStruct> messages;
|
Stack<MsgStruct> messages;
|
||||||
TikTokMessageHandler messageHandler;
|
TikTokMessageHandler messageHandler;
|
||||||
|
|
||||||
|
LiveClient client;
|
||||||
|
|
||||||
|
Thread thread;
|
||||||
|
|
||||||
private boolean isRunning;
|
private boolean isRunning;
|
||||||
|
|
||||||
|
public void setClient(LiveClientMock liveClientMock) {
|
||||||
|
this.client = liveClientMock;
|
||||||
|
}
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
public static class MsgStruct {
|
public static class MsgStruct {
|
||||||
String messageType;
|
String messageType;
|
||||||
@@ -87,38 +94,28 @@ public class WebsocketClientMock implements SocketClient {
|
|||||||
@Override
|
@Override
|
||||||
public void start(WebcastResponse webcastResponse, LiveClient tikTokLiveClient) {
|
public void start(WebcastResponse webcastResponse, LiveClient tikTokLiveClient) {
|
||||||
logger.info("Running message: " + responses.size());
|
logger.info("Running message: " + responses.size());
|
||||||
|
|
||||||
|
|
||||||
|
thread = new Thread(() ->
|
||||||
|
{
|
||||||
|
|
||||||
|
while (isRunning)
|
||||||
|
{
|
||||||
|
while (!responses.isEmpty()) {
|
||||||
|
var response = responses.pop();
|
||||||
|
messageHandler.handle(client, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
while (!responses.isEmpty() || !messages.isEmpty()) {
|
thread.start();
|
||||||
if (!responses.isEmpty()) {
|
|
||||||
var response = responses.pop();
|
|
||||||
for (var message : response.getMessagesList()) {
|
|
||||||
try {
|
|
||||||
messageHandler.handleSingleMessage(tikTokLiveClient, message);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.info("Unable to parse message for response " + response.getCursor());
|
|
||||||
throw new TikTokLiveMessageException(message, response, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!messages.isEmpty()) {
|
|
||||||
var messageStr = messages.pop();
|
|
||||||
try {
|
|
||||||
var msg = WebcastResponse.Message.newBuilder()
|
|
||||||
.setMethod(messageStr.messageType)
|
|
||||||
.setPayload(ByteString.copyFrom(messageStr.getMessageValue()))
|
|
||||||
.build();
|
|
||||||
messageHandler.handleSingleMessage(tikTokLiveClient, msg);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.info("Unable to parse message for response " + messageStr.getMessageType());
|
|
||||||
throw new TikTokLiveException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
isRunning = true;
|
isRunning = false;
|
||||||
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,16 +42,16 @@ public class MessageUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getContent(String methodName, byte[] bytes) {
|
public static String getContent(String messageName, byte[] bytes) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
var inputClazz = Class.forName("io.github.jwdeveloper.tiktok.messages.webcast." + methodName);
|
var inputClazz = Class.forName("io.github.jwdeveloper.tiktok.messages.webcast." + messageName);
|
||||||
var parseMethod = inputClazz.getDeclaredMethod("parseFrom", byte[].class);
|
var parseMethod = inputClazz.getDeclaredMethod("parseFrom", byte[].class);
|
||||||
var deserialized = parseMethod.invoke(null, bytes);
|
var deserialized = parseMethod.invoke(null, bytes);
|
||||||
return JsonUtil.messageToJson(deserialized);
|
return JsonUtil.messageToJson(deserialized);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.append("Can not find protocolbuffer file message representation for " + methodName);
|
sb.append("Can not find protocol-buffer file message representation for " + messageName);
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
var structure = ProtocolUtils.getProtocolBufferStructure(bytes);
|
var structure = ProtocolUtils.getProtocolBufferStructure(bytes);
|
||||||
var json =structure.toJson();
|
var json =structure.toJson();
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.11-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>Tools-EventsWebViewer</artifactId>
|
<artifactId>Tools-EventsWebViewer</artifactId>
|
||||||
|
|||||||
@@ -22,13 +22,35 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.webviewer;
|
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.handlers.TikTokHandler;
|
||||||
|
import io.github.jwdeveloper.tiktok.webviewer.services.TikTokCollectorService;
|
||||||
|
import io.github.jwdeveloper.tiktok.webviewer.services.TikTokDatabaseService;
|
||||||
import io.javalin.Javalin;
|
import io.javalin.Javalin;
|
||||||
|
|
||||||
public class Main {
|
import java.io.IOException;
|
||||||
public static void main(String[] args) {
|
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;
|
||||||
|
|
||||||
var manager = new TikTokManager();
|
public class Main {
|
||||||
|
public static void main(String[] args) throws SQLException, ExecutionException, InterruptedException, IOException {
|
||||||
|
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 ->
|
var app = Javalin.create(config ->
|
||||||
{
|
{
|
||||||
config.plugins.enableCors(corsContainer ->
|
config.plugins.enableCors(corsContainer ->
|
||||||
@@ -39,13 +61,19 @@ public class Main {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
config.staticFiles.add("/public");
|
config.staticFiles.add("/public");
|
||||||
}).start(8001);
|
}).start(settings.getPort());
|
||||||
|
|
||||||
var handler = new TikTokHandler(manager);
|
app.get("/tiktok/status", handler::connectionStatus);
|
||||||
app.get("/tiktok/connect", handler::connect);
|
app.get("/tiktok/connect", handler::connect);
|
||||||
app.get("/tiktok/disconnect", handler::disconnect);
|
app.get("/tiktok/disconnect", handler::disconnect);
|
||||||
app.get("/tiktok/events", handler::events);
|
|
||||||
app.get("/tiktok/events/pages", handler::eventPages);
|
app.get("/tiktok/data/pages", handler::getDataPages);
|
||||||
app.get("/tiktok/events/message", handler::eventMessage);
|
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,18 +20,17 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
package io.github.jwdeveloper.tiktok.webviewer;
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TikTokResponseModel
|
public class Settings
|
||||||
{
|
{
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
private String hostName;
|
private int port;
|
||||||
|
private String dbName;
|
||||||
private String response;
|
private String userName;
|
||||||
|
private String sessionTag;
|
||||||
private String createdAt;
|
|
||||||
}
|
}
|
||||||
@@ -1,137 +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.webviewer;
|
|
||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.client.MessageCollector;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessageCollectorClient;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessagessCollectorBuilder;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
|
|
||||||
import lombok.Value;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
public class TikTokManager {
|
|
||||||
TikTokMessagessCollectorBuilder client;
|
|
||||||
MessageCollector msgCollector;
|
|
||||||
|
|
||||||
public static String dbName= "log";
|
|
||||||
|
|
||||||
public TikTokManager() {
|
|
||||||
msgCollector = new MessageCollector(dbName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void connect(String name) throws SQLException {
|
|
||||||
disconnect();
|
|
||||||
client = TikTokMessageCollectorClient.create(msgCollector, dbName)
|
|
||||||
.addOnBuilder(liveClientBuilder ->
|
|
||||||
{
|
|
||||||
liveClientBuilder.onRoomInfo((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
});
|
|
||||||
liveClientBuilder.onGift((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
});
|
|
||||||
liveClientBuilder.onWebsocketUnhandledMessage((liveClient, event) ->
|
|
||||||
{
|
|
||||||
System.out.println("UNHANDLED MESSAGE! "+event.getMessage().getMethod());
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
||||||
.addUser(name);
|
|
||||||
client.buildAndRun();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getEventsNames() {
|
|
||||||
return msgCollector.getMessages().keySet().stream().toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getEventMessages(String eventName) {
|
|
||||||
return msgCollector.getMessages().get(eventName).stream().map(MessageCollector.MessageData::getEventData).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public MessageDto getMessage(String event, String index) throws InvalidProtocolBufferException {
|
|
||||||
var eventData = msgCollector.getMessages().get(event);
|
|
||||||
var messages = eventData.stream().toList();
|
|
||||||
var random = new Random();
|
|
||||||
|
|
||||||
var msgIndex = 0;
|
|
||||||
if (index != null && !index.isEmpty()) {
|
|
||||||
msgIndex = Integer.parseInt(index);
|
|
||||||
msgIndex = Math.min(msgIndex, messages.size() - 1);
|
|
||||||
msgIndex = Math.max(msgIndex, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var msg = messages.get(msgIndex);
|
|
||||||
|
|
||||||
|
|
||||||
var bytes = Base64.getDecoder().decode(msg.getEventData());
|
|
||||||
var content = MessageUtil.getContent(event, bytes);
|
|
||||||
return new MessageDto(content, msg.getEventData(), event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public PagesDto getPages(String event) throws InvalidProtocolBufferException {
|
|
||||||
var eventData = msgCollector.getMessages().get(event);
|
|
||||||
var messages = eventData.stream().toList();
|
|
||||||
|
|
||||||
var counter = new AtomicInteger(-1);
|
|
||||||
var pages = messages.stream().map(e ->
|
|
||||||
{
|
|
||||||
return "http://localhost:8001/tiktok/events/message?eventName=" + event + "&page=" + counter.incrementAndGet();
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
return new PagesDto(event, messages.size(), pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Value
|
|
||||||
public class PagesDto {
|
|
||||||
String eventName;
|
|
||||||
int pages;
|
|
||||||
List<String> links;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Value
|
|
||||||
public class MessageDto {
|
|
||||||
String content;
|
|
||||||
String base64;
|
|
||||||
String eventName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect() {
|
|
||||||
if (client == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
client.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* 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.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||||
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkLayerMessage;
|
||||||
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.TikTokLiveTools;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ToolsExamples {
|
||||||
|
|
||||||
|
private static final String tiktokUser = "debb.cl";
|
||||||
|
|
||||||
|
private static final String db = "db-battle";
|
||||||
|
|
||||||
|
private static final String sessionTag = "gifts";
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
liveClientBuilder.onWebsocketResponse((liveClient, event) ->
|
||||||
|
{
|
||||||
|
for (var msg : event.getResponse().getMessagesList()) {
|
||||||
|
System.out.println(msg.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,61 +25,153 @@ package io.github.jwdeveloper.tiktok.webviewer.handlers;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import io.github.jwdeveloper.tiktok.webviewer.TikTokManager;
|
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 io.javalin.http.Context;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class TikTokHandler {
|
public class TikTokHandler {
|
||||||
private final TikTokManager tikTokManager;
|
private final TikTokDatabaseService databaseService;
|
||||||
|
private final Settings settings;
|
||||||
|
private final TikTokCollectorService collectorService;
|
||||||
|
|
||||||
public TikTokHandler(TikTokManager tikTokManager) {
|
public TikTokHandler(TikTokDatabaseService databaseService,
|
||||||
this.tikTokManager = tikTokManager;
|
Settings settings,
|
||||||
|
TikTokCollectorService collectorService) {
|
||||||
|
this.databaseService = databaseService;
|
||||||
|
this.settings = settings;
|
||||||
|
this.collectorService = collectorService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void connect(Context context) throws SQLException {
|
public void connect(Context context) {
|
||||||
String name = context.queryParam("name");
|
var name = context.queryParam("name");
|
||||||
if (name.equals(" ")) {
|
var sessionTag = context.queryParam("session");
|
||||||
context.result("Name can not be empty");
|
System.out.println("Session tag" + sessionTag);
|
||||||
context.status(400);
|
collectorService.start(name, sessionTag);
|
||||||
return;
|
settings.setUserName(name);
|
||||||
}
|
|
||||||
tikTokManager.connect(name);
|
|
||||||
context.status(200);
|
context.status(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect(Context context){
|
public void connectionStatus(Context context) {
|
||||||
tikTokManager.disconnect();
|
var isWorking = collectorService.isRunning();
|
||||||
context.status(200);
|
var result = getGson().toJson(isWorking);
|
||||||
}
|
|
||||||
|
|
||||||
public void events(Context context) {
|
|
||||||
var events = tikTokManager.getEventsNames();
|
|
||||||
var gson = getGson();
|
|
||||||
var result = gson.toJson(events);
|
|
||||||
context.result(result);
|
context.result(result);
|
||||||
context.status(200);
|
context.status(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void eventMessage(Context context) throws InvalidProtocolBufferException {
|
public void disconnect(Context context) {
|
||||||
String name = context.queryParam("eventName");
|
|
||||||
String page = context.queryParam("page");
|
|
||||||
|
|
||||||
var result = tikTokManager.getMessage(name, page);
|
collectorService.stop();
|
||||||
var gson = getGson();
|
context.status(200);
|
||||||
context.result(gson.toJson(result));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void eventPages(Context context) throws InvalidProtocolBufferException {
|
|
||||||
String name = context.queryParam("eventName");
|
public void getUsers(Context context) {
|
||||||
var result = tikTokManager.getPages(name);
|
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 gson = getGson();
|
||||||
context.result(gson.toJson(result));
|
|
||||||
|
|
||||||
|
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() {
|
public Gson getGson() {
|
||||||
return new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
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 */
|
||||||
|
}
|
||||||
@@ -3,252 +3,132 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<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">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<title>Bootstrap Styled Javalin App</title>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js" type="text/javascript" charset="utf-8"></script>
|
|
||||||
|
|
||||||
|
<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"
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/editor/editor.main.css">
|
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>
|
<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">
|
||||||
<style>
|
<link rel="stylesheet" , href="index.css">
|
||||||
body, html {
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/loader.min.js"></script>
|
||||||
height: 100%;
|
<script>
|
||||||
margin: 0;
|
require.config({
|
||||||
display: flex;
|
paths: {'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs'}
|
||||||
flex-direction: column;
|
});
|
||||||
background-color: #121212; /* Dark background */
|
</script>
|
||||||
}
|
<script>
|
||||||
#app {
|
var editor;
|
||||||
height: 100vh; /* 100% of the viewport height */
|
var editor2;
|
||||||
display: flex;
|
require(['vs/editor/editor.main'], function () {
|
||||||
flex-direction: column;
|
editor = monaco.editor.create(document.getElementById('editor'), {
|
||||||
}
|
value: [
|
||||||
.header {
|
'Hello world!',
|
||||||
margin-bottom: 20px;
|
].join('\n'),
|
||||||
}
|
language: 'json',
|
||||||
.btn-primary
|
theme: 'vs-dark',
|
||||||
{
|
automaticLayout: true
|
||||||
background-color: #2c2c2c;
|
});
|
||||||
border-color: #2c2c2c;
|
|
||||||
}
|
|
||||||
.btn-primary:hover
|
|
||||||
{
|
|
||||||
background-color: #474747;
|
|
||||||
border-color: #474747;
|
|
||||||
}
|
|
||||||
|
|
||||||
#editor {
|
|
||||||
overflow-y: auto;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
.editor-container
|
|
||||||
{
|
|
||||||
|
|
||||||
padding: 10em;
|
|
||||||
}
|
|
||||||
.list-group-item:hover
|
|
||||||
{
|
|
||||||
background-color: #474747;
|
|
||||||
color: azure;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.list-group-item
|
|
||||||
{
|
|
||||||
background-color: #2c2c2c;
|
|
||||||
color: azure;
|
|
||||||
border-color: #252424;
|
|
||||||
}
|
|
||||||
.content {
|
|
||||||
flex-grow: 1; /* Takes up the remaining space */
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.col-md-10, .col-md-2 {
|
|
||||||
padding: 0; /* Remove default padding */
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/editor/editor.main.css">
|
|
||||||
|
|
||||||
<!-- Load Monaco Editor's main loader script -->
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/loader.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Configure the loader -->
|
|
||||||
<script>
|
|
||||||
require.config({
|
|
||||||
paths: {'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs'}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Load the editor -->
|
|
||||||
<script>
|
|
||||||
var editor;
|
|
||||||
require(['vs/editor/editor.main'], function() {
|
|
||||||
editor = monaco.editor.create(document.getElementById('editor'), {
|
|
||||||
value: [
|
|
||||||
'function x() {',
|
|
||||||
'\tconsole.log("Hello world!");',
|
|
||||||
'}'
|
|
||||||
].join('\n'),
|
|
||||||
language: 'json',
|
|
||||||
theme: 'vs-dark'
|
|
||||||
});
|
|
||||||
editor.onDidChangeModelContent(function () {
|
|
||||||
console.log("hello")
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
|
editor2 = monaco.editor.create(document.getElementById('editor2'), {
|
||||||
|
value: [
|
||||||
|
'Hello world!',
|
||||||
|
].join('\n'),
|
||||||
|
language: 'json',
|
||||||
|
theme: 'vs-dark',
|
||||||
|
automaticLayout: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-dark">
|
<body class="container-fluid bg-dark">
|
||||||
|
|
||||||
<div id="app" class="container-fluid mt-5">
|
|
||||||
<div >
|
<div class="row ">
|
||||||
<div class="mb-3">
|
<div class="col-2 ">
|
||||||
<label for="name" class="form-label">Name:</label>
|
<div class="form margin">
|
||||||
<input type="text" id="name" name="name" class="form-control">
|
<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>
|
||||||
<button type="button" onclick="connect()" class="btn btn-primary">Connect</button>
|
<div class="form-group ">
|
||||||
<button type="button" onclick="disconnect()" class="btn btn-primary">Disconnect</button>
|
<label class="form-label">SessionTag</label>
|
||||||
<button onclick="showEvents()" class="btn btn-primary">Show Events</button>
|
<input type="text" id="sessionTag" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
|
<button id="connectionButton" type="button" class="btn btn-primary mt-3 connect-btn">Connect </button>
|
||||||
<div class="content row mt-5">
|
|
||||||
|
</div>
|
||||||
<div class="col-md-2 ">
|
|
||||||
<ul id="eventList" class="list-group" style="max-height: 100%; overflow-y: auto;">
|
<div>
|
||||||
<!-- List items will be added dynamically -->
|
<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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-10 editor-container ">
|
|
||||||
<nav aria-label="Page navigation example">
|
|
||||||
<ul id="pages" class="pagination">
|
|
||||||
<li class="page-item btn-primary"><a class="page-link" href="#">Previous</a></li>
|
|
||||||
<li class="page-item"><a class="page-link" href="#">Next</a></li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<div id="editor"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="col-10 margin">
|
||||||
<div class="container mt-5">
|
<nav aria-label="Page navigation example">
|
||||||
<div class="row justify-content-center">
|
<ul id="pages" class="pagination">
|
||||||
<div class="col-md-6">
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="index.js"></script>
|
||||||
<script>
|
|
||||||
async function connect() {
|
|
||||||
let name = document.getElementById('name').value;
|
|
||||||
// name = "bangbetmenygy"
|
|
||||||
let response = await fetch(`http://localhost:8001/tiktok/connect?name=${name}`);
|
|
||||||
let greeting = await response.text();
|
|
||||||
console.log("connect",greeting);
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
async function disconnect() {
|
|
||||||
let response = await fetch(`http://localhost:8001/tiktok/disconnect`);
|
|
||||||
let greeting = await response.text();
|
|
||||||
console.log("disconnect",greeting);
|
|
||||||
connected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadMessage(event)
|
|
||||||
{
|
|
||||||
let response = await fetch(`http://localhost:8001/tiktok/events/message?eventName=${event}`);
|
|
||||||
let json = await response.text();
|
|
||||||
let root= JSON.parse(json);
|
|
||||||
editor.setValue(root.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadMessageLink(link)
|
|
||||||
{
|
|
||||||
let response = await fetch(link);
|
|
||||||
let json = await response.text();
|
|
||||||
let root= JSON.parse(json);
|
|
||||||
editor.setValue(root.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadPagination(event)
|
|
||||||
{
|
|
||||||
let response = await fetch(`http://localhost:8001/tiktok/events/pages?eventName=${event}`);
|
|
||||||
let json = await response.text();
|
|
||||||
let object = JSON.parse(json);
|
|
||||||
let pages = object.links;
|
|
||||||
console.log("PAGES: ",pages)
|
|
||||||
$("#pages").empty();
|
|
||||||
$.each(pages, function(index, element) {
|
|
||||||
let content = $('<button>',{
|
|
||||||
class: 'btn btn-primary',
|
|
||||||
text: index
|
|
||||||
}).click(async function()
|
|
||||||
{
|
|
||||||
await loadMessageLink(element);
|
|
||||||
console.log(editor)
|
|
||||||
});
|
|
||||||
$("#pages").append(content);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function showEvents() {
|
|
||||||
let response = await fetch(`http://localhost:8001/tiktok/events`);
|
|
||||||
let json = await response.text();
|
|
||||||
console.log("events:",json);
|
|
||||||
let events= JSON.parse(json);
|
|
||||||
|
|
||||||
$("#eventList").empty();
|
|
||||||
$.each(events, function(index, event) {
|
|
||||||
let listItem = $('<li>', {
|
|
||||||
class: 'list-group-item',
|
|
||||||
text: event
|
|
||||||
}).click(async function()
|
|
||||||
{
|
|
||||||
await loadMessage(event);
|
|
||||||
await loadPagination(event);
|
|
||||||
});
|
|
||||||
$("#eventList").append(listItem);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loop()
|
|
||||||
{
|
|
||||||
if(!connected)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("updating");
|
|
||||||
await showEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
var connected = false;
|
|
||||||
var paginationIndex = 0;
|
|
||||||
var maxPages = 10;
|
|
||||||
var pages = [];
|
|
||||||
setInterval(loop, 1000)
|
|
||||||
showEvents()
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.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://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>
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
||||||
|
|||||||
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()
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.11-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.11-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user