Compare commits

..

4 Commits

Author SHA1 Message Date
JW
46d229869e - refactor of the Http client
Changes:

Http-client settings in configure method

```
    TikTokLive.newClient("X")
                .configure(liveClientSettings ->
                {
                   var httpSetting = liveClientSettings.getHttpSettings();
                    httpSetting.setTimeout(Duration.ofSeconds(12));
                });
```

`TikTokLive.requests()` Easy and quick way of making
http request to tiktok
```
    var giftsResponse =TikTokLive.request.fetchGiftsData();
 ```

 Removed:
     TikTokLive.isLiveOnline(String hostName);
     TikTokLive.isHostNameValidAsync(String hostName);

     instead you can use
     ```
     TikTokLive.requests().fetchLiveUserData("Mike").getUserStatus()
     ```
2024-01-05 17:12:37 +01:00
JW
dd417df0ff - refactor of the Http client
Changes:

Http-client settings in configure method

```
    TikTokLive.newClient("X")
                .configure(liveClientSettings ->
                {
                   var httpSetting = liveClientSettings.getHttpSettings();
                    httpSetting.setTimeout(Duration.ofSeconds(12));
                });
```

`TikTokLive.requests()` Easy and quick way of making
http request to tiktok
```
    var giftsResponse =TikTokLive.request.fetchGiftsData();
 ```

 Removed:
     TikTokLive.isLiveOnline(String hostName);
     TikTokLive.isHostNameValidAsync(String hostName);

     instead you can use
     ```
     TikTokLive.requests().fetchLiveUserData("Mike").getUserStatus()
     ```
2024-01-05 17:09:02 +01:00
JW
bc24436269 Merge branch 'master' into develop-1.0.15 2024-01-05 17:07:20 +01:00
JW
2d260dd3f9 - refactor of the Http client
Changes:

Http-client settings in configure method

```
    TikTokLive.newClient("X")
                .configure(liveClientSettings ->
                {
                   var httpSetting = liveClientSettings.getHttpSettings();
                    httpSetting.setTimeout(Duration.ofSeconds(12));
                });
```

`TikTokLive.requests()` Easy and quick way of making
http request to tiktok
```
    var giftsResponse =TikTokLive.request.fetchGiftsData();
 ```

 Removed:
     TikTokLive.isLiveOnline(String hostName);
     TikTokLive.isHostNameValidAsync(String hostName);

     instead you can use
     ```
     TikTokLive.requests().fetchLiveUserData("Mike").getUserStatus()
     ```
2024-01-05 17:04:32 +01:00
289 changed files with 218278 additions and 6783 deletions

3
.gitignore vendored
View File

@@ -1,11 +1,10 @@
backend-infrastructure/.aws-sam backend-infrastructure/.aws-sam
.db
# Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode # Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode
*.db *.db
### Linux ### ### Linux ###
*~ *~
.db
# temporary files which can be created if a process still has a handle open of a deleted file # temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden* .fuse_hidden*

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.8.2-Release</version> <version>1.0.14-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>API</artifactId> <artifactId>API</artifactId>

View File

@@ -1,18 +0,0 @@
package io.github.jwdeveloper.tiktok.annotations;
/**
* HIGHEST 1
* HIGH 2
* NORMAL 3
* LOW 4
* LOWEST 5
*/
public enum Priority {
LOWEST(2), LOW(1), NORMAL(0), HIGH(-1), HIGHEST(-2);
public final int value;
Priority(int value) {
this.value = value;
}
}

View File

@@ -28,14 +28,5 @@ import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface TikTokEventObserver public @interface TikTokEventObserver
{ {
/**
* When more than one method listen for certain Event, you can specify the method priority
* @see Priority
*/
Priority priority() default Priority.NORMAL;
/**
* When true, action is invoked on a thread, from the threads pool
*/
boolean async() default false;
} }

View File

@@ -1,62 +0,0 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.data.dto;
import lombok.*;
import java.net.*;
@Data
@AllArgsConstructor
public class ProxyData
{
private final String address;
private final int port;
public static ProxyData map(String string) {
if (string == null || string.isBlank())
throw new IllegalArgumentException("Provided address cannot be null or empty!");
int portIndex = string.lastIndexOf(':');
try {
String address = string.substring(0, portIndex);
int port = Integer.parseInt(string.substring(portIndex+1));
// Port validation
if (port < 0 || port > 65535)
throw new IndexOutOfBoundsException("Port out of range: "+port);
// IP Validation
InetAddress res = InetAddress.getByName(address);
return new ProxyData(address, port);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Port must be a valid integer!", e);
} catch (UnknownHostException e) {
throw new IllegalArgumentException("Address must be valid IPv4, IPv6, or domain name!", e);
}
}
public InetSocketAddress toSocketAddress() {
return new InetSocketAddress(address, port);
}
}

View File

@@ -20,20 +20,24 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
package io.github.jwdeveloper.tiktok.data.events.control; package io.github.jwdeveloper.tiktok.data.events;
import io.github.jwdeveloper.tiktok.annotations.EventMeta; import io.github.jwdeveloper.tiktok.annotations.EventMeta;
import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import lombok.Data;
/** @Data
* Triggered when client is connecting to live is successfully established. @EventMeta(eventType = EventType.Message)
*/ public class CustomEvent extends TikTokHeaderEvent {
@EventMeta(eventType = EventType.Control) private final User user;
public class TikTokConnectingEvent extends TikTokLiveClientEvent { private final String title;
public static TikTokConnectingEvent of() { public CustomEvent(User user, String title) {
return new TikTokConnectingEvent(); this.user = user;
this.title = title;
} }
} }

View File

@@ -38,7 +38,8 @@ public class TikTokBarrageEvent extends TikTokHeaderEvent {
private final Picture rightIcon; private final Picture rightIcon;
private final String eventName; private final String eventName;
private final int duration; private final int duration;
private final BarrageParam barrageParam;
private BarrageParam barrageParam;
public TikTokBarrageEvent(WebcastBarrageMessage msg) { public TikTokBarrageEvent(WebcastBarrageMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
@@ -48,5 +49,6 @@ public class TikTokBarrageEvent extends TikTokHeaderEvent {
rightIcon = Picture.map(msg.getRightIcon()); rightIcon = Picture.map(msg.getRightIcon());
duration = msg.getDuration(); duration = msg.getDuration();
barrageParam = BarrageParam.map(msg); barrageParam = BarrageParam.map(msg);
} }
} }

View File

@@ -32,37 +32,26 @@ import lombok.Getter;
import java.util.List; import java.util.List;
/**
* Triggered every time a new chat comment arrives.
*/
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokCommentEvent extends TikTokHeaderEvent { public class TikTokCommentEvent extends TikTokHeaderEvent {
private final User user; private final User user;
private final String text; private final String text;
private final String userLanguage; private final String getUserLanguage;
private final User mentionedUser; private final User mentionedUser;
private final List<Picture> pictures; private final List<Picture> pictures;
private final boolean visibleToSender; private final boolean visibleToSender;
public TikTokCommentEvent(WebcastChatMessage msg) { public TikTokCommentEvent(WebcastChatMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
user = User.map(msg.getUser(), msg.getUserIdentity()); user = User.map(msg.getUser(),msg.getUserIdentity());
text = msg.getContent(); text = msg.getContent();
visibleToSender = msg.getVisibleToSender(); visibleToSender = msg.getVisibleToSender();
userLanguage = msg.getContentLanguage(); getUserLanguage = msg.getContentLanguage();
mentionedUser = User.map(msg.getAtUser()); mentionedUser = User.map(msg.getAtUser());
pictures = msg.getEmotesListList().stream().map(e -> Picture.map(e.getEmote().getImage())).toList(); pictures = msg.getEmotesListList().stream().map(e -> Picture.map(e.getEmote().getImage())).toList();
} }
public static TikTokCommentEvent of(String userName, String message) {
var builder = WebcastChatMessage.newBuilder();
builder.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
.setNickname(userName)
.setDisplayId(userName)
.build());
builder.setContentLanguage("en");
builder.setVisibleToSender(true);
builder.setContent(message);
return new TikTokCommentEvent(builder.build());
}
} }

View File

@@ -25,13 +25,11 @@ import io.github.jwdeveloper.tiktok.annotations.EventMeta;
import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
/**
* Triggered when the connection is successfully established.
*/
@EventMeta(eventType = EventType.Control) @EventMeta(eventType = EventType.Control)
public class TikTokConnectedEvent extends TikTokLiveClientEvent public class TikTokConnectedEvent extends TikTokLiveClientEvent
{ {
public static TikTokConnectedEvent of()
{
return new TikTokConnectedEvent();
}
} }

View File

@@ -30,10 +30,14 @@ import lombok.Getter;
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokDetectEvent extends TikTokHeaderEvent { public class TikTokDetectEvent extends TikTokHeaderEvent {
private final String language; String language;
public TikTokDetectEvent(WebcastMsgDetectMessage msg) { public TikTokDetectEvent(WebcastMsgDetectMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
language = msg.getFromRegion(); language = msg.getFromRegion();
} }
} }

View File

@@ -24,25 +24,12 @@ package io.github.jwdeveloper.tiktok.data.events;
import io.github.jwdeveloper.tiktok.annotations.EventMeta; import io.github.jwdeveloper.tiktok.annotations.EventMeta;
import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
import lombok.Getter;
@Getter /**
* 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.
*/
@EventMeta(eventType = EventType.Control) @EventMeta(eventType = EventType.Control)
public class TikTokDisconnectedEvent extends TikTokLiveClientEvent { public class TikTokDisconnectedEvent extends TikTokLiveClientEvent {
private final String reason;
public TikTokDisconnectedEvent(String reason) {
this.reason = reason.isBlank() ? "None" : reason;
}
public TikTokDisconnectedEvent() {
this("None");
}
public static TikTokDisconnectedEvent of(String reason)
{
return new TikTokDisconnectedEvent(reason);
}
} }

View File

@@ -25,18 +25,16 @@ package io.github.jwdeveloper.tiktok.data.events;
import io.github.jwdeveloper.tiktok.annotations.EventMeta; import io.github.jwdeveloper.tiktok.annotations.EventMeta;
import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/**
* General error event. You should handle this.
*/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
@EventMeta(eventType = EventType.Control) @EventMeta(eventType = EventType.Control)
public class TikTokErrorEvent extends TikTokLiveClientEvent { public class TikTokErrorEvent extends TikTokLiveClientEvent
{
private final Throwable exception; private final Throwable exception;
public static TikTokErrorEvent of(String message) {
return new TikTokErrorEvent(new TikTokLiveException(message));
}
} }

View File

@@ -34,10 +34,9 @@ import java.util.List;
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokIMDeleteEvent extends TikTokHeaderEvent { public class TikTokIMDeleteEvent extends TikTokHeaderEvent {
private final List<Long> msgIds, userIds; List<Long> userIds;
public TikTokIMDeleteEvent(WebcastImDeleteMessage msg) { public TikTokIMDeleteEvent(WebcastImDeleteMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
this.msgIds = msg.getDeleteMsgIdsListList();
this.userIds = msg.getDeleteUserIdsListList(); this.userIds = msg.getDeleteUserIdsListList();
} }
} }

View File

@@ -20,24 +20,24 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
package io.github.jwdeveloper.tiktok.data.events.link; package io.github.jwdeveloper.tiktok.data.events;
import io.github.jwdeveloper.tiktok.annotations.*; 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.events.common.TikTokHeaderEvent;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter; import lombok.Getter;
import java.util.List;
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokLinkEvent extends TikTokHeaderEvent { public class TikTokLinkEvent extends TikTokHeaderEvent {
private final String extra, transferExtra;
private final long expireTimestamp;
public TikTokLinkEvent(WebcastLinkMessage msg) { public TikTokLinkEvent(WebcastLinkMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
this.extra = msg.getExtra();
this.expireTimestamp = msg.getExpireTimestamp();
this.transferExtra = msg.getTransferExtra();
} }
} }

View File

@@ -33,7 +33,11 @@ import lombok.Getter;
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokLinkLayerEvent extends TikTokHeaderEvent { public class TikTokLinkLayerEvent extends TikTokHeaderEvent {
public TikTokLinkLayerEvent(WebcastLinkLayerMessage msg) { public TikTokLinkLayerEvent(WebcastLinkLayerMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
} }
} }

View File

@@ -27,12 +27,12 @@ import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
import io.github.jwdeveloper.tiktok.data.models.LinkMicArmy; import io.github.jwdeveloper.tiktok.data.models.LinkMicArmy;
import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.data.models.Picture;
import io.github.jwdeveloper.tiktok.messages.enums.LinkMicBattleStatus;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicArmies; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicArmies;
import lombok.Getter; import lombok.Getter;
import java.util.List; import java.util.List;
/** /**
* Triggered every time a battle participant receives points. Contains the current status of the battle and the army that suported the group. * Triggered every time a battle participant receives points. Contains the current status of the battle and the army that suported the group.
*/ */
@@ -40,10 +40,8 @@ import java.util.List;
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokLinkMicArmiesEvent extends TikTokHeaderEvent { public class TikTokLinkMicArmiesEvent extends TikTokHeaderEvent {
private final Long battleId; private final Long battleId;
/**
true if battle is finished otherwise false private final Integer battleStatus;
*/
private final boolean finished;
private final Picture picture; private final Picture picture;
@@ -54,6 +52,6 @@ public class TikTokLinkMicArmiesEvent extends TikTokHeaderEvent {
battleId = msg.getId(); battleId = msg.getId();
armies = msg.getBattleItemsList().stream().map(LinkMicArmy::new).toList(); armies = msg.getBattleItemsList().stream().map(LinkMicArmy::new).toList();
picture = Picture.map(msg.getImage()); picture = Picture.map(msg.getImage());
finished = msg.getBattleStatus() == LinkMicBattleStatus.ARMY_FINISHED; battleStatus = msg.getBattleStatus();
} }
} }

View File

@@ -22,62 +22,29 @@
*/ */
package io.github.jwdeveloper.tiktok.data.events; package io.github.jwdeveloper.tiktok.data.events;
import io.github.jwdeveloper.tiktok.annotations.*; 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.events.common.TikTokHeaderEvent;
import io.github.jwdeveloper.tiktok.data.models.battles.*; import io.github.jwdeveloper.tiktok.data.models.LinkMicBattleTeam;
import io.github.jwdeveloper.tiktok.messages.enums.LinkMicBattleStatus;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicBattle; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicBattle;
import lombok.*; import lombok.Getter;
import java.util.*; import java.util.List;
/** /**
* Triggered every time a battle starts & ends * Triggered every time a battle starts.
*/ */
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent {
{
private final Long battleId; private final Long battleId;
/** private final List<LinkMicBattleTeam> team1;
true if battle is finished otherwise false private final List<LinkMicBattleTeam> team2;
*/
private final boolean finished;
private final List<Team> teams;
public TikTokLinkMicBattleEvent(WebcastLinkMicBattle msg) { public TikTokLinkMicBattleEvent(WebcastLinkMicBattle msg) {
super(msg.getCommon()); super(msg.getCommon());
battleId = msg.getId(); battleId = msg.getId();
finished = msg.getBattleStatus() == LinkMicBattleStatus.BATTLE_FINISHED; team1 = msg.getTeams1List().stream().map(LinkMicBattleTeam::new).toList();
teams = new ArrayList<>(); team2 = msg.getTeams2List().stream().map(LinkMicBattleTeam::new).toList();
if (msg.getHostTeamCount() == 2) { // 1v1 battle
teams.add(new Team1v1(msg.getHostTeam(0), msg));
teams.add(new Team1v1(msg.getHostTeam(1), msg));
} else { // 2v2 battle
if (isFinished()) {
teams.add(new Team2v2(msg.getHostData2V2List().stream().filter(data -> data.getTeamNumber() == 1).findFirst().orElse(null), msg));
teams.add(new Team2v2(msg.getHostData2V2List().stream().filter(data -> data.getTeamNumber() == 2).findFirst().orElse(null), msg));
} else {
teams.add(new Team2v2(msg.getHostTeam(0), msg.getHostTeam(1), msg));
teams.add(new Team2v2(msg.getHostTeam(2), msg.getHostTeam(3), msg));
}
}
// Info:
// - msg.getDetailsList() & msg.getViewerTeamList() both only have content when battle is finished
// - msg.getDetailsCount() & msg.getViewerTeamCount() always is 2 only when battle is finished
// - msg.getHostTeamCount() always is 2 for 1v1 or 4 for 2v2
}
public boolean is1v1() {
return teams.get(0) instanceof Team1v1;
}
public boolean is2v2() {
return teams.get(0) instanceof Team2v2;
}
public boolean isTie() {
return isFinished() && teams.get(0).getTotalPoints() == teams.get(1).getTotalPoints();
} }
} }

View File

@@ -36,4 +36,6 @@ public class TikTokLinkMicMethodEvent extends TikTokHeaderEvent {
super(msg.getCommon()); super(msg.getCommon());
} }
} }

View File

@@ -24,14 +24,11 @@ package io.github.jwdeveloper.tiktok.data.events;
import io.github.jwdeveloper.tiktok.annotations.EventMeta; import io.github.jwdeveloper.tiktok.annotations.EventMeta;
import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.events.control.TikTokConnectingEvent;
/**
* Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
*/
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokLiveEndedEvent extends TikTokEvent { public class TikTokLiveEndedEvent extends TikTokEvent {
public static TikTokLiveEndedEvent of() {
return new TikTokLiveEndedEvent();
}
} }

