Compare commits

...

42 Commits

Author SHA1 Message Date
David Kohler
47493d4955 MINOR - Develop 1.8
Develop 1.8
2024-06-30 20:30:54 -04:00
jacek.wolniewicz
4d4317d96c Clean up code 2024-06-30 07:28:50 +02:00
jacek.wolniewicz
b1954a708c Fix issue: no events where triggered 2024-06-30 06:59:26 +02:00
kohlerpop1
14317337e9 Optimized TikTokLiveEventHandler 2024-06-29 23:57:53 -04:00
kohlerpop1
947c9c49a2 Improve addProxy(String addressPort) in ProxyClientSettings
Added @param action description and return values
Optimized methods in TikTokLiveMapper
Optimized Thread in TikTokWebSocketPingingTask
Optimized TikTokLiveEventHandler and TikTokLiveMessageHandler methods
2024-06-29 23:28:49 -04:00
jacek.wolniewicz
f2bd07377b Introduce dependecy injection container
- TikTokLiveClientBuilder this class has been higly modify to support DI container
2024-06-29 23:23:48 +02:00
jacek.wolniewicz
3f268f3a1a Introduce dependecy injection container
- TikTokLiveClientBuilder this class has been higly modify to support DI container
2024-06-29 23:12:24 +02:00
jacek.wolniewicz
55fcf83870 Introduce dependecy injection container
- TikTokLiveClientBuilder this class has been higly modify to support DI container
2024-06-29 23:07:50 +02:00
jacek.wolniewicz
8d3828cca8 Introduce dependecy injection container
- TikTokLiveClientBuilder this class has been higly modify to support DI container
2024-06-29 23:04:53 +02:00
jacek.wolniewicz
1c88491b8c Merge branch 'refs/heads/dev-dependecy-injection' into develop-1.7.3
# Conflicts:
#	API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/ProxyClientSettings.java
#	Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java
2024-06-29 22:57:56 +02:00
jacek.wolniewicz
47b050d0ba Introduce dependecy injection container
- TikTokLiveClientBuilder this class has been higly modify to support DI container
2024-06-29 22:52:39 +02:00
kohlerpop1
cfef082d3b Updated ProxyData exceptions to include previous exception to finish stacktrace
Updated LiveUserData.Request to throw an IllegalArgumentException when a null or blank username is provided
Updated HttpClientSettings to use setProxyClientSettings instead of direct access
Fixed ProxyRotation bug starting at index 1 instead of 0 and made methods default to synchronized in case concurrency is used in implementors code
Changed HttpClient#toUrl to toUri
Added @Getter to HttpClientFactory for liveClientSettings
Added consumer to TikTokLive#requests so that way proxies can be used when calling the fetch methods
Changed LiveUserData.Response#startTime to clarify the variable name
2024-06-28 23:07:10 -04:00
GitHub Action
34ddc74189 Update version in pom.xml 2024-06-24 14:16:40 +00:00
Jacek W
9a66d240bc Merge pull request #85 from jwdeveloper/develop-1.7.2
Develop 1.7.2
2024-06-24 08:38:22 +02:00
kohlerpop1
d825803187 Added while loop condition so it does not exit when getConnectionState returns Disconnected and stopOnDisconnect is false! 2024-06-23 23:06:05 -04:00
kohlerpop1
77c9cd6b52 Converted Consumer to BiConsumer to also accept liveClient! 2024-06-20 16:51:42 -04:00
kohlerpop1
0329d3cfeb Removed useless imports and altered logger message! 2024-06-18 22:01:47 -04:00
kohlerpop1
26659bb37d Removed not needed/used RecorderSettings#startOnConnected 2024-06-18 15:36:03 -04:00
kohlerpop1
0b9852c4d4 Moved ActionResult#message to top of toJson() for easier reading
Change Recording settings to accept an output file instead of directory and filename
2024-06-18 15:21:05 -04:00
GitHub Action
31618a16ba Update version in pom.xml 2024-06-07 10:55:14 +00:00
GitHub Action
243791f6b8 Update version in pom.xml 2024-06-02 20:11:19 +00:00
David Kohler
4f74a0f1b7 MINOR 2024-06-02 16:09:45 -04:00
GitHub Action
d1eec34fca Update version in pom.xml 2024-06-02 20:07:58 +00:00
David Kohler
82196ef8e3 MINOR: Merge pull request #84 from jwdeveloper/develop-1.6.4
Develop 1.6.4
2024-06-02 16:06:24 -04:00
kohlerpop1
8685d96ccf Moved roomId declaration to RoomInfoEvent as it is always null during onConnecting event!
Made other improvements for readability and altered createdAt field.
2024-06-01 22:36:43 -04:00
kohlerpop1
69f1d5b5c2 Fixed proto file type names, created TikTokEventListenerBase with all events, created ListUser with additional information, and created all events for TikTokLink individual events 2024-06-01 22:18:43 -04:00
kohlerpop1
6f322b2a46 Fixed custom listener manager checks. Previous implementation allowed incorrect parameter types! 2024-05-29 15:38:06 -04:00
kohlerpop1
73c4c09ea1 Moved ActionResult message above content to make it easier to read in json print out!
Added status code 420 for IP cloudflare block
2024-05-29 14:11:27 -04:00
kohlerpop1
95e357af92 Updated HTTP response code messages
General optimization of classes and removal of no longer needed classes
Removed unused imports
2024-05-29 14:00:20 -04:00
Jacek W
6b31ec7d80 Merge pull request #80 from htliang128/master
Update of Socks Proxy adding headers
2024-05-26 22:46:43 +02:00
htliang128
919554bbc8 Update of Socks Proxy adding headers 2024-05-25 12:22:31 +08:00
htliang128
bd0a1f0d01 Update of Socks Proxy adding headers 2024-05-25 12:20:57 +08:00
htliang128
f48479a92c Update of Socks Proxy adding headers 2024-05-25 12:17:46 +08:00
GitHub Action
68a86f3dbd Update version in pom.xml 2024-05-24 01:34:38 +00:00
David Kohler
c3a7a27948 Merge pull request #78 from jwdeveloper/develop-1.6.3
Develop-1.6.3
2024-05-23 21:31:48 -04:00
kohlerpop1
af52e15a45 Removal of shared cookie parameter cookie in TikTokWebSocketClient!
Privatized objects in HttpClientSettings so getters are used!
2024-05-23 21:29:03 -04:00
GitHub Action
5577df7c9c Update version in pom.xml 2024-05-23 22:45:49 +00:00
David Kohler
2c68fe3421 Merge pull request #77 from jwdeveloper/develop-1.6.2
Develop 1.6.2
2024-05-23 18:42:15 -04:00
kohlerpop1
5abfd95c89 Update of Lombok
Fixed headers being passed to Websocket. Huge thanks to @isaackogan - https://github.com/isaackogan
2024-05-23 18:32:55 -04:00
kohlerpop1
5c715bfd52 Changed Picture#Empty to Picture#empty to follow Java standards
Updated descriptions in LiveClientSettings
Added new LiveHttpClient#fetchRoomGiftsData(String room_id) to fetch gifts for this specific room/livestream and altered GiftsDataMapper to reflect the new fetchRoomGiftsData and other TikTokLive client and http client classes
2024-05-13 21:14:03 -04:00
GitHub Action
b153afb332 Update version in pom.xml 2024-05-13 00:55:24 +00:00
David Kohler
d2ea00bcae Merge pull request #72 from jwdeveloper/develop-1.6.1
Develop 1.6.1
2024-05-12 20:52:28 -04:00
112 changed files with 2411 additions and 2088 deletions

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.6.0-Release</version> <version>1.7.2-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>API</artifactId> <artifactId>API</artifactId>

View File

@@ -50,16 +50,12 @@ public class ProxyData
return new ProxyData(address, port); return new ProxyData(address, port);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new IllegalArgumentException("Port must be a valid integer!"); throw new IllegalArgumentException("Port must be a valid integer!", e);
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
throw new IllegalArgumentException("Address must be valid IPv4, IPv6, or domain name!"); throw new IllegalArgumentException("Address must be valid IPv4, IPv6, or domain name!", e);
} }
} }
public ProxyData clone() {
return new ProxyData(address, port);
}
public InetSocketAddress toSocketAddress() { public InetSocketAddress toSocketAddress() {
return new InetSocketAddress(address, port); return new InetSocketAddress(address, port);
} }

View File

@@ -38,8 +38,7 @@ 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());
@@ -49,6 +48,5 @@ 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

@@ -38,9 +38,9 @@ public class TikTokCaptionEvent extends TikTokHeaderEvent {
String text; String text;
public TikTokCaptionEvent(WebcastCaptionMessage msg) { public TikTokCaptionEvent(WebcastCaptionMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
captionTimeStamp = msg.getTimeStamp(); captionTimeStamp = msg.getTimeStamp();
iSOLanguage = msg.getCaptionData().getLanguage(); iSOLanguage = msg.getCaptionData().getLanguage();
text = msg.getCaptionData().getText(); text = msg.getCaptionData().getText();
} }
} }

View File

@@ -40,7 +40,7 @@ import java.util.List;
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 getUserLanguage; private final String userLanguage;
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;
@@ -50,7 +50,7 @@ public class TikTokCommentEvent extends TikTokHeaderEvent {
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();
getUserLanguage = msg.getContentLanguage(); userLanguage = 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();
} }
@@ -66,4 +66,4 @@ public class TikTokCommentEvent extends TikTokHeaderEvent {
builder.setContent(message); builder.setContent(message);
return new TikTokCommentEvent(builder.build()); return new TikTokCommentEvent(builder.build());
} }
} }

View File

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

View File

