Retrieve API URL from Manyvids insteaed of using a constant
This commit is contained in:
parent
4c1b311559
commit
ace7eb1220
|
@ -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.
|
||||
|
|
|
@ -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/";
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue