From 672d2a77d4e7e2ccf122cabc76447ac36f7e5db8 Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Sat, 19 Dec 2020 19:29:15 +0100 Subject: [PATCH] Add another playlist source for Cam4 models --- .../java/ctbrec/sites/cam4/Cam4Model.java | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java b/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java index 93355df9..e0258478 100644 --- a/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java +++ b/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java @@ -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 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"; + 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()); + } } } @@ -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); } } }