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); 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

@@ -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

@@ -97,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

@@ -36,7 +36,7 @@ public class ProxyClientSettings implements Iterator<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 -> {};
@@ -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 -> {
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();
}
};
onProxyUpdated.accept(nextProxy); onProxyUpdated.accept(nextProxy);
return 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 @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,19 @@ 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 +
'}';
}
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

@@ -23,12 +23,14 @@
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 {
@@ -82,13 +84,22 @@ public class TikTokLive {
return CompletableFuture.supplyAsync(() -> isHostNameValid(hostName)); return CompletableFuture.supplyAsync(() -> isHostNameValid(hostName));
} }
/**
* Use to get some data from TikTok about users are lives
*
* @return LiveHttpClient
*/
public static LiveHttpClient requests(Consumer<LiveClientSettings> consumer) {
return new TikTokLiveHttpClient(consumer);
}
/** /**
* Use to get some data from TikTok about users are lives * Use to get some data from TikTok about users are lives
* *
* @return LiveHttpClient * @return LiveHttpClient
*/ */
public static LiveHttpClient requests() { public static LiveHttpClient requests() {
return new TikTokLiveHttpClient(); return requests(liveClientSettings -> {});
} }
private static GiftsManager giftsManager; private static GiftsManager giftsManager;

View File

@@ -125,7 +125,7 @@ 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()) if (clientSettings.isFetchGifts())

View File

@@ -117,11 +117,9 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
var listenerManager = new TikTokListenersManager(listeners, eventHandler); var listenerManager = new TikTokListenersManager(listeners, eventHandler);
var httpClientFactory = new HttpClientFactory(clientSettings);
var liveHttpClient = clientSettings.isOffline() ? var liveHttpClient = clientSettings.isOffline() ?
new TikTokLiveHttpOfflineClient() : new TikTokLiveHttpOfflineClient() :
new TikTokLiveHttpClient(httpClientFactory, clientSettings); new TikTokLiveHttpClient(new HttpClientFactory(clientSettings));
var eventsMapper = createMapper(giftsManager, tiktokRoomInfo); var eventsMapper = createMapper(giftsManager, tiktokRoomInfo);
var messageHandler = new TikTokLiveMessageHandler(eventHandler, eventsMapper); 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 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
@@ -53,17 +54,18 @@ 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) { public TikTokLiveHttpClient(HttpClientFactory factory) {
this.httpFactory = factory; this.httpFactory = factory;
this.clientSettings = settings; this.clientSettings = factory.getLiveClientSettings();
this.logger = LoggerFactory.create("HttpClient-"+hashCode(), 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) { public GiftsData.Response fetchRoomGiftsData(String room_id) {
@@ -191,7 +193,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

@@ -90,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;

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 {
@@ -117,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) {