-
- {{deeplinkReport[col]}}
+
+
+ {{deeplinkReport[column]}}
+
+
+ {{deeplinkReport[column]}}
+
Delete
diff --git a/src/main/java/ch/srgssr/playfff/config/AuthenticationConfig.java b/src/main/java/ch/srgssr/playfff/config/AuthenticationConfig.java
index a910dd3..1ffbcce 100644
--- a/src/main/java/ch/srgssr/playfff/config/AuthenticationConfig.java
+++ b/src/main/java/ch/srgssr/playfff/config/AuthenticationConfig.java
@@ -67,7 +67,7 @@ protected void configure(HttpSecurity http) throws Exception {
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
- .antMatchers("/api/v1/deeplink/parsePlayUrl.js")
+ .antMatchers("/api/v{[0-9]+}/deeplink/parsePlayUrl.js")
.antMatchers(HttpMethod.POST, "/api/v1/deeplink/report");
}
diff --git a/src/main/java/ch/srgssr/playfff/controller/DeepLinkController.java b/src/main/java/ch/srgssr/playfff/controller/DeepLinkController.java
index d8072ef..2d9687f 100644
--- a/src/main/java/ch/srgssr/playfff/controller/DeepLinkController.java
+++ b/src/main/java/ch/srgssr/playfff/controller/DeepLinkController.java
@@ -56,17 +56,31 @@ public ResponseEntity create(@RequestBody DeepLinkReport deepLin
}
// Public API
- @RequestMapping(value="/api/v1/deeplink/parsePlayUrl.js")
+ @RequestMapping(value="/api/v{version}/deeplink/parsePlayUrl.js")
@ResponseBody
- public ResponseEntity parsePlayUrlJavascript() {
+ public ResponseEntity parsePlayUrlJavascript(@PathVariable("version") int version) {
DeepLinkJSContent deepLinkJSContent = service.getParsePlayUrlJSContent();
- if (deepLinkJSContent != null) {
+ String content = null;
+ String hash = null;
+
+ switch (version) {
+ case 1:
+ content = deepLinkJSContent.getContentV1();
+ hash = deepLinkJSContent.getHashV1();
+ break;
+ case 2:
+ content = deepLinkJSContent.getContentV2();
+ hash = deepLinkJSContent.getHashV2();
+ break;
+ }
+
+ if (content != null && hash != null) {
return ResponseEntity.ok()
.cacheControl(CacheControl.empty().cachePublic())
- .eTag(deepLinkJSContent.getHash())
- .body(deepLinkJSContent.getContent());
+ .eTag(hash)
+ .body(content);
} else {
return ResponseEntity.notFound().build();
}
diff --git a/src/main/java/ch/srgssr/playfff/model/DeepLinkJSContent.java b/src/main/java/ch/srgssr/playfff/model/DeepLinkJSContent.java
index c49c9df..e46a55c 100644
--- a/src/main/java/ch/srgssr/playfff/model/DeepLinkJSContent.java
+++ b/src/main/java/ch/srgssr/playfff/model/DeepLinkJSContent.java
@@ -7,19 +7,32 @@
*/
public class DeepLinkJSContent {
- private String content;
- private String hash;
+ private String contentV1;
+ private String hashV1;
- public DeepLinkJSContent(String content, String hash) {
- this.content = content;
- this.hash = hash;
+ private String contentV2;
+ private String hashV2;
+
+ public DeepLinkJSContent(String contentV1, String hashV1, String contentV2, String hashV2) {
+ this.contentV1 = contentV1;
+ this.hashV1 = hashV1;
+ this.contentV2 = contentV2;
+ this.hashV2 = hashV2;
+ }
+
+ public String getContentV1() {
+ return contentV1;
+ }
+
+ public String getHashV1() {
+ return hashV1;
}
- public String getContent() {
- return content;
+ public String getContentV2() {
+ return contentV2;
}
- public String getHash() {
- return hash;
+ public String getHashV2() {
+ return hashV2;
}
}
diff --git a/src/main/java/ch/srgssr/playfff/service/DeepLinkService.java b/src/main/java/ch/srgssr/playfff/service/DeepLinkService.java
index 74c92e9..74db868 100644
--- a/src/main/java/ch/srgssr/playfff/service/DeepLinkService.java
+++ b/src/main/java/ch/srgssr/playfff/service/DeepLinkService.java
@@ -69,7 +69,8 @@ public DeepLinkJSContent getParsePlayUrlJSContent() {
@CachePut(DeepLinkCacheName)
public synchronized DeepLinkJSContent refreshParsePlayUrlJSContent() {
- String javascript = BaseResourceString.getString(applicationContext, "parsePlayUrl.js");
+ String javascriptV1 = BaseResourceString.getString(applicationContext, "deeplink/v1/parsePlayUrl.js");
+ String javascriptV2 = BaseResourceString.getString(applicationContext, "deeplink/v2/parsePlayUrl.js");
Map buProdMap = new HashMap<>();
buProdMap.put("srf", "www.srf.ch");
@@ -125,7 +126,8 @@ public synchronized DeepLinkJSContent refreshParsePlayUrlJSContent() {
}
if (tvTopics != null) {
- javascript = javascript.replaceAll("\\/\\* INJECT TVTOPICS OBJECT \\*\\/", "var tvTopics = " + tvTopics + ";");
+ javascriptV1 = javascriptV1.replaceAll("\\/\\* INJECT TVTOPICS OBJECT \\*\\/", "var tvTopics = " + tvTopics + ";");
+ javascriptV2 = javascriptV2.replaceAll("\\/\\* INJECT TVTOPICS OBJECT \\*\\/", "var tvTopics = " + tvTopics + ";");
}
String tvEvents = null;
@@ -136,23 +138,31 @@ public synchronized DeepLinkJSContent refreshParsePlayUrlJSContent() {
}
if (tvEvents != null) {
- javascript = javascript.replaceAll("\\/\\* INJECT TVEVENTS OBJECT \\*\\/", "var tvEvents = " + tvEvents + ";");
+ javascriptV1 = javascriptV1.replaceAll("\\/\\* INJECT TVEVENTS OBJECT \\*\\/", "var tvEvents = " + tvEvents + ";");
+ javascriptV2 = javascriptV2.replaceAll("\\/\\* INJECT TVEVENTS OBJECT \\*\\/", "var tvEvents = " + tvEvents + ";");
}
- String buildHash = "NO_SHA1";
+ String buildHashV1 = "NO_SHA1";
try {
- buildHash = Sha1.sha1(javascript);
+ buildHashV1 = Sha1.sha1(javascriptV1);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
- logger.warn("sha1", e);
+ logger.warn("sha1 v1", e);
+ }
+ String buildHashV2 = "NO_SHA1";
+ try {
+ buildHashV2 = Sha1.sha1(javascriptV2);
+ } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
+ logger.warn("sha1 v2", e);
}
Date buildDate = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
dateFormat.setTimeZone(TimeZone.getTimeZone("Europe/Zurich"));
String strDate = dateFormat.format(buildDate);
- javascript = javascript.replaceAll("var parsePlayUrlBuild = \"mmf\";", "var parsePlayUrlBuild = \"" + buildHash + "\";\nvar parsePlayUrlBuildDate = \"" + strDate + "\";");
+ javascriptV1 = javascriptV1.replaceAll("var parsePlayUrlBuild = \"mmf\";", "var parsePlayUrlBuild = \"" + buildHashV1 + "\";\nvar parsePlayUrlBuildDate = \"" + strDate + "\";");
+ javascriptV2 = javascriptV2.replaceAll("var parsePlayUrlBuild = \"mmf\";", "var parsePlayUrlBuild = \"" + buildHashV2 + "\";\nvar parsePlayUrlBuildDate = \"" + strDate + "\";");
- return new DeepLinkJSContent(javascript, buildHash);
+ return new DeepLinkJSContent(javascriptV1, buildHashV1, javascriptV2, buildHashV2);
}
private Map> getTvTopicMap(Map buMap) {
diff --git a/src/main/resources/parsePlayUrl.js b/src/main/resources/deeplink/v1/parsePlayUrl.js
similarity index 98%
rename from src/main/resources/parsePlayUrl.js
rename to src/main/resources/deeplink/v1/parsePlayUrl.js
index f68cd17..f2ead3c 100644
--- a/src/main/resources/parsePlayUrl.js
+++ b/src/main/resources/deeplink/v1/parsePlayUrl.js
@@ -3,22 +3,10 @@
var parsePlayUrlVersion = 21;
var parsePlayUrlBuild = "mmf";
-function parsePlayUrl(urlString) {
- var url = urlString;
- try {
- url = new URL(urlString);
- }
- catch(error) {
- console.log("Can't read URL: " + error);
- return null;
- }
-
- var queryParams = {};
- for (var queryItem of url.searchParams) {
- queryParams[queryItem[0]] = queryItem[1];
- }
-
- return parseForPlayApp(url.protocol.replace(':', ''), url.hostname, url.pathname, queryParams, url.hash.replace('#', ''));
+if(! console) {
+ var console = {
+ log:function(){}
+ }
}
function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
diff --git a/src/main/resources/deeplink/v2/parsePlayUrl.js b/src/main/resources/deeplink/v2/parsePlayUrl.js
new file mode 100644
index 0000000..35e0fe1
--- /dev/null
+++ b/src/main/resources/deeplink/v2/parsePlayUrl.js
@@ -0,0 +1,833 @@
+// parsePlayUrl
+
+var parsePlayUrlVersion = 21;
+var parsePlayUrlBuild = "mmf";
+
+if(! console) {
+ var console = {
+ log:function(){}
+ }
+}
+
+function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
+ // fix path issue
+ pathname = pathname.replace("//", "/");
+
+ // Get BU
+ var bu = getBuFromHostname(hostname,pathname);
+ if (! bu) {
+ console.log("This URL is not a Play SRG URL.");
+ return null;
+ }
+
+ // Get server
+ var server = serverForUrl(hostname, pathname, queryParams);
+
+ /**
+ * Catch special case: Player web
+ *
+ * Ex: https://tp.srgssr.ch/p/rts/default?urn=urn:rts:video:6735513
+ * Ex: https://player.rts.ch/p/rts/default?urn=urn:rts:video:6735513&start=60
+ */
+ if (bu == "tp") {
+ if (pathname.startsWith("/p/")) {
+ var mediaURN = queryParams["urn"];
+ if (mediaURN) {
+ var redirectBu = "tp";
+ switch (true) {
+ case pathname.startsWith("/p/srf/"):
+ redirectBu = "srf";
+ break;
+ case pathname.startsWith("/p/rts/"):
+ redirectBu = "rts";
+ break;
+ case pathname.startsWith("/p/rsi/"):
+ redirectBu = "rsi";
+ break;
+ case pathname.startsWith("/p/rtr/"):
+ redirectBu = "rtr";
+ break;
+ case pathname.startsWith("/p/swi/"):
+ redirectBu = "swi";
+ break;
+ }
+ var startTime = queryParams["start"];
+ return openMediaURN(server, redirectBu, mediaURN, startTime);
+ }
+ }
+ }
+
+ /**
+ * Catch special case: radio swiss
+ *
+ * Ex: http://www.radioswisspop.ch/de/webplayer
+ * Ex: http://www.radioswissclassic.ch/fr/webplayer
+ * Ex: http://www.radioswissjazz.ch/it/webplayer
+ */
+ if (bu == "radioswiss") {
+ var redirectBu = null;
+ switch (true) {
+ case pathname.startsWith("/de"):
+ redirectBu = "srf";
+ break;
+ case pathname.startsWith("/fr"):
+ redirectBu = "rts";
+ break;
+ case pathname.startsWith("/it"):
+ redirectBu = "rsi";
+ break;
+ }
+ if (redirectBu) {
+ return openURL(server, redirectBu, scheme, hostname, pathname, queryParams, anchor);
+ }
+ }
+
+ /**
+ * Catch special case: Play MMF
+ *
+ * Ex: https://play-mmf.herokuapp.com/mmf/
+ * Ex: https://play-mmf.herokuapp.com/mmf/media/urn:rts:video:_rts_info_delay
+ */
+ if (bu == "mmf") {
+ if (pathname.includes("/media/")) {
+ var lastPathComponent = pathname.split("/").slice(-1)[0];
+ return openMediaURN(server, bu, lastPathComponent, null);
+ }
+
+ // Returns default TV homepage
+ return openTvHomePage(server,bu);
+ }
+
+ if (hostname.includes("play-mmf") && ! pathname.startsWith("/mmf/")) {
+ pathname = pathname.substring(4);
+ }
+
+ /**
+ * Catch special case: shared RTS media urls built by RTS MAM.
+ *
+ * Ex: https://www.rts.ch/video
+ * Ex: https://www.rts.ch/video/emissions/signes/9901229-la-route-de-lexil-en-langue-des-signes.html
+ * Ex: https://www.rts.ch/audio/la-1ere
+ */
+ if (bu == "rts" && (pathname.startsWith("/video") || pathname.startsWith("/audio"))) {
+ var mediaId = null;
+
+ if (pathname.endsWith(".html")) {
+ var lastPath = pathname.substr(pathname.lastIndexOf('/') + 1);
+ mediaId = lastPath.split('.')[0].split('-')[0];
+ }
+
+ if (mediaId) {
+ var mediaType = (pathname.startsWith("/video")) ? "video" : "audio";
+ return openMedia(server, bu, mediaType, mediaId, null);
+ }
+ else if (pathname.startsWith("/video")) {
+ // Returns default TV homepage
+ return openTvHomePage(server,bu);
+ }
+ else {
+ var channelId = null;
+ var paths = pathname.split('/');
+ if (paths.length > 2) {
+ var radioId = paths[2];
+ switch (radioId) {
+ case "la-1ere":
+ channelId = "a9e7621504c6959e35c3ecbe7f6bed0446cdf8da";
+ break;
+ case "espace-2":
+ channelId = "a83f29dee7a5d0d3f9fccdb9c92161b1afb512db";
+ break;
+ case "couleur3":
+ channelId = "8ceb28d9b3f1dd876d1df1780f908578cbefc3d7";
+ break;
+ case "option-musique":
+ channelId = "f8517e5319a515e013551eea15aa114fa5cfbc3a";
+ break;
+ }
+ }
+ // Returns default radio homepage
+ return openRadioHomePage(server, bu, channelId);
+ }
+ }
+
+ if (! pathname.startsWith("/play")) {
+ console.log("No /play path in url.");
+ return null;
+ }
+
+ /**
+ * Catch classic media urls
+ *
+ * Ex: https://www.rts.ch/play/tv/faut-pas-croire/video/exportations-darmes--la-suisse-vend-t-elle-la-guerre-ou-la-paix-?id=9938530
+ */
+ var mediaType = null;
+ switch (true) {
+ case pathname.includes("/video/"):
+ mediaType = "video";
+ break;
+ case pathname.includes("/audio/"):
+ mediaType = "audio";
+ break;
+ }
+
+ if (mediaType) {
+ var mediaId = queryParams["id"];
+ if (mediaId) {
+ var startTime = queryParams["startTime"];
+ return openMedia(server, bu, mediaType, mediaId, startTime);
+ }
+ else {
+ mediaType = null;
+ }
+ }
+
+ /**
+ * Catch redirect media urls
+ *
+ * Ex: https://www.rts.ch/play/tv/redirect/detail/9938530
+ */
+ switch (true) {
+ case pathname.includes("/tv/redirect/detail/"):
+ mediaType = "video";
+ break;
+ case pathname.includes("/radio/redirect/detail/"):
+ mediaType = "audio";
+ break;
+ }
+
+ if (mediaType) {
+ var mediaId = pathname.substr(pathname.lastIndexOf('/') + 1);
+ if (mediaId) {
+ var startTime = queryParams["startTime"];
+ return openMedia(server, bu, mediaType, mediaId, startTime);
+ }
+ else {
+ mediaType = null;
+ }
+ }
+
+ /**
+ * Catch live TV urls
+ *
+ * Ex: https://www.srf.ch/play/tv/live?tvLiveId=c49c1d73-2f70-0001-138a-15e0c4ccd3d0
+ */
+ if (pathname.endsWith("/tv/live") || pathname.endsWith("/tv/direct")) {
+ var mediaId = queryParams["tvLiveId"];
+ if (mediaId) {
+ return openMedia(server, bu, "video", mediaId, null);
+ }
+ else {
+ // Returns default TV homepage
+ return openTvHomePage(server,bu);
+ }
+ }
+
+ /**
+ * Catch live radio urls
+ *
+ * Ex: https://www.rsi.ch/play/radio/livepopup/rete-uno
+ */
+ if (pathname.includes("/radio/livepopup/")) {
+ var mediaBu = null;
+ var mediaId = null;
+ switch (pathname.substr(pathname.lastIndexOf('/') + 1)) {
+ case "radio-srf-1":
+ mediaBu = "srf";
+ mediaId = "69e8ac16-4327-4af4-b873-fd5cd6e895a7";
+ break;
+ case "radio-srf-2-kultur":
+ mediaBu = "srf";
+ mediaId = "c8537421-c9c5-4461-9c9c-c15816458b46";
+ break;
+ case "radio-srf-3":
+ mediaBu = "srf";
+ mediaId = "dd0fa1ba-4ff6-4e1a-ab74-d7e49057d96f";
+ break;
+ case "radio-srf-4-news":
+ mediaBu = "srf";
+ mediaId = "ee1fb348-2b6a-4958-9aac-ec6c87e190da";
+ break;
+ case "radio-srf-musikwelle":
+ mediaBu = "srf";
+ mediaId = "a9c5c070-8899-46c7-ac27-f04f1be902fd";
+ break;
+ case "radio-srf-virus":
+ mediaBu = "srf";
+ mediaId = "66815fe2-9008-4853-80a5-f9caaffdf3a9";
+ break;
+ case "la-1ere":
+ mediaBu = "rts";
+ mediaId = "3262320";
+ break;
+ case "espace-2":
+ mediaBu = "rts";
+ mediaId = "3262362";
+ break;
+ case "couleur-3":
+ mediaBu = "rts";
+ mediaId = "3262363";
+ break;
+ case "option-musique":
+ mediaBu = "rts";
+ mediaId = "3262364";
+ break;
+ case "rete-uno":
+ mediaBu = "rsi";
+ mediaId = "livestream_ReteUno";
+ break;
+ case "rete-due":
+ mediaBu = "rsi";
+ mediaId = "livestream_ReteDue";
+ break;
+ case "rete-tre":
+ mediaBu = "rsi";
+ mediaId = "livestream_ReteTre";
+ break;
+ case "rtr":
+ mediaBu = "rtr";
+ mediaId = "a029e818-77a5-4c2e-ad70-d573bb865e31";
+ break;
+ }
+
+ if (mediaBu && mediaId) {
+ return openMedia(server, mediaBu, "audio", mediaId, null);
+ }
+ else {
+ // Returns default radio homepage
+ return openRadioHomePage(server, bu, null);
+ }
+ }
+
+ /**
+ * Catch live tv popup urls
+ *
+ * Ex: https://www.srf.ch/play/tv/popupvideoplayer?id=b833a5af-63c6-4310-bb80-05341310a4f5
+ */
+ if (pathname.includes("/tv/popupvideoplayer")) {
+ var mediaId = queryParams["id"];
+ if (mediaId) {
+ return openMedia(server, bu, "video", mediaId, null);
+ }
+ else {
+ // Returns default TV homepage
+ return openTvHomePage(server,bu);
+ }
+ }
+
+ /**
+ * Catch classic show urls
+ *
+ * Ex: https://www.rts.ch/play/tv/emission/faut-pas-croire?id=6176
+ */
+ var showTransmission = null;
+ switch (true) {
+ case pathname.includes("/tv/sendung") || pathname.includes("/tv/emission") || pathname.includes("/tv/programma") || pathname.includes("/tv/emissiuns"):
+ showTransmission = "tv";
+ break;
+ case pathname.includes("/radio/sendung") || pathname.includes("/radio/emission") || pathname.includes("/radio/programma") || pathname.includes("/radio/emissiuns"):
+ showTransmission = "radio";
+ break;
+ }
+
+ if (showTransmission) {
+ var showId = queryParams["id"];
+ if (showId) {
+ return openShow(server, bu, showTransmission, showId);
+ }
+ else {
+ showTransmission = null;
+ }
+ }
+
+ /**
+ * Catch redirect show urls
+ *
+ * Ex: https://www.rts.ch/play/tv/quicklink/6176
+ */
+ switch (true) {
+ case pathname.includes("/tv/quicklink/"):
+ showTransmission = "tv";
+ break;
+ case pathname.includes("/radio/quicklink/"):
+ showTransmission = "radio";
+ break;
+ }
+
+ if (showTransmission) {
+ var showId = pathname.substr(pathname.lastIndexOf('/') + 1);
+ if (showId) {
+ return openShow(server, bu, showTransmission, showId);
+ }
+ else {
+ showTransmission = null;
+ }
+ }
+
+ /**
+ * Catch home TV urls
+ *
+ * Ex: https://www.srf.ch/play/tv
+ */
+ if (pathname.endsWith("/tv")) {
+ return openTvHomePage(server,bu);
+ }
+
+ /**
+ * Catch home radio urls
+ *
+ * Ex: https://www.srf.ch/play/radio?station=ee1fb348-2b6a-4958-9aac-ec6c87e190da
+ */
+ if (pathname.endsWith("/radio")) {
+ var channelId = queryParams["station"];
+ return openRadioHomePage(server, bu,channelId);
+ }
+
+ /**
+ * Catch AZ TV urls
+ *
+ * Ex: https://www.rts.ch/play/tv/emissions?index=G
+ */
+ if (pathname.endsWith("/tv/sendungen") || pathname.endsWith("/tv/emissions") || pathname.endsWith("/tv/programmi") || pathname.endsWith("/tv/emissiuns")) {
+ var index = queryParams["index"];
+ if (index) {
+ index = index.toLowerCase();
+ index = (index.length > 1) ? null : index;
+ }
+ return openAtoZ(server, bu, null, index);
+ }
+
+ /**
+ * Catch AZ radio urls
+ *
+ * Ex: https://www.rts.ch/play/radio/emissions?index=S&station=8ceb28d9b3f1dd876d1df1780f908578cbefc3d7
+ */
+ if (pathname.endsWith("/radio/sendungen") || pathname.endsWith("/radio/emissions") || pathname.endsWith("/radio/programmi") || pathname.endsWith("/radio/emissiuns")) {
+ var channelId = queryParams["station"];
+ var index = queryParams["index"];
+ if (index) {
+ index = index.toLowerCase();
+ index = (index.length > 1) ? null : index;
+ }
+ return openRadioAtoZ(server, bu, channelId, index);
+ }
+
+ /**
+ * Catch by date TV urls
+ *
+ * Ex: https://www.rtr.ch/play/tv/emissiuns-tenor-data?date=07-03-2019
+ */
+ if (pathname.endsWith("/tv/sendungen-nach-datum") || pathname.endsWith("/tv/emissions-par-dates") || pathname.endsWith("/tv/programmi-per-data") || pathname.endsWith("/tv/emissiuns-tenor-data")) {
+ var date = queryParams["date"];
+ if (date) {
+ // Returns an ISO format
+ var dateArray = date.split("-");
+ if (dateArray.length == 3 && dateArray[2].length == 4 && dateArray[1].length == 2 && dateArray[0].length == 2) {
+ date = dateArray[2] + "-" + dateArray[1] + "-" + dateArray[0];
+ }
+ else {
+ date = null;
+ }
+ }
+ return openByDate(server, bu, null, date);
+ }
+
+ /**
+ * Catch by date radio urls
+ *
+ * Ex: https://www.rts.ch/play/radio/emissions-par-dates?date=07-03-2019&station=8ceb28d9b3f1dd876d1df1780f908578cbefc3d7
+ */
+ if (pathname.endsWith("/radio/sendungen-nach-datum") || pathname.endsWith("/radio/emissions-par-dates") || pathname.endsWith("/radio/programmi-per-data") || pathname.endsWith("/radio/emissiuns-tenor-data")) {
+ var channelId = queryParams["station"];
+ var date = queryParams["date"];
+ if (date) {
+ // Returns an ISO format
+ var dateArray = date.split("-");
+ if (dateArray.length == 3 && dateArray[2].length == 4 && dateArray[1].length == 2 && dateArray[0].length == 2) {
+ date = dateArray[2] + "-" + dateArray[1] + "-" + dateArray[0];
+ }
+ else {
+ date = null;
+ }
+ }
+ return openRadioByDate(server, bu, channelId, date);
+ }
+
+ /**
+ * Catch search urls
+ *
+ * Ex: https://www.rsi.ch/play/ricerca?query=federer%20finale
+ * Ex: https://www.rtr.ch/play/retschertga?query=Federer%20tennis&mediaType=video
+ */
+ if (pathname.endsWith("/suche") || pathname.endsWith("/recherche") || pathname.endsWith("/ricerca") || pathname.endsWith("/retschertga") || pathname.endsWith("/search")) {
+ var query = queryParams["query"];
+ var mediaType = queryParams["mediaType"];
+ if (mediaType) {
+ mediaType = mediaType.toLowerCase();
+ if (mediaType != "video" && mediaType != "audio") {
+ mediaType = null;
+ }
+ }
+ return openSearch(server, bu, query, mediaType);
+ }
+
+ /**
+ * Catch TV topics urls
+ *
+ * Ex: https://www.rts.ch/play/tv/categories/info
+ */
+ if (pathname.endsWith("/tv/themen") || pathname.endsWith("/tv/categories") || pathname.endsWith("/tv/categorie") || pathname.endsWith("/tv/tematicas") || pathname.endsWith("/tv/topics")) {
+ return openTvHomePage(server,bu);
+ }
+ else if (pathname.includes("/tv/themen") || pathname.includes("/tv/categories") || pathname.includes("/tv/categorie") || pathname.includes("/tv/tematicas") || pathname.includes("/tv/topics")) {
+ var lastPathComponent = pathname.split("/").slice(-1)[0];
+
+ var topicId = null;
+
+ /* INJECT TVTOPICS OBJECT */
+
+ if (typeof tvTopics !== 'undefined' && lastPathComponent.length > 0) {
+ topicId = tvTopics[server][bu][lastPathComponent];
+ }
+
+ if (topicId) {
+ return openTopic(server, bu, "tv", topicId);
+ }
+ else {
+ return openTvHomePage(server,bu);
+ }
+ }
+
+ /**
+ * Catch TV event urls
+ *
+ * Ex: https://www.srf.ch/play/tv/event/10-jahre-auf-und-davon
+ *. Ex: https://www.rsi.ch/play/tv/event/event-playrsi-8858482
+ */
+ if (pathname.endsWith("/tv/event")) {
+ return openTvHomePage(server,bu);
+ }
+ else if (pathname.includes("/tv/event")) {
+ var lastPathComponent = pathname.split("/").slice(-1)[0];
+
+ var eventId = null;
+
+ /* INJECT TVEVENTS OBJECT */
+
+ if (typeof tvEvents !== 'undefined' && lastPathComponent.length > 0) {
+ eventId = tvEvents[server][bu][lastPathComponent];
+ }
+
+ if (eventId) {
+ return openModule(server, bu, "event", eventId);
+ }
+ else {
+ return openTvHomePage(server,bu);
+ }
+ }
+
+ /**
+ * Catch base play urls
+ *
+ * Ex: https://www.srf.ch/play/
+ *. Ex: https://www.rsi.ch/play
+ */
+ if (pathname.endsWith("/play/") || pathname.endsWith("/play")) {
+ return openTvHomePage(server,bu);
+ }
+
+ /**
+ * Catch play help urls
+ *
+ * Ex: https://www.srf.ch/play/tv/hilfe
+ * Ex: https://www.rts.ch/play/tv/aide
+ * Ex: https://www.rsi.ch/play/tv/guida
+ * Ex: https://www.rtr.ch/play/tv/agid
+ * Ex: https://play.swissinfo.ch/play/tv/help
+ */
+ if (pathname.endsWith("/hilfe") || pathname.endsWith("/aide") || pathname.endsWith("/guida") || pathname.endsWith("/agid") || pathname.endsWith("/help")) {
+ return openURL(server, bu, scheme, hostname, pathname, queryParams, anchor);
+ }
+
+ // Redirect fallback.
+ console.log("Can't parse Play URL. Unsupported URL.");
+ return schemeForBu(bu) + "://unsupported?server=" + server;
+};
+
+// ---- Open functions
+
+function openMedia(server, bu, mediaType, mediaId, startTime) {
+ var urn="urn:" + bu + ":" + mediaType + ":" + mediaId;
+ return openMediaURN(server,bu,urn,startTime);
+}
+
+function openMediaURN(server, bu, mediaURN, startTime) {
+ var options = {};
+ if (startTime) {
+ options['start_time'] = startTime;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"media",mediaURN,options);
+}
+
+function openShow(server, bu, showTransmission, showId) {
+ var showUrn="urn:" + bu + ":show:" + showTransmission + ":" + showId;
+ var options = {};
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"show",showUrn,options);
+}
+
+function openTopic(server, bu, topicTransmission, topicId) {
+ var topicUrn="urn:" + bu + ":topic:" + topicTransmission + ":" + topicId;
+ var options = {};
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"topic",topicUrn,options);
+}
+
+function openModule(server, bu, moduleType, moduleId) {
+ var topicUrn="urn:" + bu + ":module:" + moduleType + ":" + moduleId;
+ var options = {};
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"module",topicUrn,options);
+}
+
+function openTvHomePage(server,bu){
+ var options = {};
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"home",null,options);
+}
+
+function openRadioHomePage(server,bu,channelId){
+ if (!channelId) {
+ channelId = primaryChannelUidForBu(bu);
+ }
+ var options={};
+ if(channelId){
+ options["channel_id"] = channelId;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"home",null,options);
+}
+
+function openAtoZ(server,bu,channelId,index){
+ var options = {};
+ if(channelId) {
+ options['channel_id'] = channelId;
+ }
+ if(index) {
+ options['index'] = index;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"az",null,options);
+}
+
+function openRadioAtoZ(server,bu,channelId,index){
+ if (!channelId) {
+ channelId = primaryChannelUidForBu(bu);
+ }
+ return openAtoZ(server,bu,channelId,index);
+}
+
+function openByDate(server,bu,channelId,date){
+ var options = {};
+ if(channelId) {
+ options['channel_id'] = channelId;
+ }
+
+ if(date) {
+ options['date'] = date;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu, "bydate", null, options);
+}
+
+function openRadioByDate(server,bu,channelId,date) {
+ if (!channelId) {
+ channelId = primaryChannelUidForBu(bu);
+ }
+ return openByDate(server,bu,channelId,date);
+}
+
+function openSearch(server, bu, query, mediaType){
+ var options = {};
+ if(query) {
+ options['query'] = query;
+ }
+ if(mediaType) {
+ options['media_type'] = mediaType;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"search", null, options);
+}
+
+function openURL(server, bu, scheme, hostname, pathname, queryParams, anchor) {
+ if (! scheme) {
+ scheme = "http";
+ }
+
+ var queryParamsString = "";
+ if (queryParams) {
+ for (var key in queryParams) {
+ queryParamsString = queryParamsString + "&" + key + "=" + encodeURIComponent(queryParams[key]);
+ }
+ }
+ if (queryParamsString.length > 0) {
+ queryParamsString = queryParamsString.replace('&','?');
+ }
+
+ var anchorString = "";
+ if (anchor) {
+ anchorString = "#" + anchor;
+ }
+
+ var url = scheme + "://" + hostname + pathname + queryParamsString + anchorString;
+ var options = {};
+ options['url'] = url;
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"link",null,options)
+}
+
+// --- parsing functions
+
+function primaryChannelUidForBu(bu) {
+ switch (bu) {
+ case "srf":
+ return "69e8ac16-4327-4af4-b873-fd5cd6e895a7";
+ break;
+ case "rts":
+ return "a9e7621504c6959e35c3ecbe7f6bed0446cdf8da";
+ break;
+ case "rsi":
+ return "rete-uno";
+ break;
+ case "rtr":
+ return "12fb886e-b7aa-4e55-beb2-45dbc619f3c4";
+ break;
+ default:
+ return null;
+ }
+}
+
+function schemeForBu(bu) {
+ switch (bu) {
+ case "srf":
+ return "playsrf";
+ break;
+ case "rts":
+ return "playrts";
+ break;
+ case "rsi":
+ return "playrsi";
+ break;
+ case "rtr":
+ return "playrtr";
+ break;
+ case "swi":
+ return "playswi";
+ break;
+ case "mmf":
+ case "tp":
+ return "letterbox";
+ break;
+ default:
+ return null;
+ }
+}
+
+function serverForUrl(hostname, pathname, queryParams) {
+ var server = "production";
+ if (hostname.includes("stage")) {
+ server = "stage";
+ }
+ else if (hostname.includes("test")) {
+ server = "test";
+ }
+ else if (hostname.includes("play-mmf")) {
+ if (pathname.startsWith("/mmf/")) {
+ server = "play mmf";
+ }
+ else {
+ var serverParam = queryParams["server"];
+ switch (serverParam) {
+ case "stage":
+ server = "stage";
+ break;
+ case "test":
+ server = "test";
+ break;
+ }
+ }
+ }
+ return server;
+}
+
+function getBuFromHostname(hostname, pathname) {
+ switch (true) {
+ case hostname.endsWith("tp.srgssr.ch") || hostname.endsWith("player.rts.ch") || hostname.endsWith("player.rsi.ch") || hostname.endsWith("player.rtr.ch") || hostname.endsWith("player.swissinfo.ch") || hostname.endsWith("player.srf.ch"):
+ return "tp";
+ case hostname.includes("rts.ch") || hostname.includes("srgplayer-rts") || (hostname.includes("play-mmf") && pathname.startsWith("/rts/")):
+ return "rts";
+ case hostname.includes("rsi.ch") || hostname.includes("srgplayer-rsi") || (hostname.includes("play-mmf") && pathname.startsWith("/rsi/")):
+ return "rsi";
+ case hostname.includes("rtr.ch") || hostname.includes("srgplayer-rtr") || (hostname.includes("play-mmf") && pathname.startsWith("/rtr/")):
+ return "rtr";
+ case hostname.includes("swissinfo.ch") || hostname.includes("srgplayer-swi") || (hostname.includes("play-mmf") && pathname.startsWith("/swi/")):
+ return "swi";
+ case hostname.includes("srf.ch") || hostname.includes("srgplayer-srf") || (hostname.includes("play-mmf") && pathname.startsWith("/srf/")):
+ return "srf";
+ case hostname.includes("play-mmf") && pathname.startsWith("/mmf/"):
+ return "mmf";
+ case hostname.includes("radioswisspop.ch") || hostname.includes("radioswissclassic.ch") || hostname.includes("radioswissjazz.ch"):
+ return "radioswiss";
+ }
+ return null;
+ }
+
+/**
+* Build scheme://host[/path][?queryParams[0]&...&queryParams[n-1]]
+* Sample:
+* playrts://media/urn:xxx?position=0&server=mmf
+*/
+function buildUri(scheme, host, path, queryParams) {
+ var uri = scheme + "://" + host;
+ if (path) {
+ uri = uri + "/" + path;
+ }
+ if (queryParams && queryParams !== {}) {
+ uri = uri + "?";
+ var optionIndex = 0;
+ for (var option in queryParams) {
+ if(queryParams[option]) {
+ if(optionIndex > 0) {
+ uri = uri + "&";
+ }
+ uri = uri + option + "=" + encodeURIComponent(queryParams[option]);
+ optionIndex++;
+ }
+ }
+ }
+ return uri;
+}
+
+function buildBuUri(bu, host, path, queryParams) {
+ return buildUri(schemeForBu(bu), host, path, queryParams);
+}
diff --git a/src/test/java/ch/srgssr/playfff/controller/DeepLinkIntegrationTest.java b/src/test/java/ch/srgssr/playfff/controller/DeepLinkIntegrationTest.java
index f69385d..e45014e 100644
--- a/src/test/java/ch/srgssr/playfff/controller/DeepLinkIntegrationTest.java
+++ b/src/test/java/ch/srgssr/playfff/controller/DeepLinkIntegrationTest.java
@@ -55,7 +55,7 @@ public void tearDown() {
}
@Test
- public void getParsePlayUrl() throws Exception {
+ public void getParsePlayUrlV1() throws Exception {
MvcResult mvcResult = mvc.perform(get("/api/v1/deeplink/parsePlayUrl.js"))
.andExpect(status().isOk())
.andExpect(header().string("ETag", IsNull.notNullValue()))
@@ -67,6 +67,19 @@ public void getParsePlayUrl() throws Exception {
.andExpect(content().string(""));
}
+ @Test
+ public void getParsePlayUrlV2() throws Exception {
+ MvcResult mvcResult = mvc.perform(get("/api/v2/deeplink/parsePlayUrl.js"))
+ .andExpect(status().isOk())
+ .andExpect(header().string("ETag", IsNull.notNullValue()))
+ .andExpect(content().string(IsNull.notNullValue())).andReturn();
+ String eTag = mvcResult.getResponse().getHeader("ETag");
+
+ mvc.perform(get("/api/v2/deeplink/parsePlayUrl.js").header("If-None-Match", eTag))
+ .andExpect(status().isNotModified())
+ .andExpect(content().string(""));
+ }
+
@Test
public void reportNotAcceptable() throws Exception {
mvc.perform(post("/api/v1/deeplink/report")).andExpect(status().isBadRequest());
diff --git a/src/test/java/ch/srgssr/playfff/controller/DeepLinkServiceTests.java b/src/test/java/ch/srgssr/playfff/controller/DeepLinkServiceTests.java
index c105cf9..bb3fd5f 100644
--- a/src/test/java/ch/srgssr/playfff/controller/DeepLinkServiceTests.java
+++ b/src/test/java/ch/srgssr/playfff/controller/DeepLinkServiceTests.java
@@ -20,19 +20,29 @@ public class DeepLinkServiceTests {
public void getParsePlayUrlContentTest() {
DeepLinkJSContent deepLinkJSContent = deepLinkService.getParsePlayUrlJSContent();
- Assert.assertNotNull(deepLinkJSContent.getContent());
- Assert.assertNotNull(deepLinkJSContent.getHash());
- Assert.assertTrue(deepLinkJSContent.getContent().contains(deepLinkJSContent.getHash()));
+ Assert.assertNotNull(deepLinkJSContent.getContentV1());
+ Assert.assertNotNull(deepLinkJSContent.getHashV1());
+ Assert.assertTrue(deepLinkJSContent.getContentV1().contains(deepLinkJSContent.getHashV1()));
+
+ Assert.assertNotNull(deepLinkJSContent.getContentV2());
+ Assert.assertNotNull(deepLinkJSContent.getHashV2());
+ Assert.assertTrue(deepLinkJSContent.getContentV2().contains(deepLinkJSContent.getHashV2()));
}
@Test
public void refreshParsePlayUrlContentTest() {
DeepLinkJSContent deepLinkJSContent = deepLinkService.refreshParsePlayUrlJSContent();
- Assert.assertNotNull(deepLinkJSContent.getContent());
- Assert.assertNotNull(deepLinkJSContent.getHash());
- Assert.assertTrue(deepLinkJSContent.getContent().contains(deepLinkJSContent.getHash()));
- Assert.assertFalse(deepLinkJSContent.getContent().contains("INJECT TVTOPICS OBJECT"));
- Assert.assertFalse(deepLinkJSContent.getContent().contains("INJECT TVEVENTS OBJECT"));
+ Assert.assertNotNull(deepLinkJSContent.getContentV1());
+ Assert.assertNotNull(deepLinkJSContent.getHashV1());
+ Assert.assertTrue(deepLinkJSContent.getContentV1().contains(deepLinkJSContent.getHashV1()));
+ Assert.assertFalse(deepLinkJSContent.getContentV1().contains("INJECT TVTOPICS OBJECT"));
+ Assert.assertFalse(deepLinkJSContent.getContentV1().contains("INJECT TVEVENTS OBJECT"));
+
+ Assert.assertNotNull(deepLinkJSContent.getContentV2());
+ Assert.assertNotNull(deepLinkJSContent.getHashV2());
+ Assert.assertTrue(deepLinkJSContent.getContentV2().contains(deepLinkJSContent.getHashV2()));
+ Assert.assertFalse(deepLinkJSContent.getContentV2().contains("INJECT TVTOPICS OBJECT"));
+ Assert.assertFalse(deepLinkJSContent.getContentV2().contains("INJECT TVEVENTS OBJECT"));
}
}