mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-27 08:49:40 -05:00
Final Proxy Commit!
This commit is contained in:
@@ -24,7 +24,7 @@ package io.github.jwdeveloper.tiktok.data.events;
|
|||||||
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@@ -32,4 +32,12 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
|
|||||||
*/
|
*/
|
||||||
@EventMeta(eventType = EventType.Control)
|
@EventMeta(eventType = EventType.Control)
|
||||||
public class TikTokDisconnectedEvent extends TikTokLiveClientEvent {
|
public class TikTokDisconnectedEvent extends TikTokLiveClientEvent {
|
||||||
|
@Getter private final String reason;
|
||||||
|
public TikTokDisconnectedEvent(String reason) {
|
||||||
|
this.reason = reason.isBlank() ? "None" : reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokDisconnectedEvent() {
|
||||||
|
this("None");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -22,10 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.data.requests;
|
package io.github.jwdeveloper.tiktok.data.requests;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.*;
|
||||||
import lombok.Data;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
public class LiveUserData {
|
public class LiveUserData {
|
||||||
|
|
||||||
@@ -38,15 +35,18 @@ public class LiveUserData {
|
|||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public static class Response {
|
public static class Response {
|
||||||
|
|
||||||
private String json;
|
private String json;
|
||||||
|
|
||||||
private UserStatus userStatus;
|
private UserStatus userStatus;
|
||||||
|
|
||||||
private String roomId;
|
private String roomId;
|
||||||
|
|
||||||
|
|
||||||
private long startedAtTimeStamp;
|
private long startedAtTimeStamp;
|
||||||
|
|
||||||
|
public boolean isLiveOnline() {
|
||||||
|
return userStatus == LiveUserData.UserStatus.Live || userStatus == LiveUserData.UserStatus.LivePaused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHostNameValid() {
|
||||||
|
return userStatus != LiveUserData.UserStatus.NotFound;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum UserStatus {
|
public enum UserStatus {
|
||||||
@@ -56,5 +56,3 @@ public class LiveUserData {
|
|||||||
Live,
|
Live,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -63,10 +63,11 @@ public class ProxyClientSettings implements Iterator<ProxyData>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProxyData next()
|
public ProxyData next() {
|
||||||
{
|
return lastSuccess ? proxyList.get(index) : rotate();
|
||||||
if (lastSuccess)
|
}
|
||||||
return proxyList.get(index);
|
|
||||||
|
public ProxyData rotate() {
|
||||||
var nextProxy = switch (rotation)
|
var nextProxy = switch (rotation)
|
||||||
{
|
{
|
||||||
case CONSECUTIVE -> {
|
case CONSECUTIVE -> {
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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.exceptions;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Happens while bad response from http proxy request to TikTok
|
||||||
|
*/
|
||||||
|
public class TikTokProxyRequestException extends TikTokLiveException
|
||||||
|
{
|
||||||
|
public TikTokProxyRequestException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokProxyRequestException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokProxyRequestException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokProxyRequestException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokProxyRequestException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
package io.github.jwdeveloper.tiktok;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
|
||||||
import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
|
import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||||
|
|
||||||
@@ -48,8 +47,7 @@ public class TikTokLive {
|
|||||||
*/
|
*/
|
||||||
public static boolean isLiveOnline(String hostName)
|
public static boolean isLiveOnline(String hostName)
|
||||||
{
|
{
|
||||||
LiveUserData.UserStatus status = requests().fetchLiveUserData(hostName).getUserStatus();
|
return requests().fetchLiveUserData(hostName).isLiveOnline();
|
||||||
return status == LiveUserData.UserStatus.Live || status == LiveUserData.UserStatus.LivePaused;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -72,8 +70,7 @@ public class TikTokLive {
|
|||||||
*/
|
*/
|
||||||
public static boolean isHostNameValid(String hostName)
|
public static boolean isHostNameValid(String hostName)
|
||||||
{
|
{
|
||||||
LiveUserData.UserStatus status = requests().fetchLiveUserData(hostName).getUserStatus();
|
return requests().fetchLiveUserData(hostName).isHostNameValid();
|
||||||
return status != LiveUserData.UserStatus.NotFound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -76,19 +76,15 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
|
|
||||||
|
|
||||||
public void connectAsync(Consumer<LiveClient> onConnection) {
|
public void connectAsync(Consumer<LiveClient> onConnection) {
|
||||||
CompletableFuture.supplyAsync(() ->
|
CompletableFuture.runAsync(() -> {
|
||||||
{
|
|
||||||
connect();
|
connect();
|
||||||
onConnection.accept(this);
|
onConnection.accept(this);
|
||||||
return this;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public CompletableFuture<LiveClient> connectAsync() {
|
public CompletableFuture<LiveClient> connectAsync() {
|
||||||
return CompletableFuture.supplyAsync(() ->
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
{
|
|
||||||
connect();
|
connect();
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
@@ -105,8 +101,7 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
if (e instanceof TikTokLiveOfflineHostException && clientSettings.isRetryOnConnectionFailure()) {
|
if (e instanceof TikTokLiveOfflineHostException && clientSettings.isRetryOnConnectionFailure()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(clientSettings.getRetryConnectionTimeout().toMillis());
|
Thread.sleep(clientSettings.getRetryConnectionTimeout().toMillis());
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {}
|
||||||
}
|
|
||||||
logger.info("Reconnecting");
|
logger.info("Reconnecting");
|
||||||
tikTokEventHandler.publish(this, new TikTokReconnectingEvent());
|
tikTokEventHandler.publish(this, new TikTokReconnectingEvent());
|
||||||
this.connect();
|
this.connect();
|
||||||
@@ -120,14 +115,12 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void tryConnect() {
|
public void tryConnect() {
|
||||||
if (!liveRoomInfo.hasConnectionState(ConnectionState.DISCONNECTED))
|
if (!liveRoomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) {
|
||||||
{
|
|
||||||
throw new TikTokLiveException("Already connected");
|
throw new TikTokLiveException("Already connected");
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(ConnectionState.CONNECTING);
|
setState(ConnectionState.CONNECTING);
|
||||||
|
|
||||||
|
|
||||||
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.getStartedAtTimeStamp());
|
||||||
@@ -139,7 +132,6 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
throw new TikTokLiveOfflineHostException("User not found: "+liveRoomInfo.getHostUser());
|
throw new TikTokLiveOfflineHostException("User not found: "+liveRoomInfo.getHostUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var liveDataRequest = new LiveData.Request(userData.getRoomId());
|
var liveDataRequest = new LiveData.Request(userData.getRoomId());
|
||||||
var liveData = httpClient.fetchLiveData(liveDataRequest);
|
var liveData = httpClient.fetchLiveData(liveDataRequest);
|
||||||
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound) {
|
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound) {
|
||||||
@@ -155,7 +147,6 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
liveRoomInfo.setAgeRestricted(liveData.isAgeRestricted());
|
liveRoomInfo.setAgeRestricted(liveData.isAgeRestricted());
|
||||||
liveRoomInfo.setHost(liveData.getHost());
|
liveRoomInfo.setHost(liveData.getHost());
|
||||||
|
|
||||||
|
|
||||||
var liveConnectionRequest =new LiveConnectionData.Request(userData.getRoomId());
|
var liveConnectionRequest =new LiveConnectionData.Request(userData.getRoomId());
|
||||||
var liveConnectionData = httpClient.fetchLiveConnectionData(liveConnectionRequest);
|
var liveConnectionData = httpClient.fetchLiveConnectionData(liveConnectionRequest);
|
||||||
webSocketClient.start(liveConnectionData, this);
|
webSocketClient.start(liveConnectionData, this);
|
||||||
@@ -181,7 +172,6 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
tikTokEventHandler.publish(this, event);
|
tikTokEventHandler.publish(this, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public LiveRoomInfo getRoomInfo() {
|
public LiveRoomInfo getRoomInfo() {
|
||||||
return liveRoomInfo;
|
return liveRoomInfo;
|
||||||
}
|
}
|
||||||
@@ -200,6 +190,4 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
public GiftManager getGiftManager() {
|
public GiftManager getGiftManager() {
|
||||||
return tikTokGiftManager;
|
return tikTokGiftManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
|
|
||||||
|
|
||||||
var httpClientFactory = new HttpClientFactory(clientSettings);
|
var httpClientFactory = new HttpClientFactory(clientSettings);
|
||||||
var tikTokLiveHttpClient = new TikTokLiveHttpClient(httpClientFactory);
|
var tikTokLiveHttpClient = new TikTokLiveHttpClient(httpClientFactory, clientSettings);
|
||||||
|
|
||||||
var webSocketClient = new TikTokWebSocketClient(
|
var webSocketClient = new TikTokWebSocketClient(
|
||||||
clientSettings,
|
clientSettings,
|
||||||
@@ -346,7 +346,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveClientBuilder onRoomInfo(EventConsumer<TikTokRoomInfoEvent> event) {
|
public TikTokLiveClientBuilder onRoomInfo(EventConsumer<TikTokRoomInfoEvent> event) {
|
||||||
tikTokEventHandler.subscribe(TikTokRoomInfoEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokRoomInfoEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -358,7 +358,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveClientBuilder onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> event) {
|
public TikTokLiveClientBuilder onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> event) {
|
||||||
tikTokEventHandler.subscribe(TikTokLiveUnpausedEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokLiveUnpausedEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ package io.github.jwdeveloper.tiktok;
|
|||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
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.*;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.*;
|
import io.github.jwdeveloper.tiktok.exceptions.*;
|
||||||
import io.github.jwdeveloper.tiktok.http.*;
|
import io.github.jwdeveloper.tiktok.http.*;
|
||||||
import io.github.jwdeveloper.tiktok.http.mappers.*;
|
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.Optional;
|
||||||
|
|
||||||
public class TikTokLiveHttpClient implements LiveHttpClient {
|
public class TikTokLiveHttpClient implements LiveHttpClient {
|
||||||
|
|
||||||
@@ -43,13 +44,15 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
private static final String TIKTOK_URL_WEBCAST = "https://webcast.tiktok.com/webcast/";
|
private static final String TIKTOK_URL_WEBCAST = "https://webcast.tiktok.com/webcast/";
|
||||||
|
|
||||||
private final HttpClientFactory httpFactory;
|
private final HttpClientFactory httpFactory;
|
||||||
|
private final LiveClientSettings clientSettings;
|
||||||
private final LiveUserDataMapper liveUserDataMapper;
|
private final LiveUserDataMapper liveUserDataMapper;
|
||||||
private final LiveDataMapper liveDataMapper;
|
private final LiveDataMapper liveDataMapper;
|
||||||
private final SignServerResponseMapper signServerResponseMapper;
|
private final SignServerResponseMapper signServerResponseMapper;
|
||||||
private final GiftsDataMapper giftsDataMapper;
|
private final GiftsDataMapper giftsDataMapper;
|
||||||
|
|
||||||
public TikTokLiveHttpClient(HttpClientFactory factory) {
|
public TikTokLiveHttpClient(HttpClientFactory factory, LiveClientSettings settings) {
|
||||||
this.httpFactory = factory;
|
this.httpFactory = factory;
|
||||||
|
clientSettings = settings;
|
||||||
liveUserDataMapper = new LiveUserDataMapper();
|
liveUserDataMapper = new LiveUserDataMapper();
|
||||||
liveDataMapper = new LiveDataMapper();
|
liveDataMapper = new LiveDataMapper();
|
||||||
signServerResponseMapper = new SignServerResponseMapper();
|
signServerResponseMapper = new SignServerResponseMapper();
|
||||||
@@ -57,7 +60,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveHttpClient() {
|
public TikTokLiveHttpClient() {
|
||||||
this(new HttpClientFactory(LiveClientSettings.createDefault()));
|
this(new HttpClientFactory(LiveClientSettings.createDefault()), LiveClientSettings.createDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +85,26 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) {
|
public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) {
|
||||||
|
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
||||||
|
if (proxyClientSettings.isEnabled()) {
|
||||||
|
while (proxyClientSettings.hasNext()) {
|
||||||
|
try {
|
||||||
|
var url = TIKTOK_URL_WEB + "api-live/user/room";
|
||||||
|
var optional = httpFactory.client(url)
|
||||||
|
.withParam("uniqueId", request.getUserName())
|
||||||
|
.withParam("sourceType", "54")
|
||||||
|
.build()
|
||||||
|
.toJsonResponse();
|
||||||
|
|
||||||
|
if (optional.isEmpty()) {
|
||||||
|
throw new TikTokLiveRequestException("Unable to get information's about user");
|
||||||
|
}
|
||||||
|
|
||||||
|
var json = optional.get();
|
||||||
|
return liveUserDataMapper.map(json);
|
||||||
|
} catch (TikTokProxyRequestException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
var url = TIKTOK_URL_WEB + "api-live/user/room";
|
var url = TIKTOK_URL_WEB + "api-live/user/room";
|
||||||
var optional = httpFactory.client(url)
|
var optional = httpFactory.client(url)
|
||||||
.withParam("uniqueId", request.getUserName())
|
.withParam("uniqueId", request.getUserName())
|
||||||
@@ -105,7 +127,25 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveData.Response fetchLiveData(LiveData.Request request) {
|
public LiveData.Response fetchLiveData(LiveData.Request request) {
|
||||||
|
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
||||||
|
if (proxyClientSettings.isEnabled()) {
|
||||||
|
while (proxyClientSettings.hasNext()) {
|
||||||
|
try {
|
||||||
|
var url = TIKTOK_URL_WEBCAST + "room/info";
|
||||||
|
var optional = httpFactory.client(url)
|
||||||
|
.withParam("room_id", request.getRoomId())
|
||||||
|
.build()
|
||||||
|
.toJsonResponse();
|
||||||
|
|
||||||
|
if (optional.isEmpty()) {
|
||||||
|
throw new TikTokLiveRequestException("Unable to get info about live room");
|
||||||
|
}
|
||||||
|
|
||||||
|
var json = optional.get();
|
||||||
|
return liveDataMapper.map(json);
|
||||||
|
} catch (TikTokProxyRequestException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
var url = TIKTOK_URL_WEBCAST + "room/info";
|
var url = TIKTOK_URL_WEBCAST + "room/info";
|
||||||
var optional = httpFactory.client(url)
|
var optional = httpFactory.client(url)
|
||||||
.withParam("room_id", request.getRoomId())
|
.withParam("room_id", request.getRoomId())
|
||||||
@@ -127,14 +167,15 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request) {
|
public LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request) {
|
||||||
|
HttpResponse<byte[]> credentialsResponse = getOptionalProxyResponse(request).orElseGet(()-> {
|
||||||
var signServerResponse = getSignedUrl(request.getRoomId());
|
SignServerResponse signServerResponse = getSignedUrl(request.getRoomId());
|
||||||
var credentialsResponse = getWebsocketCredentialsResponse(signServerResponse.getSignedUrl());
|
return getWebsocketCredentialsResponse(signServerResponse.getSignedUrl());
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var optionalHeader = credentialsResponse.headers().firstValue("set-cookie");
|
var optionalHeader = credentialsResponse.headers().firstValue("set-cookie");
|
||||||
if (optionalHeader.isEmpty()) {
|
if (optionalHeader.isEmpty()) {
|
||||||
throw new TikTokSignServerException("Sign server does not returned set-cookie header");
|
throw new TikTokSignServerException("Sign server did not return the set-cookie header");
|
||||||
}
|
}
|
||||||
var websocketCookie = optionalHeader.get();
|
var websocketCookie = optionalHeader.get();
|
||||||
var webcastResponse = WebcastResponse.parseFrom(credentialsResponse.body());
|
var webcastResponse = WebcastResponse.parseFrom(credentialsResponse.body());
|
||||||
@@ -189,4 +230,18 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
return optionalResponse.get();
|
return optionalResponse.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<HttpResponse<byte[]>> getOptionalProxyResponse(LiveConnectionData.Request request) {
|
||||||
|
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
||||||
|
if (proxyClientSettings.isEnabled()) {
|
||||||
|
while (proxyClientSettings.hasNext()) {
|
||||||
|
try {
|
||||||
|
SignServerResponse signServerResponse = getSignedUrl(request.getRoomId());
|
||||||
|
HttpResponse<byte[]> credentialsResponse = getWebsocketCredentialsResponse(signServerResponse.getSignedUrl());
|
||||||
|
clientSettings.getHttpSettings().getProxyClientSettings().rotate();
|
||||||
|
return Optional.of(credentialsResponse);
|
||||||
|
} catch (TikTokProxyRequestException | TikTokSignServerException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,12 +23,14 @@
|
|||||||
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 io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.*;
|
||||||
|
|
||||||
import javax.net.ssl.*;
|
import javax.net.ssl.*;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.net.http.*;
|
import java.net.http.*;
|
||||||
import java.net.http.HttpResponse.ResponseInfo;
|
import java.net.http.HttpResponse.ResponseInfo;
|
||||||
|
import java.security.*;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -93,7 +95,7 @@ public class HttpProxyClient extends HttpClient
|
|||||||
|
|
||||||
URL url = toUrl().toURL();
|
URL url = toUrl().toURL();
|
||||||
|
|
||||||
while (proxySettings.hasNext()) {
|
if (proxySettings.hasNext()) {
|
||||||
try {
|
try {
|
||||||
Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxySettings.next().toSocketAddress());
|
Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxySettings.next().toSocketAddress());
|
||||||
|
|
||||||
@@ -117,21 +119,24 @@ public class HttpProxyClient extends HttpClient
|
|||||||
|
|
||||||
proxySettings.setLastSuccess(true);
|
proxySettings.setLastSuccess(true);
|
||||||
return Optional.of(response);
|
return Optional.of(response);
|
||||||
} catch (SocketException | SocketTimeoutException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
|
||||||
if (proxySettings.isAutoDiscard())
|
if (proxySettings.isAutoDiscard())
|
||||||
proxySettings.remove();
|
proxySettings.remove();
|
||||||
proxySettings.setLastSuccess(false);
|
proxySettings.setLastSuccess(false);
|
||||||
|
throw new TikTokProxyRequestException(e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new TikTokLiveRequestException(e);
|
throw new TikTokLiveRequestException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new TikTokLiveRequestException("No more proxies available!");
|
throw new TikTokLiveRequestException("No more proxies available!");
|
||||||
} catch (Exception e) {
|
} catch (NoSuchAlgorithmException | MalformedURLException | KeyManagementException e) {
|
||||||
// Should never be reached!
|
// Should never be reached!
|
||||||
System.out.println("handleSocksProxyRequest()! If you see this message, reach us on discord!");
|
System.out.println("handleSocksProxyRequest()! If you see this message, reach us on discord!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
} catch (TikTokLiveRequestException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,10 @@ import com.google.gson.JsonParser;
|
|||||||
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
|
|
||||||
public class LiveUserDataMapper {
|
public class LiveUserDataMapper
|
||||||
|
{
|
||||||
|
|
||||||
public LiveUserData.Response map(String json) {
|
public LiveUserData.Response map(String json) {
|
||||||
var parsedJson = JsonParser.parseString(json);
|
var jsonObject = JsonParser.parseString(json).getAsJsonObject();
|
||||||
var jsonObject = parsedJson.getAsJsonObject();
|
|
||||||
|
|
||||||
var message = jsonObject.get("message").getAsString();
|
var message = jsonObject.get("message").getAsString();
|
||||||
|
|
||||||
@@ -64,6 +62,5 @@ public class LiveUserDataMapper {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return new LiveUserData.Response(json, statusEnum, roomId, startTime);
|
return new LiveUserData.Response(json, statusEnum, roomId, startTime);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,6 +52,7 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
this.tikTokEventHandler = tikTokEventHandler;
|
this.tikTokEventHandler = tikTokEventHandler;
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(LiveConnectionData.Response connectionData, LiveClient liveClient)
|
public void start(LiveConnectionData.Response connectionData, LiveClient liveClient)
|
||||||
{
|
{
|
||||||
@@ -71,7 +72,6 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
liveClient);
|
liveClient);
|
||||||
|
|
||||||
// ProxyClientSettings proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
// ProxyClientSettings proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
||||||
//
|
|
||||||
// if (proxyClientSettings.isEnabled())
|
// if (proxyClientSettings.isEnabled())
|
||||||
// connectProxy(proxyClientSettings);
|
// connectProxy(proxyClientSettings);
|
||||||
// else
|
// else
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ public class TikTokWebSocketListener extends WebSocketClient {
|
|||||||
messageHandler.handle(tikTokLiveClient, webcastResponse);
|
messageHandler.handle(tikTokLiveClient, webcastResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpen(ServerHandshake serverHandshake) {
|
public void onOpen(ServerHandshake serverHandshake) {
|
||||||
tikTokEventHandler.publish(tikTokLiveClient, new TikTokConnectedEvent());
|
tikTokEventHandler.publish(tikTokLiveClient, new TikTokConnectedEvent());
|
||||||
@@ -96,10 +95,9 @@ public class TikTokWebSocketListener extends WebSocketClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClose(int code, String reason, boolean remote) {
|
public void onClose(int code, String reason, boolean remote) {
|
||||||
tikTokEventHandler.publish(tikTokLiveClient, new TikTokDisconnectedEvent());
|
tikTokEventHandler.publish(tikTokLiveClient, new TikTokDisconnectedEvent(reason));
|
||||||
tikTokLiveClient.disconnect();
|
tikTokLiveClient.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,8 +109,6 @@ public class TikTokWebSocketListener extends WebSocketClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Optional<WebcastPushFrame> getWebcastPushFrame(byte[] buffer) {
|
private Optional<WebcastPushFrame> getWebcastPushFrame(byte[] buffer) {
|
||||||
try {
|
try {
|
||||||
var websocketMessage = WebcastPushFrame.parseFrom(buffer);
|
var websocketMessage = WebcastPushFrame.parseFrom(buffer);
|
||||||
@@ -137,9 +133,8 @@ public class TikTokWebSocketListener extends WebSocketClient {
|
|||||||
return !isClosed() && !isClosing();
|
return !isClosed() && !isClosing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(String s) {
|
public void onMessage(String s) {
|
||||||
System.err.println(s);
|
// System.err.println(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,54 +22,29 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
import java.net.*;
|
import java.net.Proxy;
|
||||||
import java.net.http.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class ProxyExample
|
public class ProxyExample
|
||||||
{
|
{
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
// TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||||
|
.configure(clientSettings -> {
|
||||||
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.proxyscrape.com/v2/?request=displayproxies&protocol=socks4,socks5&timeout=10000&country=us")).GET().build();
|
|
||||||
HttpResponse<Stream<String>> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofLines());
|
|
||||||
|
|
||||||
List<AbstractMap.SimpleEntry<String, Integer>> entries = new ArrayList<>(response.body().map(s -> {
|
|
||||||
String[] split = s.split(":");
|
|
||||||
return new AbstractMap.SimpleEntry<>(split[0], Integer.parseInt(split[1]));
|
|
||||||
}).toList());
|
|
||||||
|
|
||||||
TikTokLive.newClient("dash4214")
|
|
||||||
.configure(clientSettings ->
|
|
||||||
{
|
|
||||||
clientSettings.setPrintToConsole(true);
|
clientSettings.setPrintToConsole(true);
|
||||||
clientSettings.getHttpSettings().configureProxy(proxySettings -> {
|
clientSettings.getHttpSettings().configureProxy(proxySettings -> {
|
||||||
proxySettings.setOnProxyUpdated(proxyData ->
|
proxySettings.setOnProxyUpdated(proxyData -> System.err.println("Next proxy: " + proxyData.toString()));
|
||||||
{
|
|
||||||
System.err.println("Next proxy: "+proxyData.toString());
|
|
||||||
});
|
|
||||||
proxySettings.setType(Proxy.Type.SOCKS);
|
proxySettings.setType(Proxy.Type.SOCKS);
|
||||||
entries.forEach(entry -> proxySettings.addProxy(entry.getKey(), entry.getValue()));
|
proxySettings.addProxy("localhost", 8080);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.onComment((liveClient, event) -> {
|
|
||||||
liveClient.getLogger().info(event.getUser().getName()+": "+event.getText());
|
|
||||||
})
|
|
||||||
.onConnected((liveClient, event) ->
|
.onConnected((liveClient, event) ->
|
||||||
{
|
liveClient.getLogger().info("Connected "+liveClient.getRoomInfo().getHostName()))
|
||||||
liveClient.getLogger().info("Hello world!");
|
|
||||||
})
|
|
||||||
.onDisconnected((liveClient, event) ->
|
.onDisconnected((liveClient, event) ->
|
||||||
{
|
liveClient.getLogger().info("Disconnect reason: "+event.getReason()))
|
||||||
liveClient.getLogger().info("Goodbye world!");
|
.onLiveEnded((liveClient, event) ->
|
||||||
})
|
liveClient.getLogger().info("Live Ended"))
|
||||||
.onError((liveClient, event) ->
|
.onError((liveClient, event) ->
|
||||||
{
|
event.getException().printStackTrace())
|
||||||
event.getException().printStackTrace();
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
.buildAndConnect();
|
||||||
|
|
||||||
System.in.read();
|
System.in.read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user