Fix construction of Stripchat streaming URLs
This commit is contained in:
parent
14f2626492
commit
0c4cdfb795
|
@ -4,7 +4,8 @@
|
|||
* Save coonfig in a sub-directory for each version.
|
||||
* Add setting to disable tab dragging, because that might be the cause for tab
|
||||
freezes
|
||||
* Fix thumbnails for Stripchat
|
||||
* Fix Stripchat recordings
|
||||
* Fix Stripchat thumbsnails
|
||||
|
||||
4.7.5
|
||||
========================
|
||||
|
|
|
@ -1,38 +1,42 @@
|
|||
package ctbrec.sites.stripchat;
|
||||
|
||||
import static ctbrec.Model.State.*;
|
||||
import static ctbrec.io.HttpConstants.*;
|
||||
import static ctbrec.sites.stripchat.StripchatHttpClient.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import com.iheartradio.m3u8.*;
|
||||
import com.iheartradio.m3u8.data.MasterPlaylist;
|
||||
import com.iheartradio.m3u8.data.Playlist;
|
||||
import com.iheartradio.m3u8.data.PlaylistData;
|
||||
import ctbrec.AbstractModel;
|
||||
import ctbrec.Config;
|
||||
import ctbrec.io.HttpException;
|
||||
import ctbrec.recorder.download.StreamSource;
|
||||
import ctbrec.sites.Site;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.iheartradio.m3u8.ParseException;
|
||||
import com.iheartradio.m3u8.PlaylistException;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import ctbrec.AbstractModel;
|
||||
import ctbrec.Config;
|
||||
import ctbrec.io.HttpException;
|
||||
import ctbrec.recorder.download.StreamSource;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import static ctbrec.Model.State.*;
|
||||
import static ctbrec.io.HttpConstants.*;
|
||||
import static ctbrec.sites.stripchat.StripchatHttpClient.JSON;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
public class StripchatModel extends AbstractModel {
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(StripchatModel.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(StripchatModel.class);
|
||||
private String status = null;
|
||||
private int[] resolution = new int[] {0, 0};
|
||||
private int[] resolution = new int[]{0, 0};
|
||||
|
||||
private static StripchatConfig stripchatConfig;
|
||||
|
||||
@Override
|
||||
public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
|
||||
|
@ -49,25 +53,14 @@ public class StripchatModel extends AbstractModel {
|
|||
|
||||
private void mapOnlineState(String status) {
|
||||
switch (status) {
|
||||
case "public":
|
||||
setOnlineState(ONLINE);
|
||||
break;
|
||||
case "idle":
|
||||
setOnlineState(AWAY);
|
||||
break;
|
||||
case "private":
|
||||
case "p2p":
|
||||
case "groupShow":
|
||||
case "virtualPrivate":
|
||||
setOnlineState(PRIVATE);
|
||||
break;
|
||||
case "off":
|
||||
setOnlineState(OFFLINE);
|
||||
break;
|
||||
default:
|
||||
LOG.debug("Unknown online state {} for model {}", status, getName());
|
||||
setOnlineState(OFFLINE);
|
||||
break;
|
||||
case "public" -> setOnlineState(ONLINE);
|
||||
case "idle" -> setOnlineState(AWAY);
|
||||
case "private", "p2p", "groupShow", "virtualPrivate" -> setOnlineState(PRIVATE);
|
||||
case "off" -> setOnlineState(OFFLINE);
|
||||
default -> {
|
||||
LOG.debug("Unknown online state {} for model {}", status, getName());
|
||||
setOnlineState(OFFLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +86,49 @@ public class StripchatModel extends AbstractModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<StreamSource> getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException, JAXBException {
|
||||
public List<StreamSource> getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException {
|
||||
MasterPlaylist masterPlaylist = getMasterPlaylist();
|
||||
List<StreamSource> sources = new ArrayList<>();
|
||||
for (PlaylistData playlist : masterPlaylist.getPlaylists()) {
|
||||
if (playlist.hasStreamInfo()) {
|
||||
StreamSource src = new StreamSource();
|
||||
src.bandwidth = playlist.getStreamInfo().getBandwidth();
|
||||
src.height = playlist.getStreamInfo().getResolution().height;
|
||||
src.mediaPlaylistUrl = playlist.getUri();
|
||||
if (src.mediaPlaylistUrl.contains("?")) {
|
||||
src.mediaPlaylistUrl = src.mediaPlaylistUrl.substring(0, src.mediaPlaylistUrl.lastIndexOf('?'));
|
||||
}
|
||||
LOG.trace("Media playlist {}", src.mediaPlaylistUrl);
|
||||
sources.add(src);
|
||||
}
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
|
||||
private MasterPlaylist getMasterPlaylist() throws IOException, ParseException, PlaylistException {
|
||||
String url = getMasterPlaylistUrl();
|
||||
LOG.trace("Loading master playlist {}", url);
|
||||
Request req = new Request.Builder()
|
||||
.url(url)
|
||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||
.build();
|
||||
try (Response response = getSite().getHttpClient().execute(req)) {
|
||||
if (response.isSuccessful()) {
|
||||
String body = response.body().string();
|
||||
LOG.trace(body);
|
||||
InputStream inputStream = new ByteArrayInputStream(body.getBytes(UTF_8));
|
||||
PlaylistParser parser = new PlaylistParser(inputStream, Format.EXT_M3U, Encoding.UTF_8, ParsingMode.LENIENT);
|
||||
Playlist playlist = parser.parse();
|
||||
MasterPlaylist master = playlist.getMasterPlaylist();
|
||||
return master;
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getMasterPlaylistUrl() throws IOException {
|
||||
loadStripchatConfig(getSite());
|
||||
String name = getName();
|
||||
String url = getSite().getBaseUrl() + "/api/front/models/username/" + name + "/cam?triggerRequest=loadCam";
|
||||
Request req = new Request.Builder()
|
||||
|
@ -110,29 +145,35 @@ public class StripchatModel extends AbstractModel {
|
|||
String streamName = jsonResponse.optString("streamName", jsonResponse.optString(""));
|
||||
JSONObject viewServers = jsonResponse.getJSONObject("viewServers");
|
||||
String serverName = viewServers.optString("flashphoner-hls");
|
||||
JSONObject broadcastSettings = jsonResponse.getJSONObject("broadcastSettings");
|
||||
List<StreamSource> sources = new ArrayList<>();
|
||||
StreamSource best = new StreamSource();
|
||||
best.height = broadcastSettings.optInt("height");
|
||||
best.width = broadcastSettings.optInt("width");
|
||||
best.mediaPlaylistUrl = "https://b-" + serverName + ".stripst.com/hls/" + streamName + '/' + streamName + ".m3u8";
|
||||
sources.add(best);
|
||||
JSONObject presets = broadcastSettings.optJSONObject("presets");
|
||||
Object defaultObject = presets.get("testing");
|
||||
if (defaultObject instanceof JSONObject) {
|
||||
JSONObject defaults = (JSONObject) defaultObject;
|
||||
JSONArray heights = defaults.names();
|
||||
for (int i = 0; i < heights.length(); i++) {
|
||||
String h = heights.getString(i);
|
||||
StreamSource streamSource = new StreamSource();
|
||||
streamSource.height = Integer.parseInt(h.replaceAll("[^\\d]", ""));
|
||||
streamSource.width = streamSource.height * best.getWidth() / best.getHeight();
|
||||
String source = streamName + '_' + streamSource.height + 'p';
|
||||
streamSource.mediaPlaylistUrl = "https://b-" + serverName + ".stripst.com/hls/" + source + '/' + source + ".m3u8";
|
||||
sources.add(streamSource);
|
||||
}
|
||||
}
|
||||
return sources.stream().sorted((a, b) -> a.height - b.height).collect(Collectors.toList());
|
||||
return "https://b-" + serverName + '.' + stripchatConfig.hlsStreamHost + "/hls/" + streamName + "/master/" + streamName + "_auto.m3u8";
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized void loadStripchatConfig(Site site) throws IOException {
|
||||
if (stripchatConfig != null) {
|
||||
return;
|
||||
}
|
||||
Request req = new Request.Builder()
|
||||
.url(site.getBaseUrl() + "/api/front/v2/config?uniq=g8wizmarpvck4dj5")
|
||||
.header(ACCEPT, "*/*")
|
||||
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
|
||||
.header(X_REQUESTED_WITH, XML_HTTP_REQUEST)
|
||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||
.header(REFERER, site.getBaseUrl())
|
||||
.build();
|
||||
|
||||
LOG.debug("Loading config from {}", req.url());
|
||||
try (Response response = site.getHttpClient().execute(req)) {
|
||||
if (response.isSuccessful()) {
|
||||
JSONObject json = new JSONObject(Objects.requireNonNull(response.body(), "HTTP response body is null").string());
|
||||
LOG.trace(json.toString(2));
|
||||
JSONObject config = json.getJSONObject("config");
|
||||
String hlsStreamHost = config.getString("hlsStreamHost");
|
||||
stripchatConfig = new StripchatConfig();
|
||||
stripchatConfig.hlsStreamHost = hlsStreamHost;
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
|
@ -143,7 +184,7 @@ public class StripchatModel extends AbstractModel {
|
|||
@Override
|
||||
public void invalidateCacheEntries() {
|
||||
status = null;
|
||||
resolution = new int[] { 0, 0 };
|
||||
resolution = new int[]{0, 0};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -158,9 +199,9 @@ public class StripchatModel extends AbstractModel {
|
|||
List<StreamSource> sources = getStreamSources();
|
||||
if (!sources.isEmpty()) {
|
||||
StreamSource best = sources.get(sources.size() - 1);
|
||||
resolution = new int[] { best.getWidth(), best.getHeight() };
|
||||
resolution = new int[]{best.getWidth(), best.getHeight()};
|
||||
}
|
||||
} catch (IOException | ParseException | PlaylistException | JAXBException e) {
|
||||
} catch (IOException | ParseException | PlaylistException e) {
|
||||
throw new ExecutionException(e);
|
||||
}
|
||||
}
|
||||
|
@ -233,4 +274,8 @@ public class StripchatModel extends AbstractModel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class StripchatConfig {
|
||||
String hlsStreamHost;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue