Add another playlist source for Cam4 models

This commit is contained in:
0xb00bface 2020-12-19 19:29:15 +01:00
parent c9cd6e825d
commit 672d2a77d4
1 changed files with 29 additions and 22 deletions

View File

@ -6,15 +6,12 @@ import static java.util.regex.Pattern.*;
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.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -47,7 +44,6 @@ import okhttp3.Response;
public class Cam4Model extends AbstractModel {
private static final Logger LOG = LoggerFactory.getLogger(Cam4Model.class);
private transient Instant playlistRequestTimestamp = Instant.EPOCH;
private String playlistUrl;
private int[] resolution = null;
private boolean privateRoom = false;
@ -121,34 +117,44 @@ public class Cam4Model extends AbstractModel {
}
private String getPlaylistUrl() throws IOException {
if (playlistUrl == null || playlistUrl.trim().isEmpty() || playlistIsOutdated()) {
if (playlistUrl == null || playlistUrl.trim().isEmpty()) {
String page = loadModelPage();
Matcher m = Pattern.compile("hlsUrl\\s*:\\s*'(.*?)'", DOTALL | MULTILINE).matcher(page);
if (m.find()) {
playlistUrl = m.group(1);
} else {
m = Pattern.compile("\"videoPlayUrl\"\\s*:\\s*\"(.*?)\"", DOTALL | MULTILINE).matcher(page);
if (m.find()) {
generatePlaylistUrlFromStreamName(m.group(1));
}
getPlaylistUrlFromStreamUrl();
}
if (playlistUrl == null) {
throw new IOException("Couldn't determine playlist url");
}
playlistRequestTimestamp = Instant.now();
}
return playlistUrl;
}
private boolean playlistIsOutdated() {
return Duration.between(playlistRequestTimestamp, Instant.now()).getSeconds() > TimeUnit.MINUTES.toSeconds(2);
private void getPlaylistUrlFromStreamUrl() throws IOException {
String url = getSite().getBaseUrl() + "/_profile/streamURL?username=" + getName();
Request req = new Request.Builder() // @formatter:off
.url(url)
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(ACCEPT, "*/*")
.header(ACCEPT_LANGUAGE, "*")
.header(REFERER, getUrl())
.build(); // @formatter:on
try (Response response = site.getHttpClient().execute(req)) {
if (response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string());
LOG.trace(json.toString(2));
if (json.has("canUseCDN")) {
if (json.getBoolean("canUseCDN")) {
playlistUrl = json.getString("cdnURL");
} else {
playlistUrl = json.getString("edgeURL");
}
}
} else {
throw new HttpException(response.code(), response.message());
}
private void generatePlaylistUrlFromStreamName(String streamName) {
Matcher m = Pattern.compile(".*?-(\\d{3,})-.*").matcher(streamName);
if (m.find()) {
String number = m.group(1);
playlistUrl = "https://cam4-hls.xcdnpro.com/" + number + "/cam4-origin-live/ngrp:" + streamName + "_all/playlist.m3u8";
}
}
@ -184,8 +190,9 @@ public class Cam4Model extends AbstractModel {
}
private MasterPlaylist getMasterPlaylist() throws IOException, ParseException, PlaylistException {
LOG.trace("Loading master playlist [{}]", getPlaylistUrl());
Request req = new Request.Builder().url(getPlaylistUrl()).build();
String playlistUrl = getPlaylistUrl();
LOG.trace("Loading master playlist [{}]", playlistUrl);
Request req = new Request.Builder().url(playlistUrl).build();
try (Response response = site.getHttpClient().execute(req)) {
if (response.isSuccessful()) {
@ -195,7 +202,7 @@ public class Cam4Model extends AbstractModel {
MasterPlaylist master = playlist.getMasterPlaylist();
return master;
} else {
throw new HttpException(response.code(), "Couldn't download HLS playlist");
throw new HttpException(response.code(), "Couldn't download HLS playlist " + playlistUrl);
}
}
}