Switched to new Signing Server endpoint and more

This commit is contained in:
kohlerpop1
2024-02-15 11:46:13 -05:00
parent 4f141edb1a
commit c1105f1324
13 changed files with 78 additions and 188 deletions

View File

@@ -1,35 +0,0 @@
/*
* 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.requests;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class SignServerResponse
{
private String signedUrl;
private String userAgent;
}

View File

@@ -80,6 +80,11 @@ public class LiveClientSettings {
*/ */
private String roomId; private String roomId;
/**
* Optional: API Key for increased limit to signing server
*/
private String apiKey;
public static LiveClientSettings createDefault() public static LiveClientSettings createDefault()
{ {
var httpSettings = new HttpClientSettings(); var httpSettings = new HttpClientSettings();

View File

@@ -33,7 +33,7 @@ import java.util.function.Consumer;
@Setter @Setter
public class ProxyClientSettings implements Iterator<ProxyData> public class ProxyClientSettings implements Iterator<ProxyData>
{ {
private boolean enabled, lastSuccess, 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 = -1;
@@ -63,10 +63,6 @@ public class ProxyClientSettings implements Iterator<ProxyData>
@Override @Override
public ProxyData next() { public ProxyData next() {
return lastSuccess ? proxyList.get(index) : rotate();
}
public ProxyData rotate() {
var nextProxy = switch (rotation) var nextProxy = switch (rotation)
{ {
case CONSECUTIVE -> { case CONSECUTIVE -> {
@@ -89,7 +85,6 @@ public class ProxyClientSettings implements Iterator<ProxyData>
@Override @Override
public void remove() { public void remove() {
proxyList.remove(index); proxyList.remove(index);
lastSuccess = false; // index is no longer valid and lastSuccess needs falsified
} }
public void setIndex(int index) { public void setIndex(int index) {

View File

@@ -27,9 +27,8 @@ import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
import io.github.jwdeveloper.tiktok.data.requests.LiveData; import io.github.jwdeveloper.tiktok.data.requests.LiveData;
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData; import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
public interface LiveHttpClient { public interface LiveHttpClient
{
/** /**
* @return list of gifts that are available in your country * @return list of gifts that are available in your country
*/ */
@@ -37,28 +36,32 @@ public interface LiveHttpClient {
/** /**
* Returns information about user that is having a livestream * Returns information about user that is having a livestream
* * @param userName name of user
* @param userName * @return {@link LiveUserData.Response}
* @return
*/ */
LiveUserData.Response fetchLiveUserData(String userName); default LiveUserData.Response fetchLiveUserData(String userName) {
return fetchLiveUserData(new LiveUserData.Request(userName));
}
LiveUserData.Response fetchLiveUserData(LiveUserData.Request request); LiveUserData.Response fetchLiveUserData(LiveUserData.Request request);
/** /**
* @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData * @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData
* @return * @return {@link LiveData.Response}
*/ */
LiveData.Response fetchLiveData(String roomId); default LiveData.Response fetchLiveData(String roomId) {
return fetchLiveData(new LiveData.Request(roomId));
}
LiveData.Response fetchLiveData(LiveData.Request request); LiveData.Response fetchLiveData(LiveData.Request request);
/** /**
* @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData * @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData
* @return * @return {@link LiveConnectionData.Response}
*/ */
LiveConnectionData.Response fetchLiveConnectionData(String roomId); default LiveConnectionData.Response fetchLiveConnectionData(String roomId) {
return fetchLiveConnectionData(new LiveConnectionData.Request(roomId));
}
LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request); LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request);
} }

View File

@@ -32,8 +32,7 @@ import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
import io.github.jwdeveloper.tiktok.data.requests.LiveData; import io.github.jwdeveloper.tiktok.data.requests.LiveData;
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData; import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.exceptions.*;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager; import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
import io.github.jwdeveloper.tiktok.listener.ListenersManager; import io.github.jwdeveloper.tiktok.listener.ListenersManager;
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager; import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
@@ -127,22 +126,26 @@ public class TikTokLiveClient implements LiveClient {
var userData = httpClient.fetchLiveUserData(userDataRequest); var userData = httpClient.fetchLiveUserData(userDataRequest);
liveRoomInfo.setStartTime(userData.getStartedAtTimeStamp()); liveRoomInfo.setStartTime(userData.getStartedAtTimeStamp());
liveRoomInfo.setRoomId(userData.getRoomId()); liveRoomInfo.setRoomId(userData.getRoomId());
if (userData.getUserStatus() == LiveUserData.UserStatus.Offline) {
throw new TikTokLiveOfflineHostException("User is offline: "+liveRoomInfo.getHostUser()); if (userData.getUserStatus() == LiveUserData.UserStatus.Offline)
} throw new TikTokLiveOfflineHostException("User is offline: "+liveRoomInfo.getHostName());
if (userData.getUserStatus() == LiveUserData.UserStatus.NotFound) {
throw new TikTokLiveOfflineHostException("User not found: "+liveRoomInfo.getHostUser()); if (userData.getUserStatus() == LiveUserData.UserStatus.NotFound)
} throw new TikTokLiveOfflineHostException("User not found: "+liveRoomInfo.getHostName());
var liveDataRequest = new LiveData.Request(userData.getRoomId()); var liveDataRequest = new LiveData.Request(userData.getRoomId());
var liveData = httpClient.fetchLiveData(liveDataRequest); var liveData = httpClient.fetchLiveData(liveDataRequest);
if (liveData.isAgeRestricted())
throw new TikTokLiveException("Livestream for "+liveRoomInfo.getHostName()+" is 18+ or age restricted!");
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound)
throw new TikTokLiveOfflineHostException("LiveStream for "+liveRoomInfo.getHostName()+" could not be found.");
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostOffline)
throw new TikTokLiveOfflineHostException("LiveStream for "+liveRoomInfo.getHostName()+" not found, is the Host offline?");
tikTokEventHandler.publish(this, new TikTokRoomDataResponseEvent(liveData)); tikTokEventHandler.publish(this, new TikTokRoomDataResponseEvent(liveData));
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound) {
throw new TikTokLiveOfflineHostException("LiveStream for Host name could not be found.");
}
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostOffline) {
throw new TikTokLiveOfflineHostException("LiveStream for not be found, is the Host offline?");
}
liveRoomInfo.setTitle(liveData.getTitle()); liveRoomInfo.setTitle(liveData.getTitle());
liveRoomInfo.setViewersCount(liveData.getViewers()); liveRoomInfo.setViewersCount(liveData.getViewers());

View File

@@ -99,6 +99,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
} }
public TikTokLiveClientBuilder addListener(TikTokEventListener listener) { public TikTokLiveClientBuilder addListener(TikTokEventListener listener) {
if (listener != null)
listeners.add(listener); listeners.add(listener);
return this; return this;
} }

View File

@@ -36,10 +36,9 @@ import java.util.Optional;
public class TikTokLiveHttpClient implements LiveHttpClient { public class TikTokLiveHttpClient implements LiveHttpClient {
/** /**
* Signing API by Isaac Kogan * <a href="https://github-wiki-see.page/m/isaackogan/TikTokLive/wiki/All-About-Signatures">Signing API by Isaac Kogan</a>
* https://github-wiki-see.page/m/isaackogan/TikTokLive/wiki/All-About-Signatures
*/ */
private static final String TIKTOK_SIGN_API = "https://tiktok.eulerstream.com/webcast/sign_url"; private static final String TIKTOK_SIGN_API = "https://tiktok.eulerstream.com/webcast/fetch";
private static final String TIKTOK_URL_WEB = "https://www.tiktok.com/"; private static final String TIKTOK_URL_WEB = "https://www.tiktok.com/";
private static final String TIKTOK_URL_WEBCAST = "https://webcast.tiktok.com/webcast/"; private static final String TIKTOK_URL_WEBCAST = "https://webcast.tiktok.com/webcast/";
@@ -47,7 +46,6 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
private final LiveClientSettings clientSettings; private final LiveClientSettings clientSettings;
private final LiveUserDataMapper liveUserDataMapper; private final LiveUserDataMapper liveUserDataMapper;
private final LiveDataMapper liveDataMapper; private final LiveDataMapper liveDataMapper;
private final SignServerResponseMapper signServerResponseMapper;
private final GiftsDataMapper giftsDataMapper; private final GiftsDataMapper giftsDataMapper;
public TikTokLiveHttpClient(HttpClientFactory factory, LiveClientSettings settings) { public TikTokLiveHttpClient(HttpClientFactory factory, LiveClientSettings settings) {
@@ -55,7 +53,6 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
clientSettings = settings; clientSettings = settings;
liveUserDataMapper = new LiveUserDataMapper(); liveUserDataMapper = new LiveUserDataMapper();
liveDataMapper = new LiveDataMapper(); liveDataMapper = new LiveDataMapper();
signServerResponseMapper = new SignServerResponseMapper();
giftsDataMapper = new GiftsDataMapper(); giftsDataMapper = new GiftsDataMapper();
} }
@@ -94,12 +91,6 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
return giftsDataMapper.map(json); return giftsDataMapper.map(json);
} }
@Override
public LiveUserData.Response fetchLiveUserData(String userName) {
return fetchLiveUserData(new LiveUserData.Request(userName));
}
@Override @Override
public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) { public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) {
var url = TIKTOK_URL_WEB + "api-live/user/room"; var url = TIKTOK_URL_WEB + "api-live/user/room";
@@ -136,11 +127,6 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
return liveUserDataMapper.map(json); return liveUserDataMapper.map(json);
} }
@Override
public LiveData.Response fetchLiveData(String roomId) {
return fetchLiveData(new LiveData.Request(roomId));
}
@Override @Override
public LiveData.Response fetchLiveData(LiveData.Request request) { public LiveData.Response fetchLiveData(LiveData.Request request) {
var url = TIKTOK_URL_WEBCAST + "room/info"; var url = TIKTOK_URL_WEBCAST + "room/info";
@@ -175,20 +161,13 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
return liveDataMapper.map(json); return liveDataMapper.map(json);
} }
@Override
public LiveConnectionData.Response fetchLiveConnectionData(String roomId) {
return fetchLiveConnectionData(new LiveConnectionData.Request(roomId));
}
@Override @Override
public LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request) { public LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request) {
HttpResponse<byte[]> credentialsResponse = getOptionalProxyResponse(request).orElseGet(()-> { HttpResponse<byte[]> credentialsResponse = getOptionalProxyResponse(request).orElseGet(()-> getStarterPayload(request.getRoomId()));
SignServerResponse signServerResponse = getSignedUrl(request.getRoomId());
return getWebsocketCredentialsResponse(signServerResponse.getSignedUrl());
});
try { try {
var optionalHeader = credentialsResponse.headers().firstValue("set-cookie"); System.out.println(credentialsResponse.headers().map());
var optionalHeader = credentialsResponse.headers().firstValue("x-set-tt-cookie");
if (optionalHeader.isEmpty()) { if (optionalHeader.isEmpty()) {
throw new TikTokSignServerException("Sign server did not return the set-cookie header"); throw new TikTokSignServerException("Sign server did not return the set-cookie header");
} }
@@ -210,39 +189,21 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
} }
} }
SignServerResponse getSignedUrl(String roomId) { HttpResponse<byte[]> getStarterPayload(String room_id) {
var urlToSign = httpFactory HttpClientBuilder builder = httpFactory.client(TIKTOK_SIGN_API)
.client(TikTokLiveHttpClient.TIKTOK_URL_WEBCAST + "im/fetch")
.withParam("room_id", roomId)
.build()
.toUrl();
var optional = httpFactory
.client(TikTokLiveHttpClient.TIKTOK_SIGN_API)
.withParam("client", "ttlive-java") .withParam("client", "ttlive-java")
.withParam("uuc", "1") .withParam("uuc", "1")
.withParam("url", urlToSign.toString()) .withParam("room_id", room_id);
.build()
.toJsonResponse(); if (clientSettings.getApiKey() != null)
builder.withParam("apiKey", clientSettings.getApiKey());
var optional = builder.build().toResponse();
if (optional.isEmpty()) { if (optional.isEmpty()) {
throw new TikTokSignServerException("Unable to sign url: " + urlToSign);
}
var json = optional.get();
return signServerResponseMapper.map(json);
}
HttpResponse<byte[]> getWebsocketCredentialsResponse(String signedUrl) {
var optionalResponse = httpFactory
.clientEmpty(signedUrl)
.build()
.toResponse();
if (optionalResponse.isEmpty()) {
throw new TikTokSignServerException("Unable to get websocket connection credentials"); throw new TikTokSignServerException("Unable to get websocket connection credentials");
} }
return optionalResponse.get(); return optional.get();
} }
Optional<HttpResponse<byte[]>> getOptionalProxyResponse(LiveConnectionData.Request request) { Optional<HttpResponse<byte[]>> getOptionalProxyResponse(LiveConnectionData.Request request) {
@@ -250,9 +211,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
if (proxyClientSettings.isEnabled()) { if (proxyClientSettings.isEnabled()) {
while (proxyClientSettings.hasNext()) { while (proxyClientSettings.hasNext()) {
try { try {
SignServerResponse signServerResponse = getSignedUrl(request.getRoomId()); HttpResponse<byte[]> credentialsResponse = getStarterPayload(request.getRoomId());
HttpResponse<byte[]> credentialsResponse = getWebsocketCredentialsResponse(signServerResponse.getSignedUrl());
clientSettings.getHttpSettings().getProxyClientSettings().rotate();
return Optional.of(credentialsResponse); return Optional.of(credentialsResponse);
} catch (TikTokProxyRequestException | TikTokSignServerException ignored) {} } catch (TikTokProxyRequestException | TikTokSignServerException ignored) {}
} }

View File

@@ -67,16 +67,12 @@ public class HttpProxyClient extends HttpClient
var request = prepareGetRequest(); var request = prepareGetRequest();
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() != 200) { if (response.statusCode() != 200)
proxySettings.setLastSuccess(false);
continue; continue;
}
proxySettings.setLastSuccess(true);
return Optional.of(response); return Optional.of(response);
} catch (HttpConnectTimeoutException | ConnectException e) { } catch (HttpConnectTimeoutException | ConnectException e) {
if (proxySettings.isAutoDiscard()) if (proxySettings.isAutoDiscard())
proxySettings.remove(); proxySettings.remove();
proxySettings.setLastSuccess(false);
throw new TikTokProxyRequestException(e); throw new TikTokProxyRequestException(e);
} catch (IOException e) { } catch (IOException e) {
if (e.getMessage().contains("503") && proxySettings.isFallback()) // Indicates proxy protocol is not supported if (e.getMessage().contains("503") && proxySettings.isFallback()) // Indicates proxy protocol is not supported
@@ -121,14 +117,12 @@ public class HttpProxyClient extends HttpClient
var response = createHttpResponse(body, toUrl(), responseInfo); var response = createHttpResponse(body, toUrl(), responseInfo);
proxySettings.setLastSuccess(true);
return Optional.of(response); return Optional.of(response);
} catch (IOException e) { } catch (IOException e) {
if (e.getMessage().contains("503") && proxySettings.isFallback()) // Indicates proxy protocol is not supported if (e.getMessage().contains("503") && proxySettings.isFallback()) // Indicates proxy protocol is not supported
return super.toResponse(); return super.toResponse();
if (proxySettings.isAutoDiscard()) if (proxySettings.isAutoDiscard())
proxySettings.remove(); proxySettings.remove();
proxySettings.setLastSuccess(false);
throw new TikTokProxyRequestException(e); throw new TikTokProxyRequestException(e);
} catch (Exception e) { } catch (Exception e) {
throw new TikTokLiveRequestException(e); throw new TikTokLiveRequestException(e);
@@ -137,7 +131,7 @@ public class HttpProxyClient extends HttpClient
throw new TikTokLiveRequestException("No more proxies available!"); throw new TikTokLiveRequestException("No more proxies available!");
} catch (NoSuchAlgorithmException | MalformedURLException | KeyManagementException e) { } catch (NoSuchAlgorithmException | MalformedURLException | KeyManagementException e) {
// Should never be reached! // Should never be reached!
System.out.println("handleSocksProxyRequest()! If you see this message, reach us on discord!"); System.out.println("handleSocksProxyRequest: If you see this, message us on discord!");
e.printStackTrace(); e.printStackTrace();
return Optional.empty(); return Optional.empty();
} catch (TikTokLiveRequestException e) { } catch (TikTokLiveRequestException e) {

View File

@@ -64,6 +64,10 @@ public class LiveDataMapper {
default -> LiveData.LiveStatus.HostNotFound; default -> LiveData.LiveStatus.HostNotFound;
}; };
response.setLiveStatus(statusValue); response.setLiveStatus(statusValue);
} else if (data.has("prompts") && jsonObject.has("status_code") &&
data.get("prompts").getAsString().isEmpty() && jsonObject.get("status_code").isJsonPrimitive()) {
// 4003110 is age restriction code
response.setAgeRestricted(jsonObject.get("status_code").getAsInt() == 4003110);
} else { } else {
response.setLiveStatus(LiveData.LiveStatus.HostNotFound); response.setLiveStatus(LiveData.LiveStatus.HostNotFound);
} }

View File

@@ -1,37 +0,0 @@
/*
* 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.mappers;
import com.google.gson.JsonParser;
import io.github.jwdeveloper.tiktok.data.requests.SignServerResponse;
public class SignServerResponseMapper {
public SignServerResponse map(String json) {
var parsedJson = JsonParser.parseString(json);
var jsonObject = parsedJson.getAsJsonObject();
var signUrl = jsonObject.get("signedUrl").getAsString();
var userAgent = jsonObject.get("User-Agent").getAsString();
return new SignServerResponse(signUrl, userAgent);
}
}

View File

@@ -97,6 +97,10 @@ public class CodeExample {
//RoomId can be used as an override if you're having issues with HostId. //RoomId can be used as an override if you're having issues with HostId.
//You can find it in the HTML for the livestream-page //You can find it in the HTML for the livestream-page
settings.setRoomId("XXXXXXXXXXXXXXXXX"); settings.setRoomId("XXXXXXXXXXXXXXXXX");
//Optional:
//API Key for increased limit to signing server
settings.setApiKey("XXXXXXXXXXXXXXXXX");
}) })
.buildAndConnect(); .buildAndConnect();
// </code> // </code>

View File

@@ -30,7 +30,6 @@ import java.util.function.Consumer;
public class TikTokLiveRecorder public class TikTokLiveRecorder
{ {
public static LiveRecorder use(Consumer<RecorderSettings> consumer) public static LiveRecorder use(Consumer<RecorderSettings> consumer)
{ {
return new RecorderListener(consumer); return new RecorderListener(consumer);

View File

@@ -27,7 +27,6 @@ import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
import io.github.jwdeveloper.tiktok.data.events.*; import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent; import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder; 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.data.*;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality; import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality;
@@ -70,15 +69,11 @@ public class RecorderListener implements LiveRecorder {
var json = event.getLiveData().getJson(); var json = event.getLiveData().getJson();
liveClient.getLogger().info("Searching for live download url"); liveClient.getLogger().info("Searching for live download url");
if (settings.getPrepareDownloadData() != null) { downloadData = settings.getPrepareDownloadData() != null ? settings.getPrepareDownloadData().apply(json) : mapToDownloadData(json);
downloadData = settings.getPrepareDownloadData().apply(json);
} else {
downloadData = mapToDownloadData(json);
}
if (downloadData.getDownloadLiveUrl().isEmpty()) { if (downloadData.getDownloadLiveUrl().isEmpty())
throw new TikTokLiveException("Unable to find download live url!"); liveClient.getLogger().warning("Unable to find download live url!");
} else
liveClient.getLogger().info("Live download url found!"); liveClient.getLogger().info("Live download url found!");
} }
@@ -88,13 +83,13 @@ public class RecorderListener implements LiveRecorder {
try { try {
var bufferSize = 1024; var bufferSize = 1024;
var url = new URL(downloadData.getFullUrl()); var url = new URL(downloadData.getFullUrl());
HttpsURLConnection socksConnection = (HttpsURLConnection) url.openConnection(); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
var headers = LiveClientSettings.DefaultRequestHeaders(); var headers = LiveClientSettings.DefaultRequestHeaders();
for (var entry : headers.entrySet()) { for (var entry : headers.entrySet()) {
socksConnection.setRequestProperty(entry.getKey(), entry.getValue()); connection.setRequestProperty(entry.getKey(), entry.getValue());
} }
var in = new BufferedInputStream(socksConnection.getInputStream()); var in = new BufferedInputStream(connection.getInputStream());
var path = settings.getOutputPath() + File.separator + settings.getOutputFileName(); var path = settings.getOutputPath() + File.separator + settings.getOutputFileName();
var file = new File(path); var file = new File(path);
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();