Cam4: Fixed stream URLs search. Slightly increased chances to find good one

This commit is contained in:
0xb00bface 2023-12-30 22:20:41 +01:00
parent 9b45896961
commit 9da5eb2eb4
2 changed files with 35 additions and 51 deletions

View File

@ -19,6 +19,7 @@
- Online/Offline switch on all tabs. Up to 10 000 offline models in each
category. How do you like it, Elon Musk?
- Added "New Girls" tab and adjusted others. All same models on less tabs.
* Cam4: Fixed stream URLs search. Slightly increased chances to find good one.
5.2.3
========================

View File

@ -22,16 +22,14 @@ import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static ctbrec.Model.State.*;
import static ctbrec.io.HttpClient.bodyToJsonObject;
import static ctbrec.io.HttpConstants.*;
import static java.util.regex.Pattern.DOTALL;
import static java.util.regex.Pattern.MULTILINE;
@Slf4j
public class Cam4Model extends AbstractModel {
@ -40,6 +38,7 @@ public class Cam4Model extends AbstractModel {
private String playlistUrl;
private int[] resolution = null;
private transient JSONObject modelInfo;
private transient Instant lastInfoRequest = Instant.EPOCH;
@Override
public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
@ -57,12 +56,16 @@ public class Cam4Model extends AbstractModel {
}
private JSONObject loadModelInfo() throws IOException {
JSONObject roomState = new Cam4WsClient(Config.getInstance(), (Cam4) getSite(), this).getRoomState();
log.trace(roomState.toString(2));
String state = roomState.optString("newShowsState");
if (Objects.nonNull(modelInfo) && Duration.between(lastInfoRequest, Instant.now()).getSeconds() < 5) {
return modelInfo;
}
lastInfoRequest = Instant.now();
modelInfo = new Cam4WsClient(Config.getInstance(), (Cam4) getSite(), this).getRoomState();
log.trace(modelInfo.toString(2));
String state = modelInfo.optString("newShowsState");
setOnlineStateByShowType(state);
setDescription(roomState.optString("status"));
return roomState;
setDescription(modelInfo.optString("status"));
return modelInfo;
}
public void setOnlineStateByShowType(String showType) {
@ -94,37 +97,36 @@ public class Cam4Model extends AbstractModel {
}
private String getPlaylistUrl() throws IOException {
try {
getPlaylistUrlFromStreamUrl();
if (StringUtil.isNotBlank(playlistUrl)) {
return playlistUrl;
}
} catch (IOException e) {
log.debug("Couldn't get playlist url from stream info: {}", e.getMessage());
}
if (modelInfo != null && modelInfo.has("hls")) {
if (Objects.nonNull(modelInfo)) {
String hls = modelInfo.optString("hls");
log.debug("Stream hls: {}", hls);
if (StringUtil.isNotBlank(hls) && hls.startsWith("http")) {
log.debug("Stream hls: {}", hls);
playlistUrl = hls;
return playlistUrl;
}
}
if (modelInfo != null && modelInfo.has("streamUUID")) {
String uuid = modelInfo.optString("streamUUID");
log.debug("Stream UUID: {}", uuid);
String[] parts = uuid.split("-");
if (parts.length > 3) {
String urlTemplate = "https://cam4-hls.xcdnpro.com/{0}/cam4-origin-live/{1}_aac/playlist.m3u8";
playlistUrl = MessageFormat.format(urlTemplate, parts[1], uuid);
String llhls = modelInfo.optString("llhls");
if (StringUtil.isNotBlank(llhls) && llhls.startsWith("http")) {
log.debug("Stream hls: {}", llhls);
playlistUrl = llhls;
return playlistUrl;
}
}
String page = loadModelPage();
Matcher m = Pattern.compile("hlsUrl\\s*:\\s*'(.*?)'", DOTALL | MULTILINE).matcher(page);
if (m.find()) {
playlistUrl = m.group(1);
return playlistUrl;
try {
getPlaylistUrlFromStreamUrl();
} catch (IOException e) {
log.debug("Couldn't get playlist url from stream info: {}", e.getMessage());
}
if (Objects.nonNull(modelInfo) && StringUtil.isBlank(playlistUrl)) {
String uuid = modelInfo.optString("streamUUID");
if (StringUtil.isNotBlank(uuid) && uuid.toLowerCase().startsWith(getName().toLowerCase())) {
String[] parts = uuid.split("-");
if (parts.length > 5) {
String urlTemplate = "https://cam4-hls.xcdnpro.com/{0}/cam4-origin-live/{1}_aac/playlist.m3u8";
playlistUrl = MessageFormat.format(urlTemplate, parts[1], uuid);
log.debug("Stream UUID: {}, hls: {}", uuid, playlistUrl);
return playlistUrl;
}
}
}
if (StringUtil.isBlank(playlistUrl)) {
throw new IOException("Couldn't determine playlist url");
@ -161,25 +163,6 @@ public class Cam4Model extends AbstractModel {
}
}
private String loadModelPage() throws IOException {
Request req = new Request.Builder() // @formatter:off
.url(getUrl())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(ACCEPT, "*/*")
.header(ACCEPT_LANGUAGE, "*")
.header(CACHE_CONTROL, NO_CACHE)
.header(PRAGMA, NO_CACHE)
.header(REFERER, getUrl())
.build(); // @formatter:on
try (Response response = site.getHttpClient().execute(req)) {
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new HttpException(response.code(), response.message());
}
}
}
@Override
public List<StreamSource> getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException {
MasterPlaylist masterPlaylist = getMasterPlaylist();