From bc8c56982f65b0fe73abe13698844c284a2a9a56 Mon Sep 17 00:00:00 2001 From: kohlerpop1 Date: Thu, 11 Jan 2024 11:34:12 -0500 Subject: [PATCH] Push for proxy test! --- .../tiktok/data/dto/ProxyData.java | 66 ++++++ .../data/settings/HttpClientSettings.java | 4 +- .../data/settings/ProxyClientSettings.java | 101 ++++++++- .../tiktok/TikTokLiveHttpClient.java | 11 +- .../jwdeveloper/tiktok/http/HttpClient.java | 62 +++--- .../tiktok/http/HttpClientBuilder.java | 8 +- .../tiktok/http/HttpProxyClient.java | 196 ++++++++++++++++++ .../websocket/TikTokWebSocketClient.java | 50 ++++- .../jwdeveloper/tiktok/ProxyExample.java | 66 ++++++ 9 files changed, 499 insertions(+), 65 deletions(-) create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/data/dto/ProxyData.java create mode 100644 Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpProxyClient.java create mode 100644 Examples/src/main/java/io/github/jwdeveloper/tiktok/ProxyExample.java diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/dto/ProxyData.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/dto/ProxyData.java new file mode 100644 index 0000000..e1a75ea --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/dto/ProxyData.java @@ -0,0 +1,66 @@ +/* + * 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.dto; + +import lombok.*; + +import java.net.*; + +@Data +@AllArgsConstructor +public class ProxyData +{ + private final String address; + private final int port; + + public static ProxyData map(String string) { + if (string == null || string.isBlank()) + throw new IllegalArgumentException("Provided address cannot be null or empty!"); + int portIndex = string.lastIndexOf(':'); + try { + String address = string.substring(0, portIndex); + int port = Integer.parseInt(string.substring(portIndex+1)); + + // Port validation + if (port < 0 || port > 65535) + throw new IndexOutOfBoundsException("Port out of range: "+port); + + // IP Validation + InetAddress res = InetAddress.getByName(address); + + return new ProxyData(address, port); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Port must be a valid integer!"); + } catch (UnknownHostException e) { + throw new IllegalArgumentException("Address must be valid IPv4, IPv6, or domain name!"); + } + } + + public ProxyData clone() { + return new ProxyData(address, port); + } + + public InetSocketAddress toSocketAddress() { + return new InetSocketAddress(address, port); + } +} \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/HttpClientSettings.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/HttpClientSettings.java index a38a69a..b693396 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/HttpClientSettings.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/HttpClientSettings.java @@ -74,7 +74,7 @@ public class HttpClientSettings { * @param consumer Use to configure proxy settings for http client */ public void configureProxy(Consumer consumer) { - proxyClientSettings.setUseProxy(true); + proxyClientSettings.setEnabled(true); consumer.accept(proxyClientSettings); } @@ -108,4 +108,4 @@ public class HttpClientSettings { return newSettings; } -} +} \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/ProxyClientSettings.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/ProxyClientSettings.java index 7d9b415..72bf7b9 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/ProxyClientSettings.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/ProxyClientSettings.java @@ -22,19 +22,100 @@ */ package io.github.jwdeveloper.tiktok.data.settings; -import lombok.Getter; -import lombok.Setter; +import io.github.jwdeveloper.tiktok.data.dto.ProxyData; +import lombok.*; + +import java.net.*; +import java.util.*; +import java.util.function.Consumer; -//TODO proxy implementation @Getter -public class ProxyClientSettings +@Setter +public class ProxyClientSettings implements Iterator { - @Setter - private boolean useProxy; + private boolean enabled; + private Rotation rotation = Rotation.CONSECUTIVE; + private final List proxyList = new ArrayList<>(); + private int index = 0; + private boolean autoDiscard = true; + private Proxy.Type type = Proxy.Type.DIRECT; + private Consumer onProxyUpdated = (x)->{}; - public ProxyClientSettings clone() - { - return new ProxyClientSettings(); + public boolean addProxy(String addressPort) { + return proxyList.add(ProxyData.map(addressPort)); } -} + + public boolean addProxy(String address, int port) { + return addProxy(new InetSocketAddress(address, port)); + } + + public boolean addProxy(InetSocketAddress inetAddress) { + return proxyList.add(new ProxyData(inetAddress.getHostString(), inetAddress.getPort())); + } + + public void addProxies(List list) { + list.forEach(this::addProxy); + } + + @Override + public 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(); + } + default -> { + yield proxyList.get(index).clone(); + } + }; + onProxyUpdated.accept(nextProxy); + return nextProxy; + } + + @Override + public void remove() { + proxyList.remove(index); + } + + public void setIndex(int index) { + if (index == 0 && proxyList.isEmpty()) + this.index = 0; + else { + if (index < 0 || index >= proxyList.size()) + throw new IndexOutOfBoundsException("Index " + index + " exceeds list of size: " + proxyList.size()); + this.index = index; + } + } + + public ProxyClientSettings clone() { + ProxyClientSettings settings = new ProxyClientSettings(); + settings.setEnabled(enabled); + settings.setRotation(rotation); + settings.setIndex(index); + settings.setType(type); + proxyList.forEach(proxyData -> settings.addProxy(proxyData.getAddress(), proxyData.getPort())); + return settings; + } + + public enum Rotation + { + /** Rotate addresses consecutively, from proxy 0 -> 1 -> 2 -> ...etc. */ + CONSECUTIVE, + /** Rotate addresses randomly, from proxy 0 -> 69 -> 420 -> 1 -> ...etc. */ + RANDOM, + /** Don't rotate addresses at all, pin to the indexed address. */ + NONE + } +} \ No newline at end of file diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java index 66ad2aa..3874ae6 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java @@ -25,14 +25,9 @@ package io.github.jwdeveloper.tiktok; import com.google.protobuf.InvalidProtocolBufferException; import io.github.jwdeveloper.tiktok.data.requests.*; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; -import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException; -import io.github.jwdeveloper.tiktok.exceptions.TikTokSignServerException; -import io.github.jwdeveloper.tiktok.http.HttpClientFactory; -import io.github.jwdeveloper.tiktok.http.LiveHttpClient; -import io.github.jwdeveloper.tiktok.http.mappers.GiftsDataMapper; -import io.github.jwdeveloper.tiktok.http.mappers.LiveDataMapper; -import io.github.jwdeveloper.tiktok.http.mappers.LiveUserDataMapper; -import io.github.jwdeveloper.tiktok.http.mappers.SignServerResponseMapper; +import io.github.jwdeveloper.tiktok.exceptions.*; +import io.github.jwdeveloper.tiktok.http.*; +import io.github.jwdeveloper.tiktok.http.mappers.*; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import java.net.http.HttpResponse; diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpClient.java index e0ad8fc..723caa0 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpClient.java @@ -26,42 +26,34 @@ import io.github.jwdeveloper.tiktok.data.settings.HttpClientSettings; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException; import lombok.AllArgsConstructor; -import java.net.CookieManager; -import java.net.URI; -import java.net.URLEncoder; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.Map; -import java.util.Optional; +import java.net.*; +import java.net.http.*; +import java.nio.charset.*; +import java.util.*; +import java.util.regex.*; import java.util.stream.Collectors; @AllArgsConstructor public class HttpClient { - private final HttpClientSettings httpClientSettings; - private final String url; - + protected final HttpClientSettings httpClientSettings; + protected final String url; + private final Pattern pattern = Pattern.compile("charset=(.*?)(?=&|$)"); public Optional> toResponse(HttpResponse.BodyHandler bodyHandler) { var client = prepareClient(); var request = prepareGetRequest(); - try - { - var response = client.send(request, bodyHandler); - if(response.statusCode() != 200) - { + try { + var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); + if (response.statusCode() != 200) { return Optional.empty(); } - - return Optional.of(response); } catch (Exception e) { throw new TikTokLiveRequestException(e); } } - public Optional toJsonResponse() { var optional = toResponse(HttpResponse.BodyHandlers.ofString()); if (optional.isEmpty()) { @@ -69,12 +61,24 @@ public class HttpClient { } var response = optional.get(); - - var body = response.body(); return Optional.of(body); } + private Charset charsetFrom(HttpHeaders headers) { + String type = headers.firstValue("Content-type").orElse("text/html; charset=utf-8"); + int i = type.indexOf(";"); + if (i >= 0) type = type.substring(i+1); + try { + Matcher matcher = pattern.matcher(type); + if (!matcher.find()) + return StandardCharsets.UTF_8; + return Charset.forName(matcher.group(1)); + } catch (Throwable x) { + return StandardCharsets.UTF_8; + } + } + public Optional toBinaryResponse() { var optional = toResponse(HttpResponse.BodyHandlers.ofByteArray()); if (optional.isEmpty()) { @@ -84,13 +88,12 @@ public class HttpClient { return Optional.of(body); } - public URI toUrl() { var stringUrl = prepareUrlWithParameters(url, httpClientSettings.getParams()); return URI.create(stringUrl); } - private HttpRequest prepareGetRequest() { + protected HttpRequest prepareGetRequest() { var requestBuilder = HttpRequest.newBuilder().GET(); requestBuilder.uri(toUrl()); requestBuilder.timeout(httpClientSettings.getTimeout()); @@ -100,18 +103,17 @@ public class HttpClient { return requestBuilder.build(); } - private java.net.http.HttpClient prepareClient() { + protected java.net.http.HttpClient prepareClient() { var builder = java.net.http.HttpClient.newBuilder() - .followRedirects(java.net.http.HttpClient.Redirect.NORMAL) - .cookieHandler(new CookieManager()) - .connectTimeout(httpClientSettings.getTimeout()); - + .followRedirects(java.net.http.HttpClient.Redirect.NORMAL) + .cookieHandler(new CookieManager()) + .connectTimeout(httpClientSettings.getTimeout()); httpClientSettings.getOnClientCreating().accept(builder); return builder.build(); } - private String prepareUrlWithParameters(String url, Map parameters) { + protected String prepareUrlWithParameters(String url, Map parameters) { if (parameters.isEmpty()) { return url; } @@ -123,4 +125,4 @@ public class HttpClient { return encodedKey + "=" + encodedValue; }).collect(Collectors.joining("&")); } -} +} \ No newline at end of file diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpClientBuilder.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpClientBuilder.java index 0eeb0fb..fe0ce98 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpClientBuilder.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpClientBuilder.java @@ -77,11 +77,9 @@ public class HttpClientBuilder { return this; } - public HttpClient build() { - + if (httpClientSettings.getProxyClientSettings().isEnabled()) + return new HttpProxyClient(httpClientSettings, url); return new HttpClient(httpClientSettings, url); } - - -} +} \ No newline at end of file diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpProxyClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpProxyClient.java new file mode 100644 index 0000000..8aa8b8b --- /dev/null +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/HttpProxyClient.java @@ -0,0 +1,196 @@ +/* + * 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.data.settings.*; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException; + +import javax.net.ssl.*; +import java.net.*; +import java.net.http.*; +import java.net.http.HttpResponse.ResponseInfo; +import java.security.cert.X509Certificate; +import java.util.*; +import java.util.stream.Collectors; + +public class HttpProxyClient extends HttpClient +{ + private final ProxyClientSettings proxySettings; + + public HttpProxyClient(HttpClientSettings httpClientSettings, String url) { + super(httpClientSettings, url); + this.proxySettings = httpClientSettings.getProxyClientSettings(); + } + + public Optional> toResponse() { + return switch (proxySettings.getType()) { + case HTTP, DIRECT -> handleHttpProxyRequest(); + default -> handleSocksProxyRequest(); + }; + } + + public Optional> handleHttpProxyRequest() { + var builder = java.net.http.HttpClient.newBuilder() + .followRedirects(java.net.http.HttpClient.Redirect.NORMAL) + .cookieHandler(new CookieManager()) + .connectTimeout(httpClientSettings.getTimeout()); + + while (proxySettings.hasNext()) { + try { + InetSocketAddress address = proxySettings.next().toSocketAddress(); + builder.proxy(ProxySelector.of(address)); + + httpClientSettings.getOnClientCreating().accept(builder); + var client = builder.build(); + var request = prepareGetRequest(); + + var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); + if (response.statusCode() != 200) { + continue; + } + return Optional.of(response); + } catch (HttpConnectTimeoutException | ConnectException e) { + if (proxySettings.isAutoDiscard()) + proxySettings.remove(); + } catch (Exception e) { + throw new TikTokLiveRequestException(e); + } + } + throw new TikTokLiveRequestException("No more proxies available!"); + } + + private Optional> handleSocksProxyRequest() { + try { + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[]{ new X509TrustManager() { + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {} + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {} + public X509Certificate[] getAcceptedIssuers() { return null; } + }}, null); + + URL url = toUrl().toURL(); + + while (proxySettings.hasNext()) { + try { + Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxySettings.next().toSocketAddress()); + + HttpsURLConnection socksConnection = (HttpsURLConnection) url.openConnection(proxy); + socksConnection.setSSLSocketFactory(sc.getSocketFactory()); + socksConnection.setConnectTimeout(httpClientSettings.getTimeout().toMillisPart()); + socksConnection.setReadTimeout(httpClientSettings.getTimeout().toMillisPart()); + + byte[] body = socksConnection.getInputStream().readAllBytes(); + + Map> headers = socksConnection.getHeaderFields() + .entrySet() + .stream() + .filter(entry -> entry.getKey() != null) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + var responseInfo = createResponseInfo(socksConnection.getResponseCode(), headers); + + var response = createHttpResponse(body, toUrl(), responseInfo); + + return Optional.of(response); + } catch (SocketException | SocketTimeoutException e) { + if (proxySettings.isAutoDiscard()) + proxySettings.remove(); + } catch (Exception e) { + throw new TikTokLiveRequestException(e); + } + } + throw new TikTokLiveRequestException("No more proxies available!"); + } catch (Exception e) { + // Should never be reached! + System.out.println("handleSocksProxyRequest()! If you see this message, reach us on discord!"); + e.printStackTrace(); + return Optional.empty(); + } + } + + private ResponseInfo createResponseInfo(int code, Map> headers) { + return new ResponseInfo() { + @Override + public int statusCode() { + return code; + } + + @Override + public HttpHeaders headers() { + return HttpHeaders.of(headers, (s, s1) -> s != null); + } + + @Override + public java.net.http.HttpClient.Version version() { + return java.net.http.HttpClient.Version.HTTP_2; + } + }; + } + + private HttpResponse createHttpResponse(byte[] body, + URI uri, + ResponseInfo info) { + return new HttpResponse<>() + { + @Override + public int statusCode() { + return info.statusCode(); + } + + @Override + public HttpRequest request() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public Optional> previousResponse() { + return Optional.empty(); + } + + @Override + public HttpHeaders headers() { + return info.headers(); + } + + @Override + public byte[] body() { + return body; + } + + @Override + public Optional sslSession() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public URI uri() { + return uri; + } + + @Override + public java.net.http.HttpClient.Version version() { + return info.version(); + } + }; + } +} \ No newline at end of file diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java index b0463f0..492cbbc 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java @@ -23,14 +23,15 @@ package io.github.jwdeveloper.tiktok.websocket; -import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; -import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; -import io.github.jwdeveloper.tiktok.TikTokLiveEventHandler; -import io.github.jwdeveloper.tiktok.TikTokLiveMessageHandler; +import io.github.jwdeveloper.tiktok.*; +import io.github.jwdeveloper.tiktok.data.dto.ProxyData; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; +import io.github.jwdeveloper.tiktok.data.settings.*; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.live.LiveClient; import org.java_websocket.client.WebSocketClient; +import java.net.Proxy; import java.util.HashMap; public class TikTokWebSocketClient implements SocketClient { @@ -52,7 +53,6 @@ public class TikTokWebSocketClient implements SocketClient { @Override public void start(LiveConnectionData.Response connectionData, LiveClient liveClient) { - if (isConnected) { stop(); } @@ -68,8 +68,16 @@ public class TikTokWebSocketClient implements SocketClient { tikTokEventHandler, liveClient); - try - { + ProxyClientSettings proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings(); + + if (proxyClientSettings.isEnabled()) + connectProxy(proxyClientSettings); + else + connectDefault(); + } + + private void connectDefault() { + try { webSocketClient.connect(); isConnected = true; } catch (Exception e) @@ -79,9 +87,31 @@ public class TikTokWebSocketClient implements SocketClient { } } + public void connectProxy(ProxyClientSettings proxySettings) { + while (proxySettings.hasNext()) { + ProxyData proxyData = proxySettings.next(); + if (!tryProxyConnection(proxySettings, proxyData)) { + if (proxySettings.isAutoDiscard()) + proxySettings.remove(); + continue; + } + isConnected = true; + break; + } + if (!isConnected) + throw new TikTokLiveException("Failed to connect to the websocket"); + } - - + public boolean tryProxyConnection(ProxyClientSettings proxySettings, ProxyData proxyData) { + webSocketClient.setProxy(new Proxy(proxySettings.getType(), proxyData.toSocketAddress())); + try { + webSocketClient.connect(); + return true; + } catch (Exception e) + { + return false; + } + } public void stop() { if (isConnected && webSocketClient != null) { @@ -90,4 +120,4 @@ public class TikTokWebSocketClient implements SocketClient { webSocketClient = null; isConnected = false; } -} +} \ No newline at end of file diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/ProxyExample.java b/Examples/src/main/java/io/github/jwdeveloper/tiktok/ProxyExample.java new file mode 100644 index 0000000..e83d2a6 --- /dev/null +++ b/Examples/src/main/java/io/github/jwdeveloper/tiktok/ProxyExample.java @@ -0,0 +1,66 @@ +/* + * 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; + +import java.net.*; +import java.net.http.*; +import java.util.*; +import java.util.stream.Stream; + +public class ProxyExample +{ + public static void main(String[] args) throws Exception { + // TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME) + + HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.proxyscrape.com/v2/?request=displayproxies&protocol=socks4,socks5&timeout=10000&country=us")).GET().build(); + HttpResponse> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofLines()); + + List> entries = new ArrayList<>(response.body().map(s -> { + String[] split = s.split(":"); + return new AbstractMap.SimpleEntry<>(split[0], Integer.parseInt(split[1])); + }).toList()); + + TikTokLive.newClient("boost_grow_live_qc") + .configure(clientSettings -> + { + clientSettings.setPrintToConsole(true); + clientSettings.getHttpSettings().configureProxy(proxySettings -> { + proxySettings.setType(Proxy.Type.SOCKS); + proxySettings.setOnProxyUpdated(proxyData -> + { + System.out.println("Next proxy! "+proxyData.toString()); + }); + entries.forEach(entry -> proxySettings.addProxy(entry.getKey(), entry.getValue())); + }); + }) + .onConnected((liveClient, event) -> + { + liveClient.getLogger().info("Hello world!"); + }) + .onError((liveClient, event) -> + { + event.getException().printStackTrace(); + }) + .buildAndConnect(); + } +} \ No newline at end of file