Skip to content

Commit

Permalink
Merge branch 'master' into hotfix/3.1.233
Browse files Browse the repository at this point in the history
  • Loading branch information
alex1702 committed May 17, 2024
2 parents 54927c2 + e0139db commit 3caa3e6
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 54 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
group = 'de.mediathekview'
archivesBaseName = "MServer"
version = '3.1.230'
version = '3.1.232'

def jarName = 'MServer.jar'
def mainClass = 'mServer.Main'
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/mServer/crawler/sender/base/JsonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ public static boolean hasElements(
return true;
}

public static Optional<Integer> getElementValueAsInteger(final JsonElement aJsonElement, final String... aElementIds) {
Optional<JsonElement> rs = JsonUtils.getElement(aJsonElement, aElementIds);
if (rs.isPresent()) {
return Optional.of(rs.get().getAsInt());
}
return Optional.empty();
}
/**
* Checks if the {@link JsonObject} has all given elements and if no element
* is null or empty.
Expand Down Expand Up @@ -142,7 +149,7 @@ public static Optional<String> getElementValueAsString(final JsonElement aJsonEl

public static Optional<JsonElement> getElement(final JsonElement aJsonElement, final String... aElementIds) {
Optional<JsonElement> rs = Optional.empty();
if (aElementIds == null || aElementIds.length == 0) {
if (aElementIds == null || aElementIds.length == 0 || aJsonElement == null || !aJsonElement.isJsonObject()) {
return rs;
}
JsonObject aJsonObject = aJsonElement.getAsJsonObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public class OrfOnEpisodeDeserializer implements JsonDeserializer<OrfOnVideoInfo

private static final String[] TAG_SUBTITLE_SECTION = {"_embedded", "subtitle"};
private static final String TAG_SUBTITLE_TTML = "ttml_url";
private static final String[] PREFERED_CODEC = {"hls", "hds", "streaming", "progressive"};
private static final String[] PREFERED_CODEC = {"hls", "hds", "progressive"};
private static final String[] VIDEO_THUMBNAIL = {"thumbnail_sources","hls"};
//
private final OrfHttpClient connection;
//
Expand Down Expand Up @@ -91,7 +92,7 @@ public OrfOnVideoInfoDTO deserialize(
parseDuration(JsonUtils.getElementValueAsString(jsonElement, TAG_DURATION)),
JsonUtils.getElementValueAsString(jsonElement, TAG_DESCRIPTION),
parseWebsite(JsonUtils.getElementValueAsString(jsonElement, TAG_SHARE_BODY)),
optimizeUrls(parseUrl(jsonElement)),
optimizeUrls(parseVideoFromSegmentPlaylist(jsonElement)),
buildOrResolveSubs(jsonElement)

);
Expand Down Expand Up @@ -139,31 +140,28 @@ private Optional<String> parseSubtitleUrls(JsonElement element) {
return JsonUtils.getElementValueAsString(element, TAG_SUBTITLE_TTML);
}

private Optional<Map<Qualities, String>> parseUrl(JsonElement jsonElement) {
private Optional<Map<Qualities, String>> parseVideoFromSegmentPlaylist(JsonElement jsonElement) {
Optional<JsonElement> videoPath1 = JsonUtils.getElement(jsonElement, TAG_VIDEO_PATH_1);
if (videoPath1.isEmpty() || !videoPath1.get().isJsonArray() || videoPath1.get().getAsJsonArray().size() == 0) {
return Optional.empty();
}
// We need to fallback to episode.sources in case there are many elements in the playlist
if (videoPath1.get().getAsJsonArray().size() > 1) {
return parseFallbackVideo(jsonElement);
}

Optional<JsonElement> videoPath2 = JsonUtils.getElement(videoPath1.get().getAsJsonArray().get(0), TAG_VIDEO_PATH_2);
if (videoPath2.isEmpty() || !videoPath2.get().isJsonArray()) {
return Optional.empty();
}
for (String key : PREFERED_CODEC) {
Optional<Map<Qualities, String>> resultingVideos = readVideoForTargetCodec(videoPath2.get(), key);
if (resultingVideos.isPresent()) {
return resultingVideos;
if (videoPath1.get().getAsJsonArray().size() == 1) {
Optional<JsonElement> videoPath2 = JsonUtils.getElement(videoPath1.get().getAsJsonArray().get(0), TAG_VIDEO_PATH_2);
if (videoPath2.isEmpty() || !videoPath2.get().isJsonArray()) {
return Optional.empty();
}
for (String key : PREFERED_CODEC) {
Optional<Map<Qualities, String>> resultingVideos = readVideoForTargetCodec(videoPath2.get(), key);
if (resultingVideos.isPresent()) {
return resultingVideos;
}
}
}

return Optional.empty();
return parseVideoFromSources(jsonElement);
}

private Optional<Map<Qualities, String>> parseFallbackVideo(JsonElement root) {
private Optional<Map<Qualities, String>> parseVideoFromSources(JsonElement root) {
Optional<JsonElement> videoSources = JsonUtils.getElement(root, TAG_VIDEO_FALLBACK);
if (videoSources.isPresent()) {
Map<Qualities, String> urls = new EnumMap<>(Qualities.class);
Expand All @@ -172,15 +170,39 @@ private Optional<Map<Qualities, String>> parseFallbackVideo(JsonElement root) {
if (codecs.isPresent() && codecs.get().isJsonArray()) {
for (JsonElement singleVideo : codecs.get().getAsJsonArray()) {
Optional<String> tgtUrl = JsonUtils.getElementValueAsString(singleVideo, TAG_VIDEO_FALLBACK_URL);
if (tgtUrl.isPresent()) {
if (tgtUrl.isPresent() && !tgtUrl.get().contains("/Jugendschutz") && !tgtUrl.get().contains("/no_drm_support") && !tgtUrl.get().contains("/schwarzung")) {
urls.put(Qualities.NORMAL, tgtUrl.get());
return Optional.of(urls);
}
}
}
}
}
return Optional.empty();
return parseVideoFromThumbnail(root);
}

private Optional<Map<Qualities, String>> parseVideoFromThumbnail(JsonElement root) {
Map<Qualities, String> urls = new EnumMap<>(Qualities.class);
try {
Optional<JsonElement> id = JsonUtils.getElement(root, TAG_ID);
Optional<JsonElement> thumbnailSources = JsonUtils.getElement(root, VIDEO_THUMBNAIL);
if (id.isPresent() && thumbnailSources.isPresent() && thumbnailSources.get().isJsonArray() && thumbnailSources.get().getAsJsonArray().size() > 0 ) {
Optional<JsonElement> thumbnailSrc = JsonUtils.getElement(thumbnailSources.get().getAsJsonArray().get(0), "src");
if (thumbnailSrc.isPresent()) {
int indexId = thumbnailSrc.get().getAsString().indexOf(id.get().getAsString());
String fromSecondIdOnwards = thumbnailSrc.get().getAsString().substring(indexId + id.get().getAsString().length() + 1);
String secondId = fromSecondIdOnwards.substring(0, fromSecondIdOnwards.indexOf("_"));
String url = String.format("https://apasfiis.sf.apa.at/ipad/cms-worldwide_episodes/%s_%s_QXA.mp4/playlist.m3u8", id.get().getAsString(), secondId);
urls.put(Qualities.NORMAL, url);
}
}
} catch (Exception e) {
LOG.error("generateFallbackVideo {}", e);
}
if (urls.size() == 0) {
return Optional.empty();
}
return Optional.of(urls);
}

private Optional<Map<Qualities, String>> readVideoForTargetCodec(JsonElement urlArray, String targetCodec) {
Expand All @@ -190,9 +212,11 @@ private Optional<Map<Qualities, String>> readVideoForTargetCodec(JsonElement url
Optional<String> qualityValue = JsonUtils.getElementValueAsString(videoElement, TAG_VIDEO_QUALITY);
Optional<String> url = JsonUtils.getElementValueAsString(videoElement, TAG_VIDEO_URL);
if (url.isPresent() && codec.isPresent() && qualityValue.isPresent() && targetCodec.equalsIgnoreCase(codec.get()) && OrfOnEpisodeDeserializer.getQuality(qualityValue.get()).isPresent()) {
final Optional<Qualities> quality = OrfOnEpisodeDeserializer.getQuality(qualityValue.get());
if (quality.isPresent()) {
urls.put(quality.get(), url.get());
if (!url.get().contains("/Jugendschutz") && !url.get().contains("/no_drm_support") && !url.get().contains("/schwarzung")) {
final Optional<Qualities> quality = OrfOnEpisodeDeserializer.getQuality(qualityValue.get());
if (quality.isPresent()) {
urls.put(quality.get(), url.get());
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ public class ZdfFilmDetailDeserializer implements JsonDeserializer<Optional<ZdfF
private static final String JSON_ELEMENT_TITLE = "title";
private static final String JSON_ELEMENT_TEASER_TEXT = "teasertext";
private static final String JSON_ATTRIBUTE_TEMPLATE = "http://zdf.de/rels/streams/ptmd-template";

private static final String EPISODENUMBER = "episodeNumber";
private static final String[] SEASONNUMBER = {"http://zdf.de/rels/cmdm/season", "seasonNumber"};

private static final String PLACEHOLDER_PLAYER_ID = "{playerId}";
private static final String PLAYER_ID = "android_native_5";

Expand Down Expand Up @@ -215,38 +217,53 @@ private Optional<String> parseDescription(JsonObject aRootNode) {
return Optional.empty();
}

private Optional<String> parseTitle(JsonObject aRootNode, JsonObject aTarget) {
Optional<String> title = parseTitleValue(aRootNode, aTarget);
return title.map(s -> s.replaceAll("\\(CC.*\\) - .* Creative Commons.*", ""));
private Optional<String> parseTitle(final JsonObject aRootNode, final JsonObject aTarget) {
final Optional<String> programmTitle = JsonUtils.getElementValueAsString(aRootNode, JSON_ELEMENT_TITLE);
final Optional<String> programmSubtitle = JsonUtils.getElementValueAsString(aRootNode, JSON_ELEMENT_SUBTITLE);
Optional<String> resultingTitle = formatTitle(programmTitle, programmSubtitle);
if (resultingTitle.isEmpty()) {
final Optional<String> targetTitle = JsonUtils.getElementValueAsString(aTarget, JSON_ELEMENT_TITLE);
final Optional<String> targetSubtitle = JsonUtils.getElementValueAsString(aTarget, JSON_ELEMENT_SUBTITLE);
resultingTitle = formatTitle(targetTitle, targetSubtitle);
}
if (resultingTitle.isPresent()) {
final Optional<Integer> season = JsonUtils.getElementValueAsInteger(aTarget, SEASONNUMBER);
final Optional<Integer> episode = JsonUtils.getElementValueAsInteger(aTarget, EPISODENUMBER);
final Optional<String> seasonEpisodeTitle = formatEpisodeTitle(season, episode);
final Optional<String> title = cleanupTitle((resultingTitle.get() + " " + seasonEpisodeTitle.orElse("")).trim());
return title;
}
return Optional.empty();
}

private Optional<String> parseTitleValue(JsonObject aRootNode, JsonObject aTarget) {
// use property "title" if found
JsonElement titleElement = aRootNode.get(JSON_ELEMENT_TITLE);
if (titleElement != null) {
JsonElement subTitleElement = aRootNode.get(JSON_ELEMENT_SUBTITLE);
if (subTitleElement != null) {
return Optional.of(titleElement.getAsString().trim() + " - " + subTitleElement.getAsString());
} else {
return Optional.of(titleElement.getAsString());
}
private Optional<String> cleanupTitle(String title) {
return Optional.of(title.replaceAll("\\(CC.*\\) - .* Creative Commons.*", ""));
}

private Optional<String> formatTitle(Optional<String> title, Optional<String> sub) {
if (title.isEmpty()) {
return Optional.empty();
}
if (sub.isPresent() && !sub.get().isBlank()) {
return Optional.of(title.get().trim() + " - " + sub.get().trim());
} else {
// programmItem target required to determine title
if (aTarget != null && aTarget.has(JSON_ELEMENT_TITLE)) {
String title = aTarget.get(JSON_ELEMENT_TITLE).getAsString();
String subTitle = aTarget.get(JSON_ELEMENT_SUBTITLE).getAsString();

if (subTitle.isEmpty()) {
return Optional.of(title);
} else {
return Optional.of(title.trim() + " - " + subTitle);
}
}
return Optional.of(title.get().trim());
}

return Optional.empty();
}


private Optional<String> formatEpisodeTitle(Optional<Integer> season, Optional<Integer> episode) {
if (season.isEmpty() && episode.isEmpty()) {
return Optional.empty();
}
String result = "";
if (season.isPresent()) {
result += String.format("S%02d", season.get());
}
if (episode.isPresent()) {
result += String.format("E%02d", episode.get());
}
return Optional.of("("+result+")");
}
private Optional<String> parseTopic(JsonObject aRootNode) {
JsonObject brand = aRootNode.getAsJsonObject(JSON_ELEMENT_BRAND);
JsonObject category = aRootNode.getAsJsonObject(JSON_ELEMENT_CATEGORY);
Expand Down

0 comments on commit 3caa3e6

Please sign in to comment.