View File

@@ -29,7 +29,9 @@ import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastQuestionNewMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastQuestionNewMessage;
import lombok.Getter; import lombok.Getter;
/*
Triggered every time someone asks a new question via the question feature.
*/
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokQuestionEvent extends TikTokHeaderEvent { public class TikTokQuestionEvent extends TikTokHeaderEvent {

View File

@@ -42,4 +42,5 @@ public class TikTokRankTextEvent extends TikTokHeaderEvent {
label = text.getPattern(); label = text.getPattern();
eventType = text.getKey(); eventType = text.getKey();
} }
} }

View File

@@ -35,9 +35,11 @@ public class TikTokRankUpdateEvent extends TikTokHeaderEvent {
public TikTokRankUpdateEvent(WebcastHourlyRankMessage msg) { public TikTokRankUpdateEvent(WebcastHourlyRankMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
} }
public TikTokRankUpdateEvent(WebcastRankUpdateMessage msg) { public TikTokRankUpdateEvent(WebcastRankUpdateMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
} }
} }

View File

@@ -52,4 +52,5 @@ public class TikTokShopEvent extends TikTokHeaderEvent {
shopUrl = data.getShopUrl(); shopUrl = data.getShopUrl();
shopName = data.getShopName(); shopName = data.getShopName();
} }
} }

View File

@@ -31,13 +31,15 @@ import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSubNotifyMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSubNotifyMessage;
import lombok.Getter; import lombok.Getter;
/**
* Triggers when a user creates a subscription.
*/
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokSubscribeEvent extends TikTokHeaderEvent { public class TikTokSubscribeEvent extends TikTokHeaderEvent
{
private final User user; private final User user;
public TikTokSubscribeEvent(WebcastMemberMessage msg) { public TikTokSubscribeEvent(WebcastMemberMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
user = User.map(msg.getUser()); user = User.map(msg.getUser());
@@ -50,12 +52,4 @@ public class TikTokSubscribeEvent extends TikTokHeaderEvent {
user.addAttribute(UserAttribute.Subscriber); user.addAttribute(UserAttribute.Subscriber);
} }
public static TikTokSubscribeEvent of(String userName) {
return new TikTokSubscribeEvent(WebcastMemberMessage.newBuilder()
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
.setDisplayId(userName)
.setNickname(userName)
.build())
.build());
}
} }

View File

@@ -26,6 +26,9 @@ package io.github.jwdeveloper.tiktok.data.events.common;
import io.github.jwdeveloper.tiktok.utils.JsonUtil; import io.github.jwdeveloper.tiktok.utils.JsonUtil;
import lombok.Getter; import lombok.Getter;
/**
* Base class for all events
*/
@Getter @Getter
public abstract class TikTokEvent { public abstract class TikTokEvent {

View File

@@ -1,43 +0,0 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.data.events.control;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
import io.github.jwdeveloper.tiktok.data.requests.*;
import lombok.*;
@Getter
@EventMeta(eventType = EventType.Control)
public class TikTokPreConnectionEvent extends TikTokLiveClientEvent
{
private final LiveUserData.Response userData;
private final LiveData.Response roomData;
@Setter boolean cancelConnection = false;
public TikTokPreConnectionEvent(LiveUserData.Response userData, LiveData.Response liveData) {
this.userData = userData;
this.roomData = liveData;
}
}

View File

@@ -22,28 +22,35 @@
*/ */
package io.github.jwdeveloper.tiktok.data.events.gift; package io.github.jwdeveloper.tiktok.data.events.gift;
import io.github.jwdeveloper.tiktok.annotations.*; import io.github.jwdeveloper.tiktok.annotations.EventMeta;
import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.models.gifts.*; import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
import io.github.jwdeveloper.tiktok.data.models.users.User; import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
import lombok.Getter; import lombok.Getter;
/**
* 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>
* <p>
* Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
*/
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
@Getter @Getter
public class TikTokGiftComboEvent extends TikTokGiftEvent { public class TikTokGiftComboEvent extends TikTokGiftEvent {
private final GiftComboStateType comboState; private final GiftSendType comboState;
public TikTokGiftComboEvent(Gift gift, User host, WebcastGiftMessage msg, GiftComboStateType comboState) { public TikTokGiftComboEvent(Gift gift, User host, WebcastGiftMessage msg, GiftSendType comboState) {
super(gift, host, msg); super(gift, host, msg);
this.comboState = comboState; this.comboState = comboState;
} }
public static TikTokGiftComboEvent of(Gift gift, int combo, GiftComboStateType comboState) {
return new TikTokGiftComboEvent(
gift,
new User(0L, "Test", new Picture("")),
WebcastGiftMessage.newBuilder().setComboCount(combo).build(),
comboState);
}
} }

View File

@@ -22,14 +22,25 @@
*/ */
package io.github.jwdeveloper.tiktok.data.events.gift; package io.github.jwdeveloper.tiktok.data.events.gift;
import io.github.jwdeveloper.tiktok.annotations.*;
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.events.common.TikTokHeaderEvent;
import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.data.models.Picture;
import io.github.jwdeveloper.tiktok.data.models.gifts.*; import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
import io.github.jwdeveloper.tiktok.data.models.users.User; import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
import lombok.Getter; import lombok.Getter;
import java.util.ArrayList;
/**
* Triggered when user sends gifts that has
* no combo (most of expensive gifts)
* or if combo has finished
*/
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
@Getter @Getter
public class TikTokGiftEvent extends TikTokHeaderEvent { public class TikTokGiftEvent extends TikTokHeaderEvent {
@@ -49,20 +60,4 @@ public class TikTokGiftEvent extends TikTokHeaderEvent {
} }
combo = msg.getComboCount(); combo = msg.getComboCount();
} }
public TikTokGiftEvent(Gift gift) {
this.gift = gift;
user = new User(0L, "sender", new Picture(""));
toUser = new User(0L, "receiver", new Picture(""));
combo = 1;
}
public static TikTokGiftEvent of(Gift gift) {
return new TikTokGiftEvent(gift);
}
public static TikTokGiftEvent of(String name, int id, int diamonds) {
return TikTokGiftEvent.of(new Gift(id, name, diamonds, ""));
}
} }

View File

@@ -1,45 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkAcceptNoticeEvent extends TikTokLinkEvent {
private final long fromUserId, fromRoomId, toUserId;
public TikTokLinkAcceptNoticeEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasAcceptNoticeContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Accept Notice Content!");
var content = msg.getAcceptNoticeContent();
this.fromUserId = content.getFromUserId();
this.fromRoomId = content.getFromRoomId();
this.toUserId = content.getToUserId();
}
}

View File

@@ -1,46 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkCancelEvent extends TikTokLinkEvent {
private final long fromUserId, toUserId, cancelType, actionId;
public TikTokLinkCancelEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasCancelContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Cancel Content!");
var content = msg.getCancelContent();
this.fromUserId = content.getFromUserId();
this.toUserId = content.getToUserId();
this.cancelType = content.getCancelType();
this.actionId = content.getActionId();
}
}

View File

@@ -1,39 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkCloseEvent extends TikTokLinkEvent {
public TikTokLinkCloseEvent(WebcastLinkMessage msg) {
super(msg);
// if (!msg.hasCloseContent())
// throw new IllegalArgumentException("Expected WebcastLinkMessage with Close Content!");
// Proto Empty
}
}

View File

@@ -1,39 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkCohostListChangeEvent extends TikTokLinkEvent {
public TikTokLinkCohostListChangeEvent(WebcastLinkMessage msg) {
super(msg);
// if (!msg.hasCohostListChangeContent())
// throw new IllegalArgumentException("Expected WebcastLinkMessage with Cohost List Change Content!");
// Proto Empty
}
}

View File

@@ -1,44 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkCreateEvent extends TikTokLinkEvent {
private final long hostId, roomId, linkType;
public TikTokLinkCreateEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasCreateContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Create Content!");
var content = msg.getCreateContent();
this.hostId = content.getOwnerId();
this.roomId = content.getOwnerRoomId();
this.linkType = content.getLinkType();
}
}

View File

@@ -1,48 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.data.models.users.ListUser;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
import java.util.List;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkEnterEvent extends TikTokLinkEvent {
private final List<ListUser> listUsers;
private final int anchorMultiLiveEnum;
public TikTokLinkEnterEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasEnterContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Enter Content!");
var content = msg.getEnterContent();
this.listUsers = content.getLinkedUsersListList().stream().map(ListUser::map).toList();
this.anchorMultiLiveEnum = content.getAnchorMultiLiveEnum();
}
}

View File

@@ -1,46 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkInviteEvent extends TikTokLinkEvent {
private final long roomId;
private final User inviter;
public TikTokLinkInviteEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasInviteContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Invite Content!");
var content = msg.getInviteContent();
this.roomId = content.getFromRoomId();
this.inviter = User.map(content.getFromUser());
}
}

View File

@@ -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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkKickOutEvent extends TikTokLinkEvent {
private final long fromUserId;
private final KickOutReason kickOutReason;
public TikTokLinkKickOutEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasKickOutContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Kick Out Content!");
var content = msg.getKickOutContent();
this.fromUserId = content.getFromUserId();
this.kickOutReason = KickOutReason.values()[content.getKickoutReasonValue()];
}
public enum KickOutReason {
KICKOUT_REASON_UNKNOWN,
KICKOUT_REASON_FIRST_FRAME_TIMEOUT,
KICKOUT_REASON_BY_HOST,
KICKOUT_REASON_RTC_LOST_CONNECTION,
KICKOUT_REASON_BY_PUNISH,
KICKOUT_REASON_BY_ADMIN,
KICKOUT_REASON_HOST_REMOVE_ALL_GUESTS
}
}

View File

@@ -1,47 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkLeaveEvent extends TikTokLinkEvent {
private final long userId, sendLeaveUid, leaveReason;
private final String linkmicIdStr;
public TikTokLinkLeaveEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasLeaveContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Leave Content!");
var content = msg.getLeaveContent();
this.userId = content.getUserId();
this.linkmicIdStr = content.getLinkmicIdStr();
this.sendLeaveUid = content.getSendLeaveUid();
this.leaveReason = content.getLeaveReason();
}
}

View File

@@ -1,39 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkLinkedListChangeEvent extends TikTokLinkEvent {
public TikTokLinkLinkedListChangeEvent(WebcastLinkMessage msg) {
super(msg);
// if (!msg.hasLinkedListChangeContent())
// throw new IllegalArgumentException("Expected WebcastLinkMessage with Linked List Change Content!");
// Proto Empty
}
}

View File

@@ -1,48 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.data.models.users.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
import java.util.List;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkListChangeEvent extends TikTokLinkEvent {
private final List<ListUser> linkedUsers, appliedUsers, connectingUsers;
public TikTokLinkListChangeEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasListChangeContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with List Change Content!");
var content = msg.getListChangeContent();
this.linkedUsers = content.getLinkedUsersList().stream().map(ListUser::map).toList();
this.appliedUsers = content.getAppliedUsersList().stream().map(ListUser::map).toList();
this.connectingUsers = content.getConnectingUsersList().stream().map(ListUser::map).toList();
}
}

View File

@@ -1,47 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkMediaChangeEvent extends TikTokLinkEvent {
private final long op, toUserId, anchorId, roomId, changeScene;
public TikTokLinkMediaChangeEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasMediaChangeContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Media Change Content!");
var content = msg.getMediaChangeContent();
this.op = content.getOp();
this.toUserId = content.getToUserId();
this.anchorId = content.getAnchorId();
this.roomId = content.getRoomId();
this.changeScene = content.getChangeScene();
}
}

View File

@@ -1,39 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkMicIdxUpdateEvent extends TikTokLinkEvent {
public TikTokLinkMicIdxUpdateEvent(WebcastLinkMessage msg) {
super(msg);
// if (!msg.hasMicIdxUpdateContent())
// throw new IllegalArgumentException("Expected WebcastLinkMessage with Mic Idx Update Content!");
// Proto Empty
}
}

View File

@@ -1,44 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkMuteEvent extends TikTokLinkEvent {
private final long userId, status;
public TikTokLinkMuteEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasMuteContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Mute Content!");
var content = msg.getMuteContent();
this.userId = content.getUserId();
this.status = content.getStatus();
}
}

View File

@@ -1,50 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkRandomMatchEvent extends TikTokLinkEvent {
private final User user;
private final long roomId, inviteType, innerChannelId;
private final String matchId;
public TikTokLinkRandomMatchEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasRandomMatchContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Random Match Content!");
var content = msg.getRandomMatchContent();
this.user = User.map(content.getUser());
this.roomId = content.getRoomId();
this.inviteType = content.getInviteType();
this.matchId = content.getMatchId();
this.innerChannelId = content.getInnerChannelId();
}
}

View File

@@ -1,47 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkReplyEvent extends TikTokLinkEvent {
private final long roomId;
private final User fromUser, toUser;
public TikTokLinkReplyEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasReplyContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Reply Content!");
var content = msg.getReplyContent();
this.roomId = content.getFromRoomId();
this.fromUser = User.map(content.getFromUser());
this.toUser = User.map(content.getToUser());
}
}

View File

@@ -1,45 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkSysKickOutEvent extends TikTokLinkEvent {
private final long userId;
private final String linkmicIdStr;
public TikTokLinkSysKickOutEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasSysKickOutContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Sys Kick Out Content!");
var content = msg.getSysKickOutContent();
this.userId = content.getUserId();
this.linkmicIdStr = content.getLinkmicIdStr();
}
}

View File

@@ -1,44 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkUpdateUserEvent extends TikTokLinkEvent {
private final long fromUserId, toUserId;
public TikTokLinkUpdateUserEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasUpdateUserContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with Update User Content!");
var content = msg.getUpdateUserContent();
this.fromUserId = content.getFromUserId();
this.toUserId = content.getToUserId();
}
}

View File

@@ -1,39 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkUpdateUserSettingEvent extends TikTokLinkEvent {
public TikTokLinkUpdateUserSettingEvent(WebcastLinkMessage msg) {
super(msg);
// if (!msg.hasUpdateUserSettingContent())
// throw new IllegalArgumentException("Expected WebcastLinkMessage with Update User Setting Content!");
// Proto Empty
}
}

View File

@@ -1,47 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.data.models.Text;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkUserToastEvent extends TikTokLinkEvent {
private final long userId, roomId;
private final Text displayText;
public TikTokLinkUserToastEvent(WebcastLinkMessage msg) {
super(msg);
if (!msg.hasUserToastContent())
throw new IllegalArgumentException("Expected WebcastLinkMessage with User Toast Content!");
var content = msg.getUserToastContent();
this.userId = content.getUserId();
this.roomId = content.getRoomId();
this.displayText = Text.map(content.getDisplayText());
}
}

View File

@@ -1,39 +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.link;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkWaitListChangeEvent extends TikTokLinkEvent {
public TikTokLinkWaitListChangeEvent(WebcastLinkMessage msg) {
super(msg);
// if (!msg.hasWaitingListChangeContent())
// throw new IllegalArgumentException("Expected WebcastLinkMessage with Waiting List Change Content!");
// Proto Empty
}
}

View File

@@ -30,7 +30,9 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/*
Triggered when LiveRoomInfo got updated such as likes, viewers, ranking ....
*/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)

View File

@@ -33,8 +33,9 @@ import lombok.Getter;
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokRoomPinEvent extends TikTokHeaderEvent public class TikTokRoomPinEvent extends TikTokHeaderEvent
{ {
private final TikTokCommentEvent pinnedMessage;
private final long timestamp; private TikTokCommentEvent pinnedMessage;
private long timestamp;
public TikTokRoomPinEvent(WebcastRoomPinMessage msg, TikTokCommentEvent commentEvent) public TikTokRoomPinEvent(WebcastRoomPinMessage msg, TikTokCommentEvent commentEvent)
{ {
@@ -42,4 +43,5 @@ public class TikTokRoomPinEvent extends TikTokHeaderEvent
this.timestamp = msg.getTimestamp(); this.timestamp = msg.getTimestamp();
this.pinnedMessage = commentEvent; this.pinnedMessage = commentEvent;
} }
} }

View File

@@ -29,10 +29,13 @@ import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage;
import lombok.Value; import lombok.Value;
/**
* Triggers when a user follows the streamer. Based on social event.
*/
@Value @Value
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokFollowEvent extends TikTokHeaderEvent { public class TikTokFollowEvent extends TikTokHeaderEvent
{
User user; User user;
int totalFollowers; int totalFollowers;
@@ -42,12 +45,4 @@ public class TikTokFollowEvent extends TikTokHeaderEvent {
totalFollowers = msg.getFollowCount(); totalFollowers = msg.getFollowCount();
} }
public static TikTokFollowEvent of(String userName) {
return new TikTokFollowEvent(WebcastSocialMessage.newBuilder()
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
.setDisplayId(userName)
.setNickname(userName)
.build())
.build());
}
} }

View File

@@ -26,7 +26,6 @@ import io.github.jwdeveloper.tiktok.annotations.EventMeta;
import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
import io.github.jwdeveloper.tiktok.data.models.users.User; import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage;
import lombok.Getter; import lombok.Getter;
@@ -48,14 +47,4 @@ public class TikTokJoinEvent extends TikTokHeaderEvent {
user = User.map(msg.getUser()); user = User.map(msg.getUser());
totalUsers = msg.getMemberCount(); totalUsers = msg.getMemberCount();
} }
public static TikTokJoinEvent of(String userName)
{
return new TikTokJoinEvent(WebcastMemberMessage.newBuilder()
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
.setDisplayId(userName)
.setNickname(userName)
.build())
.build());
}
} }

View File

@@ -31,7 +31,9 @@ import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage;
import lombok.Getter; import lombok.Getter;
/**
* Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
*/
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokLikeEvent extends TikTokHeaderEvent public class TikTokLikeEvent extends TikTokHeaderEvent
@@ -55,16 +57,4 @@ public class TikTokLikeEvent extends TikTokHeaderEvent
likes = msg.getCount(); likes = msg.getCount();
totalLikes = msg.getTotal(); totalLikes = msg.getTotal();
} }
public static TikTokLikeEvent of(String userName, int likes)
{
return new TikTokLikeEvent(WebcastLikeMessage.newBuilder()
.setCount(likes)
.setTotal(likes)
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
.setDisplayId(userName)
.setNickname(userName)
.build())
.build());
}
} }

View File

@@ -26,11 +26,12 @@ import io.github.jwdeveloper.tiktok.annotations.EventMeta;
import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.annotations.EventType;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
import io.github.jwdeveloper.tiktok.data.models.users.User; import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage;
import lombok.Getter; import lombok.Getter;
/**
* Triggers when a user shares the stream. Based on social event.
*/
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokShareEvent extends TikTokHeaderEvent { public class TikTokShareEvent extends TikTokHeaderEvent {
@@ -49,12 +50,4 @@ public class TikTokShareEvent extends TikTokHeaderEvent {
totalShares = 1; totalShares = 1;
} }
public static TikTokShareEvent of(String userName, int shaders) {
return new TikTokShareEvent(WebcastSocialMessage.newBuilder()
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
.setDisplayId(userName)
.setNickname(userName)
.build())
.build(), shaders);
}
} }

View File

@@ -35,7 +35,10 @@ import lombok.Value;
import java.time.Duration; import java.time.Duration;
/**
* Triggered every time TikTok sends data. Data incoming as protobuf message.
* You can deserialize the binary object depending on the use case.
*/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
@EventMeta(eventType = EventType.Debug) @EventMeta(eventType = EventType.Debug)

View File

@@ -29,7 +29,9 @@ import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import lombok.Getter; import lombok.Getter;
/**
* Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
*/
@Getter @Getter
@EventMeta(eventType = EventType.Debug) @EventMeta(eventType = EventType.Debug)
public class TikTokWebsocketUnhandledMessageEvent extends TikTokUnhandledEvent<WebcastResponse.Message> public class TikTokWebsocketUnhandledMessageEvent extends TikTokUnhandledEvent<WebcastResponse.Message>

View File

@@ -20,11 +20,18 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
package io.github.jwdeveloper.tiktok.exceptions; package io.github.jwdeveloper.tiktok.data.models;
public class TikTokLiveUnknownHostException extends TikTokLiveException import lombok.Value;
@Value
public class EnumValue
{ {
public TikTokLiveUnknownHostException(String message) { public int value;
super(message); public String name;
public static EnumValue Map(Enum<?> _enum)
{
return new EnumValue(_enum.ordinal() ,_enum.name());
} }
} }

View File

@@ -20,17 +20,22 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
package io.github.jwdeveloper.tiktok.data.events.link; package io.github.jwdeveloper.tiktok.data.models;
import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Getter import io.github.jwdeveloper.tiktok.data.models.users.User;
@EventMeta(eventType = EventType.Message) import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicBattle;
public class TikTokLinkApplyEvent extends TikTokLinkEvent { import lombok.Value;
public TikTokLinkApplyEvent(WebcastLinkMessage msg) { import java.util.List;
super(msg);
@Value
public class LinkMicBattleTeam {
Long teamId;
List<User> users;
public LinkMicBattleTeam(WebcastLinkMicBattle.LinkMicBattleTeam team) {
this.teamId = team.getId();
this.users = team.getUsersList().stream().map(User::new).toList();
} }
} }

View File

@@ -44,11 +44,11 @@ public class Picture {
} }
public static Picture map(io.github.jwdeveloper.tiktok.messages.data.Image profilePicture) { public static Picture map(io.github.jwdeveloper.tiktok.messages.data.Image profilePicture) {
var index = profilePicture.getUrlCount() - 1; var index = profilePicture.getUrlListCount() - 1;
if (index < 0) { if (index < 0) {
return new Picture(""); return new Picture("");
} }
var url = profilePicture.getUrl(index); var url = profilePicture.getUrlList(index);
return new Picture(url); return new Picture(url);
} }
@@ -93,7 +93,7 @@ public class Picture {
} }
} }
public static Picture empty() { public static Picture Empty() {
return new Picture(""); return new Picture("");
} }

View File

@@ -1,74 +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.models.battles;
import lombok.Getter;
public abstract class Team {
/** Value >= 0 when finished otherwise -1 */
@Getter protected int totalPoints;
/**
* Provides a check for verifying if this team represents a 1v1 Team.
* @return true if this team is of type {@link Team1v1}, false otherwise.
*/
public boolean is1v1Team() {
return this instanceof Team1v1;
}
/**
* Provides a check for verifying if this team represents a 1v1 Team.
* @return true if this team is of type {@link Team1v1}, false otherwise.
*/
public boolean is2v2Team() {
return this instanceof Team2v2;
}
/**
* Convenience method to get this team as a {@link Team1v1}. If this team is of some
* other type, an {@link IllegalStateException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #is1v1Team()} first.
*
* @return this team as a {@link Team1v1}.
* @throws IllegalStateException if this team is of another type.
*/
public Team1v1 getAs1v1Team() {
if (is1v1Team())
return (Team1v1) this;
throw new IllegalStateException("Not a 1v1Team: " + this);
}
/**
* Convenience method to get this team as a {@link Team2v2}. If this team is of some
* other type, an {@link IllegalStateException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #is2v2Team()} first.
*
* @return this team as a {@link Team2v2}.
* @throws IllegalStateException if this team is of another type.
*/
public Team2v2 getAs2v2Team() {
if (is2v2Team())
return (Team2v2) this;
throw new IllegalStateException("Not a 2v2Team: " + this);
}
}

View File

@@ -1,45 +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.models.battles;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicBattle;
import lombok.Getter;
import java.util.*;
@Getter
public class Team1v1 extends Team {
private final int winStreak;
private final User host;
private final List<Viewer> viewers;
public Team1v1(WebcastLinkMicBattle.LinkMicBattleHost hostTeam, WebcastLinkMicBattle msg) {
long hostId = hostTeam.getId();
this.winStreak = msg.getTeamDataList().stream().filter(data -> data.getTeamId() == hostId).map(data -> data.getData().getWinStreak()).findFirst().orElse(-1);
this.totalPoints = msg.getDetailsList().stream().filter(dets -> dets.getId() == hostId).map(dets -> dets.getSummary().getPoints()).findFirst().orElse(-1);
this.host = new User(hostTeam.getHostGroup(0).getHost(0));
this.viewers = msg.getViewerTeamList().stream().filter(team -> team.getId() == hostId).findFirst().map(topViewers ->
topViewers.getViewerGroup(0).getViewerList().stream().map(Viewer::new).toList()).orElseGet(ArrayList::new);
}
}

View File

@@ -1,50 +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.models.battles;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicBattle;
import lombok.Getter;
import java.util.*;
@Getter
public class Team2v2 extends Team {
private final List<User> hosts;
private final List<Viewer> viewers;
public Team2v2(WebcastLinkMicBattle.LinkMicBattleHost hostTeam1, WebcastLinkMicBattle.LinkMicBattleHost hostTeam2, WebcastLinkMicBattle msg) {
this.totalPoints = -1;
this.hosts = List.of(new User(hostTeam1.getHostGroup(0).getHost(0)), new User(hostTeam2.getHostGroup(0).getHost(0)));
this.viewers = new ArrayList<>();
}
public Team2v2(WebcastLinkMicBattle.Host2v2Data hd, WebcastLinkMicBattle msg) {
this.totalPoints = hd.getTotalPoints();
var host = new User(msg.getHostTeamList().stream().filter(data -> data.getId() == hd.getHostdata(0).getHostId()).findFirst().orElseThrow().getHostGroup(0).getHost(0));
var cohost = new User(msg.getHostTeamList().stream().filter(data -> data.getId() == hd.getHostdata(1).getHostId()).findFirst().orElseThrow().getHostGroup(0).getHost(0));
this.hosts = List.of(host, cohost);
this.viewers = msg.getViewerTeamList().stream().filter(team -> team.getId() == host.getId() || team.getId() == cohost.getId()).findFirst().map(topViewers ->
topViewers.getViewerGroup(0).getViewerList().stream().map(Viewer::new).toList()).orElseGet(ArrayList::new);
}
}

View File

@@ -22,15 +22,19 @@
*/ */
package io.github.jwdeveloper.tiktok.data.models.gifts; package io.github.jwdeveloper.tiktok.data.models.gifts;
public enum GiftComboStateType { public enum GiftSendType
{
Finished,
Begin, Begin,
Active, Active;
Finished;
public static GiftComboStateType fromNumber(long number) {
public static GiftSendType fromNumber(long number)
{
return switch ((int) number) { return switch ((int) number) {
case 1, 2, 4 -> GiftComboStateType.Active; case 0 -> GiftSendType.Finished;
default -> GiftComboStateType.Finished; case 1, 2, 4 -> GiftSendType.Active;
default -> GiftSendType.Finished;
}; };
} }
} }

View File

@@ -1,71 +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.models.users;
import lombok.Getter;
@Getter
public class ListUser
{
private final User user;
private final LinkType linkType;
private final long linkMicId, linkStatus, modifyTime, linkerId;
private final int userPosition, silenceStatus, roleType;
public ListUser(io.github.jwdeveloper.tiktok.messages.data.ListUser listUser) {
this.user = User.map(listUser.getUser());
this.linkMicId = listUser.getLinkmicId();
this.linkStatus = listUser.getLinkStatus();
this.linkType = LinkType.values()[listUser.getLinkTypeValue()];
this.userPosition = listUser.getUserPosition();
this.silenceStatus = listUser.getSilenceStatus();
this.modifyTime = listUser.getModifyTime();
this.linkerId = listUser.getLinkerId();
this.roleType = listUser.getRoleType();
}
public static ListUser map(io.github.jwdeveloper.tiktok.messages.data.ListUser listUser) {
return new ListUser(listUser);
}
public enum LinkType {
UNKNOWN,
AUDIO,
VIDEO
}
@Override
public String toString() {
return "ListUser{" +
"user=" + user +
", linkType=" + linkType +
", linkMicId=" + linkMicId +
", linkStatus=" + linkStatus +
", modifyTime=" + modifyTime +
", linkerId=" + linkerId +
", userPosition=" + userPosition +
", silenceStatus=" + silenceStatus +
", roleType=" + roleType +
"}";
}
}

View File

@@ -22,12 +22,16 @@
*/ */
package io.github.jwdeveloper.tiktok.data.models.users; package io.github.jwdeveloper.tiktok.data.models.users;
import io.github.jwdeveloper.tiktok.data.models.Picture;
import io.github.jwdeveloper.tiktok.data.models.badges.Badge; import io.github.jwdeveloper.tiktok.data.models.badges.Badge;
import io.github.jwdeveloper.tiktok.messages.webcast.*; import io.github.jwdeveloper.tiktok.data.models.Picture;
import lombok.*; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastEnvelopeMessage;
import lombok.AccessLevel;
import lombok.Getter;
import java.util.*; import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Getter @Getter
public class User { public class User {
@@ -45,12 +49,12 @@ public class User {
return attributes.stream().toList(); return attributes.stream().toList();
} }
public boolean hasAttribute(UserAttribute attribute) { public boolean hasAttribute(UserAttribute userFlag) {
return attributes.contains(attribute); return attributes.contains(userFlag);
} }
public void addAttribute(UserAttribute... attributes) { public void addAttribute(UserAttribute... flags) {
this.attributes.addAll(List.of(attributes)); this.attributes.addAll(Arrays.stream(flags).toList());
} }
public boolean isGiftGiver() { public boolean isGiftGiver() {
@@ -132,14 +136,6 @@ public class User {
this.picture = picture; this.picture = picture;
} }
public User(long id, String name, String profileId, Picture picture) {
this(id, name, profileId, picture, 0, 0, List.of(Badge.empty()));
}
public User(WebcastLinkMicBattle.LinkMicBattleHost.HostGroup.Host host) {
this(host.getId(), host.getName(), host.getProfileId(), Picture.map(host.getImages(0)));
}
public User(io.github.jwdeveloper.tiktok.messages.data.User user) { public User(io.github.jwdeveloper.tiktok.messages.data.User user) {
this(user.getId(), user.getDisplayId(), Picture.map(user.getAvatarThumb())); this(user.getId(), user.getDisplayId(), Picture.map(user.getAvatarThumb()));
profileName = user.getNickname(); profileName = user.getNickname();
@@ -163,9 +159,10 @@ public class User {
} }
} }
public static User EMPTY = new User(0L, public static User EMPTY = new User(0L,
"", "",
Picture.empty(), Picture.Empty(),
0, 0,
0, 0,
List.of(Badge.empty())); List.of(Badge.empty()));
@@ -212,18 +209,4 @@ public class User {
0, 0,
List.of(Badge.empty())); List.of(Badge.empty()));
} }
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + "'" +
", profileName='" + profileName + "'" +
", picture=" + picture +
", following=" + following +
", followers=" + followers +
", badges=" + badges +
", attributes=" + attributes +
"}";
}
} }

View File

@@ -23,17 +23,35 @@
package io.github.jwdeveloper.tiktok.data.requests; package io.github.jwdeveloper.tiktok.data.requests;
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
import lombok.*; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import java.util.List; import java.util.List;
public class GiftsData public class GiftsData
{ {
@Getter
public final class Request
{
}
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public static final class Response public static final class Response
{ {
private String json; private String json;
private List<Gift> gifts; private List<GiftModel> gifts;
} }
@Data
public static class GiftModel
{
private int id;
private String name;
private int diamondCost;
private String image;
}
} }

View File

@@ -35,7 +35,6 @@ public class LiveData {
} }
@Data @Data
@AllArgsConstructor
public static class Response { public static class Response {
private String json; private String json;
private LiveStatus liveStatus; private LiveStatus liveStatus;
@@ -45,12 +44,6 @@ public class LiveData {
private int totalViewers; private int totalViewers;
private boolean ageRestricted; private boolean ageRestricted;
private User host; private User host;
private LiveType liveType;
public Response() {
}
} }
public enum LiveStatus { public enum LiveStatus {
@@ -58,11 +51,4 @@ public class LiveData {
HostOnline, HostOnline,
HostOffline, HostOffline,
} }
public enum LiveType {
SOLO,
BOX,
BATTLE,
CO_HOST
}
} }

View File

