Establish connection with websocket

This commit is contained in:
JW
2023-08-06 02:09:03 +02:00
parent a58612d4c4
commit b75d6da7ab
10 changed files with 187 additions and 58 deletions

View File

@@ -1,6 +1,7 @@
package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
import io.github.jwdeveloper.tiktok.http.TikTokHttpApiClient;
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
import io.github.jwdeveloper.tiktok.live.LiveClient;
@@ -85,10 +86,11 @@ public class TikTokClientBuilder {
meta.setUserName(userName);
var requestFactory = new TikTokHttpRequestFactory();
var apiClient = new TikTokHttpApiClient(clientSettings, requestFactory);
var cookieJar = new TikTokCookieJar();
var requestFactory = new TikTokHttpRequestFactory(cookieJar);
var apiClient = new TikTokHttpApiClient(cookieJar,clientSettings, requestFactory);
var apiService = new TikTokApiService(apiClient, logger,clientParameters);
var webSocketClient = new TikTokWebsocketClient(logger,clientParameters, clientSettings);
var webSocketClient = new TikTokWebsocketClient(logger, cookieJar,clientParameters, requestFactory,clientSettings);
var giftManager =new TikTokGiftManager(logger, apiService, clientSettings);
return new TikTokLiveClient(meta,apiService, webSocketClient, giftManager, logger);
}

View File

@@ -5,19 +5,11 @@ import java.util.Map;
import java.util.Set;
public class TikTokCookieJar {
/// <summary>
/// Cookies in Jar
/// </summary>
private final Map<String, String> cookies;
/// <summary>
/// Create a TikTok cookie jar instance.
/// </summary>
public TikTokCookieJar() {
cookies = new HashMap<>();
}
public String get(String key) {
return cookies.get(key);
}
@@ -26,19 +18,17 @@ public class TikTokCookieJar {
cookies.put(key, value);
}
/// <summary>
/// Enumerates Cookies
/// </summary>
public Set<Map.Entry<String, String>> GetEnumerator() {
return cookies.entrySet();
}
/* /// <summary>
/// Enumerates Cookies
/// </summary>
public IEnumerator<string> GetEnumerator()
public String parseCookies()
{
foreach (var cookie in cookies)
yield return $"{cookie.Key}={cookie.Value};";
}*/
var sb = new StringBuilder();
for(var entry : cookies.entrySet())
{
sb.append(entry.getKey()).append("=").append(entry.getValue()).append(";");
}
return sb.toString();
}
}

View File

