diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/LiveClientSettings.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/LiveClientSettings.java index 99e9e015..26d6f624 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/LiveClientSettings.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/LiveClientSettings.java @@ -36,7 +36,6 @@ public class LiveClientSettings { /** * ISO-Language for Client */ - private String clientLanguage; /** @@ -44,7 +43,6 @@ public class LiveClientSettings { */ private boolean retryOnConnectionFailure; - /** * Before retrying connect, wait for select amount of time */ @@ -53,42 +51,35 @@ public class LiveClientSettings { /** * Whether to print Logs to Console */ - private boolean printToConsole = true; + /** * LoggingLevel for Logs */ private Level logLevel; - /** * Optional: Use it if you need to change TikTok live hostname in builder */ private String hostName; - /** * Parameters used in requests to TikTok api */ private HttpClientSettings httpSettings; - - /* + /** * Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId * documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages */ private String sessionId; - /* + /** * Optional: By default roomID is fetched before connect to live, but you can set it manually * */ private String roomId; - - - - public static LiveClientSettings createDefault() { var httpSettings = new HttpClientSettings(); @@ -103,12 +94,10 @@ public static LiveClientSettings createDefault() clientSettings.setPrintToConsole(false); clientSettings.setLogLevel(Level.ALL); - clientSettings.setHttpSettings(httpSettings); return clientSettings; } - /** * Default Parameters for HTTP-Request */ @@ -147,11 +136,9 @@ public static Map DefaultClientParams() { clientParams.put("webcast_sdk_version", "1.3.0"); clientParams.put("update_version_code", "1.3.0"); - return clientParams; } - /** * Default Headers for HTTP-Request */ @@ -167,6 +154,4 @@ public static Map DefaultRequestHeaders() { headers.put("Accept-Language", "en-US,en; q=0.9"); return headers; } - -} - +} \ 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 6354acbd..48061efa 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 @@ -87,6 +87,7 @@ public ProxyData rotate() { @Override public void remove() { proxyList.remove(index); + lastSuccess = false; // index is no longer valid and lastSuccess needs falsified } public void setIndex(int index) { 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 365fcc33..d3f0f190 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 @@ -26,7 +26,7 @@ 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.exceptions.*; import io.github.jwdeveloper.tiktok.live.LiveClient; import org.java_websocket.client.WebSocketClient; @@ -41,7 +41,7 @@ public class TikTokWebSocketClient implements SocketClient { private final TikTokLiveEventHandler tikTokEventHandler; private WebSocketClient webSocketClient; - private TikTokWebSocketPingingTask pingingTask; + private final TikTokWebSocketPingingTask pingingTask; private boolean isConnected; public TikTokWebSocketClient( @@ -91,6 +91,20 @@ private void connectDefault() { } public void connectProxy(ProxyClientSettings proxySettings) { + try { + if (proxySettings.getType() == Proxy.Type.SOCKS) { + 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); + webSocketClient.setSocketFactory(sc.getSocketFactory()); + } + } catch (Exception e) { + // This will never be thrown. + throw new TikTokProxyRequestException("Unable to set Socks proxy SSL instance"); + } while (proxySettings.hasNext()) { ProxyData proxyData = proxySettings.next(); if (!tryProxyConnection(proxySettings, proxyData)) { @@ -98,6 +112,7 @@ public void connectProxy(ProxyClientSettings proxySettings) { proxySettings.remove(); continue; } + pingingTask.run(webSocketClient); isConnected = true; break; } @@ -107,21 +122,6 @@ public void connectProxy(ProxyClientSettings proxySettings) { public boolean tryProxyConnection(ProxyClientSettings proxySettings, ProxyData proxyData) { try { - if (proxySettings.getType() == Proxy.Type.SOCKS) { - 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); - webSocketClient.setSocketFactory(sc.getSocketFactory()); - } webSocketClient.setProxy(new Proxy(proxySettings.getType(), proxyData.toSocketAddress())); webSocketClient.connect(); return true; diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java index be104067..90adbc4c 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java @@ -11,24 +11,18 @@ public class TikTokWebSocketPingingTask private final int MIN_TIMEOUT = 250; private final int MAX_TIMEOUT = 500; - public void run(WebSocket webSocket) { stop(); - thread = new Thread(() -> - { - pingTask(webSocket); - }); - isRunning =true; + thread = new Thread(() -> pingTask(webSocket)); + isRunning = true; thread.start(); } public void stop() { - if(thread != null) - { + if (thread != null) thread.interrupt(); - } isRunning = false; } @@ -36,12 +30,9 @@ public void stop() private void pingTask(WebSocket webSocket) { var random = new Random(); - while (isRunning) - { - try - { - if(!webSocket.isOpen()) - { + while (isRunning) { + try { + if (!webSocket.isOpen()) { Thread.sleep(100); continue; } @@ -50,11 +41,10 @@ private void pingTask(WebSocket webSocket) var timeout = random.nextInt(MAX_TIMEOUT)+MIN_TIMEOUT; Thread.sleep(timeout); } - catch (Exception e) - { + catch (Exception e) { isRunning = false; } } } -} +} \ No newline at end of file diff --git a/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/RecorderListener.java b/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/RecorderListener.java index 6ff5d176..ed28478b 100644 --- a/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/RecorderListener.java +++ b/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/RecorderListener.java @@ -24,24 +24,18 @@ import com.google.gson.JsonParser; import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver; -import io.github.jwdeveloper.tiktok.data.events.TikTokLiveEndedEvent; +import io.github.jwdeveloper.tiktok.data.events.*; +import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; -import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder; -import io.github.jwdeveloper.tiktok.data.events.TikTokConnectedEvent; -import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; -import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.DownloadData; -import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.RecorderSettings; -import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent; +import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder; +import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.*; import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality; -import io.github.jwdeveloper.tiktok.extension.recorder.impl.event.TikTokLiveRecorderStartedEvent; -import io.github.jwdeveloper.tiktok.http.HttpClientFactory; import io.github.jwdeveloper.tiktok.live.LiveClient; import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.URL; -import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -86,13 +80,11 @@ private void onResponse(LiveClient liveClient, TikTokRoomDataResponseEvent event throw new TikTokLiveException("Unable to find download live url!"); } liveClient.getLogger().info("Live download url found!"); - } @TikTokEventObserver private void onConnected(LiveClient liveClient, TikTokConnectedEvent event) { - liveDownloadThread = new Thread(() -> - { + liveDownloadThread = new Thread(() -> { try { var bufferSize = 1024; var url = new URL(downloadData.getFullUrl()); @@ -102,40 +94,33 @@ private void onConnected(LiveClient liveClient, TikTokConnectedEvent event) { socksConnection.setRequestProperty(entry.getKey(), entry.getValue()); } - try (var in = new BufferedInputStream(socksConnection.getInputStream())) { - var path = settings.getOutputPath() + File.separator + settings.getOutputFileName(); - var file = new File(path); - file.getParentFile().mkdirs(); - var fileOutputStream = new FileOutputStream(file); - byte dataBuffer[] = new byte[bufferSize]; - int bytesRead; - while ((bytesRead = in.read(dataBuffer, 0, bufferSize)) != -1) { - fileOutputStream.write(dataBuffer, 0, bytesRead); - } - } catch (IOException e) { - throw e; + var in = new BufferedInputStream(socksConnection.getInputStream()); + var path = settings.getOutputPath() + File.separator + settings.getOutputFileName(); + var file = new File(path); + file.getParentFile().mkdirs(); + var fileOutputStream = new FileOutputStream(file); + byte[] dataBuffer = new byte[bufferSize]; + int bytesRead; + while ((bytesRead = in.read(dataBuffer, 0, bufferSize)) != -1) { + fileOutputStream.write(dataBuffer, 0, bytesRead); } - } catch (Exception e) { + in.close(); + } catch (Exception e) { e.printStackTrace(); - ; } - }); - liveDownloadThread.start(); } - private static void downloadUsingStream(String urlStr, String file) throws IOException { URL url = new URL(urlStr); BufferedInputStream bis = new BufferedInputStream(url.openStream()); FileOutputStream fis = new FileOutputStream(file); byte[] buffer = new byte[1024]; - int count = 0; - while ((count = bis.read(buffer, 0, 1024)) != -1) { + int count; + while ((count = bis.read(buffer, 0, 1024)) != -1) fis.write(buffer, 0, count); - } fis.close(); bis.close(); } @@ -143,25 +128,23 @@ private static void downloadUsingStream(String urlStr, String file) throws IOExc @TikTokEventObserver private void onDisconnected(LiveClient liveClient, TikTokDisconnectedEvent event) { - liveDownloadThread.interrupt(); + if (isConnected()) + liveDownloadThread.interrupt(); } @TikTokEventObserver private void onDisconnected(LiveClient liveClient, TikTokLiveEndedEvent event) { - liveDownloadThread.interrupt(); + if (isConnected()) + liveDownloadThread.interrupt(); } private int terminateFfmpeg(final Process process) { if (!process.isAlive()) { - /* - * ffmpeg -version, do nothing - */ + // ffmpeg -version, do nothing return process.exitValue(); } - /* - * ffmpeg -f x11grab - */ + // ffmpeg -f x11grab System.out.println("About to destroy the child process..."); try (final OutputStreamWriter out = new OutputStreamWriter(process.getOutputStream(), UTF_8)) { out.write('q'); @@ -174,7 +157,7 @@ private int terminateFfmpeg(final Process process) { process.waitFor(); } return process.exitValue(); - } catch (final InterruptedException ie) { + } catch (InterruptedException ie) { System.out.println("Interrupted"); ie.printStackTrace(); Thread.currentThread().interrupt(); @@ -201,12 +184,10 @@ private DownloadData mapToDownloadData(String json) { .get("flv") .getAsString(); - var sessionId = streamDataJsonObject.getAsJsonObject("common") .get("session_id") .getAsString(); - //main //https://pull-f5-tt03.fcdn.eu.tiktokcdn.com/stage/stream-3284937501738533765.flv?session_id=136-20240109000954BF818F1B3A8E5E39E238&_webnoredir=1 //Working @@ -216,5 +197,7 @@ private DownloadData mapToDownloadData(String json) { return new DownloadData(urlLink, sessionId); } - -} + private boolean isConnected() { + return liveDownloadThread != null && liveDownloadThread.isAlive(); + } +} \ No newline at end of file diff --git a/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/data/DownloadData.java b/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/data/DownloadData.java index 0bc02601..6c9430cc 100644 --- a/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/data/DownloadData.java +++ b/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/data/DownloadData.java @@ -34,6 +34,6 @@ public class DownloadData { private String sessionId; public String getFullUrl() { - return downloadLiveUrl + "?_webnoredir=1&session_id=" + sessionId; + return downloadLiveUrl + "&_webnoredir=1&session_id=" + sessionId; } -} +} \ No newline at end of file diff --git a/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/data/RecorderSettings.java b/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/data/RecorderSettings.java index ea4a8ec4..d7db8209 100644 --- a/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/data/RecorderSettings.java +++ b/extension-recorder/src/main/java/io/github/jwdeveloper/tiktok/extension/recorder/impl/data/RecorderSettings.java @@ -29,25 +29,6 @@ import java.util.function.Function; -/** - * self, - * path: str, - * duration: Optional[int] = None, - * quality: Optional[VideoQuality] = None, - * verbose: bool = True, - * loglevel: str = "error", - * global_options: Set[str] = set(), - * inputs: Dict[str, str] = dict(), - * outputs: Dict[str, str] = dict() - * :param loglevel: Set the FFmpeg log level - * :param outputs: Pass custom params to FFmpeg outputs - * :param inputs: Pass custom params to FFmpeg inputs - * :param global_options: Pass custom params to FFmpeg global options - * :param path: The path to download the livestream video to - * :param duration: If duration is None or less than 1, download will go forever - * :param quality: If quality is None, download quality will auto - * :param verbose: Whether to log info about the download in console - */ @Getter @Setter public class RecorderSettings { @@ -63,20 +44,11 @@ public static RecorderSettings DEFAULT() { return new RecorderSettings(); } - public void setQuality(String format) { - this.format = format; - } - public void setQuality(LiveQuality quality) { this.quality = quality.name(); } - - public void setFormat(String format) { - this.format = format; - } - public void setFormat(LiveFormat format) { this.format = format.name(); } -} +} \ No newline at end of file