@@ -22,36 +22,31 @@
*/ */
package io.github.jwdeveloper.tiktok.data.requests; package io.github.jwdeveloper.tiktok.data.requests;
import lombok.*; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
public class LiveUserData { public class LiveUserData {
@Getter @Getter
@AllArgsConstructor
public static class Request { public static class Request {
private final String userName; private String userName;
public Request(String userName) {
if (userName == null || userName.isBlank())
throw new IllegalArgumentException("Invalid empty username!");
this.userName = userName;
}
} }
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public static class Response { public static class Response {
private final String json;
private final UserStatus userStatus;
private final String roomId;
private final long startTime;
public boolean isLiveOnline() { private String json;
return userStatus == LiveUserData.UserStatus.Live || userStatus == LiveUserData.UserStatus.LivePaused;
}
public boolean isHostNameValid() { private UserStatus userStatus;
return userStatus != LiveUserData.UserStatus.NotFound;
} private String roomId;
private long startedAtTimeStamp;
} }
public enum UserStatus { public enum UserStatus {
@@ -61,3 +56,5 @@ public class LiveUserData {
Live, Live,
} }
} }

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.data.requests;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class SignServerResponse
{
private String signedUrl;
private String userAgent;
}

View File

@@ -34,24 +34,29 @@ import java.util.TreeMap;
import java.util.function.Consumer; import java.util.function.Consumer;
@Getter
public class HttpClientSettings { public class HttpClientSettings {
private final Map<String, Object> params; @Getter
final Map<String, Object> params;
private final Map<String, String> headers; @Getter
final Map<String, String> headers;
private final Map<String, String> cookies; @Getter
final Map<String, String> cookies;
@Getter
ProxyClientSettings proxyClientSettings;
@Getter
Consumer<HttpClient.Builder> onClientCreating;
@Getter
Consumer<HttpRequest.Builder> onRequestCreating;
@Setter @Setter
private ProxyClientSettings proxyClientSettings; @Getter
Duration timeout;
private Consumer<HttpClient.Builder> onClientCreating;
private Consumer<HttpRequest.Builder> onRequestCreating;
@Setter
private Duration timeout;
public HttpClientSettings() { public HttpClientSettings() {
this.params = new TreeMap<>(); this.params = new TreeMap<>();
@@ -59,15 +64,17 @@ public class HttpClientSettings {
this.cookies = new HashMap<>(); this.cookies = new HashMap<>();
this.timeout = Duration.ofSeconds(2); this.timeout = Duration.ofSeconds(2);
this.proxyClientSettings = new ProxyClientSettings(); this.proxyClientSettings = new ProxyClientSettings();
this.onClientCreating = (x) -> {}; this.onClientCreating = (x) -> {
this.onRequestCreating = (x) -> {}; };
this.onRequestCreating = (x) -> {
};
} }
/** /**
* @param consumer Use to configure proxy settings for http client * @param consumer Use to configure proxy settings for http client
*/ */
public void configureProxy(Consumer<ProxyClientSettings> consumer) { public void configureProxy(Consumer<ProxyClientSettings> consumer) {
proxyClientSettings.setEnabled(true); proxyClientSettings.setUseProxy(true);
consumer.accept(proxyClientSettings); consumer.accept(proxyClientSettings);
} }
@@ -97,7 +104,7 @@ public class HttpClientSettings {
newSettings.getHeaders().putAll(new TreeMap<>(this.headers)); newSettings.getHeaders().putAll(new TreeMap<>(this.headers));
newSettings.getCookies().putAll(new TreeMap<>(this.cookies)); newSettings.getCookies().putAll(new TreeMap<>(this.cookies));
newSettings.getParams().putAll(new TreeMap<>(this.params)); newSettings.getParams().putAll(new TreeMap<>(this.params));
newSettings.setProxyClientSettings(this.proxyClientSettings); newSettings.proxyClientSettings = this.proxyClientSettings.clone();
return newSettings; return newSettings;
} }

View File

@@ -33,21 +33,10 @@ import java.util.logging.Level;
@Data @Data
public class LiveClientSettings { public class LiveClientSettings {
/**
* Sets client to offline mode, prohibits connection to TikTok servers
* @apiNote Useful when testing client with custom events
*/
private boolean offline;
/**
* Fetch and download gifts data before TikTokLive starts
* @apiNote If `false`, client.giftManager() does not contain initial gifts
*/
private boolean fetchGifts = true;
/** /**
* ISO-Language for Client * ISO-Language for Client
*/ */
private String clientLanguage; private String clientLanguage;
/** /**
@@ -55,6 +44,7 @@ public class LiveClientSettings {
*/ */
private boolean retryOnConnectionFailure; private boolean retryOnConnectionFailure;
/** /**
* Before retrying connect, wait for select amount of time * Before retrying connect, wait for select amount of time
*/ */
@@ -63,49 +53,44 @@ public class LiveClientSettings {
/** /**
* Whether to print Logs to Console * Whether to print Logs to Console
*/ */
private boolean printToConsole = true;
private boolean printToConsole = true;
/** /**
* LoggingLevel for Logs * LoggingLevel for Logs
*/ */
private Level logLevel; private Level logLevel;
/** /**
* Optional: Use it if you need to change TikTok live hostname in builder * Optional: Use it if you need to change TikTok live hostname in builder
*/ */
private String hostName; private String hostName;
/** /**
* Parameters used in requests to TikTok api * Parameters used in requests to TikTok api
*/ */
private HttpClientSettings httpSettings; private HttpClientSettings httpSettings;
/**
* Interval of time in milliseconds between pings to TikTok
* @apiNote Min: 250 (0.25 seconds), Default: 5000 (5 seconds)
*/
private long pingInterval = 5000;
/** Throw an exception on 18+ Age Restriction */ /*
private boolean throwOnAgeRestriction;
/**
* Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId * Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
* @see <a href="https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages">Documentation: How to obtain sessionId</a> * documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages
*/ */
private String sessionId; private String sessionId;
/** /*
* Optional: By default roomID is fetched before connect to live, but you can set it manually * Optional: By default roomID is fetched before connect to live, but you can set it manually
*
*/ */
private String roomId; private String roomId;
/**
* Optional: API Key for increased limit to signing server
*/
private String apiKey;
public static LiveClientSettings createDefault() {
public static LiveClientSettings createDefault()
{
var httpSettings = new HttpClientSettings(); var httpSettings = new HttpClientSettings();
httpSettings.getParams().putAll(DefaultClientParams()); httpSettings.getParams().putAll(DefaultClientParams());
httpSettings.getHeaders().putAll(DefaultRequestHeaders()); httpSettings.getHeaders().putAll(DefaultRequestHeaders());
@@ -118,10 +103,12 @@ public class LiveClientSettings {
clientSettings.setPrintToConsole(false); clientSettings.setPrintToConsole(false);
clientSettings.setLogLevel(Level.ALL); clientSettings.setLogLevel(Level.ALL);
clientSettings.setHttpSettings(httpSettings); clientSettings.setHttpSettings(httpSettings);
return clientSettings; return clientSettings;
} }
/** /**
* Default Parameters for HTTP-Request * Default Parameters for HTTP-Request
*/ */
@@ -160,9 +147,11 @@ public class LiveClientSettings {
clientParams.put("webcast_sdk_version", "1.3.0"); clientParams.put("webcast_sdk_version", "1.3.0");
clientParams.put("update_version_code", "1.3.0"); clientParams.put("update_version_code", "1.3.0");
return clientParams; return clientParams;
} }
/** /**
* Default Headers for HTTP-Request * Default Headers for HTTP-Request
*/ */
@@ -178,4 +167,6 @@ public class LiveClientSettings {
headers.put("Accept-Language", "en-US,en; q=0.9"); headers.put("Accept-Language", "en-US,en; q=0.9");
return headers; return headers;
} }
} }

View File

@@ -22,115 +22,19 @@
*/ */
package io.github.jwdeveloper.tiktok.data.settings; package io.github.jwdeveloper.tiktok.data.settings;
import io.github.jwdeveloper.tiktok.data.dto.ProxyData; import lombok.Getter;
import lombok.*; import lombok.Setter;
import java.net.*;
import java.util.*;
import java.util.function.Consumer;
//TODO proxy implementation
@Getter @Getter
@Setter public class ProxyClientSettings
public class ProxyClientSettings implements Iterator<ProxyData>, Iterable<ProxyData>
{ {
private boolean enabled, autoDiscard = true, fallback = true; @Setter
private Rotation rotation = Rotation.CONSECUTIVE; private boolean useProxy;
private final List<ProxyData> proxyList = new ArrayList<>();
private int index;
private Proxy.Type type = Proxy.Type.DIRECT;
private Consumer<ProxyData> onProxyUpdated = x -> {};
public boolean addProxy(String addressPort) {
return addProxy(ProxyData.map(addressPort).toSocketAddress());
}
public boolean addProxy(String address, int port) { public ProxyClientSettings clone()
return addProxy(new InetSocketAddress(address, port));
}
public boolean addProxy(InetSocketAddress inetAddress) {
return proxyList.add(new ProxyData(inetAddress.getHostString(), inetAddress.getPort()));
}
public void addProxies(List<String> list) {
list.forEach(this::addProxy);
}
@Override
public synchronized boolean hasNext() {
return !proxyList.isEmpty();
}
@Override
public synchronized ProxyData next() {
try {
var nextProxy = proxyList.get(index);
onProxyUpdated.accept(nextProxy);
return nextProxy;
} finally {
switch (rotation) {
case CONSECUTIVE -> index = ++index % proxyList.size();
case RANDOM -> index = (int) (Math.random() * proxyList.size());
case NONE -> index = Math.max(index, 0);
}
}
}
@Override
public synchronized void remove() {
proxyList.remove(index);
}
public void setIndex(int index) {
if (index == 0 && proxyList.isEmpty())
this.index = 0;
else {
if (index < 0 || index >= proxyList.size())
throw new IndexOutOfBoundsException("Index " + index + " exceeds list of size: " + proxyList.size());
this.index = index;
}
}
@Override
public ProxyClientSettings clone() {
ProxyClientSettings settings = new ProxyClientSettings();
settings.setEnabled(enabled);
settings.setRotation(rotation);
settings.setIndex(index);
settings.setType(type);
settings.setOnProxyUpdated(onProxyUpdated);
proxyList.forEach(proxyData -> settings.addProxy(proxyData.getAddress(), proxyData.getPort()));
return settings;
}
@Override
public String toString() {
return "ProxyClientSettings{" +
"enabled=" + enabled +
", autoDiscard=" + autoDiscard +
", fallback=" + fallback +
", rotation=" + rotation +
", proxyList=" + proxyList +
", index=" + index +
", type=" + type +
'}';
}
/**
* With {@code Iterable<ProxyData>} interface, you can use this object inside for loop!
*/
@Override
public Iterator<ProxyData> iterator() {
return this;
}
public enum Rotation
{ {
/** Rotate addresses consecutively, from proxy 0 -> 1 -> 2 -> ...etc. */ return new ProxyClientSettings();
CONSECUTIVE,
/** Rotate addresses randomly, from proxy 0 -> 69 -> 420 -> 1 -> ...etc. */
RANDOM,
/** Don't rotate addresses at all, pin to the indexed address. */
NONE
} }
} }

View File

@@ -23,7 +23,7 @@
package io.github.jwdeveloper.tiktok.exceptions; package io.github.jwdeveloper.tiktok.exceptions;
/** /*
* Happens while bad response from Http request to TikTok * Happens while bad response from Http request to TikTok
*/ */
public class TikTokLiveRequestException extends TikTokLiveException public class TikTokLiveRequestException extends TikTokLiveException

View File

@@ -0,0 +1,34 @@
/*
* 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.handler;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import java.util.List;
public interface TikTokMessageHandler
{
List<TikTokEvent> handle(byte[] messagePayload) throws Exception;
}

View File

@@ -27,46 +27,38 @@ import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
import io.github.jwdeveloper.tiktok.data.requests.LiveData; import io.github.jwdeveloper.tiktok.data.requests.LiveData;
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData; import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
public interface LiveHttpClient public interface LiveHttpClient {
{
/** /**
* @return {@link GiftsData.Response} list of gifts that are compiled and available on github * @return list of gifts that are available in your country
*/ */
GiftsData.Response fetchGiftsData(); GiftsData.Response fetchGiftsData();
/**
* @return {@link GiftsData.Response} list of gifts that are available in your region / livestream
*/
GiftsData.Response fetchRoomGiftsData(String room_id);
/** /**
* Returns information about user that is having a livestream * Returns information about user that is having a livestream
* @param userName name of user *
* @return {@link LiveUserData.Response} * @param userName
* @return
*/ */
default LiveUserData.Response fetchLiveUserData(String userName) { LiveUserData.Response fetchLiveUserData(String userName);
return fetchLiveUserData(new LiveUserData.Request(userName));
}
LiveUserData.Response fetchLiveUserData(LiveUserData.Request request); LiveUserData.Response fetchLiveUserData(LiveUserData.Request request);
/** /**
* @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData * @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData
* @return {@link LiveData.Response} * @return
*/ */
default LiveData.Response fetchLiveData(String roomId) { LiveData.Response fetchLiveData(String roomId);
return fetchLiveData(new LiveData.Request(roomId));
}
LiveData.Response fetchLiveData(LiveData.Request request); LiveData.Response fetchLiveData(LiveData.Request request);
/** /**
* @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData * @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData
* @return {@link LiveConnectionData.Response} * @return
*/ */
default LiveConnectionData.Response fetchLiveConnectionData(String roomId) { LiveConnectionData.Response fetchLiveConnectionData(String roomId);
return fetchLiveConnectionData(new LiveConnectionData.Request(roomId));
}
LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request); LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request);
} }

View File

@@ -25,13 +25,15 @@ package io.github.jwdeveloper.tiktok.listener;
import java.util.List; import java.util.List;
/** /**
* Manage events listeners objects * You can dynamically add or removing TikTokEventListener
*
* @see TikTokEventListener
*
*/ */
public interface ListenersManager public interface ListenersManager
{ {
List<Object> getListeners(); List<TikTokEventListener> getListeners();
void addListener(TikTokEventListener listener);
void addListener(Object listener); void removeListener(TikTokEventListener listener);
void removeListener(Object listener);
} }

View File

@@ -22,54 +22,53 @@
*/ */
package io.github.jwdeveloper.tiktok.listener; package io.github.jwdeveloper.tiktok.listener;
import io.github.jwdeveloper.tiktok.live.LiveClient;
/** /**
* ListenersManager *
* <p> * @see ListenersManager
*
* TikTokEventListener is an alternative way of handing TikTok events. * TikTokEventListener is an alternative way of handing TikTok events.
* <p> *
* {@code TikTokLive.newClient("someuser").addListener(listener);} * TikTokLive.newClient("someuser").addListener(listener)
* <p> *
* After registertion, all listeners are kept in Listener manager - {@link LiveClient#getListenersManager()} * After registertion all listeners are kept in Listener manager
* <p> * that could be obtained by client.getListenerManager();
* Method in TikTokEventListener should meet requirements below to be detected *
* <p>- @TikTokEventObserver annotation * Method in TikTokEventListener should meet 4 requirements to be detected
* <p>- 2 parameters of (LiveClient, Class extending TikTokEvent) * - must have @TikTokEventHandler annotation
* <pre> * - must have 2 parameters
* {@code * - first parameter must be LiveClient
* - second must be class that extending TikTokEvent
*
* public static class CustomListener implements TikTokEventListener * public static class CustomListener implements TikTokEventListener
* { * {
* @TikTokEventObserver * @TikTokEventHandler
* public void onError(LiveClient liveClient, TikTokErrorEvent event) * public void onError(LiveClient liveClient, TikTokErrorEvent event)
* { * {
* System.out.println(event.getException().getMessage()); * System.out.println(event.getException().getMessage());
* } * }
* *
* @TikTokEventObserver * @TikTokEventHandler
* public void onCommentMessage(LiveClient liveClient, TikTokCommentEvent event) * public void onCommentMessage(LiveClient liveClient, TikTokCommentEvent event)
* { * {
* System.out.println(event.getText()); * System.out.println(event.getText());
* } * }
* *
* @TikTokEventObserver * @TikTokEventHandler
* public void onGiftMessage(LiveClient liveClient, TikTokGiftMessageEvent event) * public void onGiftMessage(LiveClient liveClient, TikTokGiftMessageEvent event)
* { * {
* System.out.println(event.getGift().getDescription()); * System.out.println(event.getGift().getDescription());
* } * }
* *
* @TikTokEventObserver * @TikTokEventHandler
* public void onAnyEvent(LiveClient liveClient, TikTokEvent event) * public void onAnyEvent(LiveClient liveClient, TikTokEvent event)
* { * {
* System.out.println(event.getClass().getSimpleName()); * System.out.println(event.getClass().getSimpleName());
* } * }
* } * }
* } *
* </pre>
*/ */
//TODO I think this interface can be removed, since we are using, public interface TikTokEventListener
//annotation @TikTokEventHandler to check methods that are events {
@Deprecated(forRemoval = true, since = "1.8.1 (This interface is not longer needed, please remove it from your class)")
public interface TikTokEventListener {
} }

View File

