mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-03-02 02:09:40 -05:00
Changes:
- Implementation on all features in `clientSettings` - Code optimization - More detail exceptions - Downloading gifts
This commit is contained in:
@@ -1,40 +1,38 @@
|
||||
package io.github.jwdeveloper.tiktok.handlers;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||
import io.github.jwdeveloper.tiktok.events.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.events.TikTokEventConsumer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TikTokEventHandler {
|
||||
private final Map<String, Consumer> events;
|
||||
public class TikTokEventHandler {
|
||||
private final Map<String, TikTokEventConsumer> events;
|
||||
|
||||
public TikTokEventHandler()
|
||||
{
|
||||
public TikTokEventHandler() {
|
||||
events = new HashMap<>();
|
||||
}
|
||||
|
||||
public void publish(TikTokEvent tikTokEvent)
|
||||
{
|
||||
if(events.containsKey(TikTokEvent.class.getSimpleName()))
|
||||
{
|
||||
public void publish(TikTokLiveClient tikTokLiveClient, TikTokEvent tikTokEvent) {
|
||||
if (events.containsKey(TikTokEvent.class.getSimpleName())) {
|
||||
var handler = events.get(TikTokEvent.class.getSimpleName());
|
||||
handler.accept(tikTokEvent);
|
||||
handler.onEvent(tikTokLiveClient, tikTokEvent);
|
||||
}
|
||||
|
||||
var name = tikTokEvent.getClass().getSimpleName();
|
||||
if(!events.containsKey(name))
|
||||
{
|
||||
if (!events.containsKey(name)) {
|
||||
return;
|
||||
}
|
||||
var handler = events.get(name);
|
||||
handler.accept(tikTokEvent);
|
||||
handler.onEvent(tikTokLiveClient, tikTokEvent);
|
||||
}
|
||||
|
||||
public <T extends TikTokEvent> void subscribe(Class<?> clazz, Consumer<T> event)
|
||||
{
|
||||
events.put(clazz.getSimpleName(),event);
|
||||
public <T extends TikTokEvent> void subscribe(Class<?> clazz, TikTokEventConsumer<T> event) {
|
||||
events.put(clazz.getSimpleName(), event);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public <T extends TikTokEvent> void unsubscribe(Class<?> clazz) {
|
||||
events.remove(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,97 @@
|
||||
package io.github.jwdeveloper.tiktok.handlers;
|
||||
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||
import io.github.jwdeveloper.tiktok.events.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent;
|
||||
import io.github.jwdeveloper.tiktok.events.messages.TikTokUnhandledEvent;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
||||
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
||||
|
||||
public interface TikTokMessageHandler<T>
|
||||
{
|
||||
Class<T> getHandleClazz();
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
TikTokEvent handle(WebcastResponse.Message message) throws Exception;
|
||||
|
||||
public abstract class TikTokMessageHandler {
|
||||
|
||||
private final Map<String, io.github.jwdeveloper.tiktok.handler.TikTokMessageHandler> handlers;
|
||||
private final TikTokEventHandler tikTokEventHandler;
|
||||
private final ClientSettings clientSettings;
|
||||
protected final Logger logger;
|
||||
|
||||
public TikTokMessageHandler(TikTokEventHandler tikTokEventHandler,ClientSettings clientSettings, Logger logger) {
|
||||
handlers = new HashMap<>();
|
||||
this.tikTokEventHandler = tikTokEventHandler;
|
||||
this.clientSettings = clientSettings;
|
||||
this.logger = logger;
|
||||
init();
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public void register(Class<?> clazz, Function<WebcastResponse.Message, TikTokEvent> func) {
|
||||
handlers.put(clazz.getSimpleName(), func::apply);
|
||||
}
|
||||
|
||||
public void register(Class<?> input, Class<?> output) {
|
||||
register(input, (e) -> mapMessageToEvent(input, output, e));
|
||||
}
|
||||
|
||||
public void handle(TikTokLiveClient client, WebcastResponse webcastResponse) {
|
||||
for (var message : webcastResponse.getMessagesList()) {
|
||||
try
|
||||
{
|
||||
if(clientSettings.isPrintMessageData())
|
||||
{
|
||||
var type= message.getType();
|
||||
var base64 = Base64.getEncoder().encodeToString(message.getBinary().toByteArray());
|
||||
logger.info(type+": \n "+base64);
|
||||
}
|
||||
handleSingleMessage(client, message);
|
||||
} catch (Exception e) {
|
||||
var exception = new TikTokLiveMessageException(message, webcastResponse, e);
|
||||
tikTokEventHandler.publish(client, new TikTokErrorEvent(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSingleMessage(TikTokLiveClient client, WebcastResponse.Message message) throws Exception {
|
||||
if (!handlers.containsKey(message.getType())) {
|
||||
tikTokEventHandler.publish(client, new TikTokUnhandledEvent(message));
|
||||
return;
|
||||
}
|
||||
var handler = handlers.get(message.getType());
|
||||
var tiktokEvent = handler.handle(message);
|
||||
tikTokEventHandler.publish(client, tiktokEvent);
|
||||
}
|
||||
|
||||
protected TikTokEvent mapMessageToEvent(Class<?> inputClazz, Class<?> outputClass, WebcastResponse.Message message) {
|
||||
try {
|
||||
var parseMethod = inputClazz.getDeclaredMethod("parseFrom", ByteString.class);
|
||||
var deserialized = parseMethod.invoke(null, message.getBinary());
|
||||
|
||||
var constructors = Arrays.stream(outputClass.getConstructors())
|
||||
.filter(ea -> Arrays.stream(ea.getParameterTypes())
|
||||
.toList()
|
||||
.contains(inputClazz))
|
||||
.findFirst();
|
||||
|
||||
if(constructors.isEmpty())
|
||||
{
|
||||
throw new TikTokMessageMappingException(inputClazz, outputClass, "Unable to find constructor with input class type");
|
||||
}
|
||||
|
||||
var tiktokEvent = constructors.get().newInstance(deserialized);
|
||||
return (TikTokEvent) tiktokEvent;
|
||||
} catch (Exception ex) {
|
||||
throw new TikTokMessageMappingException(inputClazz, outputClass, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.github.jwdeveloper.tiktok.handlers;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||
import io.github.jwdeveloper.tiktok.TikTokGiftManager;
|
||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||
import io.github.jwdeveloper.tiktok.events.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.events.messages.*;
|
||||
import io.github.jwdeveloper.tiktok.events.objects.TikTokGift;
|
||||
@@ -9,15 +11,22 @@ import io.github.jwdeveloper.tiktok.models.GiftId;
|
||||
import io.github.jwdeveloper.tiktok.models.SocialTypes;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class WebResponseHandler extends WebResponseHandlerBase {
|
||||
public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
private final TikTokGiftManager giftManager;
|
||||
private final TikTokRoomInfo roomInfo;
|
||||
|
||||
public WebResponseHandler(TikTokEventHandler tikTokEventHandler, TikTokGiftManager giftManager) {
|
||||
super(tikTokEventHandler);
|
||||
public TikTokMessageHandlerRegistration(TikTokEventHandler tikTokEventHandler,
|
||||
ClientSettings clientSettings,
|
||||
Logger logger,
|
||||
TikTokGiftManager giftManager,
|
||||
TikTokRoomInfo roomInfo) {
|
||||
super(tikTokEventHandler, clientSettings, logger);
|
||||
this.giftManager = giftManager;
|
||||
this.roomInfo = roomInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -30,7 +39,7 @@ public class WebResponseHandler extends WebResponseHandlerBase {
|
||||
|
||||
//Room status events
|
||||
register(WebcastLiveIntroMessage.class, TikTokRoomMessageEvent.class);
|
||||
register(WebcastRoomUserSeqMessage.class, TikTokRoomViewerDataEvent.class); //TODO update viewer count ViewerCount = userSeqMessage.ViewerCount;
|
||||
register(WebcastRoomUserSeqMessage.class, this::handleRoomUserSeqMessage);
|
||||
register(RoomMessage.class, TikTokRoomMessageEvent.class);
|
||||
register(WebcastRoomMessage.class, TikTokRoomMessageEvent.class);
|
||||
register(WebcastCaptionMessage.class, TikTokCaptionEvent.class);
|
||||
@@ -74,9 +83,9 @@ public class WebResponseHandler extends WebResponseHandlerBase {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
private TikTokEvent handleWebcastControlMessage(WebcastResponse.Message msg)
|
||||
{
|
||||
private TikTokEvent handleWebcastControlMessage(WebcastResponse.Message msg) {
|
||||
var message = WebcastControlMessage.parseFrom(msg.getBinary());
|
||||
return switch (message.getAction()) {
|
||||
case STREAM_PAUSED -> new TikTokLivePausedEvent();
|
||||
@@ -88,29 +97,7 @@ public class WebResponseHandler extends WebResponseHandlerBase {
|
||||
@SneakyThrows
|
||||
private TikTokEvent handleGift(WebcastResponse.Message msg) {
|
||||
var giftMessage = WebcastGiftMessage.parseFrom(msg.getBinary());
|
||||
var giftId = new GiftId(giftMessage.getGiftId(), giftMessage.getSender().getUniqueId());
|
||||
|
||||
var activeGifts = giftManager.getActiveGifts();
|
||||
if (activeGifts.containsKey(giftId)) {
|
||||
// Debug.Log($"Updating Gift[{giftId.Gift}]Amount[{message.Amount}]");
|
||||
var gift = activeGifts.get(giftId);
|
||||
gift.setAmount(giftMessage.getAmount());
|
||||
} else {
|
||||
TikTokGift newGift = new TikTokGift(giftMessage);
|
||||
activeGifts.put(giftId, newGift);
|
||||
// Debug.Log($"New Gift[{giftId.Gift}]Amount[{message.Amount}]");
|
||||
// RunEvent(OnGift, newGift);
|
||||
}
|
||||
if (giftMessage.getRepeatEnd()) {
|
||||
//if (ShouldLog(LogLevel.Verbose))
|
||||
// Debug.Log($"GiftStreak Ended: [{giftId.Gift}] Amount[{message.Amount}]")
|
||||
var gift = activeGifts.get(giftId);
|
||||
gift.setStreakFinished(true);
|
||||
activeGifts.remove(gift);
|
||||
}
|
||||
|
||||
// Debug.Log($"Handling GiftMessage");
|
||||
|
||||
giftManager.updateActiveGift(giftMessage);
|
||||
return new TikTokGiftMessageEvent(giftMessage);
|
||||
}
|
||||
|
||||
@@ -146,4 +133,11 @@ public class WebResponseHandler extends WebResponseHandlerBase {
|
||||
default -> new TikTokUnhandledMemberEvent(message);
|
||||
};
|
||||
}
|
||||
|
||||
private TikTokEvent handleRoomUserSeqMessage(WebcastResponse.Message msg)
|
||||
{
|
||||
var event = (TikTokRoomViewerDataEvent)mapMessageToEvent(WebcastRoomUserSeqMessage.class, TikTokRoomViewerDataEvent.class, msg);
|
||||
roomInfo.setViewersCount(event.getViewerCount());
|
||||
return event;
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package io.github.jwdeveloper.tiktok.handlers;
|
||||
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.github.jwdeveloper.tiktok.events.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent;
|
||||
import io.github.jwdeveloper.tiktok.events.messages.TikTokUnhandledEvent;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageParsingException;
|
||||
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
||||
public abstract class WebResponseHandlerBase {
|
||||
|
||||
private final Map<String, TikTokMessageHandler> handlers;
|
||||
private final TikTokEventHandler tikTokEventHandler;
|
||||
|
||||
public WebResponseHandlerBase(TikTokEventHandler tikTokEventHandler) {
|
||||
handlers = new HashMap<>();
|
||||
this.tikTokEventHandler = tikTokEventHandler;
|
||||
init();
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public void register(Class<?> input, Class<?> output) {
|
||||
register(input, (e) ->
|
||||
{
|
||||
try {
|
||||
var parseMethod = input.getDeclaredMethod("parseFrom", ByteString.class);
|
||||
var deserialized = parseMethod.invoke(null, e.getBinary());
|
||||
|
||||
var constructors = Arrays.stream(output.getConstructors()).filter(ea -> Arrays.stream(ea.getParameterTypes()).toList().contains(input)).findFirst();
|
||||
|
||||
var tiktokEvent = constructors.get().newInstance(deserialized);
|
||||
return (TikTokEvent)tiktokEvent;
|
||||
} catch (Exception ex)
|
||||
{
|
||||
throw new TikTokLiveMessageParsingException("Unable to handle parsing from class: " + input.getSimpleName() + " to class " + output.getSimpleName(), ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public <T> void register(Class clazz, Function<WebcastResponse.Message, TikTokEvent> func) {
|
||||
var haandler = new TikTokMessageHandler<T>() {
|
||||
@Override
|
||||
public Class<T> getHandleClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TikTokEvent handle(WebcastResponse.Message message) throws Exception {
|
||||
return func.apply(message);
|
||||
}
|
||||
};
|
||||
|
||||
handlers.put(haandler.getHandleClazz().getSimpleName(), haandler);
|
||||
}
|
||||
|
||||
public void handle(WebcastResponse webcastResponse) {
|
||||
for (var message : webcastResponse.getMessagesList()) {
|
||||
try {
|
||||
handleSingleMessage(message);
|
||||
} catch (Exception e)
|
||||
{
|
||||
|
||||
var decoded = Base64.getEncoder().encodeToString(message.getBinary().toByteArray());
|
||||
|
||||
var exception = new TikTokLiveException("Error whilst Handling Message"+message.getType()+": \n"+decoded, e);
|
||||
tikTokEventHandler.publish(new TikTokErrorEvent(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleSingleMessage(WebcastResponse.Message message) throws Exception {
|
||||
if (!handlers.containsKey(message.getType())) {
|
||||
tikTokEventHandler.publish(new TikTokUnhandledEvent(message));
|
||||
return;
|
||||
}
|
||||
var handler = handlers.get(message.getType());
|
||||
var tiktokEvent = handler.handle(message);
|
||||
tikTokEventHandler.publish(tiktokEvent);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user