Retrieve API URL from Manyvids insteaed of using a constant

This commit is contained in:
0xb00bface 2021-04-11 13:23:52 +02:00
parent 4c1b311559
commit ace7eb1220
6 changed files with 54 additions and 44 deletions

View File

@ -2,6 +2,8 @@
========================
* Fixed bug, which caused some recordings to get stuck
* Fixed follow/unfollow for CamSoda
* Fixed MVLive downloads
* Fixed bug in cookie handling, which also prevent MVLive downloads from working
* Ignore list is now saved as URLs only. The old format is not compatible
anymore, so make sure, that you export them again, if you created a backup
before.

View File

@ -34,8 +34,6 @@ public class MVLive extends AbstractSite {
private static final Logger LOG = LoggerFactory.getLogger(MVLive.class);
public static final String APP_HOST = "app-v2.live.manyvids.com";
public static final String WS_URL = "wss://" + APP_HOST;
public static final String WS_ORIGIN = "https://live.manyvids.com";
public static final String BASE_URL = "https://www.manyvids.com/MVLive/";

View File

@ -66,10 +66,11 @@ public class MVLiveClient {
roomId = response.optString("roomId");
int randomNumber = 100 + rng.nextInt(800);
String randomString = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
String wsUrl = String.format("%s/api/%s/eventbus/%s/%s/websocket", WS_URL, roomNumber, randomNumber, randomString);
String wsUrl = model.getApiUrl().replace("https", "wss");
String url = String.format("%s/%s/eventbus/%s/%s/websocket", wsUrl, roomNumber, randomNumber, randomString);
LOG.info("Websocket is null. Starting a new connection to {}", wsUrl);
ws = createWebSocket(wsUrl, roomId, model.getDisplayName());
LOG.info("Websocket is null. Starting a new connection to {}", url);
ws = createWebSocket(url, roomId, model.getDisplayName());
}
}
@ -99,7 +100,7 @@ public class MVLiveClient {
super.onOpen(webSocket, response);
try {
connecting = false;
LOG.debug("WS open: [{}]", response.body().string());
LOG.trace("WS open: [{}]", response.body().string());
scheduler = new ScheduledThreadPoolExecutor(1);
scheduler.scheduleAtFixedRate(() -> sendMessages(new Ping()), 5, 5, TimeUnit.SECONDS);
} catch (IOException e) {
@ -111,7 +112,7 @@ public class MVLiveClient {
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
connecting = false;
LOG.info("MVLive websocket closed: {} {}", code, reason);
LOG.trace("MVLive websocket closed: {} {}", code, reason);
MVLiveClient.this.ws = null;
running = false;
synchronized (streamUrlMonitor) {
@ -146,14 +147,14 @@ public class MVLiveClient {
if (Objects.equal("o", text)) {
sendMessages(new Ping());
sendMessages(new GetBroadcastHealth(roomId, modelName, (m, r) -> {
LOG.debug("--> {}", m);
LOG.debug("<-- {}", r);
LOG.trace("--> {}", m);
LOG.trace("<-- {}", r);
String addr = r.getJSONObject("body").optString("subscribeAddress");
sendMessages(new RegisterMessage(addr, (mr, rr) -> {
LOG.debug("--> {}", mr);
LOG.debug("<-- {}", rr);
LOG.trace("--> {}", mr);
LOG.trace("<-- {}", rr);
masterPlaylist = rr.getJSONObject("body").optString("videoUrl");
LOG.debug("Got the URL: {}", masterPlaylist);
LOG.trace("Got the URL: {}", masterPlaylist);
stop();
synchronized (streamUrlMonitor) {
streamUrlMonitor.notifyAll();
@ -182,7 +183,7 @@ public class MVLiveClient {
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
LOG.debug("Binary Message: {}", bytes.hex());
LOG.trace("Binary Message: {}", bytes.hex());
}
});
}

View File

@ -44,9 +44,6 @@ public class MVLiveHlsDownload extends HlsDownload {
((MVLiveModel)getModel()).updateCloudFlareCookies();
} catch (IOException e) {
LOG.error("Couldn't update cloudflare cookies for model {}", getModel(), e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Couldn't update cloudflare cookies for model {}", getModel(), e);
}
}
}

View File

@ -45,9 +45,6 @@ public class MVLiveMergedHlsDownload extends MergedFfmpegHlsDownload {
((MVLiveModel)getModel()).updateCloudFlareCookies();
} catch (IOException e) {
LOG.error("Couldn't update cloudflare cookies for model {}", getModel(), e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Couldn't update cloudflare cookies for model {}", getModel(), e);
}
}
}

View File

@ -2,18 +2,20 @@ package ctbrec.sites.manyvids;
import static ctbrec.Model.State.*;
import static ctbrec.io.HttpConstants.*;
import static ctbrec.sites.manyvids.MVLive.*;
import static java.nio.charset.StandardCharsets.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -46,8 +48,11 @@ public class MVLiveModel extends AbstractModel {
private transient MVLiveHttpClient httpClient;
private transient MVLiveClient client;
private transient JSONObject roomLocation;
private transient Instant lastRoomLocationUpdate = Instant.EPOCH;
private String roomNumber;
@Override
public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
if (ignoreCache) {
@ -89,7 +94,7 @@ public class MVLiveModel extends AbstractModel {
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
String segmentUri = baseUrl + playlist.getUri();
src.mediaPlaylistUrl = segmentUri;
if(src.mediaPlaylistUrl.contains("?")) {
if (src.mediaPlaylistUrl.contains("?")) {
src.mediaPlaylistUrl = src.mediaPlaylistUrl.substring(0, src.mediaPlaylistUrl.lastIndexOf('?'));
}
LOG.debug("Media playlist {}", src.mediaPlaylistUrl);
@ -118,13 +123,14 @@ public class MVLiveModel extends AbstractModel {
MasterPlaylist master = playlist.getMasterPlaylist();
return master;
} else {
LOG.debug("{} URL: {}\n\tResponse: {}", response.code(), url, response.body().string());
throw new HttpException(response.code(), response.message());
}
}
}
public void updateCloudFlareCookies() throws IOException, InterruptedException {
String url = "https://" + APP_HOST + "/api/" + getRoomNumber() + "/player-settings/" + getDisplayName();
public void updateCloudFlareCookies() throws IOException {
String url = getApiUrl() + '/' + getRoomNumber() + "/player-settings/" + getDisplayName();
LOG.trace("Getting CF cookies: {}", url);
Request req = new Request.Builder()
.url(url)
@ -132,13 +138,17 @@ public class MVLiveModel extends AbstractModel {
.build();
try (Response response = getHttpClient().execute(req)) {
if (!response.isSuccessful()) {
LOG.debug(response.body().string());
LOG.debug("Loading CF cookies not successful: {}", response.body().string());
throw new HttpException(response.code(), response.message());
}
}
}
public String getRoomNumber() throws IOException, InterruptedException {
String getApiUrl() throws JSONException, IOException {
return getRoomLocation().getString("publicAPIURL");
}
public String getRoomNumber() throws IOException {
if (StringUtil.isBlank(roomNumber)) {
JSONObject json = getRoomLocation();
if (json.optBoolean("success")) {
@ -164,26 +174,31 @@ public class MVLiveModel extends AbstractModel {
}
public JSONObject getRoomLocation() throws IOException {
fetchGeneralCookies();
httpClient.fetchAuthenticationCookies();
String url = "https://roompool.live.manyvids.com/roompool/" + getDisplayName() + "?private=false";
LOG.debug("Fetching room location from {}", url);
Request req = new Request.Builder()
.url(url)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(REFERER, MVLive.WS_ORIGIN + "/stream/" + getName())
.build();
try (Response response = getHttpClient().execute(req)) {
if (response.isSuccessful()) {
String body = response.body().string();
JSONObject json = new JSONObject(body);
LOG.trace("Room location response: {}", json);
return json;
} else {
throw new HttpException(response.code(), response.message());
if (Duration.between(lastRoomLocationUpdate, Instant.now()).getSeconds() > 60) {
fetchGeneralCookies();
httpClient.fetchAuthenticationCookies();
String url = "https://roompool.live.manyvids.com/roompool/" + getDisplayName() + "?private=false";
LOG.debug("Fetching room location from {}", url);
Request req = new Request.Builder()
.url(url)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(REFERER, MVLive.WS_ORIGIN + "/stream/" + getName())
.build();
try (Response response = getHttpClient().execute(req)) {
if (response.isSuccessful()) {
String body = response.body().string();
roomLocation = new JSONObject(body);
LOG.trace("Room location response: {}", roomLocation);
lastRoomLocationUpdate = Instant.now();
return roomLocation;
} else {
throw new HttpException(response.code(), response.message());
}
}
} else {
return roomLocation;
}
}