@@ -30,9 +30,11 @@ import lombok.Getter;
* Triggered when the connection gets disconnected. In that case you can call connect() again to have a reconnect logic. * 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. * Note that you should wait a little bit before attempting a reconnect to to avoid being rate-limited.
*/ */
@Getter
@EventMeta(eventType = EventType.Control) @EventMeta(eventType = EventType.Control)
public class TikTokDisconnectedEvent extends TikTokLiveClientEvent { public class TikTokDisconnectedEvent extends TikTokLiveClientEvent {
@Getter private final String reason; private final String reason;
public TikTokDisconnectedEvent(String reason) { public TikTokDisconnectedEvent(String reason) {
this.reason = reason.isBlank() ? "None" : reason; this.reason = reason.isBlank() ? "None" : reason;
} }

View File

@@ -36,9 +36,9 @@ import lombok.Value;
@Value @Value
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokEnvelopeEvent extends TikTokHeaderEvent { public class TikTokEnvelopeEvent extends TikTokHeaderEvent {
User user; User user;
public TikTokEnvelopeEvent(WebcastEnvelopeMessage msg) { public TikTokEnvelopeEvent(WebcastEnvelopeMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
user = User.map(msg.getEnvelopeInfo()); user = User.map(msg.getEnvelopeInfo());
} }
} }

View File

@@ -34,9 +34,10 @@ import java.util.List;
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokIMDeleteEvent extends TikTokHeaderEvent { public class TikTokIMDeleteEvent extends TikTokHeaderEvent {
List<Long> userIds; private final List<Long> msgIds, 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

@@ -31,10 +31,10 @@ import lombok.Getter;
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokInRoomBannerEvent extends TikTokHeaderEvent { public class TikTokInRoomBannerEvent extends TikTokHeaderEvent {
private final String json; private final String json;
public TikTokInRoomBannerEvent(WebcastInRoomBannerMessage msg) { public TikTokInRoomBannerEvent(WebcastInRoomBannerMessage msg) {
super(msg.getHeader()); super(msg.getHeader());
json = msg.getJson(); json = msg.getJson();
} }
} }

View File

@@ -33,11 +33,7 @@ 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

@@ -32,10 +32,8 @@ import lombok.Getter;
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokLinkMicMethodEvent extends TikTokHeaderEvent { public class TikTokLinkMicMethodEvent extends TikTokHeaderEvent {
public TikTokLinkMicMethodEvent(WebcastLinkMicMethod msg) { public TikTokLinkMicMethodEvent(WebcastLinkMicMethod msg) {
super(msg.getCommon()); super(msg.getCommon());
} }
}
}

View File

@@ -32,15 +32,14 @@ import lombok.Getter;
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokRankTextEvent extends TikTokHeaderEvent { public class TikTokRankTextEvent extends TikTokHeaderEvent {
private final String eventType; private final String eventType;
private final String label; private final String label;
public TikTokRankTextEvent(WebcastRankTextMessage msg) { public TikTokRankTextEvent(WebcastRankTextMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
var text = Text.map(msg.getSelfGetBadgeMsg()); var text = Text.map(msg.getSelfGetBadgeMsg());
label = text.getPattern(); label = text.getPattern();
eventType = text.getKey(); eventType = text.getKey();
} }
}
}

View File

@@ -33,13 +33,11 @@ import lombok.Getter;
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokRankUpdateEvent extends TikTokHeaderEvent { public class TikTokRankUpdateEvent extends TikTokHeaderEvent {
public TikTokRankUpdateEvent(WebcastHourlyRankMessage msg) { public TikTokRankUpdateEvent(WebcastHourlyRankMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
}
} public TikTokRankUpdateEvent(WebcastRankUpdateMessage msg) {
super(msg.getCommon());
public TikTokRankUpdateEvent(WebcastRankUpdateMessage msg) { }
super(msg.getCommon()); }
}
}

View File

@@ -32,25 +32,24 @@ import lombok.Getter;
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokShopEvent extends TikTokHeaderEvent { public class TikTokShopEvent extends TikTokHeaderEvent {
private final String title; private final String title;
private final String price; private final String price;
private final Picture picture; private final Picture picture;
private final String shopUrl; private final String shopUrl;
private final String shopName; private final String shopName;
//Not working //Not working
public TikTokShopEvent(WebcastOecLiveShoppingMessage msg) { public TikTokShopEvent(WebcastOecLiveShoppingMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
var data = msg.getShopData(); var data = msg.getShopData();
title = data.getTitle(); title = data.getTitle();
price = data.getPriceString(); price = data.getPriceString();
picture = new Picture(data.getImageUrl()); picture = new Picture(data.getImageUrl());
shopUrl = data.getShopUrl(); shopUrl = data.getShopUrl();
shopName = data.getShopName(); shopName = data.getShopName();
} }
}
}

View File

@@ -30,12 +30,13 @@ import lombok.*;
/** /**
* Triggered before the connection is established. * Triggered before the connection is established.
*/ */
@Getter
@EventMeta(eventType = EventType.Control) @EventMeta(eventType = EventType.Control)
public class TikTokPreConnectionEvent extends TikTokLiveClientEvent public class TikTokPreConnectionEvent extends TikTokLiveClientEvent
{ {
@Getter private final LiveUserData.Response userData; private final LiveUserData.Response userData;
@Getter private final LiveData.Response roomData; private final LiveData.Response roomData;
@Getter @Setter boolean cancelConnection = false; @Setter boolean cancelConnection = false;
public TikTokPreConnectionEvent(LiveUserData.Response userData, LiveData.Response liveData) { public TikTokPreConnectionEvent(LiveUserData.Response userData, LiveData.Response liveData) {
this.userData = userData; this.userData = userData;

View File

@@ -0,0 +1,45 @@
/*
* 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

@@ -20,18 +20,17 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
package io.github.jwdeveloper.tiktok.data.models; package io.github.jwdeveloper.tiktok.data.events.link;
import lombok.Value; import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import lombok.Getter;
@Value @Getter
public class EnumValue @EventMeta(eventType = EventType.Message)
{ public class TikTokLinkApplyEvent extends TikTokLinkEvent {
public int value;
public String name;
public static EnumValue Map(Enum<?> _enum) public TikTokLinkApplyEvent(WebcastLinkMessage msg) {
{ super(msg);
return new EnumValue(_enum.ordinal() ,_enum.name());
} }
} }

View File

@@ -0,0 +1,46 @@
/*
* 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

@@ -20,15 +20,20 @@
* 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.handler; 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;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; @Getter
@EventMeta(eventType = EventType.Message)
public class TikTokLinkCloseEvent extends TikTokLinkEvent {
import java.util.List; public TikTokLinkCloseEvent(WebcastLinkMessage msg) {
super(msg);
// if (!msg.hasCloseContent())
public interface TikTokMessageHandler // throw new IllegalArgumentException("Expected WebcastLinkMessage with Close Content!");
{ // Proto Empty
List<TikTokEvent> handle(byte[] messagePayload) throws Exception; }
} }

View File

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

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

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

@@ -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; package io.github.jwdeveloper.tiktok.data.events.link;
import io.github.jwdeveloper.tiktok.annotations.EventMeta; import io.github.jwdeveloper.tiktok.annotations.*;
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

@@ -0,0 +1,46 @@
/*
* 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

@@ -0,0 +1,55 @@
/*
* 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

@@ -0,0 +1,47 @@
/*
* 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

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

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

@@ -0,0 +1,47 @@
/*
* 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

@@ -20,24 +20,20 @@
* 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; package io.github.jwdeveloper.tiktok.data.events.link;
import io.github.jwdeveloper.tiktok.annotations.EventMeta; import io.github.jwdeveloper.tiktok.annotations.*;
import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMessage;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent; import lombok.Getter;
import io.github.jwdeveloper.tiktok.data.models.users.User; @Getter
import lombok.Data;
@Data
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class CustomEvent extends TikTokHeaderEvent { public class TikTokLinkMicIdxUpdateEvent extends TikTokLinkEvent {
private final User user;
private final String title;
public CustomEvent(User user, String title) { public TikTokLinkMicIdxUpdateEvent(WebcastLinkMessage msg) {
this.user = user; super(msg);
this.title = title; // if (!msg.hasMicIdxUpdateContent())
// throw new IllegalArgumentException("Expected WebcastLinkMessage with Mic Idx Update Content!");
// Proto Empty
} }
} }

View File

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

@@ -0,0 +1,50 @@
/*
* 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

@@ -0,0 +1,47 @@
/*
* 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

@@ -0,0 +1,45 @@
/*
* 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

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

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

@@ -0,0 +1,47 @@
/*
* 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

@@ -20,7 +20,20 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
package io.github.jwdeveloper.tiktok.mappers.handlers; package io.github.jwdeveloper.tiktok.data.events.link;
public class TikTokChestEventHandler { 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,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/* /**
Triggered when LiveRoomInfo got updated such as likes, viewers, ranking .... Triggered when LiveRoomInfo got updated such as likes, viewers, ranking ....
*/ */
@Getter @Getter
@@ -39,4 +39,4 @@ Triggered when LiveRoomInfo got updated such as likes, viewers, ranking ....
public class TikTokRoomInfoEvent extends TikTokEvent public class TikTokRoomInfoEvent extends TikTokEvent
{ {
LiveRoomInfo roomInfo; LiveRoomInfo roomInfo;
} }

View File

@@ -33,15 +33,13 @@ 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; public TikTokRoomPinEvent(WebcastRoomPinMessage msg, TikTokCommentEvent commentEvent)
private long timestamp; {
super(msg.getCommon());
public TikTokRoomPinEvent(WebcastRoomPinMessage msg, TikTokCommentEvent commentEvent) this.timestamp = msg.getTimestamp();
{ this.pinnedMessage = commentEvent;
super(msg.getCommon()); }
this.timestamp = msg.getTimestamp(); }
this.pinnedMessage = commentEvent;
}
}

View File

@@ -24,10 +24,8 @@ package io.github.jwdeveloper.tiktok.data.events.social;
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.TikTokSubscribeEvent;
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.WebcastMemberMessage;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastSocialMessage;
import lombok.Value; import lombok.Value;
@@ -38,21 +36,21 @@ import lombok.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;
public TikTokFollowEvent(WebcastSocialMessage msg) { public TikTokFollowEvent(WebcastSocialMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
user = User.map(msg.getUser()); user = User.map(msg.getUser());
totalFollowers = msg.getFollowCount(); totalFollowers = msg.getFollowCount();
} }
public static TikTokFollowEvent of(String userName) public static TikTokFollowEvent of(String userName)
{ {
return new TikTokFollowEvent(WebcastSocialMessage.newBuilder() return new TikTokFollowEvent(WebcastSocialMessage.newBuilder()
.setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder() .setUser(io.github.jwdeveloper.tiktok.messages.data.User.newBuilder()
.setNickname(userName) .setNickname(userName)
.build()) .build())
.build()); .build());
} }
} }

View File

@@ -35,19 +35,18 @@ import lombok.Getter;
@Getter @Getter
@EventMeta(eventType = EventType.Message) @EventMeta(eventType = EventType.Message)
public class TikTokShareEvent extends TikTokHeaderEvent { public class TikTokShareEvent extends TikTokHeaderEvent {
private final User user; private final User user;
private final int totalShares; private final int totalShares;
public TikTokShareEvent(WebcastSocialMessage msg, Integer amount) { public TikTokShareEvent(WebcastSocialMessage msg, Integer amount) {
super(msg.getCommon()); super(msg.getCommon());
user = User.map(msg.getUser()); user = User.map(msg.getUser());
this.totalShares = amount; this.totalShares = amount;
} }
public TikTokShareEvent(WebcastSocialMessage msg) { public TikTokShareEvent(WebcastSocialMessage msg) {
super(msg.getCommon()); super(msg.getCommon());
user = User.map(msg.getUser()); user = User.map(msg.getUser());
totalShares = 1; totalShares = 1;
} }
}
}

View File

@@ -93,7 +93,7 @@ public class Picture {
} }
} }
public static Picture Empty() { public static Picture empty() {
return new Picture(""); return new Picture("");
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -22,7 +22,6 @@
*/ */
package io.github.jwdeveloper.tiktok.data.models.gifts; package io.github.jwdeveloper.tiktok.data.models.gifts;
//TODO it should be called GiftComboStateType
public enum GiftComboStateType { public enum GiftComboStateType {
Finished, Finished,
Begin, Begin,

View File

@@ -0,0 +1,56 @@
/*
* 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
}
}

View File

@@ -169,7 +169,7 @@ 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()));

View File

@@ -23,20 +23,12 @@
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.AllArgsConstructor; import lombok.*;
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
@@ -44,5 +36,4 @@ public class GiftsData
private String json; private String json;
private List<Gift> gifts; private List<Gift> gifts;
} }
}
}

View File

@@ -27,18 +27,23 @@ import lombok.*;
public class LiveUserData { public class LiveUserData {
@Getter @Getter
@AllArgsConstructor
public static class Request { public static class Request {
private String userName; private final 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 String json; private final String json;
private UserStatus userStatus; private final UserStatus userStatus;
private String roomId; private final String roomId;
private long startedAtTimeStamp; private final long startTime;
public boolean isLiveOnline() { public boolean isLiveOnline() {
return userStatus == LiveUserData.UserStatus.Live || userStatus == LiveUserData.UserStatus.LivePaused; return userStatus == LiveUserData.UserStatus.Live || userStatus == LiveUserData.UserStatus.LivePaused;

View File

@@ -34,30 +34,24 @@ import java.util.TreeMap;
import java.util.function.Consumer; import java.util.function.Consumer;
@Getter
public class HttpClientSettings { public class HttpClientSettings {
@Getter private final Map<String, Object> params;
final Map<String, Object> params;
@Getter private final Map<String, String> headers;
final Map<String, String> headers;
@Getter private final Map<String, String> cookies;
final Map<String, String> cookies;
@Getter
@Setter
ProxyClientSettings proxyClientSettings;
@Getter
Consumer<HttpClient.Builder> onClientCreating;
@Getter
Consumer<HttpRequest.Builder> onRequestCreating;
@Setter @Setter
@Getter private ProxyClientSettings proxyClientSettings;
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<>();
@@ -65,10 +59,8 @@ 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) -> {
};
} }
/** /**
@@ -105,7 +97,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.proxyClientSettings = this.proxyClientSettings; newSettings.setProxyClientSettings(this.proxyClientSettings);
return newSettings; return newSettings;
} }

View File

@@ -33,20 +33,15 @@ import java.util.logging.Level;
@Data @Data
public class LiveClientSettings { public class LiveClientSettings {
/** /**
* TODO: give better description * Sets client to offline mode, prohibits connection to TikTok servers
* <p> * @apiNote Useful when testing client with custom events
* sets client in the offline mode, so it do not connects to TikTok servers
* it makes sense to use it when you are testing client with your custom events
*/ */
private boolean offline; private boolean offline;
/** /**
* TODO: give better description * Fetch and download gifts data before TikTokLive starts
* <p> * @apiNote If `false`, client.giftManager() does not contain initial gifts
* Determines if gifts data is downloaded before TikTokLive starts,
* when `false` then client.giftManager() does not contain initial gifts
*/ */
private boolean fetchGifts = true; private boolean fetchGifts = true;
@@ -183,6 +178,4 @@ 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

@@ -31,17 +31,17 @@ import java.util.function.Consumer;
@Getter @Getter
@Setter @Setter
public class ProxyClientSettings implements Iterator<ProxyData> public class ProxyClientSettings implements Iterator<ProxyData>, Iterable<ProxyData>
{ {
private boolean enabled, autoDiscard = true, fallback = true; private boolean enabled, autoDiscard = true, fallback = true;
private Rotation rotation = Rotation.CONSECUTIVE; private Rotation rotation = Rotation.CONSECUTIVE;
private final List<ProxyData> proxyList = new ArrayList<>(); private final List<ProxyData> proxyList = new ArrayList<>();
private int index = -1; private int index;
private Proxy.Type type = Proxy.Type.DIRECT; private Proxy.Type type = Proxy.Type.DIRECT;
private Consumer<ProxyData> onProxyUpdated = x -> {}; private Consumer<ProxyData> onProxyUpdated = x -> {};
public boolean addProxy(String addressPort) { public boolean addProxy(String addressPort) {
return proxyList.add(ProxyData.map(addressPort)); return addProxy(ProxyData.map(addressPort).toSocketAddress());
} }
public boolean addProxy(String address, int port) { public boolean addProxy(String address, int port) {
@@ -57,33 +57,27 @@ public class ProxyClientSettings implements Iterator<ProxyData>
} }
@Override @Override
public boolean hasNext() { public synchronized boolean hasNext() {
return !proxyList.isEmpty(); return !proxyList.isEmpty();
} }
@Override @Override
public ProxyData next() { public synchronized ProxyData next() {
var nextProxy = switch (rotation) try {
{ var nextProxy = proxyList.get(index);
case CONSECUTIVE -> { onProxyUpdated.accept(nextProxy);
index = (index+1) % proxyList.size(); return nextProxy;
yield proxyList.get(index).clone(); } finally {
switch (rotation) {
case CONSECUTIVE -> index = ++index % proxyList.size();
case RANDOM -> index = (int) (Math.random() * proxyList.size());
case NONE -> index = Math.max(index, 0);
} }
case RANDOM -> { }
index = new Random().nextInt(proxyList.size()); }
yield proxyList.get(index).clone();
}
case NONE -> {
index = Math.max(index, 0);
yield proxyList.get(index).clone();
}
};
onProxyUpdated.accept(nextProxy);
return nextProxy;
}
@Override @Override
public void remove() { public synchronized void remove() {
proxyList.remove(index); proxyList.remove(index);
} }
@@ -97,8 +91,8 @@ public class ProxyClientSettings implements Iterator<ProxyData>
} }
} }
public ProxyClientSettings clone() @Override
{ public ProxyClientSettings clone() {
ProxyClientSettings settings = new ProxyClientSettings(); ProxyClientSettings settings = new ProxyClientSettings();
settings.setEnabled(enabled); settings.setEnabled(enabled);
settings.setRotation(rotation); settings.setRotation(rotation);
@@ -109,6 +103,27 @@ public class ProxyClientSettings implements Iterator<ProxyData>
return settings; 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 public enum Rotation
{ {
/** Rotate addresses consecutively, from proxy 0 -> 1 -> 2 -> ...etc. */ /** Rotate addresses consecutively, from proxy 0 -> 1 -> 2 -> ...etc. */

View File

@@ -30,10 +30,14 @@ import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
public interface LiveHttpClient public interface LiveHttpClient
{ {
/** /**
* @return list of gifts that are available in your country * @return {@link GiftsData.Response} list of gifts that are compiled and available on github
*/ */
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

View File

@@ -33,6 +33,7 @@ import java.util.List;
public interface ListenersManager public interface ListenersManager
{ {
List<TikTokEventListener> getListeners(); List<TikTokEventListener> getListeners();
void addListener(TikTokEventListener listener); void addListener(TikTokEventListener listener);
void removeListener(TikTokEventListener listener); void removeListener(TikTokEventListener listener);

View File

@@ -22,53 +22,52 @@
*/ */
package io.github.jwdeveloper.tiktok.listener; package io.github.jwdeveloper.tiktok.listener;
import io.github.jwdeveloper.tiktok.live.LiveClient;
/** /**
* * ListenersManager
* @see ListenersManager * <p>
*
* 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);}
* <p>
* After registertion, all listeners are kept in Listener manager - {@link LiveClient#getListenersManager()}
* <p>
* Method in TikTokEventListener should meet requirements below to be detected
* <p>- @TikTokEventObserver annotation
* <p>- 2 parameters of (LiveClient, Class extending TikTokEvent)
* <pre>
* {@code
* public static class CustomListener implements TikTokEventListener
* {
* @TikTokEventObserver
* public void onError(LiveClient liveClient, TikTokErrorEvent event)
* {
* System.out.println(event.getException().getMessage());
* }
* *
* TikTokLive.newClient("someuser").addListener(listener) * @TikTokEventObserver
* public void onCommentMessage(LiveClient liveClient, TikTokCommentEvent event)
* {
* System.out.println(event.getText());
* }
* *
* After registertion all listeners are kept in Listener manager * @TikTokEventObserver
* that could be obtained by client.getListenerManager(); * public void onGiftMessage(LiveClient liveClient, TikTokGiftMessageEvent event)
* * {
* Method in TikTokEventListener should meet 4 requirements to be detected * System.out.println(event.getGift().getDescription());
* - must have @TikTokEventHandler annotation * }
* - must have 2 parameters
* - first parameter must be LiveClient
* - second must be class that extending TikTokEvent
*
* public static class CustomListener implements TikTokEventListener
* {
* @TikTokEventHandler
* public void onError(LiveClient liveClient, TikTokErrorEvent event)
* {
* System.out.println(event.getException().getMessage());
* }
*
* @TikTokEventHandler
* public void onCommentMessage(LiveClient liveClient, TikTokCommentEvent event)
* {
* System.out.println(event.getText());
* }
*
* @TikTokEventHandler
* public void onGiftMessage(LiveClient liveClient, TikTokGiftMessageEvent event)
* {
* System.out.println(event.getGift().getDescription());
* }
*
* @TikTokEventHandler
* public void onAnyEvent(LiveClient liveClient, TikTokEvent event)
* {
* System.out.println(event.getClass().getSimpleName());
* }
* }
* *
* @TikTokEventObserver
* public void onAnyEvent(LiveClient liveClient, TikTokEvent event)
* {
* System.out.println(event.getClass().getSimpleName());
* }
* }
* }
* </pre>
*/ */
public interface TikTokEventListener public interface TikTokEventListener
{ {
} }

View File

@@ -0,0 +1,156 @@
/*
* 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

@@ -25,7 +25,13 @@ 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

@@ -52,77 +52,70 @@ public interface EventsBuilder<T> {
/** /**
* Invoked whenever any event is triggered * Invoked whenever any event is triggered
* *
* @param action * @param action consumable action
* @return * @return self instance
*/ */
T onEvent(EventConsumer<TikTokEvent> action); T onEvent(EventConsumer<TikTokEvent> 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 * @param action consumable action
* @return * @return self instance
*/ */
T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> action); T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> 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
*/ */
T onComment(EventConsumer<TikTokCommentEvent> action); T onComment(EventConsumer<TikTokCommentEvent> 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
*/ */
T onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action); T onHttpResponse(EventConsumer<TikTokHttpResponseEvent> 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
*/ */
T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> action); T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> action);
/** /**
* Invoked when there was not found event mapper for TikTok protocolBuffer data "message" * Invoked when there was not found event mapper for TikTok protocolBuffer data "message"
* * @param action consumable action
* @param action * @return self instance
* @return
*/ */
T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> action); T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> 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
*/ */
T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> action); T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> action);
/** /**
* Invoked for gifts that has no combo, or when combo finishes * Invoked for gifts that has no combo, or when combo finishes
* @param action * @param action consumable action
* @return * @return self instance
*/ */
T onGift(EventConsumer<TikTokGiftEvent> action); T onGift(EventConsumer<TikTokGiftEvent> action);
/** /**
* Invoked for gifts that has combo options such as roses * Invoked for gifts that has combo options such as roses
* @param action * @param action consumable action
* @return * @return self instance
*/ */
T onGiftCombo(EventConsumer<TikTokGiftComboEvent> action); T onGiftCombo(EventConsumer<TikTokGiftComboEvent> action);
T onQuestion(EventConsumer<TikTokQuestionEvent> action); T onQuestion(EventConsumer<TikTokQuestionEvent> action);
T onSubscribe(EventConsumer<TikTokSubscribeEvent> action); T onSubscribe(EventConsumer<TikTokSubscribeEvent> action);
@@ -145,36 +138,36 @@ public interface EventsBuilder<T> {
/** /**
* 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
*/ */
T onConnected(EventConsumer<TikTokConnectedEvent> action); T onConnected(EventConsumer<TikTokConnectedEvent> action);
/** /**
* Invoked before client has been successfully connected to live * Invoked before client has been successfully connected to live
* @param action * @param action consumable action
* @return * @return self instance
*/ */
T onPreConnection(EventConsumer<TikTokPreConnectionEvent> action); T onPreConnection(EventConsumer<TikTokPreConnectionEvent> action);
/** /**
* Invoked when client tries to reconnect * Invoked when client tries to reconnect
* @param action * @param action consumable action
* @return * @return self instance
*/ */
T onReconnecting(EventConsumer<TikTokReconnectingEvent> action); T onReconnecting(EventConsumer<TikTokReconnectingEvent> action);
/** /**
* Invoked when client disconnected * Invoked when client disconnected
* @param action * @param action consumable action
* @return * @return self instance
*/ */
T onDisconnected(EventConsumer<TikTokDisconnectedEvent> action); T onDisconnected(EventConsumer<TikTokDisconnectedEvent> 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
*/ */
T onError(EventConsumer<TikTokErrorEvent> action); T onError(EventConsumer<TikTokErrorEvent> action);

View File

@@ -32,13 +32,18 @@ import java.util.function.Function;
public interface TikTokMapper { public interface TikTokMapper {
/** /**
* * if mapper is not found for messageName, TikTokLiveException is thrown * when 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);

View File

@@ -1062,9 +1062,9 @@ message CohostListChangeContent {
message LinkerListChangeContent { message LinkerListChangeContent {
repeated ListUser linkedUsersList = 1; repeated ListUser linkedUsers = 1;
repeated ListUser appliedUsersList = 2; repeated ListUser appliedUsers = 2;
repeated ListUser connectingUsersList = 3; repeated ListUser connectingUsers = 3;
} }
message LinkerMediaChangeContent { message LinkerMediaChangeContent {

View File

@@ -250,21 +250,21 @@ enum CommonContentCase {
enum LinkMessageType { enum LinkMessageType {
TPYE_LINKER_UNKNOWN = 0; TYPE_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;
TPYE_LINKER_ENTER = 6; TYPE_LINKER_ENTER = 6;
TPYE_LINKER_LEAVE = 7; TYPE_LINKER_LEAVE = 7;
TYPE_LINKER_PERMIT = 8; TYPE_LINKER_PERMIT = 8;
TPYE_LINKER_CANCEL_INVITE = 9; TYPE_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;
TPYE_LINKER_KICK_OUT = 13; TYPE_LINKER_KICK_OUT = 13;
TPYE_LINKER_CANCEL_APPLY = 14; TYPE_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 +275,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;
TPYE_LINKER_SYS_KICK_OUT = 101; TYPE_LINKER_SYS_KICK_OUT = 101;
TPYE_LINKMIC_USER_TOAST = 102; TYPE_LINKMIC_USER_TOAST = 102;
} }
enum MessageType { enum MessageType {

View File

@@ -805,7 +805,7 @@ message WebcastLinkMessage {
LinkerListChangeContent ListChangeContent = 20; LinkerListChangeContent ListChangeContent = 20;
CohostListChangeContent CohostListChangeContent = 21; CohostListChangeContent CohostListChangeContent = 21;
LinkerMediaChangeContent MediaChangeContent = 22; LinkerMediaChangeContent MediaChangeContent = 22;
LinkerAcceptNoticeContent ReplyAcceptNoticeContent = 23; LinkerAcceptNoticeContent AcceptNoticeContent = 23;
LinkerSysKickOutContent SysKickOutContent = 101; LinkerSysKickOutContent SysKickOutContent = 101;
LinkmicUserToastContent UserToastContent = 102; LinkmicUserToastContent UserToastContent = 102;
string extra = 200; string extra = 200;

View File

@@ -5,12 +5,18 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.6.0-Release</version> <version>1.7.2-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>Client</artifactId> <artifactId>Client</artifactId>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies> <dependencies>
<dependency> <dependency>
@@ -24,7 +30,12 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.github.jwdeveloper.DepenDance</groupId>
<artifactId>DepenDance-Full</artifactId>
<version>0.0.18-Release</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId> <artifactId>protobuf-java</artifactId>

View File

@@ -23,19 +23,21 @@
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.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.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.concurrent.CompletableFuture;
import java.util.function.Consumer;
public class TikTokLive { public class TikTokLive {
/** /**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo' * Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
* *
* @param hostName profile name of Tiktok user could be found in profile link * @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) {
@@ -45,7 +47,7 @@ public class TikTokLive {
/** /**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo' * Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
* *
* @param hostName profile name of Tiktok user could be found in profile link * @param hostName profile name of TikTok user could be found in profile link
* @return true if live is Online, false if is offline * @return true if live is Online, false if is offline
*/ */
public static boolean isLiveOnline(String hostName) { public static boolean isLiveOnline(String hostName) {
@@ -55,7 +57,7 @@ public class TikTokLive {
/** /**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo' * Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
* *
* @param hostName profile name of Tiktok user could be found in profile link * @param hostName profile name of TikTok user could be found in profile link
* @return true if live is Online, false if is offline * @return true if live is Online, false if is offline
*/ */
public static CompletableFuture<Boolean> isLiveOnlineAsync(String hostName) { public static CompletableFuture<Boolean> isLiveOnlineAsync(String hostName) {
@@ -65,7 +67,7 @@ public class TikTokLive {
/** /**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo' * Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
* *
* @param hostName profile name of Tiktok user could be found in profile link * @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 * @return true is hostName name is valid and exists, false if not
*/ */
public static boolean isHostNameValid(String hostName) { public static boolean isHostNameValid(String hostName) {
@@ -75,7 +77,7 @@ public class TikTokLive {
/** /**
* Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo' * Example: https://www.tiktok.com/@dostawcavideo - hostName would be 'dostawcavideo'
* *
* @param hostName profile name of Tiktok user could be found in profile link * @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 * @return true is hostName name is valid and exists, false if not
*/ */
public static CompletableFuture<Boolean> isHostNameValidAsync(String hostName) { public static CompletableFuture<Boolean> isHostNameValidAsync(String hostName) {
@@ -87,11 +89,19 @@ public class TikTokLive {
* *
* @return LiveHttpClient * @return LiveHttpClient
*/ */
public static LiveHttpClient requests() { public static LiveHttpClient requests(Consumer<LiveClientSettings> consumer) {
return new TikTokLiveHttpClient(); return new TikTokLiveHttpClient(consumer);
}
/**
* Use to get some data from TikTok about users are lives
*
* @return LiveHttpClient
*/
public static LiveHttpClient requests() {
return requests(liveClientSettings -> {});
} }
//I don't like it, but it is reasonable for now
private static GiftsManager giftsManager; private static GiftsManager giftsManager;
/** /**

View File

@@ -23,6 +23,7 @@
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import io.github.jwdeveloper.dependance.injector.api.annotations.Inject;
import io.github.jwdeveloper.tiktok.data.events.*; import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.events.control.*; import io.github.jwdeveloper.tiktok.data.events.control.*;
@@ -43,13 +44,14 @@ 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;
public class TikTokLiveClient implements LiveClient { public class TikTokLiveClient implements LiveClient
{
private final TikTokRoomInfo liveRoomInfo; private final TikTokRoomInfo liveRoomInfo;
private final LiveHttpClient httpClient; private final LiveHttpClient httpClient;
private final SocketClient webSocketClient; private final SocketClient webSocketClient;
private final TikTokLiveEventHandler tikTokEventHandler; private final TikTokLiveEventHandler tikTokEventHandler;
private final LiveClientSettings clientSettings; private final LiveClientSettings clientSettings;
private final TikTokListenersManager listenersManager; private final ListenersManager listenersManager;
private final Logger logger; private final Logger logger;
private final GiftsManager giftsManager; private final GiftsManager giftsManager;
private final TikTokLiveMessageHandler messageHandler; private final TikTokLiveMessageHandler messageHandler;
@@ -62,7 +64,7 @@ public class TikTokLiveClient implements LiveClient {
SocketClient webSocketClient, SocketClient webSocketClient,
TikTokLiveEventHandler tikTokEventHandler, TikTokLiveEventHandler tikTokEventHandler,
LiveClientSettings clientSettings, LiveClientSettings clientSettings,
TikTokListenersManager listenersManager, ListenersManager listenersManager,
Logger logger) { Logger logger) {
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
this.giftsManager = giftsManager; this.giftsManager = giftsManager;
@@ -125,9 +127,12 @@ public class TikTokLiveClient implements LiveClient {
tikTokEventHandler.publish(this, new TikTokConnectingEvent()); tikTokEventHandler.publish(this, new TikTokConnectingEvent());
var userDataRequest = new LiveUserData.Request(liveRoomInfo.getHostName()); var userDataRequest = new LiveUserData.Request(liveRoomInfo.getHostName());
var userData = httpClient.fetchLiveUserData(userDataRequest); var userData = httpClient.fetchLiveUserData(userDataRequest);
liveRoomInfo.setStartTime(userData.getStartedAtTimeStamp()); liveRoomInfo.setStartTime(userData.getStartTime());
liveRoomInfo.setRoomId(userData.getRoomId()); liveRoomInfo.setRoomId(userData.getRoomId());
if (clientSettings.isFetchGifts())
giftsManager.attachGiftsList(httpClient.fetchRoomGiftsData(userData.getRoomId()).getGifts());
if (userData.getUserStatus() == LiveUserData.UserStatus.Offline) if (userData.getUserStatus() == LiveUserData.UserStatus.Offline)
throw new TikTokLiveOfflineHostException("User is offline: " + liveRoomInfo.getHostName()); throw new TikTokLiveOfflineHostException("User is offline: " + liveRoomInfo.getHostName());

View File

@@ -22,6 +22,9 @@
*/ */
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.dependance.Dependance;
import io.github.jwdeveloper.dependance.api.DependanceContainer;
import io.github.jwdeveloper.tiktok.mappers.MessagesMapperFactory;
import io.github.jwdeveloper.tiktok.common.LoggerFactory; import io.github.jwdeveloper.tiktok.common.LoggerFactory;
import io.github.jwdeveloper.tiktok.data.events.*; import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
@@ -29,6 +32,7 @@ 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.envelop.TikTokChestEvent;
import io.github.jwdeveloper.tiktok.data.events.gift.*; import io.github.jwdeveloper.tiktok.data.events.gift.*;
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent; 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.poll.TikTokPollEvent;
import io.github.jwdeveloper.tiktok.data.events.room.*; import io.github.jwdeveloper.tiktok.data.events.room.*;
import io.github.jwdeveloper.tiktok.data.events.social.*; import io.github.jwdeveloper.tiktok.data.events.social.*;
@@ -37,15 +41,16 @@ import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
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.TikTokGiftsManager;
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.*; import io.github.jwdeveloper.tiktok.listener.*;
import io.github.jwdeveloper.tiktok.live.*; import io.github.jwdeveloper.tiktok.live.*;
import io.github.jwdeveloper.tiktok.live.builder.*; import io.github.jwdeveloper.tiktok.live.builder.*;
import io.github.jwdeveloper.tiktok.mappers.*; import io.github.jwdeveloper.tiktok.mappers.*;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokCommonEventHandler;
import io.github.jwdeveloper.tiktok.mappers.handlers.*; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
import io.github.jwdeveloper.tiktok.messages.webcast.*; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokRoomInfoEventHandler;
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient; import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokSocialMediaEventHandler;
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketOfflineClient; import io.github.jwdeveloper.tiktok.websocket.*;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -57,21 +62,18 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
protected final LiveClientSettings clientSettings; protected final LiveClientSettings clientSettings;
protected final TikTokLiveEventHandler eventHandler; protected final TikTokLiveEventHandler eventHandler;
protected final List<TikTokEventListener> listeners; protected final List<TikTokEventListener> listeners;
protected Consumer<TikTokMapper> onCustomMappings; protected final List<Consumer<TikTokMapper>> onCustomMappings;
protected Logger logger;
protected GiftsManager giftsManager;
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.eventHandler = new TikTokLiveEventHandler();
this.listeners = new ArrayList<>(); this.listeners = new ArrayList<>();
this.onCustomMappings = (e) -> { this.onCustomMappings = new ArrayList<>();
};
} }
public LiveClientBuilder onMapping(Consumer<TikTokMapper> onCustomMappings) { public LiveClientBuilder onMapping(Consumer<TikTokMapper> consumer) {
this.onCustomMappings = onCustomMappings; this.onCustomMappings.add(consumer);
return this; return this;
} }
@@ -102,142 +104,81 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
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());
this.logger = LoggerFactory.create(clientSettings.getHostName(), clientSettings);
this.giftsManager = clientSettings.isFetchGifts() ? TikTokLive.gifts() : new TikTokGiftsManager(List.of());
} }
//TODO each class registered to container should implement own interface,
public LiveClient build() { public LiveClient build() {
validate(); validate();
var tiktokRoomInfo = new TikTokRoomInfo(); //Docs: https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#01-basic
tiktokRoomInfo.setHostName(clientSettings.getHostName()); var dependance = Dependance.newContainer();
var listenerManager = new TikTokListenersManager(listeners, eventHandler); //config
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;
});
var httpClientFactory = new HttpClientFactory(clientSettings); //messages
dependance.registerSingleton(TikTokLiveEventHandler.class, eventHandler);
dependance.registerSingleton(TikTokLiveMessageHandler.class);
var liveHttpClient = clientSettings.isOffline() ? //listeners
new TikTokLiveHttpOfflineClient() : dependance.registerSingletonList(TikTokEventListener.class, (e) -> listeners);
new TikTokLiveHttpClient(httpClientFactory, clientSettings); dependance.registerSingleton(ListenersManager.class, TikTokListenersManager.class);
var eventsMapper = createMapper(giftsManager, tiktokRoomInfo); //networking
var messageHandler = new TikTokLiveMessageHandler(eventHandler, eventsMapper); dependance.registerSingleton(HttpClientFactory.class);
if (clientSettings.isOffline()) {
dependance.registerSingleton(SocketClient.class, TikTokWebSocketOfflineClient.class);
dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpOfflineClient.class);
} else {
dependance.registerSingleton(SocketClient.class, TikTokWebSocketClient.class);
dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpClient.class);
}
var webSocketClient = clientSettings.isOffline() ? /* TODO in future, custom proxy implementation that can be provided via builder
new TikTokWebSocketOfflineClient(eventHandler) : * if(customProxy != null)
new TikTokWebSocketClient( * dependance.registerSingleton(TikTokProxyProvider.class,customProxy);
clientSettings, * else
messageHandler, * dependance.registerSingleton(TikTokProxyProvider.class,DefaultProxyProvider.class);
eventHandler); */
return new TikTokLiveClient( //gifts
messageHandler, if (clientSettings.isFetchGifts()) {
giftsManager, dependance.registerSingleton(GiftsManager.class, TikTokLive.gifts());
tiktokRoomInfo, } else {
liveHttpClient, dependance.registerSingleton(GiftsManager.class, new TikTokGiftsManager(List.of()));
webSocketClient, }
eventHandler,
clientSettings, //mapper
listenerManager, dependance.registerSingleton(TikTokGenericEventMapper.class);
logger); dependance.registerSingleton(TikTokMapperHelper.class, TikTokLiveMapperHelper.class);
dependance.registerSingleton(TikTokMapper.class, (container) ->
{
var dependace = (DependanceContainer) container.find(DependanceContainer.class);
var mapper = MessagesMapperFactory.create(dependace);
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
dependance.registerSingleton(LiveClient.class, TikTokLiveClient.class);
var container = dependance.build();
return container.find(LiveClient.class);
} }
public TikTokLiveMapper createMapper(GiftsManager giftsManager, TikTokRoomInfo roomInfo) {
var eventMapper = new TikTokGenericEventMapper();
var mapper = new TikTokLiveMapper(new TikTokLiveMapperHelper(eventMapper));
//ConnectionEvents events
var commonHandler = new TikTokCommonEventHandler();
var giftHandler = new TikTokGiftEventHandler(giftsManager, 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 messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastCaptionMessage.class);
return MappingResult.of(messageObject, new TikTokCaptionEvent(messageObject));
});
//User Interactions events
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));
});
mapper.forMessage(WebcastLikeMessage.class, roomInfoHandler::handleLike);
mapper.forMessage(WebcastGiftMessage.class, giftHandler::handleGifts);
mapper.forMessage(WebcastSocialMessage.class, socialHandler::handle);
mapper.forMessage(WebcastMemberMessage.class, roomInfoHandler::handleMemberMessage);
//Host Interaction events
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.forMessage(WebcastLinkMicBattle.class, (inputBytes, messageName, mapperHelper) -> {
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastLinkMicBattle.class);
return MappingResult.of(message, new TikTokLinkMicBattleEvent(message));
});
mapper.forMessage(WebcastLinkMicArmies.class, (inputBytes, messageName, mapperHelper) -> {
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastLinkMicArmies.class);
return MappingResult.of(message, new TikTokLinkMicArmiesEvent(message));
});
// 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();
@@ -248,6 +189,10 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
return build().connectAsync(); return build().connectAsync();
} }
/**
* To do figure out how to use Annotation processor.
* Goal is to generates methods for all possible events, everytime library is compiled
*/
public TikTokLiveClientBuilder onUnhandledSocial(EventConsumer<TikTokUnhandledSocialEvent> event) { public TikTokLiveClientBuilder onUnhandledSocial(EventConsumer<TikTokUnhandledSocialEvent> event) {
eventHandler.subscribe(TikTokUnhandledSocialEvent.class, event); eventHandler.subscribe(TikTokUnhandledSocialEvent.class, event);
return this; return this;
@@ -341,6 +286,111 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
return this; return this;
} }
public TikTokLiveClientBuilder onLinkInvite(EventConsumer<TikTokLinkInviteEvent> event) {
eventHandler.subscribe(TikTokLinkInviteEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkReply(EventConsumer<TikTokLinkReplyEvent> event) {
eventHandler.subscribe(TikTokLinkReplyEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkCreate(EventConsumer<TikTokLinkCreateEvent> event) {
eventHandler.subscribe(TikTokLinkCreateEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkClose(EventConsumer<TikTokLinkCloseEvent> event) {
eventHandler.subscribe(TikTokLinkCloseEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkEnter(EventConsumer<TikTokLinkEnterEvent> event) {
eventHandler.subscribe(TikTokLinkEnterEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkLeave(EventConsumer<TikTokLinkLeaveEvent> event) {
eventHandler.subscribe(TikTokLinkLeaveEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkCancel(EventConsumer<TikTokLinkCancelEvent> event) {
eventHandler.subscribe(TikTokLinkCancelEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkKickOut(EventConsumer<TikTokLinkKickOutEvent> event) {
eventHandler.subscribe(TikTokLinkKickOutEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkLinkedListChange(EventConsumer<TikTokLinkLinkedListChangeEvent> event) {
eventHandler.subscribe(TikTokLinkLinkedListChangeEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkUpdateUser(EventConsumer<TikTokLinkUpdateUserEvent> event) {
eventHandler.subscribe(TikTokLinkUpdateUserEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkWaitListChange(EventConsumer<TikTokLinkWaitListChangeEvent> event) {
eventHandler.subscribe(TikTokLinkWaitListChangeEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkMute(EventConsumer<TikTokLinkMuteEvent> event) {
eventHandler.subscribe(TikTokLinkMuteEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkRandomMatch(EventConsumer<TikTokLinkRandomMatchEvent> event) {
eventHandler.subscribe(TikTokLinkRandomMatchEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkUpdateUserSettings(EventConsumer<TikTokLinkUpdateUserSettingEvent> event) {
eventHandler.subscribe(TikTokLinkUpdateUserSettingEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkMicIdxUpdate(EventConsumer<TikTokLinkMicIdxUpdateEvent> event) {
eventHandler.subscribe(TikTokLinkMicIdxUpdateEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkListChange(EventConsumer<TikTokLinkListChangeEvent> event) {
eventHandler.subscribe(TikTokLinkListChangeEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkCohostListChange(EventConsumer<TikTokLinkCohostListChangeEvent> event) {
eventHandler.subscribe(TikTokLinkCohostListChangeEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkMediaChange(EventConsumer<TikTokLinkMediaChangeEvent> event) {
eventHandler.subscribe(TikTokLinkMediaChangeEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkAcceptNotice(EventConsumer<TikTokLinkAcceptNoticeEvent> event) {
eventHandler.subscribe(TikTokLinkAcceptNoticeEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkSysKickOut(EventConsumer<TikTokLinkSysKickOutEvent> event) {
eventHandler.subscribe(TikTokLinkSysKickOutEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onLinkUserToast(EventConsumer<TikTokLinkUserToastEvent> event) {
eventHandler.subscribe(TikTokLinkUserToastEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onBarrage(EventConsumer<TikTokBarrageEvent> event) { public TikTokLiveClientBuilder onBarrage(EventConsumer<TikTokBarrageEvent> event) {
eventHandler.subscribe(TikTokBarrageEvent.class, event); eventHandler.subscribe(TikTokBarrageEvent.class, event);
return this; return this;

View File

@@ -26,10 +26,7 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer; import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import java.util.HashMap; import java.util.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class TikTokLiveEventHandler { public class TikTokLiveEventHandler {
private final Map<Class<?>, Set<EventConsumer>> events; private final Map<Class<?>, Set<EventConsumer>> events;
@@ -39,21 +36,8 @@ public class TikTokLiveEventHandler {
} }
public void publish(LiveClient tikTokLiveClient, TikTokEvent tikTokEvent) { public void publish(LiveClient tikTokLiveClient, TikTokEvent tikTokEvent) {
if (events.containsKey(TikTokEvent.class)) { Optional.ofNullable(events.get(TikTokEvent.class)).ifPresent(handlers -> handlers.forEach(handler -> handler.onEvent(tikTokLiveClient, tikTokEvent)));
var handlers = events.get(TikTokEvent.class); Optional.ofNullable(events.get(tikTokEvent.getClass())).ifPresent(handlers -> handlers.forEach(handler -> handler.onEvent(tikTokLiveClient, tikTokEvent)));
for (var handle : handlers) {
handle.onEvent(tikTokLiveClient, tikTokEvent);
}
}
if (!events.containsKey(tikTokEvent.getClass())) {
return;
}
var handlers = events.get(tikTokEvent.getClass());
for (var handler : handlers) {
handler.onEvent(tikTokLiveClient, tikTokEvent);
}
} }
public <T extends TikTokEvent> void subscribe(Class<?> clazz, EventConsumer<T> event) { public <T extends TikTokEvent> void subscribe(Class<?> clazz, EventConsumer<T> event) {
@@ -65,22 +49,10 @@ public class TikTokLiveEventHandler {
} }
public <T extends TikTokEvent> void unsubscribe(EventConsumer<T> consumer) { public <T extends TikTokEvent> void unsubscribe(EventConsumer<T> consumer) {
for (var entry : events.entrySet()) { events.forEach((key, value) -> value.remove(consumer));
entry.getValue().remove(consumer);
}
} }
public <T extends TikTokEvent> void unsubscribe(Class<?> clazz, EventConsumer<T> consumer) { public <T extends TikTokEvent> void unsubscribe(Class<?> clazz, EventConsumer<T> consumer) {
if (clazz == null) { Optional.ofNullable(clazz).map(events::get).ifPresent(consumers -> consumers.remove(consumer));
return; }
} }
if (!events.containsKey(clazz)) {
return;
}
var eventSet = events.get(clazz);
eventSet.remove(consumer);
}
}

View File

@@ -23,6 +23,7 @@
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import io.github.jwdeveloper.dependance.injector.api.annotations.Inject;
import io.github.jwdeveloper.tiktok.common.*; import io.github.jwdeveloper.tiktok.common.*;
import io.github.jwdeveloper.tiktok.data.requests.*; import io.github.jwdeveloper.tiktok.data.requests.*;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
@@ -32,6 +33,7 @@ import io.github.jwdeveloper.tiktok.http.mappers.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.util.function.Consumer;
import java.util.logging.Logger; import java.util.logging.Logger;
public class TikTokLiveHttpClient implements LiveHttpClient public class TikTokLiveHttpClient implements LiveHttpClient
@@ -43,6 +45,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
private static final String TIKTOK_URL_WEB = "https://www.tiktok.com/"; private static final String TIKTOK_URL_WEB = "https://www.tiktok.com/";
private static final String TIKTOK_URL_WEBCAST = "https://webcast.tiktok.com/webcast/"; private static final String TIKTOK_URL_WEBCAST = "https://webcast.tiktok.com/webcast/";
public static final String TIKTOK_GIFTS_URL = "https://raw.githubusercontent.com/TikTok-LIVE-Private/GiftsGenerator/master/page/public/gifts.json"; public static final String TIKTOK_GIFTS_URL = "https://raw.githubusercontent.com/TikTok-LIVE-Private/GiftsGenerator/master/page/public/gifts.json";
public static final String TIKTOK_ROOM_GIFTS_URL = TIKTOK_URL_WEBCAST+"gift/list/";
public static final int TIKTOK_AGE_RESTRICTED_CODE = 4003110; public static final int TIKTOK_AGE_RESTRICTED_CODE = 4003110;
private final HttpClientFactory httpFactory; private final HttpClientFactory httpFactory;
@@ -52,17 +55,44 @@ public class TikTokLiveHttpClient implements LiveHttpClient
private final GiftsDataMapper giftsDataMapper; private final GiftsDataMapper giftsDataMapper;
private final Logger logger; private final Logger logger;
public TikTokLiveHttpClient(HttpClientFactory factory, LiveClientSettings settings) { @Inject
public TikTokLiveHttpClient(HttpClientFactory factory) {
this.httpFactory = factory; this.httpFactory = factory;
this.clientSettings = settings; this.clientSettings = factory.getLiveClientSettings();
this.logger = LoggerFactory.create("HttpClient", clientSettings); this.logger = LoggerFactory.create("HttpClient-"+hashCode(), clientSettings);
liveUserDataMapper = new LiveUserDataMapper(); liveUserDataMapper = new LiveUserDataMapper();
liveDataMapper = new LiveDataMapper(); liveDataMapper = new LiveDataMapper();
giftsDataMapper = new GiftsDataMapper(); giftsDataMapper = new GiftsDataMapper();
} }
public TikTokLiveHttpClient() { public TikTokLiveHttpClient(Consumer<LiveClientSettings> consumer) {
this(new HttpClientFactory(LiveClientSettings.createDefault()), LiveClientSettings.createDefault()); this(new HttpClientFactory(LiveClientSettings.createDefault()));
consumer.accept(clientSettings);
}
public GiftsData.Response fetchRoomGiftsData(String room_id) {
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
if (proxyClientSettings.isEnabled()) {
while (proxyClientSettings.hasNext()) {
try {
return getRoomGiftsData(room_id);
} catch (TikTokProxyRequestException ignored) {}
}
}
return getRoomGiftsData(room_id);
}
public GiftsData.Response getRoomGiftsData(String room_id) {
var result = httpFactory.client(TIKTOK_ROOM_GIFTS_URL)
.withParam("room_id", room_id)
.build()
.toJsonResponse();
if (result.isFailure())
throw new TikTokLiveRequestException("Unable to fetch gifts information's - "+result);
var json = result.getContent();
return giftsDataMapper.mapRoom(json);
} }
public GiftsData.Response fetchGiftsData() { public GiftsData.Response fetchGiftsData() {
@@ -152,7 +182,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
try { try {
var resultHeader = ActionResult.of(credentialsResponse.headers().firstValue("x-set-tt-cookie")); var resultHeader = ActionResult.of(credentialsResponse.headers().firstValue("x-set-tt-cookie"));
if (resultHeader.isFailure()) { if (resultHeader.isFailure()) {
logger.warning("SignServer Headers: "+request.getRoomId()+" - "+credentialsResponse.headers().map()); logger.warning("Sign Server Headers: "+request.getRoomId()+" - "+credentialsResponse.headers().map());
throw new TikTokSignServerException("Sign server did not return the x-set-tt-cookie header - "+result); throw new TikTokSignServerException("Sign server did not return the x-set-tt-cookie header - "+result);
} }
var websocketCookie = resultHeader.getContent(); var websocketCookie = resultHeader.getContent();
@@ -165,7 +195,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
.withParam("internal_ext", webcastResponse.getInternalExt()) .withParam("internal_ext", webcastResponse.getInternalExt())
.withParams(webcastResponse.getRouteParamsMapMap()) .withParams(webcastResponse.getRouteParamsMapMap())
.build() .build()
.toUrl(); .toUri();
return new LiveConnectionData.Response(websocketCookie, webSocketUrl, webcastResponse); return new LiveConnectionData.Response(websocketCookie, webSocketUrl, webcastResponse);
} catch (InvalidProtocolBufferException e) { } catch (InvalidProtocolBufferException e) {

View File

@@ -1,3 +1,25 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.data.models.Picture;
@@ -18,6 +40,11 @@ public class TikTokLiveHttpOfflineClient implements LiveHttpClient {
return new GiftsData.Response("", List.of()); return new GiftsData.Response("", List.of());
} }
@Override
public GiftsData.Response fetchRoomGiftsData(String room_id) {
return new GiftsData.Response("", List.of());
}
@Override @Override
public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) { public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) {
return new LiveUserData.Response("", LiveUserData.UserStatus.Live, "offline_room_id", 0); return new LiveUserData.Response("", LiveUserData.UserStatus.Live, "offline_room_id", 0);
@@ -42,4 +69,4 @@ public class TikTokLiveHttpOfflineClient implements LiveHttpClient {
URI.create("https://example.live"), URI.create("https://example.live"),
WebcastResponse.newBuilder().build()); WebcastResponse.newBuilder().build());
} }
} }

View File

@@ -31,6 +31,7 @@ import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandl
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper; import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper;
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.utils.Stopwatch; import io.github.jwdeveloper.tiktok.utils.Stopwatch;
@@ -41,9 +42,9 @@ public class TikTokLiveMessageHandler {
private final TikTokLiveEventHandler tikTokEventHandler; private final TikTokLiveEventHandler tikTokEventHandler;
private final TikTokLiveMapper mapper; private final TikTokLiveMapper mapper;
public TikTokLiveMessageHandler(TikTokLiveEventHandler tikTokEventHandler, TikTokLiveMapper mapper) { public TikTokLiveMessageHandler(TikTokLiveEventHandler tikTokEventHandler, TikTokMapper mapper) {
this.tikTokEventHandler = tikTokEventHandler; this.tikTokEventHandler = tikTokEventHandler;
this.mapper = mapper; this.mapper = (TikTokLiveMapper) mapper;
} }
public void handle(LiveClient client, WebcastResponse webcastResponse) { public void handle(LiveClient client, WebcastResponse webcastResponse) {
@@ -61,10 +62,12 @@ public class TikTokLiveMessageHandler {
public void handleSingleMessage(LiveClient client, WebcastResponse.Message message) public void handleSingleMessage(LiveClient client, WebcastResponse.Message message)
{ {
var messageClassName = message.getMethod(); var messageClassName = message.getMethod();
if (!mapper.isRegistered(messageClassName)) { if (!mapper.isRegistered(messageClassName))
{
tikTokEventHandler.publish(client, new TikTokWebsocketUnhandledMessageEvent(message)); tikTokEventHandler.publish(client, new TikTokWebsocketUnhandledMessageEvent(message));
return; return;
} }
var stopwatch = new Stopwatch(); var stopwatch = new Stopwatch();
stopwatch.start(); stopwatch.start();
var events = mapper.handleMapping(messageClassName, message.getPayload().toByteArray()); var events = mapper.handleMapping(messageClassName, message.getPayload().toByteArray());
@@ -76,5 +79,4 @@ public class TikTokLiveMessageHandler {
tikTokEventHandler.publish(client, event); tikTokEventHandler.publish(client, event);
} }
} }
}
}

View File

@@ -1,3 +1,25 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.common; package io.github.jwdeveloper.tiktok.common;
import com.google.gson.*; import com.google.gson.*;
@@ -18,8 +40,8 @@ public class ActionResult<T> {
.setPrettyPrinting().create(); .setPrettyPrinting().create();
private boolean success = true; private boolean success = true;
private T content;
private String message; private String message;
private T content;
@Accessors(chain = true, fluent = true) @Accessors(chain = true, fluent = true)
private ActionResult<?> previous; private ActionResult<?> previous;
@@ -100,8 +122,8 @@ public class ActionResult<T> {
public JsonObject toJson() { public JsonObject toJson() {
JsonObject map = new JsonObject(); JsonObject map = new JsonObject();
map.addProperty("success", success); map.addProperty("success", success);
map.add("content", gson.toJsonTree(content));
map.addProperty("message", message); map.addProperty("message", message);
map.add("content", gson.toJsonTree(content));
map.add("previous", hasPrevious() ? previous.toJson() : null); map.add("previous", hasPrevious() ? previous.toJson() : null);
return map; return map;
} }

View File

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

View File

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

View File

@@ -1,18 +1,41 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.gifts; package io.github.jwdeveloper.tiktok.gifts;
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
import io.github.jwdeveloper.tiktok.live.GiftsManager; import io.github.jwdeveloper.tiktok.live.GiftsManager;
import java.util.*; import java.util.*;
import java.util.function.Predicate; import java.util.function.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
//TODO I should've been called it TikTokGiftsRepository
public class TikTokGiftsManager implements GiftsManager { public class TikTokGiftsManager implements GiftsManager {
private final Map<Integer, Gift> giftsByIdIndex; private final Map<Integer, Gift> giftsByIdIndex;
public TikTokGiftsManager(List<Gift> giftList) public TikTokGiftsManager(List<Gift> giftList)
{ {
giftsByIdIndex = giftList.stream().collect(Collectors.toConcurrentMap(Gift::getId, e -> e)); giftsByIdIndex = giftList.stream().collect(Collectors.toConcurrentMap(Gift::getId, Function.identity()));
} }
public void attachGift(Gift gift) { public void attachGift(Gift gift) {

View File

@@ -30,6 +30,7 @@ import lombok.AllArgsConstructor;
import java.net.*; import java.net.*;
import java.net.http.*; import java.net.http.*;
import java.nio.charset.*; import java.nio.charset.*;
import java.time.*;
import java.util.*; import java.util.*;
import java.util.regex.*; import java.util.regex.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -47,7 +48,21 @@ public class HttpClient {
try { try {
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
var result = ActionResult.of(response); var result = ActionResult.of(response);
return response.statusCode() != 200 ? result.message("HttpResponse Code: ", response.statusCode()).failure() : result.success(); return switch (response.statusCode()) {
case 420 -> result.message("HttpResponse Code:", response.statusCode(), "| IP Cloudflare Blocked.").failure();
case 429 -> {
var wait = response.headers().firstValue("ratelimit-reset");
if (wait.isEmpty())
yield result.message("HttpResponse Code:", response.statusCode(), "| Sign server rate limit reached. Try again later.").failure();
Duration duration = Duration.ofSeconds(Long.parseLong(wait.get()));
yield result.message("HttpResponse Code:", response.statusCode(),
String.format("| Sign server rate limit reached. Try again in %02d:%02d.", duration.toMinutesPart(), duration.toSecondsPart())).failure();
}
case 500, 501, 502, 503 -> result.message("HttpResponse Code:", response.statusCode(), "| Sign server Error. Try again later.").failure();
case 504 -> result.message("HttpResponse Code:", response.statusCode(), "| Sign server Timeout. Try again later.").failure();
case 200 -> result.success();
default -> result.message("HttpResponse Code:", response.statusCode()).failure();
};
} catch (Exception e) { } catch (Exception e) {
throw new TikTokLiveRequestException(e); throw new TikTokLiveRequestException(e);
} }
@@ -75,14 +90,14 @@ public class HttpClient {
return toResponse().map(HttpResponse::body); return toResponse().map(HttpResponse::body);
} }
public URI toUrl() { public URI toUri() {
var stringUrl = prepareUrlWithParameters(url, httpClientSettings.getParams()); var stringUrl = prepareUrlWithParameters(url, httpClientSettings.getParams());
return URI.create(stringUrl); return URI.create(stringUrl);
} }
protected HttpRequest prepareGetRequest() { protected HttpRequest prepareGetRequest() {
var requestBuilder = HttpRequest.newBuilder().GET(); var requestBuilder = HttpRequest.newBuilder().GET();
requestBuilder.uri(toUrl()); requestBuilder.uri(toUri());
requestBuilder.timeout(httpClientSettings.getTimeout()); requestBuilder.timeout(httpClientSettings.getTimeout());
httpClientSettings.getHeaders().forEach(requestBuilder::setHeader); httpClientSettings.getHeaders().forEach(requestBuilder::setHeader);

View File

@@ -23,7 +23,9 @@
package io.github.jwdeveloper.tiktok.http; package io.github.jwdeveloper.tiktok.http;
import io.github.jwdeveloper.tiktok.data.settings.*; import io.github.jwdeveloper.tiktok.data.settings.*;
import lombok.Getter;
@Getter
public class HttpClientFactory { public class HttpClientFactory {
private final LiveClientSettings liveClientSettings; private final LiveClientSettings liveClientSettings;
@@ -35,7 +37,9 @@ public class HttpClientFactory {
return new HttpClientBuilder(url, liveClientSettings.getHttpSettings().clone()); return new HttpClientBuilder(url, liveClientSettings.getHttpSettings().clone());
} }
//Does not contains default httpClientSettings, Params, headers, etd //Does not contains default httpClientSettings, Params, headers, etd
//Edit: Do we even use it?
public HttpClientBuilder clientEmpty(String url) { public HttpClientBuilder clientEmpty(String url) {
var settings = new HttpClientSettings(); var settings = new HttpClientSettings();
settings.setProxyClientSettings(liveClientSettings.getHttpSettings().getProxyClientSettings()); settings.setProxyClientSettings(liveClientSettings.getHttpSettings().getProxyClientSettings());

View File

@@ -95,7 +95,7 @@ public class HttpProxyClient extends HttpClient {
public X509Certificate[] getAcceptedIssuers() { return null; } public X509Certificate[] getAcceptedIssuers() { return null; }
}}, null); }}, null);
URL url = toUrl().toURL(); URL url = toUri().toURL();
if (proxySettings.hasNext()) { if (proxySettings.hasNext()) {
try { try {
@@ -105,6 +105,7 @@ public class HttpProxyClient extends HttpClient {
socksConnection.setSSLSocketFactory(sc.getSocketFactory()); socksConnection.setSSLSocketFactory(sc.getSocketFactory());
socksConnection.setConnectTimeout(httpClientSettings.getTimeout().toMillisPart()); socksConnection.setConnectTimeout(httpClientSettings.getTimeout().toMillisPart());
socksConnection.setReadTimeout(httpClientSettings.getTimeout().toMillisPart()); socksConnection.setReadTimeout(httpClientSettings.getTimeout().toMillisPart());
httpClientSettings.getHeaders().forEach(socksConnection::setRequestProperty);
byte[] body = socksConnection.getInputStream().readAllBytes(); byte[] body = socksConnection.getInputStream().readAllBytes();
@@ -116,7 +117,7 @@ public class HttpProxyClient extends HttpClient {
var responseInfo = createResponseInfo(socksConnection.getResponseCode(), headers); var responseInfo = createResponseInfo(socksConnection.getResponseCode(), headers);
var response = createHttpResponse(body, toUrl(), responseInfo); var response = createHttpResponse(body, toUri(), responseInfo);
return ActionResult.success(response); return ActionResult.success(response);
} catch (IOException e) { } catch (IOException e) {

View File

@@ -22,15 +22,15 @@
*/ */
package io.github.jwdeveloper.tiktok.http.mappers; package io.github.jwdeveloper.tiktok.http.mappers;
import com.google.gson.JsonElement; import com.google.gson.*;
import com.google.gson.JsonParser;
import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.data.models.Picture;
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
import io.github.jwdeveloper.tiktok.data.requests.GiftsData; import io.github.jwdeveloper.tiktok.data.requests.GiftsData;
import java.util.ArrayList; import java.util.List;
public class GiftsDataMapper { public class GiftsDataMapper {
public GiftsData.Response map(String json) { public GiftsData.Response map(String json) {
var parsedJson = JsonParser.parseString(json); var parsedJson = JsonParser.parseString(json);
var jsonObject = parsedJson.getAsJsonObject(); var jsonObject = parsedJson.getAsJsonObject();
@@ -42,7 +42,6 @@ public class GiftsDataMapper {
return new GiftsData.Response(json, gifts); return new GiftsData.Response(json, gifts);
} }
private Gift mapSingleGift(JsonElement jsonElement) { private Gift mapSingleGift(JsonElement jsonElement) {
var jsonObject = jsonElement.getAsJsonObject(); var jsonObject = jsonElement.getAsJsonObject();
@@ -52,4 +51,34 @@ public class GiftsDataMapper {
var image = jsonObject.get("image").getAsString(); var image = jsonObject.get("image").getAsString();
return new Gift(id, name, diamondCost, new Picture(image), jsonObject); return new Gift(id, name, diamondCost, new Picture(image), jsonObject);
} }
}
public GiftsData.Response mapRoom(String json) {
var parsedJson = JsonParser.parseString(json);
var jsonObject = parsedJson.getAsJsonObject();
if (jsonObject.get("data") instanceof JsonObject data && data.get("gifts") instanceof JsonArray giftArray) {
var gifts = giftArray.asList().parallelStream()
.map(this::mapSingleRoomGift)
.toList();
return new GiftsData.Response(json, gifts);
}
return new GiftsData.Response("", List.of());
}
private Gift mapSingleRoomGift(JsonElement jsonElement) {
var jsonObject = jsonElement.getAsJsonObject();
var id = jsonObject.get("id").getAsInt();
var name = jsonObject.get("name").getAsString();
var diamondCost = jsonObject.get("diamond_count").getAsInt();
Picture picture;
if (jsonObject.get("image") instanceof JsonObject image && image.get("url_list") instanceof JsonArray urls && !urls.isEmpty()) {
String url = urls.get(0).getAsString();
if (url.endsWith(".webp"))
url = url.substring(0, url.length()-4)+"png";
picture = new Picture(url);
} else
picture = Picture.empty();
return new Gift(id, name, diamondCost, picture, jsonObject);
}
}

View File

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

View File

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

View File

@@ -96,16 +96,17 @@ public class TikTokListenersManager implements ListenersManager {
m.isAnnotationPresent(TikTokEventObserver.class)).toList(); m.isAnnotationPresent(TikTokEventObserver.class)).toList();
var eventsMap = new HashMap<Class<?>, List<EventConsumer<?>>>(); var eventsMap = new HashMap<Class<?>, List<EventConsumer<?>>>();
for (var method : methods) { for (var method : methods) {
var eventClazz = method.getParameterTypes()[1]; var liveclientClass = method.getParameterTypes()[0];
var eventClass = method.getParameterTypes()[1];
if (eventClazz.isAssignableFrom(LiveClient.class) && if (!LiveClient.class.isAssignableFrom(liveclientClass) && !liveclientClass.equals(LiveClient.class)) {
!eventClazz.equals(LiveClient.class)) { throw new TikTokEventListenerMethodException("Method " + method.getName() + "() 1st parameter must be instance of " + LiveClient.class.getName()
throw new TikTokEventListenerMethodException("Method " + method.getName() + "() 1nd parameter must instance of " + LiveClient.class.getName()); + " | Invalid parameter class: "+liveclientClass.getName());
} }
if (eventClazz.isAssignableFrom(TikTokEvent.class) && if (!TikTokEvent.class.isAssignableFrom(eventClass) && !eventClass.equals(TikTokEvent.class)) {
!eventClazz.equals(TikTokEvent.class)) { throw new TikTokEventListenerMethodException("Method " + method.getName() + "() 2nd parameter must be instance of " + TikTokEvent.class.getName()
throw new TikTokEventListenerMethodException("Method " + method.getName() + "() 2nd parameter must instance of " + TikTokEvent.class.getName()); + " | Invalid parameter class: "+eventClass.getName());
} }
EventConsumer eventMethodRef = (liveClient, event) -> EventConsumer eventMethodRef = (liveClient, event) ->
@@ -117,7 +118,7 @@ public class TikTokListenersManager implements ListenersManager {
throw new TikTokEventListenerMethodException(e); throw new TikTokEventListenerMethodException(e);
} }
}; };
eventsMap.computeIfAbsent(eventClazz, (a) -> new ArrayList<>()).add(eventMethodRef); eventsMap.computeIfAbsent(eventClass, (a) -> new ArrayList<>()).add(eventMethodRef);
} }
return new ListenerBindingModel(listener, eventsMap); return new ListenerBindingModel(listener, eventsMap);
} }

View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.mappers;
import io.github.jwdeveloper.dependance.api.DependanceContainer;
import io.github.jwdeveloper.dependance.injector.api.containers.Container;
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.link.*;
import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokCommonEventHandler;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokRoomInfoEventHandler;
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokSocialMediaEventHandler;
import io.github.jwdeveloper.tiktok.messages.webcast.*;
import static io.github.jwdeveloper.tiktok.messages.enums.LinkMessageType.*;
public class MessagesMapperFactory {
public static TikTokLiveMapper create(DependanceContainer container) {
var helper = container.find(TikTokMapperHelper.class);
var mapper = new TikTokLiveMapper(helper);
//ConnectionEvents events
var commonHandler = container.find(TikTokCommonEventHandler.class);
var giftHandler = container.find(TikTokGiftEventHandler.class);
var roomInfoHandler = container.find(TikTokRoomInfoEventHandler.class);
var socialHandler = container.find(TikTokSocialMediaEventHandler.class);
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 messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastCaptionMessage.class);
return MappingResult.of(messageObject, new TikTokCaptionEvent(messageObject));
});
//User Interactions events
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));
});
mapper.forMessage(WebcastLikeMessage.class, roomInfoHandler::handleLike);
mapper.forMessage(WebcastGiftMessage.class, giftHandler::handleGifts);
mapper.forMessage(WebcastSocialMessage.class, socialHandler::handle);
mapper.forMessage(WebcastMemberMessage.class, roomInfoHandler::handleMemberMessage);
//Host Interaction events
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.forMessage(WebcastLinkMicBattle.class, (inputBytes, messageName, mapperHelper) -> {
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastLinkMicBattle.class);
return MappingResult.of(message, new TikTokLinkMicBattleEvent(message));
});
mapper.forMessage(WebcastLinkMicArmies.class, (inputBytes, messageName, mapperHelper) -> {
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastLinkMicArmies.class);
return MappingResult.of(message, new TikTokLinkMicArmiesEvent(message));
});
mapper.forMessage(WebcastLinkMessage.class, ((inputBytes, messageName, mapperHelper) -> {
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastLinkMessage.class);
return MappingResult.of(message, switch (message.getMessageType()) {
case TYPE_LINKER_INVITE -> new TikTokLinkInviteEvent(message);
case TYPE_LINKER_CREATE -> new TikTokLinkCreateEvent(message);
case TYPE_LINKER_CLOSE -> new TikTokLinkCloseEvent(message);
case TYPE_LINKER_ENTER -> new TikTokLinkEnterEvent(message);
case TYPE_LINKER_LEAVE -> new TikTokLinkLeaveEvent(message);
case TYPE_LINKER_CANCEL_INVITE, TYPE_LINKER_CANCEL_APPLY -> new TikTokLinkCancelEvent(message);
case TYPE_LINKER_KICK_OUT -> new TikTokLinkKickOutEvent(message);
case TYPE_LINKER_LINKED_LIST_CHANGE -> new TikTokLinkLinkedListChangeEvent(message);
case TYPE_LINKER_UPDATE_USER -> new TikTokLinkUpdateUserEvent(message);
case TYPE_LINKER_WAITING_LIST_CHANGE, TYPE_LINKER_WAITING_LIST_CHANGE_V2 ->
new TikTokLinkWaitListChangeEvent(message);
case TYPE_LINKER_MUTE -> new TikTokLinkMuteEvent(message);
case TYPE_LINKER_MATCH -> new TikTokLinkRandomMatchEvent(message);
case TYPE_LINKER_UPDATE_USER_SETTING -> new TikTokLinkUpdateUserSettingEvent(message);
case TYPE_LINKER_MIC_IDX_UPDATE -> new TikTokLinkMicIdxUpdateEvent(message);
case TYPE_LINKER_LINKED_LIST_CHANGE_V2 -> new TikTokLinkListChangeEvent(message);
case TYPE_LINKER_COHOST_LIST_CHANGE -> new TikTokLinkCohostListChangeEvent(message);
case TYPE_LINKER_MEDIA_CHANGE -> new TikTokLinkMediaChangeEvent(message);
case TYPE_LINKER_ACCEPT_NOTICE -> new TikTokLinkAcceptNoticeEvent(message);
case TYPE_LINKER_SYS_KICK_OUT -> new TikTokLinkSysKickOutEvent(message);
case TYPE_LINKMIC_USER_TOAST -> new TikTokLinkUserToastEvent(message);
default -> new TikTokLinkEvent(message);
});
}));
// 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);
return mapper;
}
}

View File

@@ -23,14 +23,10 @@
package io.github.jwdeveloper.tiktok.mappers; package io.github.jwdeveloper.tiktok.mappers;
import com.google.protobuf.GeneratedMessageV3; import com.google.protobuf.GeneratedMessageV3;
import io.github.jwdeveloper.tiktok.TikTokLive;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction; import io.github.jwdeveloper.tiktok.mappers.data.*;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import java.util.HashMap; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
public class TikTokLiveMapper implements TikTokMapper { public class TikTokLiveMapper implements TikTokMapper {
@@ -47,11 +43,7 @@ public class TikTokLiveMapper implements TikTokMapper {
@Override @Override
public TikTokMapperModel forMessage(String messageName) { public TikTokMapperModel forMessage(String messageName) {
if (!isRegistered(messageName)) { return mappers.computeIfAbsent(messageName, TikTokLiveMapperModel::new);
var model = new TikTokLiveMapperModel(messageName);
mappers.put(messageName, model);
}
return mappers.get(messageName);
} }
@Override @Override
@@ -66,7 +58,6 @@ public class TikTokLiveMapper implements TikTokMapper {
return model; return model;
} }
@Override @Override
public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, MappingAction<MappingResult> onMapping) { public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, MappingAction<MappingResult> onMapping) {
var model = forMessage(mapperName); var model = forMessage(mapperName);
@@ -84,7 +75,6 @@ public class TikTokLiveMapper implements TikTokMapper {
return globalMapperModel; return globalMapperModel;
} }
public boolean isRegistered(String mapperName) { public boolean isRegistered(String mapperName) {
return mappers.containsKey(mapperName); return mappers.containsKey(mapperName);
} }
@@ -94,23 +84,19 @@ public class TikTokLiveMapper implements TikTokMapper {
} }
public List<TikTokEvent> handleMapping(String messageName, byte[] bytes) { public List<TikTokEvent> handleMapping(String messageName, byte[] bytes) {
if (!isRegistered(messageName)) {
return List.of();
}
var mapperModel = mappers.get(messageName); var mapperModel = mappers.get(messageName);
if (mapperModel == null)
return List.of();
var inputBytes = mapperModel.getOnBeforeMapping().onMapping(bytes, messageName, mapperUtils); var inputBytes = mapperModel.getOnBeforeMapping().onMapping(bytes, messageName, mapperUtils);
var globalInputBytes = globalMapperModel.getOnBeforeMapping().onMapping(inputBytes, messageName, mapperUtils); var globalInputBytes = globalMapperModel.getOnBeforeMapping().onMapping(inputBytes, messageName, mapperUtils);
var mappingResult = mapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils); var mappingResult = mapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
if (mappingResult == null) { if (mappingResult == null)
mappingResult = globalMapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils); mappingResult = globalMapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
}
var afterMappingResult = mapperModel.getOnAfterMapping().apply(mappingResult); var afterMappingResult = mapperModel.getOnAfterMapping().apply(mappingResult);
var globalAfterMappingResult = globalMapperModel.getOnAfterMapping().apply(MappingResult.of(mappingResult.getSource(), afterMappingResult)); return globalMapperModel.getOnAfterMapping().apply(MappingResult.of(mappingResult.getSource(), afterMappingResult));
return globalAfterMappingResult;
} }
} }

View File

@@ -75,5 +75,4 @@ public class TikTokLiveMapperModel implements TikTokMapperModel {
return this; return this;
} }
} }

View File

@@ -22,6 +22,7 @@
*/ */
package io.github.jwdeveloper.tiktok.websocket; package io.github.jwdeveloper.tiktok.websocket;
import io.github.jwdeveloper.dependance.injector.api.containers.Container;
import io.github.jwdeveloper.tiktok.*; import io.github.jwdeveloper.tiktok.*;
import io.github.jwdeveloper.tiktok.data.dto.ProxyData; import io.github.jwdeveloper.tiktok.data.dto.ProxyData;
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
@@ -63,7 +64,7 @@ public class TikTokWebSocketClient implements SocketClient {
messageHandler.handle(liveClient, connectionData.getWebcastResponse()); messageHandler.handle(liveClient, connectionData.getWebcastResponse());
var headers = new HashMap<String, String>(); var headers = new HashMap<>(clientSettings.getHttpSettings().getHeaders());
headers.put("Cookie", connectionData.getWebsocketCookies()); headers.put("Cookie", connectionData.getWebsocketCookies());
webSocketClient = new TikTokWebSocketListener(connectionData.getWebsocketUrl(), webSocketClient = new TikTokWebSocketListener(connectionData.getWebsocketUrl(),
headers, headers,

View File

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

View File

@@ -1,9 +1,29 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.websocket; package io.github.jwdeveloper.tiktok.websocket;
import org.java_websocket.WebSocket; import org.java_websocket.WebSocket;
import java.util.Random;
public class TikTokWebSocketPingingTask public class TikTokWebSocketPingingTask
{ {
private Thread thread; private Thread thread;
@@ -14,7 +34,7 @@ public class TikTokWebSocketPingingTask
public void run(WebSocket webSocket, long pingTaskTime) public void run(WebSocket webSocket, long pingTaskTime)
{ {
stop(); stop();
thread = new Thread(() -> pingTask(webSocket, pingTaskTime)); thread = new Thread(() -> pingTask(webSocket, pingTaskTime), "pinging-task");
isRunning = true; isRunning = true;
thread.start(); thread.start();
} }
@@ -28,18 +48,16 @@ public class TikTokWebSocketPingingTask
private void pingTask(WebSocket webSocket, long pingTaskTime) private void pingTask(WebSocket webSocket, long pingTaskTime)
{ {
var random = new Random();
while (isRunning) { while (isRunning) {
try { try {
if (!webSocket.isOpen()) { if (webSocket.isOpen()) {
webSocket.sendPing();
Thread.sleep(pingTaskTime+(int)(Math.random() * MAX_TIMEOUT));
} else
Thread.sleep(SLEEP_TIME); Thread.sleep(SLEEP_TIME);
continue;
}
webSocket.sendPing();
Thread.sleep(pingTaskTime+random.nextInt(MAX_TIMEOUT));
} }
catch (Exception e) { catch (Exception e) {
//TODO we should display some kind of error message
isRunning = false; isRunning = false;
} }
} }

View File

@@ -22,12 +22,7 @@
*/ */
package io.github.jwdeveloper.tiktok.gifts; package io.github.jwdeveloper.tiktok.gifts;
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftOld;
import io.github.jwdeveloper.tiktok.data.models.Picture;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;

View File

@@ -41,7 +41,7 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.6.0-Release</version> <version>1.7.2-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -75,7 +75,7 @@
<dependency> <dependency>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>extension-collector</artifactId> <artifactId>extension-collector</artifactId>
<version>1.6.0-Release</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -32,7 +32,7 @@ import java.time.Duration;
import java.util.logging.Level; import java.util.logging.Level;
public class ConnectionExample { public class ConnectionExample {
public static String TIKTOK_HOSTNAME = "kvadromama_marina1"; public static String TIKTOK_HOSTNAME = "yttvandroid";
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {

View File

@@ -1,3 +1,25 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent;
@@ -47,9 +69,7 @@ public class Events_And_Gifts_Testing_Example
var fakeGift = TikTokGiftEvent.of(roseGift); var fakeGift = TikTokGiftEvent.of(roseGift);
var fakeComboGift = TikTokGiftComboEvent.of(roseGift, 12, GiftComboStateType.Begin); var fakeComboGift = TikTokGiftComboEvent.of(roseGift, 12, GiftComboStateType.Begin);
var fakeMessage = TikTokCommentEvent.of("Mark", "Hello world"); var fakeMessage = TikTokCommentEvent.of("Mark", "Hello world");
var fakeSubscriber = TikTokSubscribeEvent.of("Mark"); var fakeSubscriber = TikTokSubscribeEvent.of("Mark");
var fakeFollow = TikTokFollowEvent.of("Mark"); var fakeFollow = TikTokFollowEvent.of("Mark");
var fakeLike = TikTokLikeEvent.of("Mark", 12); var fakeLike = TikTokLikeEvent.of("Mark", 12);

View File

@@ -26,6 +26,8 @@ package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.extension.recorder.TikTokLiveRecorder; import io.github.jwdeveloper.tiktok.extension.recorder.TikTokLiveRecorder;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.event.TikTokLiveRecorderStartedEvent; import io.github.jwdeveloper.tiktok.extension.recorder.impl.event.TikTokLiveRecorderStartedEvent;
import java.io.File;
public class RecorderExample { public class RecorderExample {
public static void main(String[] args) { public static void main(String[] args) {
@@ -39,11 +41,10 @@ public class RecorderExample {
{ {
event.getException().printStackTrace(); event.getException().printStackTrace();
}) })
.addListener(TikTokLiveRecorder.use(recorderSettings -> .addListener(TikTokLiveRecorder.use((recorderSettings, liveClient) ->
{ {
recorderSettings.setFfmpegPath("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\extension-recorder\\libs\\ffmpeg.exe"); recorderSettings.setFfmpegPath("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\extension-recorder\\libs\\ffmpeg.exe");
recorderSettings.setOutputPath("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\extension-recorder\\out"); recorderSettings.setOutputFile(new File("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\extension-recorder\\out", "test.flv"));
recorderSettings.setOutputFileName("test.flv");
})) }))
.onEvent(TikTokLiveRecorderStartedEvent.class, (liveClient, event) -> .onEvent(TikTokLiveRecorderStartedEvent.class, (liveClient, event) ->
{ {
@@ -52,4 +53,4 @@ public class RecorderExample {
.buildAndConnect(); .buildAndConnect();
} }
} }

View File

@@ -70,7 +70,7 @@ Maven
<dependency> <dependency>
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId> <groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
<artifactId>Client</artifactId> <artifactId>Client</artifactId>
<version>1.6.0-Release</version> <version>1.7.0-Release</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

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.6.0-Release</version> <version>1.7.2-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

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