mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-27 08:49:40 -05:00
Merge pull request #17 from jwdeveloper/develop-1-0-5
New Events - onLiveUnpaused() - onRoomInfo() triggered when LiveRoomInfo got updated Removed: - clientSettings.setHandleExistingEvents - onRoom Replaced with onRoomInfo event - onRoomUserInfo Replaced with onRoomInfo event Gifts: - onGift event was not triggered for the more expensive gifts - onGiftCombo with more expensive gifts was stuck in the GiftSendType.Begin state Fixed: - setPrintToConsole(false) was not disabling logs
This commit is contained in:
@@ -52,11 +52,6 @@ public class ClientSettings {
|
||||
*/
|
||||
private Duration retryConnectionTimeout;
|
||||
|
||||
/**
|
||||
* Whether to handle Events received from Room when Connecting
|
||||
*/
|
||||
private boolean handleExistingEvents;
|
||||
|
||||
/**
|
||||
* Whether to print Logs to Console
|
||||
*/
|
||||
|
||||
@@ -57,7 +57,6 @@ public class Constants {
|
||||
var clientSettings = new ClientSettings();
|
||||
clientSettings.setTimeout(Duration.ofSeconds(DEFAULT_TIMEOUT));
|
||||
clientSettings.setClientLanguage("en-US");
|
||||
clientSettings.setHandleExistingEvents(true);
|
||||
clientSettings.setRetryOnConnectionFailure(false);
|
||||
clientSettings.setRetryConnectionTimeout(Duration.ofSeconds(1));
|
||||
clientSettings.setPrintToConsole(false);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package io.github.jwdeveloper.tiktok.data.events;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
|
||||
|
||||
@EventMeta(eventType = EventType.Message)
|
||||
public class TikTokLiveUnpausedEvent extends TikTokEvent {
|
||||
}
|
||||
@@ -1,67 +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.data.events.room;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.UserAttribute;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.RoomMessage;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLiveIntroMessage;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastRoomMessage;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSystemMessage;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@EventMeta(eventType = EventType.Message)
|
||||
public class TikTokRoomEvent extends TikTokHeaderEvent
|
||||
{
|
||||
private User hostUser;
|
||||
private String hostLanguage;
|
||||
private final String welcomeMessage;
|
||||
|
||||
public TikTokRoomEvent(WebcastRoomMessage msg) {
|
||||
super(msg.getCommon());
|
||||
welcomeMessage = msg.getContent();
|
||||
}
|
||||
|
||||
public TikTokRoomEvent(RoomMessage msg) {
|
||||
super(msg.getCommon());
|
||||
welcomeMessage = msg.getContent();
|
||||
}
|
||||
|
||||
public TikTokRoomEvent(WebcastSystemMessage msg) {
|
||||
super(msg.getCommon());
|
||||
welcomeMessage = msg.getMessage();
|
||||
}
|
||||
|
||||
public TikTokRoomEvent(WebcastLiveIntroMessage msg) {
|
||||
super(msg.getCommon());
|
||||
hostUser = User.map(msg.getHost());
|
||||
hostUser.addAttribute(UserAttribute.LiveHost);
|
||||
welcomeMessage = msg.getContent();
|
||||
hostLanguage = msg.getLanguage();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.github.jwdeveloper.tiktok.data.events.room;
|
||||
|
||||
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.live.LiveRoomInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
/*
|
||||
Triggered when LiveRoomInfo got updated such as likes, viewers, ranking ....
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@EventMeta(eventType = EventType.Message)
|
||||
public class TikTokRoomInfoEvent extends TikTokEvent
|
||||
{
|
||||
LiveRoomInfo roomInfo;
|
||||
}
|
||||
@@ -1,55 +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.data.events.room;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastRoomUserSeqMessage;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
|
||||
@Getter
|
||||
@EventMeta(eventType = EventType.Message)
|
||||
public class TikTokRoomUserInfoEvent extends TikTokHeaderEvent {
|
||||
private final int totalUsers;
|
||||
|
||||
/**
|
||||
* Only top 5 users in ranking has detailed data
|
||||
* rest has only ID
|
||||
*/
|
||||
private final List<RankingUser> usersRanking;
|
||||
public TikTokRoomUserInfoEvent(WebcastRoomUserSeqMessage msg) {
|
||||
super(msg.getCommon());
|
||||
totalUsers = msg.getTotalUser();
|
||||
usersRanking = msg.getRanksListList().stream().map(RankingUser::new)
|
||||
.sorted((ru1, ru2) -> Integer.compare(ru2.getScore(), ru1.getScore()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,6 +45,8 @@ public class User {
|
||||
@Getter(AccessLevel.NONE)
|
||||
private Set<UserAttribute> attributes;
|
||||
|
||||
|
||||
|
||||
public List<UserAttribute> getAttributes() {
|
||||
return attributes.stream().toList();
|
||||
}
|
||||
@@ -107,6 +109,23 @@ public class User {
|
||||
this.attributes = new HashSet<>();
|
||||
}
|
||||
|
||||
public User(Long id,
|
||||
String name,
|
||||
String profileName,
|
||||
Picture picture,
|
||||
long following,
|
||||
long followers,
|
||||
List<Badge> badges) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.profileName = profileName;
|
||||
this.picture = picture;
|
||||
this.following = following;
|
||||
this.followers = followers;
|
||||
this.badges = badges;
|
||||
this.attributes = new HashSet<>();
|
||||
}
|
||||
|
||||
public User(Long userId,
|
||||
String nickName) {
|
||||
this.id = userId;
|
||||
|
||||
@@ -22,14 +22,31 @@
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.live;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.models.ConnectionState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface LiveRoomInfo
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @return get current count of viewers of live
|
||||
*/
|
||||
int getViewersCount();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return get total current count of viewers since beginning of live
|
||||
*/
|
||||
int getTotalViewersCount();
|
||||
int getLikesCount();
|
||||
boolean isAgeRestricted();
|
||||
String getRoomId();
|
||||
String getHostName();
|
||||
String getTitle();
|
||||
User getHostUser();
|
||||
List<RankingUser> getUsersRanking();
|
||||
ConnectionState getConnectionState();
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.live;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@@ -29,6 +30,11 @@ public class LiveRoomMeta {
|
||||
|
||||
private LiveRoomStatus status;
|
||||
private boolean ageRestricted;
|
||||
private String titie;
|
||||
private int likeCount;
|
||||
private int totalViewers;
|
||||
private int viewers;
|
||||
private User host;
|
||||
|
||||
public enum LiveRoomStatus
|
||||
{
|
||||
|
||||
@@ -24,11 +24,9 @@ package io.github.jwdeveloper.tiktok.live.builder;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||
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.TikTokGiftEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomUserInfoEvent;
|
||||
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.TikTokJoinEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
||||
@@ -40,9 +38,7 @@ import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandl
|
||||
|
||||
public interface EventsBuilder<T> {
|
||||
|
||||
T onRoom(EventConsumer<TikTokRoomEvent> event);
|
||||
|
||||
T onRoomUserInfo(EventConsumer<TikTokRoomUserInfoEvent> event);
|
||||
T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> event);
|
||||
|
||||
T onComment(EventConsumer<TikTokCommentEvent> event);
|
||||
|
||||
@@ -53,8 +49,6 @@ public interface EventsBuilder<T> {
|
||||
T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> event);
|
||||
|
||||
|
||||
|
||||
|
||||
T onGiftCombo(EventConsumer<TikTokGiftComboEvent> event);
|
||||
T onGift(EventConsumer<TikTokGiftEvent> event);
|
||||
|
||||
@@ -71,12 +65,13 @@ public interface EventsBuilder<T> {
|
||||
T onJoin(EventConsumer<TikTokJoinEvent> event);
|
||||
|
||||
T onShare(EventConsumer<TikTokShareEvent> event);
|
||||
T onUnhandledSocial(EventConsumer<TikTokUnhandledSocialEvent> event);
|
||||
|
||||
// T onChest(EventConsumer<TikTokChestEvent> event);
|
||||
|
||||
T onLivePaused(EventConsumer<TikTokLivePausedEvent> event);
|
||||
|
||||
T onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> event);
|
||||
|
||||
T onLiveEnded(EventConsumer<TikTokLiveEndedEvent> event);
|
||||
|
||||
T onConnected(EventConsumer<TikTokConnectedEvent> event);
|
||||
|
||||
@@ -68,6 +68,7 @@ enum MemberMessageAction {
|
||||
enum ControlAction {
|
||||
ControlActionUNKNOWN = 0;
|
||||
STREAM_PAUSED = 1; // Stream Paused by Host
|
||||
STREAM_UNPAUSED = 2;
|
||||
STREAM_ENDED = 3; // Stream Ended by Host
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ package io.github.jwdeveloper.tiktok;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||
@@ -138,14 +139,24 @@ public class TikTokLiveClient implements LiveClient {
|
||||
}
|
||||
|
||||
|
||||
var roomData = apiService.fetchRoomInfo();
|
||||
if (roomData.getStatus() != LiveRoomMeta.LiveRoomStatus.HostOnline) {
|
||||
throw new TikTokLiveOfflineHostException("LiveStream for Host name could not be found. Is the Host online?");
|
||||
var liveRoomMeta = apiService.fetchRoomInfo();
|
||||
if (liveRoomMeta.getStatus() == LiveRoomMeta.LiveRoomStatus.HostNotFound) {
|
||||
throw new TikTokLiveOfflineHostException("LiveStream for Host name could not be found.");
|
||||
}
|
||||
if (liveRoomMeta.getStatus() == LiveRoomMeta.LiveRoomStatus.HostOffline) {
|
||||
throw new TikTokLiveOfflineHostException("LiveStream for not be found, is the Host offline?");
|
||||
}
|
||||
|
||||
liveRoomInfo.setTitle(liveRoomMeta.getTitie());
|
||||
liveRoomInfo.setViewersCount(liveRoomMeta.getViewers());
|
||||
liveRoomInfo.setTotalViewersCount(liveRoomMeta.getTotalViewers());
|
||||
liveRoomInfo.setAgeRestricted(liveRoomMeta.isAgeRestricted());
|
||||
liveRoomInfo.setHost(liveRoomMeta.getHost());
|
||||
|
||||
var clientData = apiService.fetchClientData();
|
||||
webSocketClient.start(clientData, this);
|
||||
setState(ConnectionState.CONNECTED);
|
||||
tikTokEventHandler.publish(this,new TikTokRoomInfoEvent(liveRoomInfo));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,9 +28,8 @@ 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.TikTokGiftEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomEvent;
|
||||
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.TikTokRoomUserInfoEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokFollowEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
||||
@@ -43,6 +42,8 @@ import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokGiftEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokRoomInfoEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokSocialMediaEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
||||
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
||||
@@ -131,8 +132,8 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
|
||||
logger.setLevel(clientSettings.getLogLevel());
|
||||
|
||||
if (clientSettings.isPrintToConsole() && clientSettings.getLogLevel() == Level.OFF) {
|
||||
logger.setLevel(Level.ALL);
|
||||
if (!clientSettings.isPrintToConsole()) {
|
||||
logger.setLevel(Level.OFF);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,12 +153,16 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
var apiService = new TikTokApiService(apiClient, logger, clientSettings);
|
||||
var giftManager = new TikTokGiftManager(logger);
|
||||
var eventMapper = new TikTokGenericEventMapper();
|
||||
|
||||
var giftHandler = new TikTokGiftEventHandler(giftManager);
|
||||
var roomInfoHandler = new TikTokRoomInfoEventHandler(tiktokRoomInfo);
|
||||
var socialHandler = new TikTokSocialMediaEventHandler(tiktokRoomInfo);
|
||||
|
||||
var webResponseHandler = new TikTokMessageHandlerRegistration(tikTokEventHandler,
|
||||
tiktokRoomInfo,
|
||||
roomInfoHandler,
|
||||
eventMapper,
|
||||
giftHandler
|
||||
giftHandler,
|
||||
socialHandler
|
||||
);
|
||||
|
||||
var webSocketClient = new TikTokWebSocketClient(logger,
|
||||
@@ -247,16 +252,25 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onRoom(EventConsumer<TikTokRoomEvent> event) {
|
||||
tikTokEventHandler.subscribe(TikTokRoomEvent.class, event);
|
||||
@Override
|
||||
public LiveClientBuilder onRoomInfo(EventConsumer<TikTokRoomInfoEvent> event) {
|
||||
tikTokEventHandler.subscribe(TikTokRoomInfoEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public TikTokLiveClientBuilder onLivePaused(EventConsumer<TikTokLivePausedEvent> event) {
|
||||
tikTokEventHandler.subscribe(TikTokLivePausedEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveClientBuilder onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> event) {
|
||||
tikTokEventHandler.subscribe(TikTokLiveUnpausedEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onLike(EventConsumer<TikTokLikeEvent> event) {
|
||||
tikTokEventHandler.subscribe(TikTokLikeEvent.class, event);
|
||||
return this;
|
||||
@@ -329,13 +343,6 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TikTokLiveClientBuilder onRoomUserInfo(
|
||||
EventConsumer<TikTokRoomUserInfoEvent> event) {
|
||||
tikTokEventHandler.subscribe(TikTokRoomUserInfoEvent.class, event);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public TikTokLiveClientBuilder onComment(EventConsumer<TikTokCommentEvent> event) {
|
||||
tikTokEventHandler.subscribe(TikTokCommentEvent.class, event);
|
||||
return this;
|
||||
|
||||
@@ -23,34 +23,51 @@
|
||||
package io.github.jwdeveloper.tiktok;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||
import io.github.jwdeveloper.tiktok.messages.data.User;
|
||||
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.models.ConnectionState;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveRoomInfo;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class TikTokRoomInfo implements LiveRoomInfo
|
||||
{
|
||||
public class TikTokRoomInfo implements LiveRoomInfo {
|
||||
private String roomId;
|
||||
|
||||
private int likesCount;
|
||||
|
||||
private int viewersCount;
|
||||
|
||||
private int totalViewersCount;
|
||||
|
||||
private boolean ageRestricted;
|
||||
|
||||
private User host;
|
||||
|
||||
private Picture picture;
|
||||
|
||||
private String description;
|
||||
private List<RankingUser> usersRanking = new LinkedList<>();
|
||||
|
||||
private String hostName;
|
||||
|
||||
private String title;
|
||||
|
||||
private String language = "en";
|
||||
|
||||
private ConnectionState connectionState = ConnectionState.DISCONNECTED;
|
||||
|
||||
public boolean hasConnectionState(ConnectionState state)
|
||||
{
|
||||
public boolean hasConnectionState(ConnectionState state) {
|
||||
return connectionState == state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getHostUser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateRanking(List<RankingUser> rankingUsers) {
|
||||
usersRanking.clear();
|
||||
usersRanking.addAll(rankingUsers);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.handlers;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
||||
@@ -30,39 +29,36 @@ import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEndEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollStartEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollUpdateEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomPinEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomUserInfoEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokFollowEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokShareEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.Text;
|
||||
import io.github.jwdeveloper.tiktok.data.models.chest.Chest;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokGiftEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokRoomInfoEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokSocialMediaEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper;
|
||||
import io.github.jwdeveloper.tiktok.messages.enums.EnvelopeDisplay;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.*;
|
||||
import io.github.jwdeveloper.tiktok.models.SocialTypes;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
|
||||
private final TikTokRoomInfo roomInfo;
|
||||
private final TikTokGiftEventHandler giftHandler;
|
||||
private final Pattern socialMediaPattern = Pattern.compile("pm_mt_guidance_viewer_([0-9]+)_share");
|
||||
private final TikTokRoomInfoEventHandler roomInfoHandler;
|
||||
private final TikTokSocialMediaEventHandler socialHandler;
|
||||
|
||||
public TikTokMessageHandlerRegistration(TikTokEventObserver tikTokEventHandler,
|
||||
TikTokRoomInfo roomInfo,
|
||||
TikTokRoomInfoEventHandler roomInfoHandler,
|
||||
TikTokGenericEventMapper genericTikTokEventMapper,
|
||||
TikTokGiftEventHandler tikTokGiftEventHandler) {
|
||||
TikTokGiftEventHandler tikTokGiftEventHandler,
|
||||
TikTokSocialMediaEventHandler tikTokSocialMediaEventHandler) {
|
||||
super(tikTokEventHandler, genericTikTokEventMapper);
|
||||
this.giftHandler = tikTokGiftEventHandler;
|
||||
this.roomInfo = roomInfo;
|
||||
this.roomInfoHandler = roomInfoHandler;
|
||||
this.socialHandler = tikTokSocialMediaEventHandler;
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -70,22 +66,19 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
|
||||
//ConnectionEvents events
|
||||
registerMapping(WebcastControlMessage.class, this::handleWebcastControlMessage);
|
||||
registerMapping(WebcastSystemMessage.class, TikTokRoomEvent.class);
|
||||
|
||||
|
||||
//Room status events
|
||||
registerMapping(WebcastLiveIntroMessage.class, TikTokRoomEvent.class);
|
||||
registerMapping(WebcastRoomUserSeqMessage.class, this::handleRoomUserSeqMessage);
|
||||
registerMapping(RoomMessage.class, TikTokRoomEvent.class);
|
||||
registerMapping(WebcastRoomMessage.class, TikTokRoomEvent.class);
|
||||
registerMapping(WebcastLiveIntroMessage.class, roomInfoHandler::handleIntro);
|
||||
registerMapping(WebcastRoomUserSeqMessage.class, roomInfoHandler::handleUserRanking);
|
||||
|
||||
registerMapping(WebcastCaptionMessage.class, TikTokCaptionEvent.class);
|
||||
|
||||
//User Interactions events
|
||||
registerMapping(WebcastChatMessage.class, TikTokCommentEvent.class);
|
||||
registerMapping(WebcastLikeMessage.class, this::handleLike);
|
||||
registerMappings(WebcastLikeMessage.class, this::handleLike);
|
||||
registerMappings(WebcastGiftMessage.class, giftHandler::handleGift);
|
||||
registerMapping(WebcastSocialMessage.class, this::handleSocialMedia);
|
||||
registerMapping(WebcastMemberMessage.class, this::handleMemberMessage);
|
||||
registerMapping(WebcastSocialMessage.class, socialHandler::handle);
|
||||
registerMappings(WebcastMemberMessage.class, this::handleMemberMessage);
|
||||
|
||||
//Host Interaction events
|
||||
registerMapping(WebcastPollMessage.class, this::handlePollEvent);
|
||||
@@ -123,54 +116,37 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
||||
return switch (message.getAction()) {
|
||||
case STREAM_PAUSED -> new TikTokLivePausedEvent();
|
||||
case STREAM_ENDED -> new TikTokLiveEndedEvent();
|
||||
case STREAM_UNPAUSED -> new TikTokLiveUnpausedEvent();
|
||||
default -> new TikTokUnhandledControlEvent(message);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
private TikTokEvent handleSocialMedia(byte[] msg) {
|
||||
var message = WebcastSocialMessage.parseFrom(msg);
|
||||
|
||||
var socialType = Text.map(message.getCommon().getDisplayText()).getKey();
|
||||
var matcher = socialMediaPattern.matcher(socialType);
|
||||
|
||||
if (matcher.find()) {
|
||||
var value = matcher.group(1);
|
||||
var number = Integer.parseInt(value);
|
||||
return new TikTokShareEvent(message, number);
|
||||
}
|
||||
|
||||
return switch (socialType) {
|
||||
case SocialTypes.LikeType -> new TikTokLikeEvent(message, roomInfo.getLikesCount());
|
||||
case SocialTypes.FollowType -> new TikTokFollowEvent(message);
|
||||
case SocialTypes.ShareType -> new TikTokShareEvent(message);
|
||||
case SocialTypes.JoinType -> new TikTokJoinEvent(message, roomInfo.getViewersCount());
|
||||
default -> new TikTokUnhandledSocialEvent(message);
|
||||
};
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private TikTokEvent handleMemberMessage(byte[] msg) {
|
||||
private List<TikTokEvent> handleMemberMessage(byte[] msg) {
|
||||
var message = WebcastMemberMessage.parseFrom(msg);
|
||||
roomInfo.setViewersCount(message.getMemberCount());
|
||||
return switch (message.getAction()) {
|
||||
|
||||
var event = switch (message.getAction()) {
|
||||
case JOINED -> new TikTokJoinEvent(message);
|
||||
case SUBSCRIBED -> new TikTokSubscribeEvent(message);
|
||||
default -> new TikTokUnhandledMemberEvent(message);
|
||||
};
|
||||
|
||||
var roomInfoEvent = roomInfoHandler.handleRoomInfo(tikTokRoomInfo ->
|
||||
{
|
||||
tikTokRoomInfo.setViewersCount(message.getMemberCount());
|
||||
});
|
||||
|
||||
return List.of(event, roomInfoEvent);
|
||||
}
|
||||
|
||||
private TikTokEvent handleRoomUserSeqMessage(byte[] msg) {
|
||||
var event = (TikTokRoomUserInfoEvent) mapper.mapToEvent(WebcastRoomUserSeqMessage.class, TikTokRoomUserInfoEvent.class, msg);
|
||||
roomInfo.setViewersCount(event.getTotalUsers());
|
||||
return event;
|
||||
}
|
||||
|
||||
private TikTokEvent handleLike(byte[] msg) {
|
||||
private List<TikTokEvent> handleLike(byte[] msg) {
|
||||
var event = (TikTokLikeEvent) mapper.mapToEvent(WebcastLikeMessage.class, TikTokLikeEvent.class, msg);
|
||||
roomInfo.setLikesCount(event.getTotalLikes());
|
||||
return event;
|
||||
var roomInfoEvent = roomInfoHandler.handleRoomInfo(tikTokRoomInfo ->
|
||||
{
|
||||
tikTokRoomInfo.setLikesCount(event.getTotalLikes());
|
||||
});
|
||||
return List.of(event, roomInfoEvent);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
|
||||
@@ -53,12 +53,19 @@ public class TikTokGiftEventHandler {
|
||||
return handleGift(currentMessage);
|
||||
}
|
||||
|
||||
public List<TikTokEvent> handleGift(WebcastGiftMessage currentMessage)
|
||||
{
|
||||
public List<TikTokEvent> handleGift(WebcastGiftMessage currentMessage) {
|
||||
var userId = currentMessage.getUser().getId();
|
||||
var currentType = GiftSendType.fromNumber(currentMessage.getSendType());
|
||||
var containsPreviousMessage = giftsMessages.containsKey(userId);
|
||||
|
||||
|
||||
//If gift is not streakable just return onGift event
|
||||
if (currentMessage.getGift().getType() != 1) {
|
||||
var comboEvent = getGiftComboEvent(currentMessage, GiftSendType.Finished);
|
||||
var giftEvent = getGiftEvent(currentMessage);
|
||||
return List.of(comboEvent, giftEvent);
|
||||
}
|
||||
|
||||
if (!containsPreviousMessage) {
|
||||
if (currentType == GiftSendType.Finished) {
|
||||
return List.of(getGiftEvent(currentMessage));
|
||||
@@ -89,7 +96,6 @@ public class TikTokGiftEventHandler {
|
||||
}
|
||||
|
||||
|
||||
|
||||
private TikTokGiftEvent getGiftEvent(WebcastGiftMessage message) {
|
||||
var gift = getGiftObject(message);
|
||||
return new TikTokGiftEvent(gift, message);
|
||||
@@ -100,15 +106,13 @@ public class TikTokGiftEventHandler {
|
||||
return new TikTokGiftComboEvent(gift, message, state);
|
||||
}
|
||||
|
||||
private Gift getGiftObject(WebcastGiftMessage giftMessage)
|
||||
{
|
||||
private Gift getGiftObject(WebcastGiftMessage giftMessage) {
|
||||
var giftId = (int) giftMessage.getGiftId();
|
||||
var gift = giftManager.findById(giftId);
|
||||
if (gift == Gift.UNDEFINED) {
|
||||
gift = giftManager.findByName(giftMessage.getGift().getName());
|
||||
}
|
||||
if (gift == Gift.UNDEFINED)
|
||||
{
|
||||
if (gift == Gift.UNDEFINED) {
|
||||
gift = giftManager.registerGift(
|
||||
giftId,
|
||||
giftMessage.getGift().getName(),
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package io.github.jwdeveloper.tiktok.handlers.events;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLiveIntroMessage;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastRoomUserSeqMessage;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class TikTokRoomInfoEventHandler {
|
||||
private final TikTokRoomInfo roomInfo;
|
||||
|
||||
public TikTokRoomInfoEventHandler(TikTokRoomInfo roomInfo) {
|
||||
this.roomInfo = roomInfo;
|
||||
}
|
||||
|
||||
public TikTokEvent handleRoomInfo(Consumer<TikTokRoomInfo> consumer) {
|
||||
consumer.accept(roomInfo);
|
||||
return new TikTokRoomInfoEvent(roomInfo);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public TikTokEvent handleUserRanking(byte[] msg) {
|
||||
var message = WebcastRoomUserSeqMessage.parseFrom(msg);
|
||||
var totalUsers = message.getTotalUser();
|
||||
var userRanking = message.getRanksListList().stream().map(RankingUser::new)
|
||||
.sorted((ru1, ru2) -> Integer.compare(ru2.getScore(), ru1.getScore()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return handleRoomInfo(tikTokRoomInfo ->
|
||||
{
|
||||
tikTokRoomInfo.setTotalViewersCount(totalUsers);
|
||||
tikTokRoomInfo.updateRanking(userRanking);
|
||||
});
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public TikTokEvent handleIntro(byte[] msg) {
|
||||
var message = WebcastLiveIntroMessage.parseFrom(msg);
|
||||
var hostUser = User.map(message.getHost());
|
||||
var language = message.getLanguage();
|
||||
|
||||
return handleRoomInfo(tikTokRoomInfo ->
|
||||
{
|
||||
if(tikTokRoomInfo.getHost() == null)
|
||||
{
|
||||
tikTokRoomInfo.setHost(hostUser);
|
||||
}
|
||||
tikTokRoomInfo.setLanguage(language);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package io.github.jwdeveloper.tiktok.handlers.events;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokUnhandledSocialEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokFollowEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokShareEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.Text;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage;
|
||||
import io.github.jwdeveloper.tiktok.models.SocialTypes;
|
||||
import lombok.SneakyThrows;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class TikTokSocialMediaEventHandler
|
||||
{
|
||||
private final TikTokRoomInfo roomInfo;
|
||||
private final Pattern socialMediaPattern = Pattern.compile("pm_mt_guidance_viewer_([0-9]+)_share");
|
||||
|
||||
public TikTokSocialMediaEventHandler(TikTokRoomInfo roomInfo) {
|
||||
this.roomInfo = roomInfo;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public TikTokEvent handle(byte[] msg)
|
||||
{
|
||||
var message = WebcastSocialMessage.parseFrom(msg);
|
||||
|
||||
var socialType = Text.map(message.getCommon().getDisplayText()).getKey();
|
||||
var matcher = socialMediaPattern.matcher(socialType);
|
||||
|
||||
if (matcher.find()) {
|
||||
var value = matcher.group(1);
|
||||
var number = Integer.parseInt(value);
|
||||
return new TikTokShareEvent(message, number);
|
||||
}
|
||||
|
||||
return switch (socialType) {
|
||||
case SocialTypes.LikeType -> new TikTokLikeEvent(message, roomInfo.getLikesCount());
|
||||
case SocialTypes.FollowType -> new TikTokFollowEvent(message);
|
||||
case SocialTypes.ShareType -> new TikTokShareEvent(message);
|
||||
case SocialTypes.JoinType -> new TikTokJoinEvent(message, roomInfo.getViewersCount());
|
||||
default -> new TikTokUnhandledSocialEvent(message);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -70,6 +70,7 @@ public class TikTokHttpClient {
|
||||
|
||||
public JsonObject getJsonFromWebcastApi(String path, Map<String, Object> parameters) {
|
||||
var get = getRequest(Constants.TIKTOK_URL_WEBCAST + path, parameters);
|
||||
|
||||
var json = JsonParser.parseString(get);
|
||||
var jsonObject = json.getAsJsonObject();
|
||||
return jsonObject;
|
||||
|
||||
@@ -22,9 +22,15 @@
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.mappers;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||
import io.github.jwdeveloper.tiktok.data.models.users.UserAttribute;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveRoomMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class LiveRoomMetaMapper {
|
||||
/**
|
||||
* 0 - Unknown
|
||||
@@ -46,15 +52,12 @@ public class LiveRoomMetaMapper {
|
||||
var status = data.get("status");
|
||||
var statusId = status.getAsInt();
|
||||
var statusValue = switch (statusId) {
|
||||
case 0 -> LiveRoomMeta.LiveRoomStatus.HostNotFound;
|
||||
case 2 -> LiveRoomMeta.LiveRoomStatus.HostOnline;
|
||||
case 4 -> LiveRoomMeta.LiveRoomStatus.HostOffline;
|
||||
default-> LiveRoomMeta.LiveRoomStatus.HostNotFound;
|
||||
default -> LiveRoomMeta.LiveRoomStatus.HostNotFound;
|
||||
};
|
||||
liveRoomMeta.setStatus(statusValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
liveRoomMeta.setStatus(LiveRoomMeta.LiveRoomStatus.HostNotFound);
|
||||
}
|
||||
|
||||
@@ -63,6 +66,61 @@ public class LiveRoomMetaMapper {
|
||||
var restricted = element.get("restricted").getAsBoolean();
|
||||
liveRoomMeta.setAgeRestricted(restricted);
|
||||
}
|
||||
|
||||
if (data.has("title")) {
|
||||
var element = data.get("title");
|
||||
var title = element.getAsString();
|
||||
liveRoomMeta.setTitie(title);
|
||||
}
|
||||
|
||||
if (data.has("stats")) {
|
||||
var statsElement = data.getAsJsonObject("stats");
|
||||
var likeElement = statsElement.get("like_count");
|
||||
var likes = likeElement.getAsInt();
|
||||
|
||||
var titalUsersElement = statsElement.get("total_user");
|
||||
var totalUsers = titalUsersElement.getAsInt();
|
||||
|
||||
|
||||
liveRoomMeta.setLikeCount(likes);
|
||||
liveRoomMeta.setTotalViewers(totalUsers);
|
||||
}
|
||||
|
||||
if(data.has("user_count"))
|
||||
{
|
||||
var element = data.get("user_count");
|
||||
var viewers = element.getAsInt();
|
||||
liveRoomMeta.setViewers(viewers);
|
||||
}
|
||||
|
||||
if(data.has("owner"))
|
||||
{
|
||||
var element = data.getAsJsonObject("owner");
|
||||
var user = getUser(element);
|
||||
liveRoomMeta.setHost(user);
|
||||
}
|
||||
|
||||
return liveRoomMeta;
|
||||
}
|
||||
|
||||
public User getUser(JsonObject jsonElement)
|
||||
{
|
||||
var id = jsonElement.get("id").getAsLong();
|
||||
var name = jsonElement.get("display_id").getAsString();
|
||||
var profileName = jsonElement.get("nickname").getAsString();
|
||||
|
||||
|
||||
var followElement =jsonElement.getAsJsonObject("follow_info");
|
||||
var followers = followElement.get("follower_count").getAsInt();
|
||||
var followingCount = followElement.get("following_count").getAsInt();
|
||||
|
||||
|
||||
var pictureElement =jsonElement.getAsJsonObject("avatar_large");
|
||||
var link = pictureElement.getAsJsonArray("url_list").get(1).getAsString();
|
||||
var picture = new Picture(link);
|
||||
|
||||
var user = new User(id,name,profileName,picture,followers,followingCount,new ArrayList<>());
|
||||
user.addAttribute(UserAttribute.LiveHost);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,10 +74,7 @@ public class TikTokWebSocketClient implements SocketClient {
|
||||
}
|
||||
|
||||
try {
|
||||
if (clientSettings.isHandleExistingEvents()) {
|
||||
logger.info("Handling existing events");
|
||||
webResponseHandler.handle(tikTokLiveClient, webcastResponse);
|
||||
}
|
||||
webResponseHandler.handle(tikTokLiveClient, webcastResponse);
|
||||
var url = getWebSocketUrl(webcastResponse);
|
||||
webSocketClient = startWebSocket(url, tikTokLiveClient);
|
||||
webSocketClient.connect();
|
||||
@@ -85,7 +82,8 @@ public class TikTokWebSocketClient implements SocketClient {
|
||||
pingingTask = new TikTokWebSocketPingingTask();
|
||||
pingingTask.run(webSocketClient);
|
||||
isConnected = true;
|
||||
} catch (Exception e) {
|
||||
} catch (Exception e)
|
||||
{
|
||||
isConnected = false;
|
||||
throw new TikTokLiveException("Failed to connect to the websocket", e);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
*/
|
||||
package io.github.jwdeveloper.tiktok.handlers.events;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||
import io.github.jwdeveloper.tiktok.messages.data.GiftStruct;
|
||||
import io.github.jwdeveloper.tiktok.messages.data.Image;
|
||||
@@ -52,7 +54,20 @@ class TikTokGiftEventHandlerTest {
|
||||
|
||||
@Test
|
||||
void shouldHandleGifts() {
|
||||
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1);
|
||||
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,false);
|
||||
var result = handler.handleGift(message);
|
||||
|
||||
Assertions.assertEquals(2, result.size());
|
||||
|
||||
var event = (TikTokGiftEvent) result.get(0);
|
||||
var gift = event.getGift();
|
||||
Assertions.assertEquals("image-new.png",gift.getPicture().getLink());
|
||||
Assertions.assertEquals(123,gift.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleStrakableGift() {
|
||||
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,true);
|
||||
var result = handler.handleGift(message);
|
||||
|
||||
Assertions.assertEquals(1, result.size());
|
||||
@@ -63,12 +78,35 @@ class TikTokGiftEventHandlerTest {
|
||||
Assertions.assertEquals(123,gift.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleStrike()
|
||||
{
|
||||
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 message3 = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,true);
|
||||
|
||||
var result1 = handler.handleGift(message1);
|
||||
var result2 = handler.handleGift(message2);
|
||||
var result3 = handler.handleGift(message3);
|
||||
|
||||
var event1 = (TikTokGiftComboEvent) result1.get(0);
|
||||
var event2 = (TikTokGiftComboEvent) result2.get(0);
|
||||
|
||||
Assertions.assertEquals(2, result3.size());
|
||||
var event3 = (TikTokGiftComboEvent) result3.get(0);
|
||||
|
||||
Assertions.assertEquals(GiftSendType.Begin,event1.getComboState());
|
||||
Assertions.assertEquals(GiftSendType.Active,event2.getComboState());
|
||||
Assertions.assertEquals(GiftSendType.Finished,event3.getComboState());
|
||||
}
|
||||
|
||||
|
||||
public WebcastGiftMessage getGiftMessage(String giftName,
|
||||
int giftId,
|
||||
String giftImage,
|
||||
int sendType,
|
||||
int userId) {
|
||||
int userId,
|
||||
boolean streakable) {
|
||||
var builder = WebcastGiftMessage.newBuilder();
|
||||
var giftBuilder = GiftStruct.newBuilder();
|
||||
var userBuilder = User.newBuilder();
|
||||
@@ -77,6 +115,7 @@ class TikTokGiftEventHandlerTest {
|
||||
giftBuilder.setId(giftId);
|
||||
giftBuilder.setName(giftName);
|
||||
giftBuilder.setImage(Image.newBuilder().addUrlList(giftImage).build());
|
||||
giftBuilder.setType(streakable?1:0);
|
||||
userBuilder.setId(userId);
|
||||
|
||||
builder.setGiftId(giftId);
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.logging.Level;
|
||||
|
||||
public class SimpleExample
|
||||
{
|
||||
public static String TIKTOK_HOSTNAME = "seanfitzness";
|
||||
public static String TIKTOK_HOSTNAME = "bangbetmenygy";
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
showLogo();
|
||||
@@ -59,7 +59,6 @@ public class SimpleExample
|
||||
clientSettings.setTimeout(Duration.ofSeconds(2)); // Connection timeout
|
||||
clientSettings.setLogLevel(Level.ALL); // Log level
|
||||
clientSettings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF
|
||||
clientSettings.setHandleExistingEvents(true); // Invokes all TikTok events that had occurred before connection
|
||||
clientSettings.setRetryOnConnectionFailure(true); // Reconnecting if TikTok user is offline
|
||||
clientSettings.setRetryConnectionTimeout(Duration.ofSeconds(1)); // Timeout before next reconnection
|
||||
|
||||
@@ -95,9 +94,9 @@ public class SimpleExample
|
||||
{
|
||||
print(ConsoleColors.RED,"[Disconnected]");
|
||||
})
|
||||
.onRoom((liveClient, event) ->
|
||||
.onRoomInfo((liveClient, event) ->
|
||||
{
|
||||
|
||||
var info = event.getRoomInfo();
|
||||
})
|
||||
.onFollow((liveClient, event) ->
|
||||
{
|
||||
|
||||
Binary file not shown.
695
README.md
695
README.md
@@ -1,9 +1,8 @@
|
||||
<div align="center" >
|
||||
<a target="blank" >
|
||||
<img src="https://github.com/jwdeveloper/TikTokLiveJava/assets/79764581/1f9951b4-a270-4535-bf38-a6f41cdf8f43" 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>
|
||||
|
||||
</div>
|
||||
<div align="center" >
|
||||
<h1>TikTok Live Java</h1>
|
||||
@@ -17,7 +16,6 @@
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<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>
|
||||
@@ -30,11 +28,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
# Introduction
|
||||
A Java library inspired by [TikTokLive](https://github.com/isaackogan/TikTokLive) and [TikTokLiveSharp](https://github.com/sebheron/TikTokLiveSharp). Use it to receive live stream events such as comments and gifts in realtime from [TikTok LIVE](https://www.tiktok.com/live) by connecting to TikTok's internal WebCast push service.
|
||||
A Java library inspired by [TikTokLive](https://github.com/isaackogan/TikTokLive) and [TikTokLiveSharp](https://github.com/frankvHoof93/TikTokLiveSharp). Use it to receive live stream events such as comments and gifts in realtime from [TikTok LIVE](https://www.tiktok.com/live) by connecting to TikTok's internal WebCast push service.
|
||||
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.
|
||||
|
||||
@@ -52,19 +47,12 @@ Do you prefer other programming languages?
|
||||
|
||||
**NOTE:** This is not an official API. It's a reverse engineering project.
|
||||
|
||||
|
||||
#### Overview
|
||||
- [Getting started](#getting-started)
|
||||
- [Events](#events)
|
||||
- [Listeners](#listeners)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Install the package via Maven
|
||||
@@ -81,7 +69,7 @@ Do you prefer other programming languages?
|
||||
<dependency>
|
||||
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||
<artifactId>Client</artifactId>
|
||||
<version>1.0.4-Release</version>
|
||||
<version>1.0.5-Release</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -107,6 +95,13 @@ TikTokLive.newClient("bangbetmenygy")
|
||||
{
|
||||
System.out.println(event.getComboState()+ " " + event.getCombo() + " " + event.getGift().getName());
|
||||
})
|
||||
.onRoomInfo((liveClient, event) ->
|
||||
{
|
||||
var roomInfo = event.getRoomInfo();
|
||||
System.out.println("Room Id: "+roomInfo.getRoomId());
|
||||
System.out.println("Likes: "+roomInfo.getLikesCount());
|
||||
System.out.println("Viewers: "+roomInfo.getViewersCount());
|
||||
})
|
||||
.onJoin((liveClient, event) ->
|
||||
{
|
||||
System.out.println(event.getUser().getProfileName() + "Hello on my stream! ");
|
||||
@@ -134,7 +129,6 @@ TikTokLive.newClient("bangbetmenygy")
|
||||
settings.setTimeout(Duration.ofSeconds(2)); // Connection timeout
|
||||
settings.setLogLevel(Level.ALL); // Log level
|
||||
settings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF
|
||||
settings.setHandleExistingEvents(true); // Invokes all TikTok events that had occurred before connection
|
||||
settings.setRetryOnConnectionFailure(true); // Reconnecting if TikTok user is offline
|
||||
settings.setRetryConnectionTimeout(Duration.ofSeconds(1)); // Timeout before next reconnection
|
||||
|
||||
@@ -156,36 +150,35 @@ TikTokLive.newClient("bangbetmenygy")
|
||||
|
||||
|
||||
|
||||
**Control**:
|
||||
**Control**:
|
||||
|
||||
- [onConnected](#onconnected-tiktokconnectedevent)
|
||||
- [onReconnecting](#onreconnecting-tiktokreconnectingevent)
|
||||
- [onDisconnected](#ondisconnected-tiktokdisconnectedevent)
|
||||
- [onReconnecting](#onreconnecting-tiktokreconnectingevent)
|
||||
- [onError](#onerror-tiktokerrorevent)
|
||||
|
||||
**Message**:
|
||||
**Message**:
|
||||
|
||||
- [onEvent](#onevent-tiktokevent)
|
||||
- [onShare](#onshare-tiktokshareevent)
|
||||
- [onLivePaused](#onlivepaused-tiktoklivepausedevent)
|
||||
- [onRoom](#onroom-tiktokroomevent)
|
||||
- [onGiftCombo](#ongiftcombo-tiktokgiftcomboevent)
|
||||
- [onJoin](#onjoin-tiktokjoinevent)
|
||||
- [onRoomUserInfo](#onroomuserinfo-tiktokroomuserinfoevent)
|
||||
- [onComment](#oncomment-tiktokcommentevent)
|
||||
- [onGift](#ongift-tiktokgiftevent)
|
||||
- [onLike](#onlike-tiktoklikeevent)
|
||||
- [onSubscribe](#onsubscribe-tiktoksubscribeevent)
|
||||
- [onQuestion](#onquestion-tiktokquestionevent)
|
||||
- [onEmote](#onemote-tiktokemoteevent)
|
||||
- [onLiveEnded](#onliveended-tiktokliveendedevent)
|
||||
- [onFollow](#onfollow-tiktokfollowevent)
|
||||
- [onUnhandledSocial](#onunhandledsocial-tiktokunhandledsocialevent)
|
||||
- [onLike](#onlike-tiktoklikeevent)
|
||||
- [onLiveEnded](#onliveended-tiktokliveendedevent)
|
||||
- [onRoomInfo](#onroominfo-tiktokroominfoevent)
|
||||
- [onShare](#onshare-tiktokshareevent)
|
||||
- [onGiftCombo](#ongiftcombo-tiktokgiftcomboevent)
|
||||
- [onEmote](#onemote-tiktokemoteevent)
|
||||
- [onGift](#ongift-tiktokgiftevent)
|
||||
- [onComment](#oncomment-tiktokcommentevent)
|
||||
- [onLivePaused](#onlivepaused-tiktoklivepausedevent)
|
||||
- [onLiveUnpaused](#onliveunpaused-tiktokliveunpausedevent)
|
||||
- [onJoin](#onjoin-tiktokjoinevent)
|
||||
|
||||
**Debug**:
|
||||
**Debug**:
|
||||
|
||||
- [onWebsocketResponse](#onwebsocketresponse-tiktokwebsocketresponseevent)
|
||||
- [onWebsocketUnhandledMessage](#onwebsocketunhandledmessage-tiktokwebsocketunhandledmessageevent)
|
||||
- [onWebsocketResponse](#onwebsocketresponse-tiktokwebsocketresponseevent)
|
||||
- [onWebsocketMessage](#onwebsocketmessage-tiktokwebsocketmessageevent)
|
||||
# Examples
|
||||
<br>
|
||||
@@ -193,7 +186,7 @@ TikTokLive.newClient("bangbetmenygy")
|
||||
## onConnected [TikTokConnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokConnectedEvent.java)
|
||||
|
||||
|
||||
Triggered when the connection is successfully established.
|
||||
Triggered when the connection is successfully established.
|
||||
|
||||
|
||||
```java
|
||||
@@ -207,6 +200,26 @@ TikTokLive.newClient("host-name")
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onDisconnected [TikTokDisconnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokDisconnectedEvent.java)
|
||||
|
||||
|
||||
Triggered when the connection gets disconnected. In that case you can call connect() again to have a reconnect logic.
|
||||
Note that you should wait a little bit before attempting a reconnect to to avoid being rate-limited.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onDisconnected((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onReconnecting [TikTokReconnectingEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokReconnectingEvent.java)
|
||||
@@ -224,32 +237,12 @@ TikTokLive.newClient("host-name")
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onDisconnected [TikTokDisconnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokDisconnectedEvent.java)
|
||||
|
||||
|
||||
Triggered when the connection gets disconnected. In that case you can call connect() again to have a reconnect logic.
|
||||
Note that you should wait a little bit before attempting a reconnect to to avoid being rate-limited.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onDisconnected((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onError [TikTokErrorEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokErrorEvent.java)
|
||||
|
||||
|
||||
General error event. You should handle this.
|
||||
General error event. You should handle this.
|
||||
|
||||
|
||||
```java
|
||||
@@ -268,7 +261,7 @@ TikTokLive.newClient("host-name")
|
||||
## onEvent [TikTokEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEvent.java)
|
||||
|
||||
|
||||
Base class for all events
|
||||
Base class for all events
|
||||
|
||||
|
||||
```java
|
||||
@@ -282,190 +275,12 @@ TikTokLive.newClient("host-name")
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onShare [TikTokShareEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokShareEvent.java)
|
||||
|
||||
|
||||
Triggers when a user shares the stream. Based on social event.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onShare((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLivePaused [TikTokLivePausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLivePausedEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLivePaused((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onRoom [TikTokRoomEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/room/TikTokRoomEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onRoom((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onGiftCombo [TikTokGiftComboEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java)
|
||||
|
||||
|
||||
Triggered every time gift is sent
|
||||
|
||||
@see GiftSendType it has 3 states
|
||||
|
||||
<p>Example when user sends gift with combo</p>
|
||||
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
||||
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||
<p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
||||
|
||||
Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onGiftCombo((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onJoin [TikTokJoinEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokJoinEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onJoin((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onRoomUserInfo [TikTokRoomUserInfoEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/room/TikTokRoomUserInfoEvent.java)
|
||||
|
||||
|
||||
Only top 5 users in ranking has detailed data
|
||||
rest has only ID
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onRoomUserInfo((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onComment [TikTokCommentEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokCommentEvent.java)
|
||||
|
||||
|
||||
Triggered every time a new chat comment arrives.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onComment((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onGift [TikTokGiftEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java)
|
||||
|
||||
|
||||
Triggered when user sends gifts that has
|
||||
no combo (most of expensive gifts)
|
||||
or if combo has finished
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onGift((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLike [TikTokLikeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokLikeEvent.java)
|
||||
|
||||
|
||||
Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLike((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onSubscribe [TikTokSubscribeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokSubscribeEvent.java)
|
||||
|
||||
|
||||
Triggers when a user creates a subscription.
|
||||
Triggers when a user creates a subscription.
|
||||
|
||||
|
||||
```java
|
||||
@@ -498,50 +313,12 @@ TikTokLive.newClient("host-name")
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onEmote [TikTokEmoteEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokEmoteEvent.java)
|
||||
|
||||
|
||||
Triggered every time a subscriber sends an emote (sticker).
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onEmote((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLiveEnded [TikTokLiveEndedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveEndedEvent.java)
|
||||
|
||||
|
||||
Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLiveEnded((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onFollow [TikTokFollowEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokFollowEvent.java)
|
||||
|
||||
|
||||
Triggers when a user follows the streamer. Based on social event.
|
||||
Triggers when a user follows the streamer. Based on social event.
|
||||
|
||||
|
||||
```java
|
||||
@@ -557,13 +334,228 @@ TikTokLive.newClient("host-name")
|
||||
|
||||
<br>
|
||||
|
||||
## onUnhandledSocial [TikTokUnhandledSocialEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokUnhandledSocialEvent.java)
|
||||
## onLike [TikTokLikeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokLikeEvent.java)
|
||||
|
||||
|
||||
Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLike((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLiveEnded [TikTokLiveEndedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveEndedEvent.java)
|
||||
|
||||
|
||||
Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLiveEnded((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onRoomInfo [TikTokRoomInfoEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/room/TikTokRoomInfoEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onUnhandledSocial((liveClient, event) ->
|
||||
.onRoomInfo((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onShare [TikTokShareEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokShareEvent.java)
|
||||
|
||||
|
||||
Triggers when a user shares the stream. Based on social event.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onShare((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onGiftCombo [TikTokGiftComboEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java)
|
||||
|
||||
|
||||
Triggered every time gift is sent
|
||||
|
||||
@see GiftSendType it has 3 states
|
||||
|
||||
<p>Example when user sends gift with combo</p>
|
||||
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
||||
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||
<p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
||||
|
||||
Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onGiftCombo((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onEmote [TikTokEmoteEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokEmoteEvent.java)
|
||||
|
||||
|
||||
Triggered every time a subscriber sends an emote (sticker).
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onEmote((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onGift [TikTokGiftEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java)
|
||||
|
||||
|
||||
Triggered when user sends gifts that has
|
||||
no combo (most of expensive gifts)
|
||||
or if combo has finished
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onGift((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onComment [TikTokCommentEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokCommentEvent.java)
|
||||
|
||||
|
||||
Triggered every time a new chat comment arrives.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onComment((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLivePaused [TikTokLivePausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLivePausedEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLivePaused((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLiveUnpaused [TikTokLiveUnpausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveUnpausedEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLiveUnpaused((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onJoin [TikTokJoinEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokJoinEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onJoin((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onWebsocketUnhandledMessage [TikTokWebsocketUnhandledMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketUnhandledMessageEvent.java)
|
||||
|
||||
|
||||
Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
@@ -580,30 +572,11 @@ TikTokLive.newClient("host-name")
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onWebsocketResponse((liveClient, event) ->
|
||||
{
|
||||
.onWebsocketResponse((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onWebsocketUnhandledMessage [TikTokWebsocketUnhandledMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketUnhandledMessageEvent.java)
|
||||
|
||||
|
||||
Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
@@ -613,16 +586,16 @@ TikTokLive.newClient("host-name")
|
||||
## onWebsocketMessage [TikTokWebsocketMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java)
|
||||
|
||||
|
||||
Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
|
||||
Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onWebsocketMessage((liveClient, event) ->
|
||||
{
|
||||
.onWebsocketMessage((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
@@ -635,72 +608,72 @@ TikTokLive.newClient("host-name")
|
||||
|
||||
```java
|
||||
|
||||
/**
|
||||
*
|
||||
* Listeners are an alternative way of handling events.
|
||||
* I would to suggest to use then when logic of handing event
|
||||
* is more complex
|
||||
*
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
/**
|
||||
*
|
||||
* Listeners are an alternative way of handling events.
|
||||
* I would to suggest to use then when logic of handing event
|
||||
* is more complex
|
||||
*
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
showLogo();
|
||||
CustomListener customListener = new CustomListener();
|
||||
|
||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||
.addListener(customListener)
|
||||
.buildAndConnect();
|
||||
.addListener(customListener)
|
||||
.buildAndConnect();
|
||||
System.in.read();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Method in TikTokEventListener should meet 4 requirements to be detected
|
||||
* - must have @TikTokEventHandler annotation
|
||||
* - must have 2 parameters
|
||||
* - first parameter must be LiveClient
|
||||
* - second must be class that extending TikTokEvent
|
||||
*/
|
||||
|
||||
public static class CustomListener implements TikTokEventListener {
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
||||
System.out.println(event.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Method in TikTokEventListener should meet 4 requirements to be detected
|
||||
* - must have @TikTokEventHandler annotation
|
||||
* - must have 2 parameters
|
||||
* - first parameter must be LiveClient
|
||||
* - second must be class that extending TikTokEvent
|
||||
*/
|
||||
|
||||
public static class CustomListener implements TikTokEventListener {
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
||||
System.out.println(event.toString());
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
||||
// event.getException().printStackTrace();
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
||||
var userName = event.getUser().getName();
|
||||
var text = event.getText();
|
||||
liveClient.getLogger().info(userName + ": " + text);
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
||||
var message = switch (event.getGift()) {
|
||||
case ROSE -> "Thanks :)";
|
||||
case APPETIZERS -> ":OO";
|
||||
case APRIL -> ":D";
|
||||
case TIKTOK -> ":P";
|
||||
case CAP -> ":F";
|
||||
default -> ":I";
|
||||
};
|
||||
liveClient.getLogger().info(message);
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
||||
liveClient.getLogger().info(event.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
||||
// event.getException().printStackTrace();
|
||||
}
|
||||
|
||||
//
|
||||
@TikTokEventHandler
|
||||
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
||||
var userName = event.getUser().getName();
|
||||
var text = event.getText();
|
||||
liveClient.getLogger().info(userName + ": " + text);
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
||||
var message = switch (event.getGift()) {
|
||||
case ROSE -> "Thanks :)";
|
||||
case APPETIZERS -> ":OO";
|
||||
case APRIL -> ":D";
|
||||
case TIKTOK -> ":P";
|
||||
case CAP -> ":F";
|
||||
default -> ":I";
|
||||
};
|
||||
liveClient.getLogger().info(message);
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
||||
liveClient.getLogger().info(event.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessageCollecto
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class RunCollector {
|
||||
|
||||
@@ -38,22 +39,38 @@ public class RunCollector {
|
||||
public static void main(String[] args) throws SQLException, IOException {
|
||||
|
||||
TikTokMessageCollectorClient.create("giftsCollector")
|
||||
.addUser("crece.sara")
|
||||
.addUser("moniczkka")
|
||||
//.addUser("crece.sara")
|
||||
//.addUser("moniczkka")
|
||||
.addUser("valeria.viral")
|
||||
// .addUser("cbcgod")
|
||||
// .addUser("psychotropnazywo")
|
||||
// .addUser("accordionistka")
|
||||
.addEventFilter(WebcastGiftMessage.class)
|
||||
//.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());
|
||||
});
|
||||
|
||||
Binary file not shown.
@@ -39,16 +39,21 @@ public class TikTokManager {
|
||||
TikTokMessagessCollectorBuilder client;
|
||||
MessageCollector msgCollector;
|
||||
|
||||
public static String dbName= "ab";
|
||||
|
||||
public TikTokManager() {
|
||||
msgCollector = new MessageCollector("ab");
|
||||
msgCollector = new MessageCollector(dbName);
|
||||
}
|
||||
|
||||
public void connect(String name) throws SQLException {
|
||||
disconnect();
|
||||
client = TikTokMessageCollectorClient.create(msgCollector, "ab")
|
||||
client = TikTokMessageCollectorClient.create(msgCollector, dbName)
|
||||
.addOnBuilder(liveClientBuilder ->
|
||||
{
|
||||
liveClientBuilder.onRoomInfo((liveClient, event) ->
|
||||
{
|
||||
|
||||
});
|
||||
liveClientBuilder.onGift((liveClient, event) ->
|
||||
{
|
||||
|
||||
|
||||
@@ -54,6 +54,13 @@ public class CodeExample {
|
||||
{
|
||||
System.out.println(event.getComboState()+ " " + event.getCombo() + " " + event.getGift().getName());
|
||||
})
|
||||
.onRoomInfo((liveClient, event) ->
|
||||
{
|
||||
var roomInfo = event.getRoomInfo();
|
||||
System.out.println("Room Id: "+roomInfo.getRoomId());
|
||||
System.out.println("Likes: "+roomInfo.getLikesCount());
|
||||
System.out.println("Viewers: "+roomInfo.getViewersCount());
|
||||
})
|
||||
.onJoin((liveClient, event) ->
|
||||
{
|
||||
System.out.println(event.getUser().getProfileName() + "Hello on my stream! ");
|
||||
@@ -80,7 +87,6 @@ public class CodeExample {
|
||||
settings.setTimeout(Duration.ofSeconds(2)); // Connection timeout
|
||||
settings.setLogLevel(Level.ALL); // Log level
|
||||
settings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF
|
||||
settings.setHandleExistingEvents(true); // Invokes all TikTok events that had occurred before connection
|
||||
settings.setRetryOnConnectionFailure(true); // Reconnecting if TikTok user is offline
|
||||
settings.setRetryConnectionTimeout(Duration.ofSeconds(1)); // Timeout before next reconnection
|
||||
|
||||
|
||||
681
Tools-ReadmeGenerator/src/main/resources/output.md
Normal file
681
Tools-ReadmeGenerator/src/main/resources/output.md
Normal file
@@ -0,0 +1,681 @@
|
||||
<div align="center" >
|
||||
<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>
|
||||
</a>
|
||||
</div>
|
||||
<div align="center" >
|
||||
<h1>TikTok Live Java</h1>
|
||||
|
||||
❤️❤️🎁 *Connect to TikTok live in 3 lines* 🎁❤️❤️
|
||||
|
||||
<div align="center" >
|
||||
<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>
|
||||
</a>
|
||||
|
||||
|
||||
<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>
|
||||
</a>
|
||||
|
||||
<a target="blank" >
|
||||
<img src="https://img.shields.io/badge/java-%23ED8B00.svg?style=for-the-badge&logo=openjdk&logoColor=white" >
|
||||
</img>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
# Introduction
|
||||
A Java library inspired by [TikTokLive](https://github.com/isaackogan/TikTokLive) and [TikTokLiveSharp](https://github.com/frankvHoof93/TikTokLiveSharp). Use it to receive live stream events such as comments and gifts in realtime from [TikTok LIVE](https://www.tiktok.com/live) by connecting to TikTok's internal WebCast push service.
|
||||
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.
|
||||
|
||||
<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>
|
||||
</div>
|
||||
|
||||
Join the support [discord](https://discord.gg/e2XwPNTBBr) and visit the `#java-support` channel for questions, contributions and ideas. Feel free to make pull requests with missing/new features, fixes, etc
|
||||
|
||||
Do you prefer other programming languages?
|
||||
- **Node** orginal: [TikTok-Live-Connector](https://github.com/isaackogan/TikTok-Live-Connector) by [@zerodytrash](https://github.com/zerodytrash)
|
||||
- **Python** rewrite: [TikTokLive](https://github.com/isaackogan/TikTokLive) by [@isaackogan](https://github.com/isaackogan)
|
||||
- **Go** rewrite: [GoTikTokLive](https://github.com/Davincible/gotiktoklive) by [@Davincible](https://github.com/Davincible)
|
||||
- **C#** rewrite: [TikTokLiveSharp](https://github.com/frankvHoof93/TikTokLiveSharp) by [@frankvHoof93](https://github.com/frankvHoof93)
|
||||
|
||||
**NOTE:** This is not an official API. It's a reverse engineering project.
|
||||
|
||||
#### Overview
|
||||
- [Getting started](#getting-started)
|
||||
- [Events](#events)
|
||||
- [Listeners](#listeners)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Install the package via Maven
|
||||
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||
<artifactId>Client</artifactId>
|
||||
<version>NOT_FOUND</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
2. Create your first chat connection
|
||||
|
||||
```java
|
||||
|
||||
TikTokLive.newClient("bangbetmenygy")
|
||||
.onGift((liveClient, event) ->
|
||||
{
|
||||
String message = switch (event.getGift()) {
|
||||
case ROSE -> "ROSE!";
|
||||
case GG -> "GOOD GAME";
|
||||
case TIKTOK -> "Ye";
|
||||
case CORGI -> "Nice gift";
|
||||
default -> "Thank you for " + event.getGift().getName();
|
||||
};
|
||||
System.out.println(event.getUser().getProfileName() + " sends " + message);
|
||||
})
|
||||
.onGiftCombo((liveClient, event) ->
|
||||
{
|
||||
System.out.println(event.getComboState()+ " " + event.getCombo() + " " + event.getGift().getName());
|
||||
})
|
||||
.onRoomInfo((liveClient, event) ->
|
||||
{
|
||||
var roomInfo = event.getRoomInfo();
|
||||
System.out.println("Room Id: "+roomInfo.getRoomId());
|
||||
System.out.println("Likes: "+roomInfo.getLikesCount());
|
||||
System.out.println("Viewers: "+roomInfo.getViewersCount());
|
||||
})
|
||||
.onJoin((liveClient, event) ->
|
||||
{
|
||||
System.out.println(event.getUser().getProfileName() + "Hello on my stream! ");
|
||||
})
|
||||
.onConnected((liveClient, event) ->
|
||||
{
|
||||
System.out.println("Connected to live ");
|
||||
})
|
||||
.onError((liveClient, event) ->
|
||||
{
|
||||
System.out.println("Error! " + event.getException().getMessage());
|
||||
})
|
||||
.buildAndConnect();
|
||||
|
||||
```
|
||||
3. Configure (optional)
|
||||
|
||||
```java
|
||||
|
||||
TikTokLive.newClient("bangbetmenygy")
|
||||
.configure((settings) ->
|
||||
{
|
||||
settings.setHostName("bangbetmenygy"); // This method is useful in case you want change hostname later
|
||||
settings.setClientLanguage("en"); // Language
|
||||
settings.setTimeout(Duration.ofSeconds(2)); // Connection timeout
|
||||
settings.setLogLevel(Level.ALL); // Log level
|
||||
settings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF
|
||||
settings.setRetryOnConnectionFailure(true); // Reconnecting if TikTok user is offline
|
||||
settings.setRetryConnectionTimeout(Duration.ofSeconds(1)); // Timeout before next reconnection
|
||||
|
||||
//Optional: Sometimes not every message from chat are send to TikTokLiveJava to fix this issue you can set sessionId
|
||||
// documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages
|
||||
settings.setSessionId("86c3c8bf4b17ebb2d74bb7fa66fd0000");
|
||||
|
||||
//Optional:
|
||||
//RoomId can be used as an override if you're having issues with HostId.
|
||||
//You can find it in the HTML for the livestream-page
|
||||
settings.setRoomId("XXXXXXXXXXXXXXXXX");
|
||||
})
|
||||
.buildAndConnect();
|
||||
//
|
||||
```
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
|
||||
|
||||
**Control**:
|
||||
|
||||
- [onConnected](#onconnected-tiktokconnectedevent)
|
||||
- [onDisconnected](#ondisconnected-tiktokdisconnectedevent)
|
||||
- [onReconnecting](#onreconnecting-tiktokreconnectingevent)
|
||||
- [onError](#onerror-tiktokerrorevent)
|
||||
|
||||
**Message**:
|
||||
|
||||
- [onEvent](#onevent-tiktokevent)
|
||||
- [onSubscribe](#onsubscribe-tiktoksubscribeevent)
|
||||
- [onQuestion](#onquestion-tiktokquestionevent)
|
||||
- [onFollow](#onfollow-tiktokfollowevent)
|
||||
- [onLike](#onlike-tiktoklikeevent)
|
||||
- [onLiveEnded](#onliveended-tiktokliveendedevent)
|
||||
- [onRoomInfo](#onroominfo-tiktokroominfoevent)
|
||||
- [onShare](#onshare-tiktokshareevent)
|
||||
- [onGiftCombo](#ongiftcombo-tiktokgiftcomboevent)
|
||||
- [onEmote](#onemote-tiktokemoteevent)
|
||||
- [onGift](#ongift-tiktokgiftevent)
|
||||
- [onComment](#oncomment-tiktokcommentevent)
|
||||
- [onLivePaused](#onlivepaused-tiktoklivepausedevent)
|
||||
- [onLiveUnpaused](#onliveunpaused-tiktokliveunpausedevent)
|
||||
- [onJoin](#onjoin-tiktokjoinevent)
|
||||
|
||||
**Debug**:
|
||||
|
||||
- [onWebsocketUnhandledMessage](#onwebsocketunhandledmessage-tiktokwebsocketunhandledmessageevent)
|
||||
- [onWebsocketResponse](#onwebsocketresponse-tiktokwebsocketresponseevent)
|
||||
- [onWebsocketMessage](#onwebsocketmessage-tiktokwebsocketmessageevent)
|
||||
# Examples
|
||||
<br>
|
||||
|
||||
## onConnected [TikTokConnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokConnectedEvent.java)
|
||||
|
||||
|
||||
Triggered when the connection is successfully established.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onConnected((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onDisconnected [TikTokDisconnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokDisconnectedEvent.java)
|
||||
|
||||
|
||||
Triggered when the connection gets disconnected. In that case you can call connect() again to have a reconnect logic.
|
||||
Note that you should wait a little bit before attempting a reconnect to to avoid being rate-limited.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onDisconnected((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onReconnecting [TikTokReconnectingEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokReconnectingEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onReconnecting((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onError [TikTokErrorEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokErrorEvent.java)
|
||||
|
||||
|
||||
General error event. You should handle this.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onError((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onEvent [TikTokEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEvent.java)
|
||||
|
||||
|
||||
Base class for all events
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onEvent((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onSubscribe [TikTokSubscribeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokSubscribeEvent.java)
|
||||
|
||||
|
||||
Triggers when a user creates a subscription.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onSubscribe((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onQuestion [TikTokQuestionEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokQuestionEvent.java)
|
||||
|
||||
|
||||
Triggered every time someone asks a new question via the question feature.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onQuestion((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onFollow [TikTokFollowEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokFollowEvent.java)
|
||||
|
||||
|
||||
Triggers when a user follows the streamer. Based on social event.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onFollow((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLike [TikTokLikeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokLikeEvent.java)
|
||||
|
||||
|
||||
Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLike((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLiveEnded [TikTokLiveEndedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveEndedEvent.java)
|
||||
|
||||
|
||||
Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLiveEnded((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onRoomInfo [TikTokRoomInfoEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/room/TikTokRoomInfoEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onRoomInfo((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onShare [TikTokShareEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokShareEvent.java)
|
||||
|
||||
|
||||
Triggers when a user shares the stream. Based on social event.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onShare((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onGiftCombo [TikTokGiftComboEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java)
|
||||
|
||||
|
||||
Triggered every time gift is sent
|
||||
|
||||
@see GiftSendType it has 3 states
|
||||
|
||||
<p>Example when user sends gift with combo</p>
|
||||
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
||||
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||
<p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
||||
|
||||
Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onGiftCombo((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onEmote [TikTokEmoteEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokEmoteEvent.java)
|
||||
|
||||
|
||||
Triggered every time a subscriber sends an emote (sticker).
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onEmote((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onGift [TikTokGiftEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java)
|
||||
|
||||
|
||||
Triggered when user sends gifts that has
|
||||
no combo (most of expensive gifts)
|
||||
or if combo has finished
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onGift((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onComment [TikTokCommentEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokCommentEvent.java)
|
||||
|
||||
|
||||
Triggered every time a new chat comment arrives.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onComment((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLivePaused [TikTokLivePausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLivePausedEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLivePaused((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onLiveUnpaused [TikTokLiveUnpausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveUnpausedEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onLiveUnpaused((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onJoin [TikTokJoinEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokJoinEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onJoin((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onWebsocketUnhandledMessage [TikTokWebsocketUnhandledMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketUnhandledMessageEvent.java)
|
||||
|
||||
|
||||
Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onWebsocketResponse [TikTokWebsocketResponseEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketResponseEvent.java)
|
||||
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onWebsocketResponse((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## onWebsocketMessage [TikTokWebsocketMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java)
|
||||
|
||||
|
||||
Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
|
||||
|
||||
|
||||
```java
|
||||
TikTokLive.newClient("host-name")
|
||||
.onWebsocketMessage((liveClient, event) ->
|
||||
{
|
||||
|
||||
})
|
||||
.buildAndConnect();
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## Listeners
|
||||
|
||||
```java
|
||||
|
||||
/**
|
||||
*
|
||||
* Listeners are an alternative way of handling events.
|
||||
* I would to suggest to use then when logic of handing event
|
||||
* is more complex
|
||||
*
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
showLogo();
|
||||
CustomListener customListener = new CustomListener();
|
||||
|
||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||
.addListener(customListener)
|
||||
.buildAndConnect();
|
||||
System.in.read();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Method in TikTokEventListener should meet 4 requirements to be detected
|
||||
* - must have @TikTokEventHandler annotation
|
||||
* - must have 2 parameters
|
||||
* - first parameter must be LiveClient
|
||||
* - second must be class that extending TikTokEvent
|
||||
*/
|
||||
|
||||
public static class CustomListener implements TikTokEventListener {
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
||||
System.out.println(event.toString());
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
||||
// event.getException().printStackTrace();
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
||||
var userName = event.getUser().getName();
|
||||
var text = event.getText();
|
||||
liveClient.getLogger().info(userName + ": " + text);
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
||||
var message = switch (event.getGift()) {
|
||||
case ROSE -> "Thanks :)";
|
||||
case APPETIZERS -> ":OO";
|
||||
case APRIL -> ":D";
|
||||
case TIKTOK -> ":P";
|
||||
case CAP -> ":F";
|
||||
default -> ":I";
|
||||
};
|
||||
liveClient.getLogger().info(message);
|
||||
}
|
||||
|
||||
@TikTokEventHandler
|
||||
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
||||
liveClient.getLogger().info(event.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
```
|
||||
|
||||
|
||||
## Contributing
|
||||
Your improvements are welcome! Feel free to open an <a href="https://github.com/jwdeveloper/TikTok-Live-Java/issues">issue</a> or <a href="https://github.com/jwdeveloper/TikTok-Live-Java/pulls">pull request</a>.
|
||||
@@ -28,6 +28,8 @@ import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokGiftEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokRoomInfoEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.handlers.events.TikTokSocialMediaEventHandler;
|
||||
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
||||
@@ -98,9 +100,10 @@ public class TikTokMockBuilder extends TikTokLiveClientBuilder {
|
||||
var apiClient = new TikTokHttpClient(cookie, requestFactory);
|
||||
var apiService = new ApiServiceMock(apiClient, logger, clientSettings);
|
||||
var webResponseHandler = new TikTokMessageHandlerRegistration(tikTokEventHandler,
|
||||
tiktokRoomInfo,
|
||||
new TikTokRoomInfoEventHandler(tiktokRoomInfo),
|
||||
new TikTokGenericEventMapper(),
|
||||
new TikTokGiftEventHandler(giftManager));
|
||||
new TikTokGiftEventHandler(giftManager),
|
||||
new TikTokSocialMediaEventHandler(tiktokRoomInfo));
|
||||
var webSocketClient = new WebsocketClientMock(logger, responses, webResponseHandler);
|
||||
|
||||
return new LiveClientMock(tiktokRoomInfo,
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user