@@ -1,156 +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.listener;
import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.events.control.TikTokPreConnectionEvent;
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
import io.github.jwdeveloper.tiktok.data.events.gift.*;
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
import io.github.jwdeveloper.tiktok.data.events.link.*;
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
import io.github.jwdeveloper.tiktok.data.events.room.*;
import io.github.jwdeveloper.tiktok.data.events.social.*;
import io.github.jwdeveloper.tiktok.data.events.websocket.*;
import io.github.jwdeveloper.tiktok.live.LiveClient;
public abstract class TikTokEventListenerBase implements TikTokEventListener
{
public void onUnhandledSocial(LiveClient client, TikTokUnhandledSocialEvent event) {}
public void onChest(LiveClient client, TikTokChestEvent event) {}
public void onLinkMicFanTicket(LiveClient client, TikTokLinkMicFanTicketEvent event) {}
public void onEnvelope(LiveClient client, TikTokEnvelopeEvent event) {}
public void onShop(LiveClient client, TikTokShopEvent event) {}
public void onDetect(LiveClient client, TikTokDetectEvent event) {}
public void onLinkLayer(LiveClient client, TikTokLinkLayerEvent event) {}
public void onConnected(LiveClient client, TikTokConnectedEvent event) {}
public void onPreConnection(LiveClient client, TikTokPreConnectionEvent event) {}
public void onCaption(LiveClient client, TikTokCaptionEvent event) {}
public void onQuestion(LiveClient client, TikTokQuestionEvent event) {}
public void onRoomPin(LiveClient client, TikTokRoomPinEvent event) {}
public void onRoomInfo(LiveClient client, TikTokRoomInfoEvent event) {}
public void onLivePaused(LiveClient client, TikTokLivePausedEvent event) {}
public void onLiveUnpaused(LiveClient client, TikTokLiveUnpausedEvent event) {}
public void onLike(LiveClient client, TikTokLikeEvent event) {}
public void onLink(LiveClient client, TikTokLinkEvent event) {}
public void onLinkInvite(LiveClient client, TikTokLinkInviteEvent event) {}
public void onLinkReply(LiveClient client, TikTokLinkReplyEvent event) {}
public void onLinkCreate(LiveClient client, TikTokLinkCreateEvent event) {}
public void onLinkClose(LiveClient client, TikTokLinkCloseEvent event) {}
public void onLinkEnter(LiveClient client, TikTokLinkEnterEvent event) {}
public void onLinkLeave(LiveClient client, TikTokLinkLeaveEvent event) {}
public void onLinkCancel(LiveClient client, TikTokLinkCancelEvent event) {}
public void onLinkKickOut(LiveClient client, TikTokLinkKickOutEvent event) {}
public void onLinkLinkedListChange(LiveClient client, TikTokLinkLinkedListChangeEvent event) {}
public void onLinkUpdateUser(LiveClient client, TikTokLinkUpdateUserEvent event) {}
public void onLinkWaitListChange(LiveClient client, TikTokLinkWaitListChangeEvent event) {}
public void onLinkMute(LiveClient client, TikTokLinkMuteEvent event) {}
public void onLinkRandomMatch(LiveClient client, TikTokLinkRandomMatchEvent event) {}
public void onLinkUpdateUserSettings(LiveClient client, TikTokLinkUpdateUserSettingEvent event) {}
public void onLinkMicIdxUpdate(LiveClient client, TikTokLinkMicIdxUpdateEvent event) {}
public void onLinkListChange(LiveClient client, TikTokLinkListChangeEvent event) {}
public void onLinkCohostListChange(LiveClient client, TikTokLinkCohostListChangeEvent event) {}
public void onLinkMediaChange(LiveClient client, TikTokLinkMediaChangeEvent event) {}
public void onLinkAcceptNotice(LiveClient client, TikTokLinkAcceptNoticeEvent event) {}
public void onLinkSysKickOut(LiveClient client, TikTokLinkSysKickOutEvent event) {}
public void onLinkUserToast(LiveClient client, TikTokLinkUserToastEvent event) {}
public void onBarrage(LiveClient client, TikTokBarrageEvent event) {}
public void onGift(LiveClient client, TikTokGiftEvent event) {}
public void onGiftCombo(LiveClient client, TikTokGiftComboEvent event) {}
public void onLinkMicArmies(LiveClient client, TikTokLinkMicArmiesEvent event) {}
public void onEmote(LiveClient client, TikTokEmoteEvent event) {}
public void onUnauthorizedMember(LiveClient client, TikTokUnauthorizedMemberEvent event) {}
public void onInRoomBanner(LiveClient client, TikTokInRoomBannerEvent event) {}
public void onLinkMicMethod(LiveClient client, TikTokLinkMicMethodEvent event) {}
public void onSubscribe(LiveClient client, TikTokSubscribeEvent event) {}
public void onPoll(LiveClient client, TikTokPollEvent event) {}
public void onFollow(LiveClient client, TikTokFollowEvent event) {}
public void onComment(LiveClient client, TikTokCommentEvent event) {}
public void onHttpResponse(LiveClient client, TikTokHttpResponseEvent action) {}
public void onGoalUpdate(LiveClient client, TikTokGoalUpdateEvent event) {}
public void onRankUpdate(LiveClient client, TikTokRankUpdateEvent event) {}
public void onIMDelete(LiveClient client, TikTokIMDeleteEvent event) {}
public void onLiveEnded(LiveClient client, TikTokLiveEndedEvent event) {}
public void onError(LiveClient client, TikTokErrorEvent event) {}
public void onJoin(LiveClient client, TikTokJoinEvent event) {}
public void onRankText(LiveClient client, TikTokRankTextEvent event) {}
public void onShare(LiveClient client, TikTokShareEvent event) {}
public void onUnhandledMember(LiveClient client, TikTokUnhandledMemberEvent event) {}
public void onSubNotify(LiveClient client, TikTokSubNotifyEvent event) {}
public void onLinkMicBattle(LiveClient client, TikTokLinkMicBattleEvent event) {}
public void onDisconnected(LiveClient client, TikTokDisconnectedEvent event) {}
public void onUnhandledControl(LiveClient client, TikTokUnhandledControlEvent event) {}
public void onEvent(LiveClient client, TikTokEvent event) {}
public void onWebsocketResponse(LiveClient client, TikTokWebsocketResponseEvent event) {}
public void onWebsocketMessage(LiveClient client, TikTokWebsocketMessageEvent event) {}
public void onWebsocketUnhandledMessage(LiveClient client, TikTokWebsocketUnhandledMessageEvent event) {}
public void onReconnecting(LiveClient client, TikTokReconnectingEvent event) {}
}

View File

@@ -20,20 +20,44 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
package io.github.jwdeveloper.tiktok.data.models.battles; package io.github.jwdeveloper.tiktok.live;
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.data.models.Picture;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicBattle;
import lombok.Getter;
@Getter import java.util.List;
public class Viewer {
private final User user;
private final int points;
public Viewer(WebcastLinkMicBattle.LinkMicBattleTopViewers.TopViewerGroup.TopViewer topViewer) { public interface GiftManager {
this.user = new User(topViewer.getId(), null, topViewer.getProfileId(), Picture.map(topViewer.getImages(0)));
this.points = topViewer.getPoints(); /**
} * In case you can't find your gift in Gift enum. You can register gift
* manually here to make it detected while TikTokGiftEvent
*
* @param id gift's id
* @param name gift's name
* @param diamondCost diamond cost
* @return
*/
Gift registerGift(int id, String name, int diamondCost, Picture picture);
/**
*
* @param giftId
* @return
*/
Gift findById(int giftId);
/**
*
* @param giftName
* @return
*/
Gift findByName(String giftName);
/**
*
* @return all gifts
*/
List<Gift> getGifts();
} }

View File

@@ -1,86 +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.live;
import com.google.gson.JsonObject;
import io.github.jwdeveloper.tiktok.data.models.Picture;
import io.github.jwdeveloper.tiktok.data.models.gifts.*;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
public interface GiftsManager {
/**
* You can create and attach your own custom gift to manager
*
* @param gift
*/
void attachGift(Gift gift);
/**
* You can create and attach your own custom gift to manager
*
* @param gifts
*/
void attachGiftsList(List<Gift> gifts);
/**
* finds gift by name
* When gift not found return Gift.UNDEFINED;
*
* @param name gift name
*/
Gift getByName(String name);
/**
* finds gift by id
* When gift not found return Gift.UNDEFINED;
*
* @param giftId giftId
*/
Gift getById(int giftId);
/**
* finds gift by filter
* When gift not found return Gift.UNDEFINED;
*/
Gift getByFilter(Predicate<Gift> filter);
List<Gift> getManyByFilter(Predicate<Gift> filter);
/**
* @return list of all gifts
*/
List<Gift> toList();
/**
* @return list of all map of all gifts where Integer is gift Id
*/
Map<Integer, Gift> toMap();
}

View File

@@ -61,19 +61,10 @@ public interface LiveClient {
*/ */
void publishEvent(TikTokEvent event); void publishEvent(TikTokEvent event);
/**
* @param webcastMessageName name of TikTok protocol-buffer message
* @param payloadBase64 protocol-buffer message bytes payload
*/
void publishMessage(String webcastMessageName, String payloadBase64);
void publishMessage(String webcastMessageName, byte[] payload);
/** /**
* Get information about gifts * Get information about gifts
*/ */
GiftsManager getGiftManager(); GiftManager getGiftManager();
/** /**
* Gets the current room info from TikTok API including streamer info, room status and statistics. * Gets the current room info from TikTok API including streamer info, room status and statistics.

View File

@@ -1,19 +0,0 @@
package io.github.jwdeveloper.tiktok.live;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
import java.util.HashSet;
import java.util.Optional;
public interface LiveEventsHandler {
void publish(LiveClient tikTokLiveClient, TikTokEvent tikTokEvent);
<T extends TikTokEvent> void subscribe(Class<?> clazz, EventConsumer<T> event);
<T extends TikTokEvent> void unsubscribeAll(Class<?> clazz);
<T extends TikTokEvent> void unsubscribe(EventConsumer<T> consumer);
<T extends TikTokEvent> void unsubscribe(Class<?> clazz, EventConsumer<T> consumer);
}

View File

@@ -1,18 +0,0 @@
package io.github.jwdeveloper.tiktok.live;
import io.github.jwdeveloper.tiktok.data.dto.MessageMetaData;
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketMessageEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandledMessageEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.utils.Stopwatch;
import java.time.Duration;
public interface LiveMessagesHandler {
void handle(LiveClient client, WebcastResponse webcastResponse);
void handleSingleMessage(LiveClient client, WebcastResponse.Message message);
}

View File

@@ -47,7 +47,7 @@ public interface LiveRoomInfo
String getRoomId(); String getRoomId();
String getHostName(); String getHostName();
String getTitle(); String getTitle();
User getHost(); User getHostUser();
List<RankingUser> getUsersRanking(); List<RankingUser> getUsersRanking();
ConnectionState getConnectionState(); ConnectionState getConnectionState();
} }

View File

@@ -25,13 +25,7 @@ package io.github.jwdeveloper.tiktok.live.builder;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
@FunctionalInterface
public interface EventConsumer<T extends TikTokEvent> public interface EventConsumer<T extends TikTokEvent>
{ {
/**
*
* @param liveClient TikTok live client
* @param event event data object
*/
void onEvent(LiveClient liveClient, T event); void onEvent(LiveClient liveClient, T event);
} }

View File

@@ -22,10 +22,8 @@
*/ */
package io.github.jwdeveloper.tiktok.live.builder; package io.github.jwdeveloper.tiktok.live.builder;
import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.events.control.TikTokConnectingEvent; import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.control.TikTokPreConnectionEvent;
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent; import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent; import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent; import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
@@ -37,7 +35,6 @@ import io.github.jwdeveloper.tiktok.data.events.social.TikTokShareEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketMessageEvent; import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketMessageEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent; import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandledMessageEvent; import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandledMessageEvent;
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftComboStateType;
public interface EventsBuilder<T> { public interface EventsBuilder<T> {
@@ -54,269 +51,124 @@ public interface EventsBuilder<T> {
/** /**
* Invoked whenever any event is triggered * Invoked whenever any event is triggered
* *
* @param action consumable action * @param action
* @return self instance * @return
*/ */
default T onEvent(EventConsumer<TikTokEvent> action) { T onEvent(EventConsumer<TikTokEvent> action);
return onEvent(TikTokEvent.class, action);
}
/**
* As a first event after method `LiveClient::connect()` is performed
*
* @param action consumable action
* @return self instance
*/
default T onConnecting(EventConsumer<TikTokConnectingEvent> action)
{
return onEvent(TikTokConnectingEvent.class, action);
}
/** /**
* Invoked when information about room (live) got updated such as viewer count, etc.. * Invoked when information about room (live) got updated such as viewer count, etc..
* *
* @param action consumable action * @param action
* @return self instance * @return
*/ */
default T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> action) { T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> action);
return onEvent(TikTokRoomInfoEvent.class, action);
}
/** /**
* Invoked when someone send message to chat * Invoked when someone send message to chat
* *
* @param action consumable action * @param action
* @return self instance * @return
*/ */
default T onComment(EventConsumer<TikTokCommentEvent> action) { T onComment(EventConsumer<TikTokCommentEvent> action);
return onEvent(TikTokCommentEvent.class, action);
}
/** /**
* Invoked when TikTokLiveJava makes http request and getting response * Invoked when TikTokLiveJava makes http request and getting response
* *
* @param action consumable action * @param action
* @return self instance * @return
*/ */
default T onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action) { T onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action);
return onEvent(TikTokHttpResponseEvent.class, action);
}
/** /**
* Invoked when TikTok protocolBuffer data "message" was successfully mapped to event * Invoked when TikTok protocolBuffer data "message" was successfully mapped to event
* events contains protocol-buffer "Message" and TikTokLiveJava "Event" * events contains protocol-buffer "Message" and TikTokLiveJava "Event"
* *
* @param action consumable action * @param action
* @return self instance * @return
*/ */
default T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> action) { T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> action);
return onEvent(TikTokWebsocketMessageEvent.class, action);
}
/** /**
* Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case. * Invoked when there was not found event mapper for TikTok protocolBuffer data "message"
* *
* @param action consumable action * @param action
* @return self instance * @return
*/ */
default T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> action) { T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> action);
return onEvent(TikTokWebsocketUnhandledMessageEvent.class, action);
}
/** /**
* Invoked every time TikTok sends protocolBuffer data to websocket * Invoked every time TikTok sends protocolBuffer data to websocket
* Response contains list of messages that are later mapped to events * Response contains list of messages that are later mapped to events
* * @param action
* @param action consumable action * @return
* @return self instance
*/ */
default T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> action) { T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> action);
return onEvent(TikTokWebsocketResponseEvent.class, action);
}
/** /**
* Triggers for these different reasons: * Invoked for gifts that has no combo, or when combo finishes
* <ol> * @param action
* <li>User sends gifts that have no combo (most of expensive gifts)</li> * @return
* <li>{@link TikTokGiftComboEvent} has combaState = {@link GiftComboStateType#Finished}</li>
* </ol>
* @param action consumable action
* @return self instance
*/ */
default T onGift(EventConsumer<TikTokGiftEvent> action) { T onGift(EventConsumer<TikTokGiftEvent> action);
return onEvent(TikTokGiftEvent.class, action);
}
/** /**
* Triggered every time a gift is sent * Invoked for gifts that has combo options such as roses
* <p>Example when user sends gift with combo</p> * @param action
* <ul> * @return
* <li>Combo: 1 -> comboState = {@link GiftComboStateType#Begin}</li>
* <li>Combo: 4 -> comboState = {@link GiftComboStateType#Active}</li>
* <li>Combo: 8 -> comboState = {@link GiftComboStateType#Active}</li>
* <li>Combo: 12 -> comboState = {@link GiftComboStateType#Finished}</li>
* </ul>
* Both {@link TikTokGiftComboEvent} and {@link TikTokGiftEvent} events are triggered when comboState is Finished
*
* @apiNote {@link GiftComboStateType} has 3 states: {@link GiftComboStateType#Begin Begin}, {@link GiftComboStateType#Active Active}, & {@link GiftComboStateType#Finished Finished}
* @param action consumable action
* @return self instance
*/ */
default T onGiftCombo(EventConsumer<TikTokGiftComboEvent> action) { T onGiftCombo(EventConsumer<TikTokGiftComboEvent> action);
return onEvent(TikTokGiftComboEvent.class, action);
}
/**
* Triggered every time someone asks a new question via the question feature.
*
* @param action consumable action
* @return self instance
*/
default T onQuestion(EventConsumer<TikTokQuestionEvent> action) {
return onEvent(TikTokQuestionEvent.class, action);
}
/** T onQuestion(EventConsumer<TikTokQuestionEvent> action);
* Triggers when a user subscribe the streamer.
*
* @param action consumable action
* @return self instance
*/
default T onSubscribe(EventConsumer<TikTokSubscribeEvent> action) {
return onEvent(TikTokSubscribeEvent.class, action);
}
/** T onSubscribe(EventConsumer<TikTokSubscribeEvent> action);
* Triggers when a user follows the streamer. Based on social event.
*
* @param action consumable action
* @return self instance
*/
default T onFollow(EventConsumer<TikTokFollowEvent> action) {
return onEvent(TikTokFollowEvent.class, action);
}
/** T onFollow(EventConsumer<TikTokFollowEvent> action);
* Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
*
* @param action consumable action
* @return self instance
*/
default T onLike(EventConsumer<TikTokLikeEvent> action) {
return onEvent(TikTokLikeEvent.class, action);
}
/** T onLike(EventConsumer<TikTokLikeEvent> action);
* Triggers when a user sends emote
*
* @param action consumable action
* @return self instance
*/
default T onEmote(EventConsumer<TikTokEmoteEvent> action) {
return onEvent(TikTokEmoteEvent.class, action);
}
/** T onEmote(EventConsumer<TikTokEmoteEvent> action);
* Triggers when a user joins to the live
*
* @param action consumable action
* @return self instance
*/
default T onJoin(EventConsumer<TikTokJoinEvent> action) {
return onEvent(TikTokJoinEvent.class, action);
}
/** T onJoin(EventConsumer<TikTokJoinEvent> action);
* Triggers when a user shares the stream.
*
* @param action consumable action
* @return self instance
*/
default T onShare(EventConsumer<TikTokShareEvent> action) {
return onEvent(TikTokShareEvent.class, action);
}
/** T onShare(EventConsumer<TikTokShareEvent> action);
* Triggered when the live stream gets paused
*
* @param action consumable action
* @return self instance
*/
default T onLivePaused(EventConsumer<TikTokLivePausedEvent> action) {
return onEvent(TikTokLivePausedEvent.class, action);
}
/** T onLivePaused(EventConsumer<TikTokLivePausedEvent> action);
* Triggered when the live stream gets unpaused
*
* @param action consumable action
* @return self instance
*/
default T onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> action) {
return onEvent(TikTokLiveUnpausedEvent.class, action);
}
/** T onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> action);
* Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
* T onLiveEnded(EventConsumer<TikTokLiveEndedEvent> action);
* @param action consumable action
* @return self instance
*/
default T onLiveEnded(EventConsumer<TikTokLiveEndedEvent> action) {
return onEvent(TikTokLiveEndedEvent.class, action);
}
/** /**
* Invoked when client has been successfully connected to live * Invoked when client has been successfully connected to live
* * @param action
* @param action consumable action * @return
* @return self instance
*/ */
default T onConnected(EventConsumer<TikTokConnectedEvent> action) { T onConnected(EventConsumer<TikTokConnectedEvent> action);
return onEvent(TikTokConnectedEvent.class, action);
}
/**
* Invoked before client has been successfully connected to live
*
* @param action consumable action
* @return self instance
*/
default T onPreConnection(EventConsumer<TikTokPreConnectionEvent> action) {
return onEvent(TikTokPreConnectionEvent.class, action);
}
/** /**
* Invoked when client tries to reconnect * Invoked when client tries to reconnect
* * @param action
* @param action consumable action * @return
* @return self instance
*/ */
default T onReconnecting(EventConsumer<TikTokReconnectingEvent> action) { T onReconnecting(EventConsumer<TikTokReconnectingEvent> action);
return onEvent(TikTokReconnectingEvent.class, action);
}
/** /**
* Triggered when the connection gets disconnected. In that case you can call connect() again to have a reconnect logic. * Invoked when client disconnected
* Note that you should wait a little bit before attempting a reconnect to avoid being rate-limited. * @param action
* * @return
* @param action consumable action
* @return self instance
*/ */
default T onDisconnected(EventConsumer<TikTokDisconnectedEvent> action) { T onDisconnected(EventConsumer<TikTokDisconnectedEvent> action);
return onEvent(TikTokDisconnectedEvent.class, action);
}
/** /**
* Invoked when exception was throed inside client or event handler * Invoked when exception was throed inside client or event handler
* * @param action
* @param action consumable action * @return
* @return self instance
*/ */
default T onError(EventConsumer<TikTokErrorEvent> action) { T onError(EventConsumer<TikTokErrorEvent> action);
return onEvent(TikTokErrorEvent.class, action);
}
// TODO Figure out how those events works // TODO Figure out how those events works
@@ -363,10 +215,6 @@ public interface EventsBuilder<T> {
//T onLinkMicBattle(TikTokEventConsumer<TikTokLinkMicBattleEvent> event); //T onLinkMicBattle(TikTokEventConsumer<TikTokLinkMicBattleEvent> event);
//T onUnhandledControl(TikTokEventConsumer<TikTokUnhandledControlEvent> event); //T onUnhandledControl(TikTokEventConsumer<TikTokUnhandledControlEvent> event);
/**
* To do figure out how to use Annotation processor.
* Goal is to generates methods for all possible events, everytime library is compiled
*/
} }

