mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-03-02 02:09:40 -05:00
Breaking changes:
'Gift': changed from class to enum, so now you can handle
incoming gifts in switch
`Events`
- new:
onGiftComboFinished
- Removed:
onGiftBrodcast
- Rename:
onGiftMessage -> onGift
onRoomPinMessage -> onRoomPin
onRoomMessage -> onRoom
onLinkMessage -> onLink
onBarrageMessage -> onBarrage
onPollMessage -> onPoll
onShopMessage -> onShop
onDetectMessage -> onDetect
`GiftManager`
added:
registerGift
findById
findByName
getGifts
removed:
getActiveGifts
This commit is contained in:
@@ -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.handlers;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||
@@ -10,35 +32,32 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class TikTokEventObserver {
|
||||
private final Map<String, Set<TikTokEventConsumer>> events;
|
||||
private final Map<Class<?>, Set<TikTokEventConsumer>> events;
|
||||
|
||||
public TikTokEventObserver() {
|
||||
events = new HashMap<>();
|
||||
}
|
||||
|
||||
public void publish(TikTokLiveClient tikTokLiveClient, TikTokEvent tikTokEvent) {
|
||||
if (events.containsKey(TikTokEvent.class.getSimpleName())) {
|
||||
var handlers = events.get(TikTokEvent.class.getSimpleName());
|
||||
for(var handle : handlers)
|
||||
{
|
||||
if (events.containsKey(TikTokEvent.class)) {
|
||||
var handlers = events.get(TikTokEvent.class);
|
||||
for (var handle : handlers) {
|
||||
handle.onEvent(tikTokLiveClient, tikTokEvent);
|
||||
}
|
||||
}
|
||||
|
||||
var name = tikTokEvent.getClass().getSimpleName();
|
||||
if (!events.containsKey(name)) {
|
||||
|
||||
if (!events.containsKey(tikTokEvent.getClass())) {
|
||||
return;
|
||||
}
|
||||
var handlers = events.get(name);
|
||||
for(var handler : handlers)
|
||||
{
|
||||
var handlers = events.get(tikTokEvent.getClass());
|
||||
for (var handler : handlers) {
|
||||
handler.onEvent(tikTokLiveClient, tikTokEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends TikTokEvent> void subscribe(Class<?> clazz, TikTokEventConsumer<T> event)
|
||||
{
|
||||
events.computeIfAbsent(clazz.getSimpleName(), e -> new HashSet<>()).add(event);
|
||||
public <T extends TikTokEvent> void subscribe(Class<?> clazz, TikTokEventConsumer<T> event) {
|
||||
events.computeIfAbsent(clazz, e -> new HashSet<>()).add(event);
|
||||
}
|
||||
|
||||
public <T extends TikTokEvent> void unsubscribeAll(Class<?> clazz) {
|
||||
@@ -46,9 +65,22 @@ public class TikTokEventObserver {
|
||||
}
|
||||
|
||||
public <T extends TikTokEvent> void unsubscribe(TikTokEventConsumer<T> consumer) {
|
||||
for(var entry : events.entrySet())
|
||||
{
|
||||
for (var entry : events.entrySet()) {
|
||||
entry.getValue().remove(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends TikTokEvent> void unsubscribe(Class<?> clazz, TikTokEventConsumer<T> consumer) {
|
||||
if (clazz == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!events.containsKey(clazz)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var eventSet = events.get(clazz);
|
||||
eventSet.remove(consumer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
/*
|
||||
* 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.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;
|
||||
@@ -13,57 +34,47 @@ import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
||||
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;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
public abstract class TikTokMessageHandler {
|
||||
|
||||
private final Map<String, io.github.jwdeveloper.tiktok.handler.TikTokMessageHandler> handlers;
|
||||
private final TikTokEventObserver tikTokEventHandler;
|
||||
private final ClientSettings clientSettings;
|
||||
protected final Logger logger;
|
||||
|
||||
public TikTokMessageHandler(TikTokEventObserver tikTokEventHandler, ClientSettings clientSettings, Logger logger) {
|
||||
public TikTokMessageHandler(TikTokEventObserver tikTokEventHandler) {
|
||||
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) {
|
||||
public void registerMapping(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 registerMapping(Class<?> input, Class<?> output) {
|
||||
registerMapping(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) {
|
||||
} 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 {
|
||||
|
||||
public void handleSingleMessage(TikTokLiveClient client, WebcastResponse.Message message) throws Exception {
|
||||
if (!handlers.containsKey(message.getType())) {
|
||||
tikTokEventHandler.publish(client, new TikTokUnhandledWebsocketMessageEvent(message));
|
||||
return;
|
||||
|
||||
@@ -1,27 +1,48 @@
|
||||
/*
|
||||
* 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.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.Gift;
|
||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||
import io.github.jwdeveloper.tiktok.messages.*;
|
||||
import io.github.jwdeveloper.tiktok.models.SocialTypes;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
private final TikTokGiftManager giftManager;
|
||||
private final TikTokRoomInfo roomInfo;
|
||||
|
||||
private final Pattern socialMediaPattern = Pattern.compile("pm_mt_guidance_viewer_([0-9]+)_share");
|
||||
|
||||
public TikTokMessageHandlerRegistration(TikTokEventObserver tikTokEventHandler,
|
||||
ClientSettings clientSettings,
|
||||
Logger logger,
|
||||
TikTokGiftManager giftManager,
|
||||
TikTokRoomInfo roomInfo) {
|
||||
super(tikTokEventHandler, clientSettings, logger);
|
||||
super(tikTokEventHandler);
|
||||
this.giftManager = giftManager;
|
||||
this.roomInfo = roomInfo;
|
||||
}
|
||||
@@ -30,57 +51,55 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
public void init() {
|
||||
|
||||
//ConnectionEvents events
|
||||
register(WebcastControlMessage.class, this::handleWebcastControlMessage);
|
||||
register(SystemMessage.class,TikTokRoomMessageEvent.class);
|
||||
registerMapping(WebcastControlMessage.class, this::handleWebcastControlMessage);
|
||||
registerMapping(SystemMessage.class, TikTokRoomEvent.class);
|
||||
|
||||
|
||||
//Room status events
|
||||
register(WebcastLiveIntroMessage.class, TikTokRoomMessageEvent.class);
|
||||
register(WebcastRoomUserSeqMessage.class, this::handleRoomUserSeqMessage);
|
||||
register(RoomMessage.class, TikTokRoomMessageEvent.class);
|
||||
register(WebcastRoomMessage.class, TikTokRoomMessageEvent.class);
|
||||
register(WebcastCaptionMessage.class, TikTokCaptionEvent.class);
|
||||
registerMapping(WebcastLiveIntroMessage.class, TikTokRoomEvent.class);
|
||||
registerMapping(WebcastRoomUserSeqMessage.class, this::handleRoomUserSeqMessage);
|
||||
registerMapping(RoomMessage.class, TikTokRoomEvent.class);
|
||||
registerMapping(WebcastRoomMessage.class, TikTokRoomEvent.class);
|
||||
registerMapping(WebcastCaptionMessage.class, TikTokCaptionEvent.class);
|
||||
|
||||
//User Interactions events
|
||||
register(WebcastChatMessage.class, TikTokCommentEvent.class);
|
||||
register(WebcastLikeMessage.class, TikTokLikeEvent.class);
|
||||
register(WebcastGiftMessage.class, this::handleGift);
|
||||
register(WebcastSocialMessage.class, this::handleSocialMedia);
|
||||
register(WebcastMemberMessage.class, this::handleMemberMessage);
|
||||
registerMapping(WebcastChatMessage.class, TikTokCommentEvent.class);
|
||||
registerMapping(WebcastLikeMessage.class, TikTokLikeEvent.class);
|
||||
registerMapping(WebcastGiftMessage.class, this::handleGift);
|
||||
registerMapping(WebcastSocialMessage.class, this::handleSocialMedia);
|
||||
registerMapping(WebcastMemberMessage.class, this::handleMemberMessage);
|
||||
|
||||
//Host Interaction events
|
||||
register(WebcastPollMessage.class, TikTokPollMessageEvent.class);
|
||||
register(WebcastRoomPinMessage.class, TikTokRoomPinMessageEvent.class);
|
||||
register(WebcastGoalUpdateMessage.class, TikTokGoalUpdateEvent.class);
|
||||
registerMapping(WebcastPollMessage.class, TikTokPollEvent.class);
|
||||
registerMapping(WebcastRoomPinMessage.class, TikTokRoomPinEvent.class);
|
||||
registerMapping(WebcastGoalUpdateMessage.class, TikTokGoalUpdateEvent.class);
|
||||
|
||||
//LinkMic events
|
||||
register(WebcastLinkMicBattle.class, TikTokLinkMicBattleEvent.class);
|
||||
register(WebcastLinkMicArmies.class, TikTokLinkMicArmiesEvent.class);
|
||||
register(LinkMicMethod.class, TikTokLinkMicMethodEvent.class);
|
||||
register(WebcastLinkMicMethod.class, TikTokLinkMicMethodEvent.class);
|
||||
register(WebcastLinkMicFanTicketMethod.class, TikTokLinkMicFanTicketEvent.class);
|
||||
registerMapping(WebcastLinkMicBattle.class, TikTokLinkMicBattleEvent.class);
|
||||
registerMapping(WebcastLinkMicArmies.class, TikTokLinkMicArmiesEvent.class);
|
||||
registerMapping(LinkMicMethod.class, TikTokLinkMicMethodEvent.class);
|
||||
registerMapping(WebcastLinkMicMethod.class, TikTokLinkMicMethodEvent.class);
|
||||
registerMapping(WebcastLinkMicFanTicketMethod.class, TikTokLinkMicFanTicketEvent.class);
|
||||
|
||||
//Rank events
|
||||
register(WebcastRankTextMessage.class, TikTokRankTextEvent.class);
|
||||
register(WebcastRankUpdateMessage.class, TikTokRankUpdateEvent.class);
|
||||
register(WebcastHourlyRankMessage.class, TikTokRankUpdateEvent.class);
|
||||
registerMapping(WebcastRankTextMessage.class, TikTokRankTextEvent.class);
|
||||
registerMapping(WebcastRankUpdateMessage.class, TikTokRankUpdateEvent.class);
|
||||
registerMapping(WebcastHourlyRankMessage.class, TikTokRankUpdateEvent.class);
|
||||
|
||||
//Others events
|
||||
register(WebcastInRoomBannerMessage.class, TikTokInRoomBannerEvent.class);
|
||||
register(WebcastMsgDetectMessage.class, TikTokDetectMessageEvent.class);
|
||||
register(WebcastBarrageMessage.class, TikTokBarrageMessageEvent.class);
|
||||
register(WebcastUnauthorizedMemberMessage.class, TikTokUnauthorizedMemberEvent.class);
|
||||
register(WebcastGiftBroadcastMessage.class, TikTokGiftBroadcastEvent.class);
|
||||
register(WebcastOecLiveShoppingMessage.class, TikTokShopMessageEvent.class);
|
||||
register(WebcastImDeleteMessage.class, TikTokIMDeleteEvent.class);
|
||||
register(WebcastQuestionNewMessage.class, TikTokQuestionEvent.class);
|
||||
register(WebcastEnvelopeMessage.class, TikTokEnvelopeEvent.class);
|
||||
register(WebcastSubNotifyMessage.class, TikTokSubNotifyEvent.class);
|
||||
register(WebcastEmoteChatMessage.class, TikTokEmoteEvent.class);
|
||||
registerMapping(WebcastInRoomBannerMessage.class, TikTokInRoomBannerEvent.class);
|
||||
registerMapping(WebcastMsgDetectMessage.class, TikTokDetectEvent.class);
|
||||
registerMapping(WebcastBarrageMessage.class, TikTokBarrageEvent.class);
|
||||
registerMapping(WebcastUnauthorizedMemberMessage.class, TikTokUnauthorizedMemberEvent.class);
|
||||
registerMapping(WebcastOecLiveShoppingMessage.class, TikTokShopEvent.class);
|
||||
registerMapping(WebcastImDeleteMessage.class, TikTokIMDeleteEvent.class);
|
||||
registerMapping(WebcastQuestionNewMessage.class, TikTokQuestionEvent.class);
|
||||
registerMapping(WebcastEnvelopeMessage.class, TikTokEnvelopeEvent.class);
|
||||
registerMapping(WebcastSubNotifyMessage.class, TikTokSubNotifyEvent.class);
|
||||
registerMapping(WebcastEmoteChatMessage.class, TikTokEmoteEvent.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
private TikTokEvent handleWebcastControlMessage(WebcastResponse.Message msg) {
|
||||
var message = WebcastControlMessage.parseFrom(msg.getBinary());
|
||||
@@ -95,7 +114,23 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
private TikTokEvent handleGift(WebcastResponse.Message msg) {
|
||||
var giftMessage = WebcastGiftMessage.parseFrom(msg.getBinary());
|
||||
giftManager.updateActiveGift(giftMessage);
|
||||
return new TikTokGiftMessageEvent(giftMessage);
|
||||
|
||||
var gift = giftManager.findById((int) giftMessage.getGiftId());
|
||||
if (gift == Gift.UNDEFINED) {
|
||||
gift = giftManager.findByName(giftMessage.getGift().getName());
|
||||
}
|
||||
if (gift == Gift.UNDEFINED) {
|
||||
gift = giftManager.registerGift(
|
||||
(int) giftMessage.getGift().getId(),
|
||||
giftMessage.getGift().getName(),
|
||||
giftMessage.getGift().getDiamondCount());
|
||||
}
|
||||
|
||||
if (giftMessage.getRepeatEnd() > 0) {
|
||||
return new TikTokGiftComboFinishedEvent(gift, giftMessage);
|
||||
}
|
||||
|
||||
return new TikTokGiftEvent(gift, giftMessage);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@@ -103,11 +138,9 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
var message = WebcastSocialMessage.parseFrom(msg.getBinary());
|
||||
|
||||
var socialType = message.getHeader().getSocialData().getType();
|
||||
var pattern = Pattern.compile("pm_mt_guidance_viewer_([0-9]+)_share");
|
||||
var matcher = pattern.matcher(socialType);
|
||||
var matcher = socialMediaPattern.matcher(socialType);
|
||||
|
||||
if (matcher.find())
|
||||
{
|
||||
if (matcher.find()) {
|
||||
var value = matcher.group(1);
|
||||
var number = Integer.parseInt(value);
|
||||
return new TikTokShareEvent(message, number);
|
||||
@@ -132,9 +165,8 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
};
|
||||
}
|
||||
|
||||
private TikTokEvent handleRoomUserSeqMessage(WebcastResponse.Message msg)
|
||||
{
|
||||
var event = (TikTokRoomViewerDataEvent)mapMessageToEvent(WebcastRoomUserSeqMessage.class, TikTokRoomViewerDataEvent.class, msg);
|
||||
private TikTokEvent handleRoomUserSeqMessage(WebcastResponse.Message msg) {
|
||||
var event = (TikTokRoomViewerDataEvent) mapMessageToEvent(WebcastRoomUserSeqMessage.class, TikTokRoomViewerDataEvent.class, msg);
|
||||
roomInfo.setViewersCount(event.getViewerCount());
|
||||
return event;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user