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
This commit is contained in:
kohlerpop1
2024-06-28 23:07:10 -04:00
parent 34ddc74189
commit cfef082d3b
11 changed files with 71 additions and 50 deletions

View File

@@ -50,16 +50,12 @@ public class ProxyData
return new ProxyData(address, port);
} 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) {
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() {
return new InetSocketAddress(address, port);
}

View File

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

View File

@@ -97,7 +97,7 @@ public class HttpClientSettings {
newSettings.getHeaders().putAll(new TreeMap<>(this.headers));
newSettings.getCookies().putAll(new TreeMap<>(this.cookies));
newSettings.getParams().putAll(new TreeMap<>(this.params));
newSettings.proxyClientSettings = this.proxyClientSettings;
newSettings.setProxyClientSettings(this.proxyClientSettings);
return newSettings;
}

View File

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

View File

@@ -23,12 +23,14 @@
package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager;
import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
public class TikTokLive {
@@ -82,13 +84,22 @@ public class TikTokLive {
return CompletableFuture.supplyAsync(() -> isHostNameValid(hostName));
}
/**
* Use to get some data from TikTok about users are lives
*
* @return LiveHttpClient
*/
public static LiveHttpClient requests(Consumer<LiveClientSettings> consumer) {
return new TikTokLiveHttpClient(consumer);
}
/**
* Use to get some data from TikTok about users are lives
*
* @return LiveHttpClient
*/
public static LiveHttpClient requests() {
return new TikTokLiveHttpClient();
return requests(liveClientSettings -> {});
}
private static GiftsManager giftsManager;

View File

@@ -125,7 +125,7 @@ public class TikTokLiveClient implements LiveClient {
tikTokEventHandler.publish(this, new TikTokConnectingEvent());
var userDataRequest = new LiveUserData.Request(liveRoomInfo.getHostName());
var userData = httpClient.fetchLiveUserData(userDataRequest);
liveRoomInfo.setStartTime(userData.getStartedAtTimeStamp());
liveRoomInfo.setStartTime(userData.getStartTime());
liveRoomInfo.setRoomId(userData.getRoomId());
if (clientSettings.isFetchGifts())

View File

@@ -117,11 +117,9 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
var listenerManager = new TikTokListenersManager(listeners, eventHandler);
var httpClientFactory = new HttpClientFactory(clientSettings);
var liveHttpClient = clientSettings.isOffline() ?
new TikTokLiveHttpOfflineClient() :
new TikTokLiveHttpClient(httpClientFactory, clientSettings);
new TikTokLiveHttpClient(new HttpClientFactory(clientSettings));
var eventsMapper = createMapper(giftsManager, tiktokRoomInfo);
var messageHandler = new TikTokLiveMessageHandler(eventHandler, eventsMapper);

View File

@@ -32,6 +32,7 @@ import io.github.jwdeveloper.tiktok.http.mappers.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import java.net.http.HttpResponse;
import java.util.function.Consumer;
import java.util.logging.Logger;
public class TikTokLiveHttpClient implements LiveHttpClient
@@ -53,17 +54,18 @@ public class TikTokLiveHttpClient implements LiveHttpClient
private final GiftsDataMapper giftsDataMapper;
private final Logger logger;
public TikTokLiveHttpClient(HttpClientFactory factory, LiveClientSettings settings) {
public TikTokLiveHttpClient(HttpClientFactory factory) {
this.httpFactory = factory;
this.clientSettings = settings;
this.clientSettings = factory.getLiveClientSettings();
this.logger = LoggerFactory.create("HttpClient-"+hashCode(), clientSettings);
liveUserDataMapper = new LiveUserDataMapper();
liveDataMapper = new LiveDataMapper();
giftsDataMapper = new GiftsDataMapper();
}
public TikTokLiveHttpClient() {
this(new HttpClientFactory(LiveClientSettings.createDefault()), LiveClientSettings.createDefault());
public TikTokLiveHttpClient(Consumer<LiveClientSettings> consumer) {
this(new HttpClientFactory(LiveClientSettings.createDefault()));
consumer.accept(clientSettings);
}
public GiftsData.Response fetchRoomGiftsData(String room_id) {
@@ -191,7 +193,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
.withParam("internal_ext", webcastResponse.getInternalExt())
.withParams(webcastResponse.getRouteParamsMapMap())
.build()
.toUrl();
.toUri();
return new LiveConnectionData.Response(websocketCookie, webSocketUrl, webcastResponse);
} catch (InvalidProtocolBufferException e) {

View File

@@ -90,14 +90,14 @@ public class HttpClient {
return toResponse().map(HttpResponse::body);
}
public URI toUrl() {
public URI toUri() {
var stringUrl = prepareUrlWithParameters(url, httpClientSettings.getParams());
return URI.create(stringUrl);
}
protected HttpRequest prepareGetRequest() {
var requestBuilder = HttpRequest.newBuilder().GET();
requestBuilder.uri(toUrl());
requestBuilder.uri(toUri());
requestBuilder.timeout(httpClientSettings.getTimeout());
httpClientSettings.getHeaders().forEach(requestBuilder::setHeader);

View File

@@ -23,7 +23,9 @@
package io.github.jwdeveloper.tiktok.http;
import io.github.jwdeveloper.tiktok.data.settings.*;
import lombok.Getter;
@Getter
public class HttpClientFactory {
private final LiveClientSettings liveClientSettings;

View File

@@ -95,7 +95,7 @@ public class HttpProxyClient extends HttpClient {
public X509Certificate[] getAcceptedIssuers() { return null; }
}}, null);
URL url = toUrl().toURL();
URL url = toUri().toURL();
if (proxySettings.hasNext()) {
try {
@@ -117,7 +117,7 @@ public class HttpProxyClient extends HttpClient {
var responseInfo = createResponseInfo(socksConnection.getResponseCode(), headers);
var response = createHttpResponse(body, toUrl(), responseInfo);
var response = createHttpResponse(body, toUri(), responseInfo);
return ActionResult.success(response);
} catch (IOException e) {