This commit is contained in:
JW
2023-12-11 03:56:17 +01:00
parent e3e0d8a88e
commit 46d5f15d3f
56 changed files with 45793 additions and 7503 deletions

View File

@@ -131,6 +131,7 @@ public class TikTokLiveClient implements LiveClient {
setState(ConnectionState.CONNECTING);
apiService.updateSessionId();
if (clientSettings.getRoomId() != null) {

View File

@@ -191,6 +191,12 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
return build().connectAsync();
}
public LiveClientBuilder onCustomEvent(EventConsumer<CustomEvent> event) {
tikTokEventHandler.subscribe(CustomEvent.class, event);
return this;
}
public TikTokLiveClientBuilder onUnhandledSocial(
EventConsumer<TikTokUnhandledSocialEvent> event) {
tikTokEventHandler.subscribe(TikTokUnhandledSocialEvent.class, event);
@@ -203,6 +209,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
return this;
}
public TikTokLiveClientBuilder onLinkMicFanTicket(
EventConsumer<TikTokLinkMicFanTicketEvent> event) {
tikTokEventHandler.subscribe(TikTokLinkMicFanTicketEvent.class, event);

View File

@@ -23,6 +23,7 @@
package io.github.jwdeveloper.tiktok.handlers;
import io.github.jwdeveloper.tiktok.data.dto.MessageMetaData;
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketMessageEvent;
@@ -88,10 +89,10 @@ public abstract class TikTokMessageHandler {
stopwatch.start();
var events = handler.handle(message.getPayload().toByteArray());
var handlingTimeInMs = stopwatch.stop();
var metadata = new TikTokWebsocketMessageEvent.MetaData(Duration.ofNanos(handlingTimeInMs));
var metadata = new MessageMetaData(Duration.ofNanos(handlingTimeInMs));
for (var event : events) {
tikTokEventHandler.publish(client, new TikTokWebsocketMessageEvent(event, message, metadata));
tikTokEventHandler.publish(client, new TikTokWebsocketMessageEvent(message, event, metadata));
tikTokEventHandler.publish(client, event);
}
}

View File

@@ -33,6 +33,8 @@ import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomPinEvent;
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
import io.github.jwdeveloper.tiktok.data.models.chest.Chest;
import io.github.jwdeveloper.tiktok.data.models.users.User;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.handlers.events.TikTokGiftEventHandler;
import io.github.jwdeveloper.tiktok.handlers.events.TikTokRoomInfoEventHandler;
import io.github.jwdeveloper.tiktok.handlers.events.TikTokSocialMediaEventHandler;
@@ -64,6 +66,21 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
public void init() {
registerMapping(WebcastGiftMessage.class, bytes ->
{
try {
WebcastGiftMessage tiktokData = WebcastGiftMessage.parseFrom(bytes);
io.github.jwdeveloper.tiktok.messages.data.User tiktokProtocolBufferUser = tiktokData.getUser();
io.github.jwdeveloper.tiktok.data.models.users.User tiktokLiveJavaUser = User.map(tiktokProtocolBufferUser);
return new CustomEvent(tiktokLiveJavaUser, "hello word");
} catch (Exception e) {
throw new TikTokLiveException("Unable to parse our custom event", e);
}
});
//ConnectionEvents events
registerMapping(WebcastControlMessage.class, this::handleWebcastControlMessage);
@@ -105,7 +122,7 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
registerMapping(WebcastImDeleteMessage.class, TikTokIMDeleteEvent.class);
registerMapping(WebcastQuestionNewMessage.class, TikTokQuestionEvent.class);
registerMappings(WebcastEnvelopeMessage.class, this::handleEnvelop);
registerMapping(WebcastSubNotifyMessage.class, TikTokSubNotifyEvent.class);
registerMapping(WebcastSubNotifyMessage.class, TikTokSubscribeEvent.class);
registerMapping(WebcastEmoteChatMessage.class, TikTokEmoteEvent.class);
}
@@ -122,6 +139,9 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
}
@SneakyThrows
private List<TikTokEvent> handleMemberMessage(byte[] msg) {
var message = WebcastMemberMessage.parseFrom(msg);

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.handlers.events;
public class TikTokChestEventHandler {

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.handlers.events;
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;

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.handlers.events;
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;

View File

@@ -22,6 +22,9 @@
*/
package io.github.jwdeveloper.tiktok.http;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.github.jwdeveloper.tiktok.ClientSettings;
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
@@ -68,7 +71,14 @@ public class TikTokApiService {
var params = new HashMap<>(clientSettings.getClientParameters());
params.put("uniqueId", userName);
params.put("sourceType", 54);
var roomData = tiktokHttpClient.getJsonFromTikTokApi("api-live/user/room/", params);
JsonObject roomData = null;
try {
roomData = tiktokHttpClient.getJsonFromTikTokApi("api-live/user/room/", params);
} catch (Exception e) {
throw new TikTokLiveRequestException("Failed to fetch pre connection room information, it happens when TikTok temporary blocks you. Try to connect again in few minutes");
}
var message = roomData.get("message").getAsString();
@@ -87,7 +97,7 @@ public class TikTokApiService {
var status = user.get("status").getAsInt();
var statusEnum = switch (status) {
case 2 -> TikTokUserInfo.UserStatus.Live;
case 2 -> TikTokUserInfo.UserStatus.Live;
case 3 -> TikTokUserInfo.UserStatus.LivePaused;
case 4 -> TikTokUserInfo.UserStatus.Offline;
default -> TikTokUserInfo.UserStatus.NotFound;
@@ -101,12 +111,18 @@ public class TikTokApiService {
logger.info("Fetching RoomInfo");
try {
var response = tiktokHttpClient.getJsonFromWebcastApi("room/info/", clientSettings.getClientParameters());
if (!response.has("data")) {
var gson = new GsonBuilder().setPrettyPrinting().create();
var json = gson.toJson(response);
throw new TikTokLiveRequestException("room info response does not contains data field: \n"+ json);
}
var mapper = new LiveRoomMetaMapper();
var liveRoomMeta = mapper.map(response);
logger.info("RoomInfo status -> " + liveRoomMeta.getStatus());
return liveRoomMeta;
} catch (Exception e) {
throw new TikTokLiveRequestException("Failed to fetch room info from WebCast, see stacktrace for more info.", e);
throw new TikTokLiveRequestException("Failed to fetch room info from WebCast server, see stacktrace for more info.", e);
}
}
@@ -119,7 +135,7 @@ public class TikTokApiService {
clientSettings.getClientParameters().put("internal_ext", response.getInternalExt());
return response;
} catch (Exception e) {
throw new TikTokLiveRequestException("Failed to fetch client data", e);
throw new TikTokLiveRequestException("Failed to fetch live websocket connection data", 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.http;
import io.github.jwdeveloper.tiktok.ClientSettings;

View File

@@ -69,4 +69,7 @@ public class TikTokGiftManagerTest {
}
}

View File

@@ -125,4 +125,6 @@ class TikTokGiftEventHandlerTest {
return builder.build();
}
}

View File

@@ -1,8 +1,34 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.http;
import io.github.jwdeveloper.tiktok.TikTokLive;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Random;
public class TikTokLiveOnlineCheckerTest {
public boolean enableTests = false;
@@ -25,7 +51,7 @@ public class TikTokLiveOnlineCheckerTest {
@Test
public void shouldBeOffline() {
var TARGET_USER = "dostawcavideo";
var TARGET_USER = "karacomparetto";
var sut = new TikTokDataChecker();
var result = sut.isOnline(TARGET_USER);
@@ -33,18 +59,41 @@ public class TikTokLiveOnlineCheckerTest {
}
@Test
public void shouldBeValid() {
public void shouldBeValid() throws InterruptedException {
var TARGET_USER = "dostawcavideo";
var sut = new TikTokDataChecker();
var result = sut.isHostNameValid(TARGET_USER);
TikTokLive.newClient("asdasd")
.onWebsocketResponse((liveClient, event) ->
{
for(var message : event.getResponse().getMessagesList())
{
if(message.getMethod().equals("WebcastGiftMessage"))
{
try
{
var bytes = message.getMethodBytes();
var rawMessage = WebcastGiftMessage.parseFrom(bytes);
var giftName =rawMessage.getGift().getName();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
});
Assertions.assertTrue(result);
}
@Test
public void shouldNotBeValid() {
var TARGET_USER = "adadsdadadadadadadadddasdadsafafsafsafas";
var TARGET_USER = "dqagdagda , asdaaasd";
var sut = new TikTokDataChecker();
var result = sut.isHostNameValid(TARGET_USER);