@@ -11,17 +11,21 @@ import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class TikTokHttpApiClient {
private final ClientSettings clientSettings;
private final TikTokHttpRequestFactory requestFactory;
private final TikTokCookieJar tikTokCookieJar;
public TikTokHttpApiClient(ClientSettings clientSettings, TikTokHttpRequestFactory requestFactory) {
public TikTokHttpApiClient(TikTokCookieJar tikTokCookieJar, ClientSettings clientSettings, TikTokHttpRequestFactory requestFactory) {
this.clientSettings = clientSettings;
this.requestFactory = requestFactory;
this.tikTokCookieJar = tikTokCookieJar;
}
@@ -68,6 +72,18 @@ public class TikTokHttpApiClient {
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
var cookies = response.headers().allValues("Set-Cookie");
for(var cookie : cookies)
{
var split = cookie.split(";")[0].split("=");
var key = split[0];
var value = split[1];
tikTokCookieJar.set(key, value);
var i =0;
}
return response.body();
}
catch (Exception e)
@@ -80,7 +96,7 @@ public class TikTokHttpApiClient {
private String GetSignedUrl(String url, Map<String, Object> parameters) {
var fullUrl = HttpUtils.parseParameters(url,parameters);
var singHeaders = new HashMap<String, Object>();
var singHeaders = new TreeMap<String,Object>();
singHeaders.put("client", "ttlive-net");
singHeaders.put("uuc", 1);
singHeaders.put("url", fullUrl);
@@ -95,7 +111,6 @@ public class TikTokHttpApiClient {
var signedUrl = jsonObject.get("signedUrl").getAsString();
var userAgent = jsonObject.get("User-Agent").getAsString();
//requestFactory.setHeader()
requestFactory.setAgent(userAgent);
return signedUrl;
} catch (Exception e) {

View File

@@ -11,6 +11,7 @@ import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.WebSocket;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
@@ -29,9 +30,12 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest
private Boolean sent;
private Map<String, String> defaultHeaders;
public TikTokHttpRequestFactory() {
private TikTokCookieJar tikTokCookieJar;
public TikTokHttpRequestFactory(TikTokCookieJar tikTokCookieJar) {
cookieManager = new CookieManager();
this.tikTokCookieJar = tikTokCookieJar;
defaultHeaders = Constants.DefaultRequestHeaders();
client = HttpClient.newBuilder()
.cookieHandler(cookieManager)
@@ -39,6 +43,11 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest
.build();
}
public WebSocket.Builder openSocket()
{
return client.newWebSocketBuilder();
}
@SneakyThrows
public String Get(String url) {
var uri = URI.create(url);
@@ -124,8 +133,14 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest
{
var split = cookie.split(";")[0].split("=");
var uri = request.uri();
var key = split[0];
var value = split[1];
tikTokCookieJar.set(key, value);
var map = new HashMap<String,List<String>>();
map.put(split[0],List.of(split[1]));
map.put(key,List.of(value));
cookieManager.put(uri,map);
}

View File

@@ -0,0 +1,40 @@
package io.github.jwdeveloper.tiktok.websocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Map;
public class Client2 extends WebSocketClient {
public Client2(URI serverUri, Map<String, String> httpHeaders) {
super(serverUri,httpHeaders);
}
@Override
public void onOpen(ServerHandshake serverHandshake) {
System.out.println("Open");
}
@Override
public void onMessage(String s) {
System.out.println("MESSAGE");
}
@Override
public void onMessage(ByteBuffer bytes) {
System.out.println("MESSAGE binary");
}
@Override
public void onClose(int i, String s, boolean b) {
System.out.println("Close");
}
@Override
public void onError(Exception e) {
System.out.println("Error");
}
}

View File

@@ -1,10 +1,11 @@
package io.github.jwdeveloper.tiktok.websocket;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.util.concurrent.CompletionStage;
public class TikTokWebSocketListener implements java.net.http.WebSocket.Listener {
//Insert Body here
@Override
public void onOpen(java.net.http.WebSocket webSocket) {
@@ -18,14 +19,31 @@ public class TikTokWebSocketListener implements java.net.http.WebSocket.Listene
@Override
public CompletionStage<?> onText(java.net.http.WebSocket webSocket, CharSequence data, boolean last) {
System.out.println("Received message: " + data);
System.out.println("Received onText: " + data);
return java.net.http.WebSocket.Listener.super.onText(webSocket, data, last);
}
@Override
public CompletionStage<?> onPing(WebSocket webSocket, ByteBuffer message) {
System.out.println("Received onPing: " );
return java.net.http.WebSocket.Listener.super.onPing(webSocket, message);
}
@Override
public CompletionStage<?> onBinary(WebSocket webSocket, ByteBuffer data, boolean last) {
System.out.println("Received onBinary: " + data);
return java.net.http.WebSocket.Listener.super.onBinary(webSocket, data, last);
}
@Override
public CompletionStage<?> onClose(java.net.http.WebSocket webSocket, int statusCode, String reason) {
System.out.println("WebSocket closed with status code: " + statusCode + " and reason: " + reason);
return java.net.http.WebSocket.Listener.super.onClose(webSocket, statusCode, reason);
}
@Override
public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) {
System.out.println("Received onPong: ");
return java.net.http.WebSocket.Listener.super.onPong(webSocket,message);
}
}

View File

@@ -2,46 +2,64 @@ package io.github.jwdeveloper.tiktok.websocket;
import io.github.jwdeveloper.generated.WebcastResponse;
import io.github.jwdeveloper.tiktok.ClientSettings;
import io.github.jwdeveloper.tiktok.Constants;
import io.github.jwdeveloper.tiktok.TikTokLiveException;
import io.github.jwdeveloper.tiktok.http.HttpUtils;
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
import java.net.URI;
import java.net.http.HttpClient;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Logger;
public class TikTokWebsocketClient {
private final Logger logger;
private final Map<String, Object> clientParams;
private final ClientSettings clientSettings;
private final TikTokCookieJar tikTokCookieJar;
private final TikTokHttpRequestFactory factory;
public TikTokWebsocketClient(Logger logger, Map<String, Object> clientParams, ClientSettings clientSettings) {
public TikTokWebsocketClient(Logger logger,
TikTokCookieJar tikTokCookieJar,
Map<String, Object> clientParams,
TikTokHttpRequestFactory factory,
ClientSettings clientSettings) {
this.logger = logger;
this.clientParams = clientParams;
this.tikTokCookieJar = tikTokCookieJar;
this.clientSettings = clientSettings;
this.factory = factory;
}
public void start(WebcastResponse webcastResponse) {
if (webcastResponse.getWsUrl().isEmpty() || webcastResponse.getWsParam().getAllFields().isEmpty()) {
throw new TikTokLiveException("Could not find Room");
}
try {
for (var param : webcastResponse.getWsParam().getAllFields().entrySet()) {
var name = param.getKey().getName();
var value = param.getValue();
clientParams.put(name, value);
logger.info("Adding Custom Param" + param.getKey().getName() + " " + param.getValue());
}
try {
var params = webcastResponse.getWsParam();
var name = params.getName();
var value = params.getValue();
System.out.println("KEY: " + name + " value: " + value);
var headers = Constants.DefaultRequestHeaders();
var clone = new TreeMap<>(clientParams);
// clone.putAll(headers);
clone.put(name, value);
clone.put("compress", "gzip");
var url = webcastResponse.getWsUrl();
var wsUrl = HttpUtils.parseParametersEncode(url, clientParams);
logger.info("Creating Socket with URL " + wsUrl);
//socketClient = new TikTokWebSocket(TikTokHttpRequest.CookieJar, token, settings.SocketBufferSize);
//connectedSocketUrl = url;
//await socketClient.Connect(url);
var wsUrl = HttpUtils.parseParametersEncode(url, clone);
logger.info("Starting Socket-Threads");
//runningTask = Task.Run(WebSocketLoop, token);
//pollingTask = Task.Run(PingLoop, token);
@@ -51,28 +69,44 @@ public class TikTokWebsocketClient {
}
if (clientSettings.isHandleExistingMessagesOnConnect()) {
try {
// HandleWebcastMessages(webcastResponse);
// HandleWebcastMessages(webcastResponse);
} catch (Exception e) {
throw new TikTokLiveException("Error Handling Initial Messages", e);
}
}
}
public void startWS(String url)
{
public void startWS(String url) {
try {
var cookie = tikTokCookieJar.parseCookies();
logger.info("WssIP: " + url);
logger.info("Cookie: " + cookie);
var cookie = "tt_csrf_token=Fh92faHZ-fVnWZ8CG58Wb_kIC1hb-QzizkRM;ttwid=1%7CergNdYee4w-v_96VkhyDxkJ8NIavveA-NvCEdWF68Ik%7C1691076950%7C154533521f698b079ff5300fbd058e85e81a8ef64c41349f1d218124aa74a6db;";
// var url = "wss://webcast16-ws-useast1a.tiktok.com/webcast/im/push/?aid=1988&app_language=en-US&app_name=tiktok_web&browser_language=en&browser_name=Mozilla&browser_online=True&browser_platform=Win32&browser_version=5.0+(Windows+NT+10.0%3b+Win64%3b+x64)+AppleWebKit%2f537.36+(KHTML%2c+like+Gecko)+Chrome%2f102.0.5005.63+Safari%2f537.36&cookie_enabled=True&cursor=1691242057374_7263829320139870326_1_1_0_0&internal_ext=fetch_time%3a1691242057374%7cstart_time%3a0%7cack_ids%3a%2c%7cflag%3a0%7cseq%3a1%7cnext_cursor%3a1691242057374_7263829320139870326_1_1_0_0%7cwss_info%3a0-1691242057374-0-0&device_platform=web&focus_state=True&from_page=user&history_len=4&is_fullscreen=False&is_page_visible=True&did_rule=3&fetch_rule=1&identity=audience&last_rtt=0&live_id=12&resp_content_type=protobuf&screen_height=1152&screen_width=2048&tz_name=Europe%2fBerlin&referer=https%2c+%2f%2fwww.tiktok.com%2f&root_referer=https%2c+%2f%2fwww.tiktok.com%2f&msToken=&version_code=180800&webcast_sdk_version=1.3.0&update_version_code=1.3.0&webcast_language=en-US&room_id=7263759223213132577&imprp=u65Ja_b3czc3iEAb4x6oLXindKyTO";
HttpClient client = HttpClient.newHttpClient();
var ws = client.newWebSocketBuilder()
var map = new HashMap<String, String>();
map.put("Cookie", cookie);
//var cluent2 = new Client2(URI.create(url), map);
var builder = HttpClient.newHttpClient().newWebSocketBuilder();
var ws = builder
.subprotocols("echo-protocol")
.connectTimeout(Duration.ofSeconds(15))
.header("cookie",cookie)
.buildAsync(URI.create(url),new TikTokWebSocketListener()).get();
}
catch (Exception e)
{
.header("Cookie", cookie)
.buildAsync(URI.create(url), new TikTokWebSocketListener()).get();
var i =0;
while (true) {
byte[] message = new byte[]{58, 2, 104, 98};
ByteBuffer buffer = ByteBuffer.wrap(message);
while (buffer.hasRemaining()) {
ws.sendPing(buffer);
}
buffer.clear();
Thread.sleep(10);
}
} catch (Exception e) {
e.printStackTrace();
}
}

View File

@@ -6,7 +6,7 @@ import java.io.IOException;
public class TikTokLiveTest
{
public static String TEST_USER_SUBJECT = "moniczkka";
public static String TEST_USER_SUBJECT = "erwin_winki";
@Test