View File

@@ -22,73 +22,58 @@
*/ */
package io.github.jwdeveloper.tiktok.live.builder; package io.github.jwdeveloper.tiktok.live.builder;
import io.github.jwdeveloper.dependance.implementation.DependanceContainerBuilder;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.mappers.LiveMapper; import io.github.jwdeveloper.tiktok.mappers.TikTokMapper;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
public interface LiveClientBuilder extends EventsBuilder<LiveClientBuilder> { public interface LiveClientBuilder extends EventsBuilder<LiveClientBuilder> {
/** /**
* This method is triggered after default mappings are registered * This method is triggered after default mappings are registered
* It could be used to OVERRIDE behaviour of mappings and implement custom behaviour * It could be used to OVERRIDE behaviour of mappings and implement custom behaviour
* <p> *
* Be aware if for example you override WebcastGiftEvent, onGiftEvent() will not be working * Be aware if for example you override WebcastGiftEvent, onGiftEvent() will not be working
* *
* @param onCustomMappings lambda method * @param onCustomMappings lambda method
* @return * @return
*/ */
LiveClientBuilder mappings(Consumer<LiveMapper> onCustomMappings); LiveClientBuilder onMapping(Consumer<TikTokMapper> onCustomMappings);
@Deprecated(forRemoval = true, since = "1.8.2 use `mappings` method instead")
LiveClientBuilder onMappings(Consumer<LiveMapper> onCustomMappings);
/** /**
* Configuration of client settings * Configuration of client settings
* * @see LiveClientSettings
* @param onConfigure * @param onConfigure
* @return * @return
* @see LiveClientSettings
*/ */
LiveClientBuilder configure(Consumer<LiveClientSettings> onConfigure); LiveClientBuilder configure(Consumer<LiveClientSettings> onConfigure);
/** /**
* @see TikTokEventListener
* Adding events listener class, its fancy way to register events without using lamda method * Adding events listener class, its fancy way to register events without using lamda method
* but actual method in class that implements TikTokEventListener * but actual method in class that implements TikTokEventListener
*
* @return * @return
*/ */
LiveClientBuilder addListener(Object listener); LiveClientBuilder addListener(TikTokEventListener listener);
/** /**
* Allows you to use own implementation of internal TikTokLive dependencies,
* when the default implementation does not meet your needs
*
* @param onCustomizeDependencies access to dependency container
* @return
*/
LiveClientBuilder customize(Consumer<DependanceContainerBuilder> onCustomizeDependencies);
/**
* Builds new instance of the LiveClient
* *
* @return LiveClient object * @return LiveClient object
*/ */
LiveClient build(); LiveClient build();
/** /**
* Builds new instance of the LiveClient and connects to live
* *
* @return LiveClient object * @return LiveClient object and connects to TikTok live
*/ */
LiveClient buildAndConnect(); LiveClient buildAndConnect();
/** /**
*
* @return LiveClient object and connects to TikTok live asynchronously * @return LiveClient object and connects to TikTok live asynchronously
*/ */
CompletableFuture<LiveClient> buildAndConnectAsync(); CompletableFuture<LiveClient> buildAndConnectAsync();

View File

@@ -27,23 +27,18 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction; import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult; import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import java.util.List;
import java.util.function.Function; import java.util.function.Function;
public interface LiveMapper { public interface TikTokMapper {
/** /**
* when mapper is not found for messageName, TikTokLiveException is thrown * * if mapper is not found for messageName, TikTokLiveException is thrown
* *
* @param messageName * @param messageName
* @return TikTokMapperModel * @return TikTokMapperModel
*/ */
TikTokMapperModel forMessage(String messageName); TikTokMapperModel forMessage(String messageName);
/**
* @param mapperName protocol buffer class type
* @return
*/
TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName); TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName);
TikTokMapperModel forMessage(String mapperName, MappingAction<MappingResult> onMapping); TikTokMapperModel forMessage(String mapperName, MappingAction<MappingResult> onMapping);
@@ -54,9 +49,10 @@ public interface LiveMapper {
TikTokMapperModel forAnyMessage(); TikTokMapperModel forAnyMessage();
List<TikTokEvent> handleMapping(String messageName, byte[] bytes);
boolean isRegistered(String mapperName); boolean isRegistered(String mapperName);
<T extends GeneratedMessageV3> boolean isRegistered(Class<T> mapperName); <T extends GeneratedMessageV3> boolean isRegistered(Class<T> mapperName);
} }

View File

@@ -26,7 +26,7 @@ import com.google.protobuf.GeneratedMessageV3;
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException; import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject; import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject;
public interface LiveMapperHelper { public interface TikTokMapperHelper {
/** /**
* @param bytes protocol buffer data bytes * @param bytes protocol buffer data bytes

View File

@@ -22,7 +22,7 @@
*/ */
package io.github.jwdeveloper.tiktok.mappers.data; package io.github.jwdeveloper.tiktok.mappers.data;
import io.github.jwdeveloper.tiktok.mappers.LiveMapperHelper; import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper;
@FunctionalInterface @FunctionalInterface
public interface MappingAction<T> { public interface MappingAction<T> {
@@ -33,6 +33,6 @@ public interface MappingAction<T> {
* @param mapperHelper utils and helper methods that can be use to debbug/display/deserialize protocol buffer data * @param mapperHelper utils and helper methods that can be use to debbug/display/deserialize protocol buffer data
* @return * @return
*/ */
T onMapping(byte[] inputBytes, String messageName, LiveMapperHelper mapperHelper); T onMapping(byte[] inputBytes, String messageName, TikTokMapperHelper mapperHelper);
} }

View File

@@ -24,8 +24,9 @@ package io.github.jwdeveloper.tiktok.websocket;
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
public interface LiveSocketClient { public interface SocketClient {
void start(LiveConnectionData.Response webcastResponse, LiveClient tikTokLiveClient); void start(LiveConnectionData.Response webcastResponse, LiveClient tikTokLiveClient);
void stop(); void stop();
} }

View File

@@ -102,8 +102,7 @@ message Text {
// @Image // @Image
message Image { message Image {
repeated string url = 1; repeated string urlList = 1;
string extras = 2;
bool isAnimated = 9; bool isAnimated = 9;
} }
@@ -1062,9 +1061,9 @@ message CohostListChangeContent {
message LinkerListChangeContent { message LinkerListChangeContent {
repeated ListUser linkedUsers = 1; repeated ListUser linkedUsersList = 1;
repeated ListUser appliedUsers = 2; repeated ListUser appliedUsersList = 2;
repeated ListUser connectingUsers = 3; repeated ListUser connectingUsersList = 3;
} }
message LinkerMediaChangeContent { message LinkerMediaChangeContent {

View File

@@ -35,14 +35,6 @@ enum LinkmicApplierSortSetting {
LINKMIC_APPLIER_SORT_SETTING_BY_GIFT_SCORE = 1; LINKMIC_APPLIER_SORT_SETTING_BY_GIFT_SCORE = 1;
} }
enum LinkMicBattleStatus {
BATTLE_ARMY_UNKNOWN = 0;
ARMY_ONGOING = 1;
ARMY_FINISHED = 2;
BATTLE_ONGOING = 4;
BATTLE_FINISHED = 5;
}
enum HashtagNamespace { enum HashtagNamespace {
GLOBAL = 0; GLOBAL = 0;
GAMING = 1; GAMING = 1;
@@ -250,21 +242,21 @@ enum CommonContentCase {
enum LinkMessageType { enum LinkMessageType {
TYPE_LINKER_UNKNOWN = 0; TPYE_LINKER_UNKNOWN = 0;
TYPE_LINKER_CREATE = 1; TYPE_LINKER_CREATE = 1;
TYPE_LINKER_CLOSE = 2; TYPE_LINKER_CLOSE = 2;
TYPE_LINKER_INVITE = 3; TYPE_LINKER_INVITE = 3;
TYPE_LINKER_APPLY = 4; TYPE_LINKER_APPLY = 4;
TYPE_LINKER_REPLY = 5; TYPE_LINKER_REPLY = 5;
TYPE_LINKER_ENTER = 6; TPYE_LINKER_ENTER = 6;
TYPE_LINKER_LEAVE = 7; TPYE_LINKER_LEAVE = 7;
TYPE_LINKER_PERMIT = 8; TYPE_LINKER_PERMIT = 8;
TYPE_LINKER_CANCEL_INVITE = 9; TPYE_LINKER_CANCEL_INVITE = 9;
TYPE_LINKER_WAITING_LIST_CHANGE = 10; TYPE_LINKER_WAITING_LIST_CHANGE = 10;
TYPE_LINKER_LINKED_LIST_CHANGE = 11; TYPE_LINKER_LINKED_LIST_CHANGE = 11;
TYPE_LINKER_UPDATE_USER = 12; TYPE_LINKER_UPDATE_USER = 12;
TYPE_LINKER_KICK_OUT = 13; TPYE_LINKER_KICK_OUT = 13;
TYPE_LINKER_CANCEL_APPLY = 14; TPYE_LINKER_CANCEL_APPLY = 14;
TYPE_LINKER_MUTE = 15; TYPE_LINKER_MUTE = 15;
TYPE_LINKER_MATCH = 16; TYPE_LINKER_MATCH = 16;
TYPE_LINKER_UPDATE_USER_SETTING = 17; TYPE_LINKER_UPDATE_USER_SETTING = 17;
@@ -275,8 +267,8 @@ enum LinkMessageType {
TYPE_LINKER_COHOST_LIST_CHANGE = 22; TYPE_LINKER_COHOST_LIST_CHANGE = 22;
TYPE_LINKER_MEDIA_CHANGE = 23; TYPE_LINKER_MEDIA_CHANGE = 23;
TYPE_LINKER_ACCEPT_NOTICE = 24; TYPE_LINKER_ACCEPT_NOTICE = 24;
TYPE_LINKER_SYS_KICK_OUT = 101; TPYE_LINKER_SYS_KICK_OUT = 101;
TYPE_LINKMIC_USER_TOAST = 102; TPYE_LINKMIC_USER_TOAST = 102;
} }
enum MessageType { enum MessageType {

View File

@@ -521,7 +521,7 @@ message WebcastLinkMicArmies {
uint64 id2 = 4; uint64 id2 = 4;
uint64 timeStamp1 = 5; uint64 timeStamp1 = 5;
uint64 timeStamp2 = 6; uint64 timeStamp2 = 6;
LinkMicBattleStatus battleStatus = 7; int32 battleStatus = 7; // SHOULD BE AN ENUM
uint64 data1 = 8; uint64 data1 = 8;
uint64 data2 = 9; uint64 data2 = 9;
uint32 data3 = 10; uint32 data3 = 10;
@@ -574,26 +574,11 @@ message WebcastLinkMicBattle {
Common common = 1; Common common = 1;
uint64 id = 2; uint64 id = 2;
LinkMicBattleConfig battleConfig = 3; LinkMicBattleConfig battleConfig = 3;
LinkMicBattleStatus battleStatus = 4; uint32 data2 = 4;
repeated LinkMicBattleDetails details = 5; repeated LinkMicBattleDetails details = 5;
repeated LinkMicBattleTopViewers viewerTeam = 9; repeated LinkMicBattleTeam teams1 = 9;
repeated LinkMicBattleHost hostTeam = 10; repeated LinkMicBattleTeam teams2 = 10;
repeated LinkMicBattleTeamData teamData = 13; repeated LinkMicBattleTeamData teamData = 13;
uint64 unknownData16 = 16;
repeated Host2v2Data hostData2v2 = 17;
message Host2v2Data {
uint32 teamNumber = 1;
repeated HostData hostdata = 2;
uint32 unknownData3 = 3;
uint32 totalPoints = 4;
message HostData {
uint64 hostId = 1;
uint32 points = 2;
string hostIdStr = 3;
}
}
message LinkMicBattleConfig { message LinkMicBattleConfig {
uint64 id1 = 1; uint64 id1 = 1;
@@ -601,69 +586,29 @@ message WebcastLinkMicBattle {
uint32 data1 = 3; uint32 data1 = 3;
uint64 id2 = 4; uint64 id2 = 4;
uint32 data2 = 5; uint32 data2 = 5;
uint32 data3 = 6;
uint32 data4 = 8;
}
message LinkMicBattleTeamData {
uint64 teamId = 1;
LinkMicBattleData data = 2;
} }
message LinkMicBattleData { message LinkMicBattleData {
uint64 id = 1; uint64 id = 1;
uint32 data1 = 2; uint32 data1 = 2;
uint32 winStreak = 3; uint32 data2 = 3;
uint32 data3 = 5; uint32 data3 = 5;
string url = 6; string url = 6;
} }
message LinkMicBattleDetails { message LinkMicBattleDetails {
uint64 id = 1; uint64 id = 1;
LinkMicBattleDetailsSummary summary = 2; LinkMicBattleData details = 2;
}
message LinkMicBattleDetailsSummary { message LinkMicBattleTeam {
uint64 id = 1; uint64 id = 1;
uint32 unknownData2 = 2; repeated User users = 2;
uint32 points = 3;
}
} }
message LinkMicBattleTopViewers { message LinkMicBattleTeamData {
uint64 id = 1; uint64 teamId = 1;
repeated TopViewerGroup viewerGroup = 2; LinkMicBattleData data = 2;
message TopViewerGroup {
repeated TopViewer viewer = 1;
uint32 points = 2;
string hostIdOrTeamNum = 3; // 1v1 Battle = HostId | 2v2 Battle = Team # - 1 & 2
message TopViewer {
uint64 id = 1;
uint32 points = 2;
string profileId = 3;
repeated Image images = 4;
string stringId = 6;
}
}
}
message LinkMicBattleHost {
uint64 id = 1;
repeated HostGroup hostGroup = 2;
message HostGroup {
repeated Host host = 1;
uint32 points = 2;
string hostId = 3;
message Host {
uint64 id = 1;
string profileId = 2;
repeated Image images = 3;
string name = 4;
}
}
} }
} }
@@ -805,7 +750,7 @@ message WebcastLinkMessage {
LinkerListChangeContent ListChangeContent = 20; LinkerListChangeContent ListChangeContent = 20;
CohostListChangeContent CohostListChangeContent = 21; CohostListChangeContent CohostListChangeContent = 21;
LinkerMediaChangeContent MediaChangeContent = 22; LinkerMediaChangeContent MediaChangeContent = 22;
LinkerAcceptNoticeContent AcceptNoticeContent = 23; LinkerAcceptNoticeContent ReplyAcceptNoticeContent = 23;
LinkerSysKickOutContent SysKickOutContent = 101; LinkerSysKickOutContent SysKickOutContent = 101;
LinkmicUserToastContent UserToastContent = 102; LinkmicUserToastContent UserToastContent = 102;
string extra = 200; string extra = 200;
@@ -848,3 +793,5 @@ message RoomVerifyMessage {
int64 noticeType = 4; int64 noticeType = 4;
bool closeRoom = 5; bool closeRoom = 5;
} }

View File

@@ -5,14 +5,13 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.8.2-Release</version> <version>1.0.14-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>Client</artifactId> <artifactId>Client</artifactId>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
@@ -40,7 +39,7 @@
<dependency> <dependency>
<groupId>org.java-websocket</groupId> <groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId> <artifactId>Java-WebSocket</artifactId>
<version>1.5.5</version> <version>1.5.4</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.testng</groupId> <groupId>org.testng</groupId>

View File

@@ -23,75 +23,20 @@
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager;
import io.github.jwdeveloper.tiktok.http.LiveHttpClient; import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder; import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
public class TikTokLive { public class TikTokLive {
/** /**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo' * @param hostName profile name of Tiktok user could be found in profile link
* * example: https://www.tiktok.com/@dostawcavideo hostName would be dostawcavideo
* @param hostName profile name of TikTok user could be found in profile link
* @return LiveClientBuilder * @return LiveClientBuilder
*/ */
public static LiveClientBuilder newClient(String hostName) { public static LiveClientBuilder newClient(String hostName) {
return new TikTokLiveClientBuilder(hostName); return new TikTokLiveClientBuilder(hostName);
} }
/**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
*
* @param hostName profile name of TikTok user could be found in profile link
* @return true if live is Online, false if is offline
*/
public static boolean isLiveOnline(String hostName) {
return requests().fetchLiveUserData(hostName).isLiveOnline();
}
/**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
*
* @param hostName profile name of TikTok user could be found in profile link
* @return true if live is Online, false if is offline
*/
public static CompletableFuture<Boolean> isLiveOnlineAsync(String hostName) {
return CompletableFuture.supplyAsync(() -> isLiveOnline(hostName));
}
/**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
*
* @param hostName profile name of TikTok user could be found in profile link
* @return true is hostName name is valid and exists, false if not
*/
public static boolean isHostNameValid(String hostName) {
return requests().fetchLiveUserData(hostName).isHostNameValid();
}
/**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
*
* @param hostName profile name of TikTok user could be found in profile link
* @return true is hostName name is valid and exists, false if not
*/
public static CompletableFuture<Boolean> isHostNameValidAsync(String hostName) {
return CompletableFuture.supplyAsync(() -> isHostNameValid(hostName));
}
/**
* Use to get some data from TikTok about users are lives
*
* @return LiveHttpClient
*/
public static LiveHttpClient requests(Consumer<LiveClientSettings> consumer) {
return new TikTokLiveHttpClient(consumer);
}
/** /**
* Use to get some data from TikTok about users are lives * Use to get some data from TikTok about users are lives
@@ -99,22 +44,9 @@ public class TikTokLive {
* @return LiveHttpClient * @return LiveHttpClient
*/ */
public static LiveHttpClient requests() { public static LiveHttpClient requests() {
return requests(liveClientSettings -> {});
return new TikTokLiveHttpClient();
} }
private static GiftsManager giftsManager;
/**
* Fetch gifts from endpoint and returns GiftManager
*
* @return GiftsManager
*/
public static GiftsManager gifts() {
if (giftsManager == null) {
synchronized (GiftsManager.class) {
giftsManager = new TikTokGiftsManager(requests().fetchGiftsData().getGifts());
}
}
return giftsManager;
}
} }

View File

@@ -22,53 +22,50 @@
*/ */
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import com.google.protobuf.ByteString; import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
import io.github.jwdeveloper.tiktok.data.events.*; import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.events.control.*;
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent; import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
import io.github.jwdeveloper.tiktok.data.requests.*; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; import io.github.jwdeveloper.tiktok.data.requests.LiveData;
import io.github.jwdeveloper.tiktok.exceptions.*; import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
import io.github.jwdeveloper.tiktok.http.LiveHttpClient; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.listener.*; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
import io.github.jwdeveloper.tiktok.live.*; import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import io.github.jwdeveloper.tiktok.listener.ListenersManager;
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
import io.github.jwdeveloper.tiktok.live.GiftManager;
import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.live.LiveRoomInfo;
import io.github.jwdeveloper.tiktok.models.ConnectionState; import io.github.jwdeveloper.tiktok.models.ConnectionState;
import io.github.jwdeveloper.tiktok.websocket.LiveSocketClient; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import lombok.Getter; import io.github.jwdeveloper.tiktok.websocket.SocketClient;
import java.util.Base64;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.logging.Logger; import java.util.logging.Logger;
@Getter public class TikTokLiveClient implements LiveClient {
public class TikTokLiveClient implements LiveClient private final TikTokRoomInfo liveRoomInfo;
{ private final TikTokGiftManager tikTokGiftManager;
private final TikTokRoomInfo roomInfo; private final TikTokLiveHttpClient httpClient;
private final LiveHttpClient httpClient; private final SocketClient webSocketClient;
private final LiveSocketClient webSocketClient; private final TikTokLiveEventHandler tikTokEventHandler;
private final LiveEventsHandler tikTokEventHandler;
private final LiveClientSettings clientSettings; private final LiveClientSettings clientSettings;
private final ListenersManager listenersManager; private final TikTokListenersManager listenersManager;
private final Logger logger; private final Logger logger;
private final GiftsManager giftManager;
private final LiveMessagesHandler messageHandler;
public TikTokLiveClient( public TikTokLiveClient(TikTokRoomInfo tikTokLiveMeta,
LiveMessagesHandler messageHandler, TikTokLiveHttpClient tiktokHttpClient,
GiftsManager giftsManager, SocketClient webSocketClient,
TikTokRoomInfo tikTokLiveMeta, TikTokGiftManager tikTokGiftManager,
LiveHttpClient tiktokHttpClient, TikTokLiveEventHandler tikTokEventHandler,
LiveSocketClient webSocketClient,
LiveEventsHandler tikTokEventHandler,
LiveClientSettings clientSettings, LiveClientSettings clientSettings,
ListenersManager listenersManager, TikTokListenersManager listenersManager,
Logger logger) { Logger logger) {
this.messageHandler = messageHandler; this.liveRoomInfo = tikTokLiveMeta;
this.giftManager = giftsManager; this.tikTokGiftManager = tikTokGiftManager;
this.roomInfo = tikTokLiveMeta;
this.httpClient = tiktokHttpClient; this.httpClient = tiktokHttpClient;
this.webSocketClient = webSocketClient; this.webSocketClient = webSocketClient;
this.tikTokEventHandler = tikTokEventHandler; this.tikTokEventHandler = tikTokEventHandler;
@@ -77,6 +74,26 @@ public class TikTokLiveClient implements LiveClient
this.logger = logger; this.logger = logger;
} }
public void connectAsync(Consumer<LiveClient> onConnection) {
CompletableFuture.supplyAsync(() ->
{
connect();
onConnection.accept(this);
return this;
});
}
public CompletableFuture<LiveClient> connectAsync() {
return CompletableFuture.supplyAsync(() ->
{
connect();
return this;
});
}
public void connect() { public void connect() {
try { try {
tryConnect(); tryConnect();
@@ -88,7 +105,8 @@ public class TikTokLiveClient implements LiveClient
if (e instanceof TikTokLiveOfflineHostException && clientSettings.isRetryOnConnectionFailure()) { if (e instanceof TikTokLiveOfflineHostException && clientSettings.isRetryOnConnectionFailure()) {
try { try {
Thread.sleep(clientSettings.getRetryConnectionTimeout().toMillis()); Thread.sleep(clientSettings.getRetryConnectionTimeout().toMillis());
} catch (Exception ignored) {} } catch (Exception ignored) {
}
logger.info("Reconnecting"); logger.info("Reconnecting");
tikTokEventHandler.publish(this, new TikTokReconnectingEvent()); tikTokEventHandler.publish(this, new TikTokReconnectingEvent());
this.connect(); this.connect();
@@ -102,97 +120,86 @@ public class TikTokLiveClient implements LiveClient
} }
public void tryConnect() { public void tryConnect() {
if (!roomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) { if (!liveRoomInfo.hasConnectionState(ConnectionState.DISCONNECTED))
{
throw new TikTokLiveException("Already connected"); throw new TikTokLiveException("Already connected");
} }
setState(ConnectionState.CONNECTING); setState(ConnectionState.CONNECTING);
tikTokEventHandler.publish(this, new TikTokConnectingEvent());
var userDataRequest = new LiveUserData.Request(roomInfo.getHostName());
var userDataRequest = new LiveUserData.Request(liveRoomInfo.getHostName());
var userData = httpClient.fetchLiveUserData(userDataRequest); var userData = httpClient.fetchLiveUserData(userDataRequest);
roomInfo.setStartTime(userData.getStartTime()); liveRoomInfo.setStartTime(userData.getStartedAtTimeStamp());
roomInfo.setRoomId(userData.getRoomId()); liveRoomInfo.setRoomId(userData.getRoomId());
if (userData.getUserStatus() == LiveUserData.UserStatus.Offline) {
throw new TikTokLiveOfflineHostException("User is offline: "+liveRoomInfo.getHostUser());
}
if (userData.getUserStatus() == LiveUserData.UserStatus.NotFound) {
throw new TikTokLiveOfflineHostException("User not found: "+liveRoomInfo.getHostUser());
}
if (userData.getUserStatus() == LiveUserData.UserStatus.Offline)
throw new TikTokLiveOfflineHostException("User is offline: " + roomInfo.getHostName());
if (userData.getUserStatus() == LiveUserData.UserStatus.NotFound)
throw new TikTokLiveUnknownHostException("User not found: " + roomInfo.getHostName());
var liveDataRequest = new LiveData.Request(userData.getRoomId()); var liveDataRequest = new LiveData.Request(userData.getRoomId());
var liveData = httpClient.fetchLiveData(liveDataRequest); var liveData = httpClient.fetchLiveData(liveDataRequest);
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound) {
throw new TikTokLiveOfflineHostException("LiveStream for Host name could not be found.");
}
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostOffline) {
throw new TikTokLiveOfflineHostException("LiveStream for not be found, is the Host offline?");
}
if (liveData.isAgeRestricted() && clientSettings.isThrowOnAgeRestriction()) liveRoomInfo.setTitle(liveData.getTitle());
throw new TikTokLiveException("Livestream for " + roomInfo.getHostName() + " is 18+ or age restricted!"); liveRoomInfo.setViewersCount(liveData.getViewers());
liveRoomInfo.setTotalViewersCount(liveData.getTotalViewers());
liveRoomInfo.setAgeRestricted(liveData.isAgeRestricted());
liveRoomInfo.setHost(liveData.getHost());
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound)
throw new TikTokLiveUnknownHostException("LiveStream for " + roomInfo.getHostName() + " could not be found.");
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostOffline) var liveConnectionRequest =new LiveConnectionData.Request(userData.getRoomId());
throw new TikTokLiveOfflineHostException("LiveStream for " + roomInfo.getHostName() + " not found, is the Host offline?");
roomInfo.setTitle(liveData.getTitle());
roomInfo.setViewersCount(liveData.getViewers());
roomInfo.setTotalViewersCount(liveData.getTotalViewers());
roomInfo.setAgeRestricted(liveData.isAgeRestricted());
roomInfo.setHost(liveData.getHost());
var preconnectEvent = new TikTokPreConnectionEvent(userData, liveData);
tikTokEventHandler.publish(this, preconnectEvent);
if (preconnectEvent.isCancelConnection())
throw new TikTokLiveException("TikTokPreConnectionEvent cancelled connection!");
if (clientSettings.isFetchGifts())
giftManager.attachGiftsList(httpClient.fetchRoomGiftsData(userData.getRoomId()).getGifts());
var liveConnectionRequest = new LiveConnectionData.Request(userData.getRoomId());
var liveConnectionData = httpClient.fetchLiveConnectionData(liveConnectionRequest); var liveConnectionData = httpClient.fetchLiveConnectionData(liveConnectionRequest);
webSocketClient.start(liveConnectionData, this); webSocketClient.start(liveConnectionData, this);
setState(ConnectionState.CONNECTED); setState(ConnectionState.CONNECTED);
tikTokEventHandler.publish(this, new TikTokRoomInfoEvent(roomInfo)); tikTokEventHandler.publish(this, new TikTokRoomInfoEvent(liveRoomInfo));
} }
public void disconnect() { public void disconnect() {
if (roomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) { if (liveRoomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) {
return; return;
} }
setState(ConnectionState.DISCONNECTED);
webSocketClient.stop(); webSocketClient.stop();
setState(ConnectionState.DISCONNECTED);
} }
private void setState(ConnectionState connectionState) { private void setState(ConnectionState connectionState) {
logger.info("TikTokLive client state: " + connectionState.name()); logger.info("TikTokLive client state: " + connectionState.name());
roomInfo.setConnectionState(connectionState); liveRoomInfo.setConnectionState(connectionState);
} }
public void publishEvent(TikTokEvent event) { public void publishEvent(TikTokEvent event) {
tikTokEventHandler.publish(this, event); tikTokEventHandler.publish(this, event);
} }
public LiveRoomInfo getRoomInfo() {
return liveRoomInfo;
}
@Override @Override
public void publishMessage(String webcastMessageName, String payloadBase64) { public ListenersManager getListenersManager() {
this.publishMessage(webcastMessageName, Base64.getDecoder().decode(payloadBase64)); return listenersManager;
} }
@Override @Override
public void publishMessage(String webcastMessageName, byte[] payload) { public Logger getLogger() {
return logger;
}
var builder = WebcastResponse.Message.newBuilder(); @Override
builder.setMethod(webcastMessageName); public GiftManager getGiftManager() {
builder.setPayload(ByteString.copyFrom(payload)); return tikTokGiftManager;
var message = builder.build();
messageHandler.handleSingleMessage(this, message);
} }
public void connectAsync(Consumer<LiveClient> onConnection) {
connectAsync().thenAccept(onConnection);
}
public CompletableFuture<LiveClient> connectAsync() {
return CompletableFuture.supplyAsync(() -> {
connect();
return this;
});
}
} }

View File

@@ -22,173 +22,249 @@
*/ */
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.dependance.Dependance; import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.dependance.api.DependanceContainer;
import io.github.jwdeveloper.dependance.implementation.DependanceContainerBuilder;
import io.github.jwdeveloper.tiktok.mappers.MessagesMapperFactory;
import io.github.jwdeveloper.tiktok.common.LoggerFactory;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; 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.http.TikTokHttpResponseEvent;
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomPinEvent;
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.events.websocket.TikTokWebsocketMessageEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandledMessageEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager; import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
import io.github.jwdeveloper.tiktok.http.HttpClientFactory; import io.github.jwdeveloper.tiktok.http.HttpClientFactory;
import io.github.jwdeveloper.tiktok.http.LiveHttpClient; import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
import io.github.jwdeveloper.tiktok.listener.*; import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
import io.github.jwdeveloper.tiktok.live.*; import io.github.jwdeveloper.tiktok.live.GiftManager;
import io.github.jwdeveloper.tiktok.live.builder.*; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.mappers.*; import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper;
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper;
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapperHelper;
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokCommonEventHandler; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokCommonEventHandler;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokRoomInfoEventHandler; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokRoomInfoEventHandler;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokSocialMediaEventHandler; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokSocialMediaEventHandler;
import io.github.jwdeveloper.tiktok.websocket.*; import io.github.jwdeveloper.tiktok.messages.webcast.*;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient;
import java.util.*; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.logging.Logger; import java.util.logging.*;
public class TikTokLiveClientBuilder implements LiveClientBuilder { public class TikTokLiveClientBuilder implements LiveClientBuilder {
protected final LiveClientSettings clientSettings; protected final LiveClientSettings clientSettings;
protected final LiveEventsHandler eventHandler; protected final Logger logger;
protected final List<Object> listeners; protected final TikTokLiveEventHandler tikTokEventHandler;
protected final List<Consumer<LiveMapper>> onCustomMappings; protected final List<TikTokEventListener> listeners;
protected final List<Consumer<DependanceContainerBuilder>> onCustomDependencies; protected Consumer<TikTokMapper> onCustomMappings;
public TikTokLiveClientBuilder(String userName) { public TikTokLiveClientBuilder(String userName)
{
this.clientSettings = LiveClientSettings.createDefault(); this.clientSettings = LiveClientSettings.createDefault();
this.clientSettings.setHostName(userName); this.clientSettings.setHostName(userName);
this.eventHandler = new TikTokLiveEventHandler(); this.tikTokEventHandler = new TikTokLiveEventHandler();
this.logger = Logger.getLogger(TikTokLive.class.getSimpleName() + " " + userName);
this.listeners = new ArrayList<>(); this.listeners = new ArrayList<>();
this.onCustomMappings = new ArrayList<>(); this.onCustomMappings = (e) -> {
this.onCustomDependencies = new ArrayList<>(); };
} }
public LiveClientBuilder mappings(Consumer<LiveMapper> consumer) { public LiveClientBuilder onMapping(Consumer<TikTokMapper> onCustomMappings) {
this.onCustomMappings.add(consumer); this.onCustomMappings = onCustomMappings;
return this; return this;
} }
@Override
public LiveClientBuilder onMappings(Consumer<LiveMapper> onCustomMappings) {
mappings(onCustomMappings);
return this;
}
public TikTokLiveClientBuilder configure(Consumer<LiveClientSettings> onConfigure) { public TikTokLiveClientBuilder configure(Consumer<LiveClientSettings> onConfigure) {
onConfigure.accept(clientSettings); onConfigure.accept(clientSettings);
return this; return this;
} }
public TikTokLiveClientBuilder addListener(Object listener) { public TikTokLiveClientBuilder addListener(TikTokEventListener listener) {
if (listener != null)
listeners.add(listener); listeners.add(listener);
return this; return this;
} }
@Override protected void validate() {
public LiveClientBuilder customize(Consumer<DependanceContainerBuilder> onCustomizeDependencies) { if (clientSettings.getClientLanguage() == null || clientSettings.getClientLanguage().isEmpty()) {
this.onCustomDependencies.add(onCustomizeDependencies); clientSettings.setClientLanguage("en");
return this;
} }
protected void validate() {
if (clientSettings.getClientLanguage() == null || clientSettings.getClientLanguage().isEmpty())
clientSettings.setClientLanguage("en");
if (clientSettings.getHostName() == null || clientSettings.getHostName().isEmpty()) if (clientSettings.getHostName() == null || clientSettings.getHostName().isEmpty()) {
throw new TikTokLiveException("HostName can not be null"); throw new TikTokLiveException("HostName can not be null");
}
if (clientSettings.getHostName().startsWith("@")) if (clientSettings.getHostName().startsWith("@")) {
clientSettings.setHostName(clientSettings.getHostName().substring(1)); clientSettings.setHostName(clientSettings.getHostName().substring(1));
}
//TODO 250 Magic number
if (clientSettings.getPingInterval() < 250)
throw new TikTokLiveException("Minimum allowed ping interval is 250 milliseconds");
var httpSettings = clientSettings.getHttpSettings(); var httpSettings = clientSettings.getHttpSettings();
httpSettings.getParams().put("app_language", clientSettings.getClientLanguage()); httpSettings.getParams().put("app_language", clientSettings.getClientLanguage());
httpSettings.getParams().put("webcast_language", clientSettings.getClientLanguage()); httpSettings.getParams().put("webcast_language", clientSettings.getClientLanguage());
var handler = new ConsoleHandler();
handler.setFormatter(new Formatter() {
@Override
public String format(LogRecord record) {
var sb = new StringBuilder();
sb.append(ConsoleColors.GREEN).append("[").append(record.getLoggerName()).append("] ");
sb.append(ConsoleColors.GREEN).append("[").append(record.getLevel()).append("]: ");
sb.append(ConsoleColors.WHITE_BRIGHT).append(record.getMessage());
sb.append(ConsoleColors.RESET).append("\n");
return sb.toString();
}
});
logger.setUseParentHandlers(false);
logger.addHandler(handler);
logger.setLevel(clientSettings.getLogLevel());
if (!clientSettings.isPrintToConsole()) {
logger.setLevel(Level.OFF);
}
} }
//TODO each class registered to container should implement own interface,
public LiveClient build() { public LiveClient build() {
validate(); validate();
//Docs: https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#01-basic var tiktokRoomInfo = new TikTokRoomInfo();
var dependance = Dependance.newContainer(); tiktokRoomInfo.setHostName(clientSettings.getHostName());
//config var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
dependance.registerSingleton(LiveClientSettings.class, clientSettings);
dependance.registerSingleton(Logger.class, LoggerFactory.create(clientSettings.getHostName(), clientSettings));
dependance.registerSingleton(TikTokRoomInfo.class, container ->
{
var roomInfo = new TikTokRoomInfo();
roomInfo.setHostName(clientSettings.getHostName());
return roomInfo;
});
//messages var giftManager = new TikTokGiftManager(logger);
dependance.registerSingleton(LiveEventsHandler.class, eventHandler); var eventsMapper = createMapper(giftManager, tiktokRoomInfo);
dependance.registerSingleton(LiveMessagesHandler.class, TikTokLiveMessageHandler.class); var messageHandler = new TikTokLiveMessageHandler(tikTokEventHandler, eventsMapper);
//listeners
dependance.registerSingleton(ListenersManager.class, TikTokListenersManager.class);
//networking var httpClientFactory = new HttpClientFactory(clientSettings);
dependance.registerSingleton(HttpClientFactory.class); var tikTokLiveHttpClient = new TikTokLiveHttpClient(httpClientFactory);
dependance.registerSingleton(TikTokWebSocketPingingTask.class);
if (clientSettings.isOffline()) { var webSocketClient = new TikTokWebSocketClient(
dependance.registerSingleton(LiveSocketClient.class, TikTokWebSocketOfflineClient.class); clientSettings,
dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpOfflineClient.class); messageHandler,
} else { tikTokEventHandler);
dependance.registerSingleton(LiveSocketClient.class, TikTokWebSocketClient.class);
dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpClient.class); return new TikTokLiveClient(tiktokRoomInfo,
tikTokLiveHttpClient,
webSocketClient,
giftManager,
tikTokEventHandler,
clientSettings,
listenerManager,
logger);
} }
/* TODO in future, custom proxy implementation that can be provided via builder public TikTokLiveMapper createMapper(GiftManager giftManager, TikTokRoomInfo roomInfo) {
* if(customProxy != null) /*
* dependance.registerSingleton(TikTokProxyProvider.class,customProxy); //
* else
* dependance.registerSingleton(TikTokProxyProvider.class,DefaultProxyProvider.class);
*/ */
//gifts
if (clientSettings.isFetchGifts()) {
dependance.registerSingleton(GiftsManager.class, TikTokLive.gifts());
} else {
dependance.registerSingleton(GiftsManager.class, new TikTokGiftsManager(List.of()));
}
//mapper var eventMapper = new TikTokGenericEventMapper();
dependance.registerSingleton(TikTokGenericEventMapper.class); var mapper = new TikTokLiveMapper(new TikTokLiveMapperHelper(eventMapper));
dependance.registerSingleton(LiveMapperHelper.class, TikTokLiveMapperHelper.class);
dependance.registerSingleton(LiveMapper.class, (container) -> //ConnectionEvents events
var commonHandler = new TikTokCommonEventHandler();
var giftHandler = new TikTokGiftEventHandler(giftManager, roomInfo);
var roomInfoHandler = new TikTokRoomInfoEventHandler(roomInfo);
var socialHandler = new TikTokSocialMediaEventHandler(roomInfo);
mapper.forMessage(WebcastControlMessage.class, commonHandler::handleWebcastControlMessage);
//Room status events
mapper.forMessage(WebcastLiveIntroMessage.class, roomInfoHandler::handleIntro);
mapper.forMessage(WebcastRoomUserSeqMessage.class, roomInfoHandler::handleUserRanking);
mapper.forMessage(WebcastCaptionMessage.class, (inputBytes, messageName, mapperHelper) ->
{ {
var dependace = (DependanceContainer) container.find(DependanceContainer.class); var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastCaptionMessage.class);
var mapper = MessagesMapperFactory.create(dependace); return MappingResult.of(messageObject, new TikTokCaptionEvent(messageObject));
onCustomMappings.forEach(action -> action.accept(mapper));
return mapper;
}); });
//mapper handlers
dependance.registerSingleton(TikTokCommonEventHandler.class);
dependance.registerSingleton(TikTokGiftEventHandler.class);
dependance.registerSingleton(TikTokRoomInfoEventHandler.class);
dependance.registerSingleton(TikTokSocialMediaEventHandler.class);
//client //User Interactions events
dependance.registerSingleton(LiveClient.class, TikTokLiveClient.class); mapper.forMessage(WebcastChatMessage.class, (inputBytes, messageName, mapperHelper) ->
{
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
return MappingResult.of(messageObject, new TikTokCommentEvent(messageObject));
});
mapper.forMessage(WebcastSubNotifyMessage.class, (inputBytes, messageName, mapperHelper) ->
{
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastSubNotifyMessage.class);
return MappingResult.of(messageObject, new TikTokSubscribeEvent(messageObject));
});
mapper.forMessage(WebcastEmoteChatMessage.class, (inputBytes, messageName, mapperHelper) ->
{
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastEmoteChatMessage.class);
return MappingResult.of(messageObject, new TikTokEmoteEvent(messageObject));
});
mapper.forMessage(WebcastQuestionNewMessage.class, (inputBytes, messageName, mapperHelper) ->
{
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastQuestionNewMessage.class);
return MappingResult.of(messageObject, new TikTokQuestionEvent(messageObject));
});
onCustomDependencies.forEach(action -> action.accept(dependance)); mapper.forMessage(WebcastLikeMessage.class, roomInfoHandler::handleLike);
var container = dependance.build(); mapper.forMessage(WebcastGiftMessage.class, giftHandler::handleGifts);
mapper.forMessage(WebcastSocialMessage.class, socialHandler::handle);
mapper.forMessage(WebcastMemberMessage.class, roomInfoHandler::handleMemberMessage);
var listenerManager = container.find(ListenersManager.class);
listeners.forEach(listenerManager::addListener); //Host Interaction events
return container.find(LiveClient.class); mapper.forMessage(WebcastPollMessage.class, commonHandler::handlePollEvent);
mapper.forMessage(WebcastRoomPinMessage.class, commonHandler::handlePinMessage);
mapper.forMessage(WebcastChatMessage.class, (inputBytes, messageName, mapperHelper) ->
{
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
return MappingResult.of(messageObject, new TikTokCommentEvent(messageObject));
});
//LinkMic events
// mapper.webcastObjectToConstructor(WebcastLinkMicBattle.class, TikTokLinkMicBattleEvent.class);
// mapper.webcastObjectToConstructor(WebcastLinkMicArmies.class, TikTokLinkMicArmiesEvent.class);
// mapper.webcastObjectToConstructor(WebcastLinkMicMethod.class, TikTokLinkMicMethodEvent.class);
// mapper.webcastObjectToConstructor(WebcastLinkMicFanTicketMethod.class, TikTokLinkMicFanTicketEvent.class);
//Rank events
// mapper.webcastObjectToConstructor(WebcastRankTextMessage.class, TikTokRankTextEvent.class);
// mapper.webcastObjectToConstructor(WebcastRankUpdateMessage.class, TikTokRankUpdateEvent.class);
// mapper.webcastObjectToConstructor(WebcastHourlyRankMessage.class, TikTokRankUpdateEvent.class);
//Others events
// mapper.webcastObjectToConstructor(WebcastInRoomBannerMessage.class, TikTokInRoomBannerEvent.class);
// mapper.webcastObjectToConstructor(WebcastMsgDetectMessage.class, TikTokDetectEvent.class);
// mapper.webcastObjectToConstructor(WebcastBarrageMessage.class, TikTokBarrageEvent.class);
// mapper.webcastObjectToConstructor(WebcastUnauthorizedMemberMessage.class, TikTokUnauthorizedMemberEvent.class);
// mapper.webcastObjectToConstructor(WebcastOecLiveShoppingMessage.class, TikTokShopEvent.class);
// mapper.webcastObjectToConstructor(WebcastImDeleteMessage.class, TikTokIMDeleteEvent.class);
// mapper.bytesToEvents(WebcastEnvelopeMessage.class, commonHandler::handleEnvelop);
onCustomMappings.accept(mapper);
return mapper;
} }
public LiveClient buildAndConnect() { public LiveClient buildAndConnect() {
var client = build(); var client = build();
client.connect(); client.connect();
@@ -199,9 +275,273 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
return build().connectAsync(); return build().connectAsync();
} }
public TikTokLiveClientBuilder onUnhandledSocial(
EventConsumer<TikTokUnhandledSocialEvent> event) {
tikTokEventHandler.subscribe(TikTokUnhandledSocialEvent.class, event);
return this;
}
// @Override
public LiveClientBuilder onChest(EventConsumer<TikTokChestEvent> event) {
tikTokEventHandler.subscribe(TikTokChestEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkMicFanTicket(
EventConsumer<TikTokLinkMicFanTicketEvent> event) {
tikTokEventHandler.subscribe(TikTokLinkMicFanTicketEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onEnvelope(EventConsumer<TikTokEnvelopeEvent> event) {
tikTokEventHandler.subscribe(TikTokEnvelopeEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onShop(EventConsumer<TikTokShopEvent> event) {
tikTokEventHandler.subscribe(TikTokShopEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onDetect(
EventConsumer<TikTokDetectEvent> event) {
tikTokEventHandler.subscribe(TikTokDetectEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkLayer(
EventConsumer<TikTokLinkLayerEvent> event) {
tikTokEventHandler.subscribe(TikTokLinkLayerEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onConnected(EventConsumer<TikTokConnectedEvent> event) {
tikTokEventHandler.subscribe(TikTokConnectedEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onCaption(EventConsumer<TikTokCaptionEvent> event) {
tikTokEventHandler.subscribe(TikTokCaptionEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onQuestion(EventConsumer<TikTokQuestionEvent> event) {
tikTokEventHandler.subscribe(TikTokQuestionEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onRoomPin(
EventConsumer<TikTokRoomPinEvent> event) {
tikTokEventHandler.subscribe(TikTokRoomPinEvent.class, event);
return this;
}
@Override @Override
public <E extends TikTokEvent> LiveClientBuilder onEvent(Class<E> eventClass, EventConsumer<E> action) { public <E extends TikTokEvent> LiveClientBuilder onEvent(Class<E> eventClass, EventConsumer<E> event) {
eventHandler.subscribe(eventClass, action); tikTokEventHandler.subscribe(eventClass, event);
return this;
}
@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;
}
public TikTokLiveClientBuilder onLink(EventConsumer<TikTokLinkEvent> event) {
tikTokEventHandler.subscribe(TikTokLinkEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onBarrage(
EventConsumer<TikTokBarrageEvent> event) {
tikTokEventHandler.subscribe(TikTokBarrageEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onGift(EventConsumer<TikTokGiftEvent> event) {
tikTokEventHandler.subscribe(TikTokGiftEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onGiftCombo(EventConsumer<TikTokGiftComboEvent> event) {
tikTokEventHandler.subscribe(TikTokGiftComboEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkMicArmies(
EventConsumer<TikTokLinkMicArmiesEvent> event) {
tikTokEventHandler.subscribe(TikTokLinkMicArmiesEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onEmote(EventConsumer<TikTokEmoteEvent> event) {
tikTokEventHandler.subscribe(TikTokEmoteEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onUnauthorizedMember(
EventConsumer<TikTokUnauthorizedMemberEvent> event) {
tikTokEventHandler.subscribe(TikTokUnauthorizedMemberEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onInRoomBanner(
EventConsumer<TikTokInRoomBannerEvent> event) {
tikTokEventHandler.subscribe(TikTokInRoomBannerEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkMicMethod(
EventConsumer<TikTokLinkMicMethodEvent> event) {
tikTokEventHandler.subscribe(TikTokLinkMicMethodEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onSubscribe(EventConsumer<TikTokSubscribeEvent> event) {
tikTokEventHandler.subscribe(TikTokSubscribeEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onPoll(EventConsumer<TikTokPollEvent> event) {
tikTokEventHandler.subscribe(TikTokPollEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onFollow(EventConsumer<TikTokFollowEvent> event) {
tikTokEventHandler.subscribe(TikTokFollowEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onComment(EventConsumer<TikTokCommentEvent> event) {
tikTokEventHandler.subscribe(TikTokCommentEvent.class, event);
return this;
}
@Override
public LiveClientBuilder onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action) {
tikTokEventHandler.subscribe(TikTokHttpResponseEvent.class, action);
return this;
}
public TikTokLiveClientBuilder onGoalUpdate(EventConsumer<TikTokGoalUpdateEvent> event) {
tikTokEventHandler.subscribe(TikTokGoalUpdateEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onRankUpdate(EventConsumer<TikTokRankUpdateEvent> event) {
tikTokEventHandler.subscribe(TikTokRankUpdateEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onIMDelete(EventConsumer<TikTokIMDeleteEvent> event) {
tikTokEventHandler.subscribe(TikTokIMDeleteEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLiveEnded(EventConsumer<TikTokLiveEndedEvent> event) {
tikTokEventHandler.subscribe(TikTokLiveEndedEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onError(EventConsumer<TikTokErrorEvent> event) {
tikTokEventHandler.subscribe(TikTokErrorEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onJoin(EventConsumer<TikTokJoinEvent> event) {
tikTokEventHandler.subscribe(TikTokJoinEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onRankText(EventConsumer<TikTokRankTextEvent> event) {
tikTokEventHandler.subscribe(TikTokRankTextEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onShare(EventConsumer<TikTokShareEvent> event) {
tikTokEventHandler.subscribe(TikTokShareEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onUnhandledMember(
EventConsumer<TikTokUnhandledMemberEvent> event) {
tikTokEventHandler.subscribe(TikTokUnhandledMemberEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onSubNotify(EventConsumer<TikTokSubNotifyEvent> event) {
tikTokEventHandler.subscribe(TikTokSubNotifyEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkMicBattle(
EventConsumer<TikTokLinkMicBattleEvent> event) {
tikTokEventHandler.subscribe(TikTokLinkMicBattleEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onDisconnected(
EventConsumer<TikTokDisconnectedEvent> event) {
tikTokEventHandler.subscribe(TikTokDisconnectedEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onUnhandledControl(
EventConsumer<TikTokUnhandledControlEvent> event) {
tikTokEventHandler.subscribe(TikTokUnhandledControlEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onEvent(EventConsumer<TikTokEvent> event) {
tikTokEventHandler.subscribe(TikTokEvent.class, event);
return this;
}
@Override
public TikTokLiveClientBuilder onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> event) {
tikTokEventHandler.subscribe(TikTokWebsocketResponseEvent.class, event);
return this;
}
@Override
public TikTokLiveClientBuilder onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> event) {
tikTokEventHandler.subscribe(TikTokWebsocketMessageEvent.class, event);
return this;
}
@Override
public TikTokLiveClientBuilder onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> event) {
tikTokEventHandler.subscribe(TikTokWebsocketUnhandledMessageEvent.class, event);
return this;
}
@Override
public TikTokLiveClientBuilder onReconnecting(EventConsumer<TikTokReconnectingEvent> event) {
tikTokEventHandler.subscribe(TikTokReconnectingEvent.class, event);
return this; return this;
} }
} }

Some files were not shown because too many files have changed in this diff Show More