From 0fa2d74d694eccf7b7776bad5e75ae4103f5f872 Mon Sep 17 00:00:00 2001 From: Kishan Dev Date: Wed, 7 Jan 2026 19:53:08 +0530 Subject: [PATCH 1/5] feat: add deep link support for Jio Hotstar platforms including new types, utilities, and demo examples. --- apps/demo/index.html | 9 ++++++ apps/demo/public/icons/jioHotstar.svg | 30 +++++++++++++++++++ packages/core/README.md | 10 ++++++- packages/core/src/index.ts | 34 +--------------------- packages/core/src/platforms/index.ts | 35 ++++++++++++++++++----- packages/core/src/platforms/jioHotstar.ts | 30 +++++++++++++++++++ packages/core/src/platforms/twitch.ts | 6 ++-- packages/core/src/types.ts | 1 + packages/core/src/utils.ts | 3 ++ 9 files changed, 113 insertions(+), 45 deletions(-) create mode 100644 apps/demo/public/icons/jioHotstar.svg create mode 100644 packages/core/src/platforms/jioHotstar.ts diff --git a/apps/demo/index.html b/apps/demo/index.html index 672ad68..1b329d6 100644 --- a/apps/demo/index.html +++ b/apps/demo/index.html @@ -101,6 +101,15 @@

Try Example Links

Twitch Twitch Valorant + + Jio Hotstar + Jio Hotstar + diff --git a/apps/demo/public/icons/jioHotstar.svg b/apps/demo/public/icons/jioHotstar.svg new file mode 100644 index 0000000..6274937 --- /dev/null +++ b/apps/demo/public/icons/jioHotstar.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/core/README.md b/packages/core/README.md index c66e1a5..9dc526d 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -189,7 +189,15 @@ const result = generateDeepLink( 'https://www.twitch.tv/directory/tags/80427d95-bb46-42d3-bf4d-408e9bdca49a', ); // result.ios: 'twitch://directory/tags/80427d95-bb46-42d3-bf4d-408e9bdca49a' -// result.android: 'intent://twitch.tv/directory/tags/80427d95-bb46-42d3-bf4d-408e9bdca49a#Intent;scheme=https;package=tv.twitch.android.app;S.browser_fallback_url=https://twitch.tv/login;end' +// result.android: 'intent://twitch.tv/directory/tags/80427d95-bb46-42d3-bf4d-408e9bdca49a#Intent;scheme=https;package=tv.twitch.android.app;end' +``` + +### Jio Hotstar + +```typescript +const result = generateDeepLink('https://www.hotstar.com/in/movies/sholay/1271513578/watch'); +// result.ios: 'hotstar://1271513578' +// result.android: 'intent://1271513578#Intent;scheme=hotstar;package=in.startv.hotstar;end' ``` ### Unknown URL diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index f798dae..5e38402 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,41 +1,9 @@ -import { - linkedinHandler, - youtubeHandler, - instagramHandler, - spotifyHandler, - threadsHandler, - whatsappHandler, - facebookHandler, - redditHandler, - discordHandler, - githubHandler, - pinterestHandler, - twitchHandler, - snapchatHandler, - telegramHandler, - unknownHandler, -} from './platforms'; +import { handlers, unknownHandler } from './platforms'; import { DeepLinkResult } from './types'; import { normalizeUrl } from './utils/normalizeUrl'; export * from './types'; -const handlers = [ - linkedinHandler, - youtubeHandler, - instagramHandler, - spotifyHandler, - threadsHandler, - whatsappHandler, - snapchatHandler, - facebookHandler, - redditHandler, - discordHandler, - githubHandler, - pinterestHandler, - twitchHandler, - telegramHandler -]; export function generateDeepLink(url: string): DeepLinkResult { const webUrl = normalizeUrl(url); diff --git a/packages/core/src/platforms/index.ts b/packages/core/src/platforms/index.ts index ee76416..d1406bf 100644 --- a/packages/core/src/platforms/index.ts +++ b/packages/core/src/platforms/index.ts @@ -1,7 +1,9 @@ +import { DeepLinkHandler } from '../types'; import { discordHandler } from './discord'; import { facebookHandler } from './facebook'; import { githubHandler } from './github'; import { instagramHandler } from './instagram'; +import { jioHotstarHandler } from './jioHotstar'; import { linkedinHandler } from './linkedin'; import { pinterestHandler } from './pinterest'; import { redditHandler } from './reddit'; @@ -15,19 +17,38 @@ import { snapchatHandler } from './snapchat'; import { telegramHandler } from "./telegram"; export { - linkedinHandler, - youtubeHandler, + discordHandler, + facebookHandler, + githubHandler, instagramHandler, + jioHotstarHandler, + linkedinHandler, + pinterestHandler, + redditHandler, + snapchatHandler, spotifyHandler, + telegramHandler, threadsHandler, + twitchHandler, whatsappHandler, - facebookHandler, - redditHandler, + youtubeHandler, + unknownHandler +}; + +export const handlers: DeepLinkHandler[] = [ discordHandler, + facebookHandler, githubHandler, + instagramHandler, + jioHotstarHandler, + linkedinHandler, pinterestHandler, - twitchHandler, + redditHandler, snapchatHandler, + spotifyHandler, telegramHandler, - unknownHandler, -}; + threadsHandler, + twitchHandler, + whatsappHandler, + youtubeHandler, +]; diff --git a/packages/core/src/platforms/jioHotstar.ts b/packages/core/src/platforms/jioHotstar.ts new file mode 100644 index 0000000..1d7700e --- /dev/null +++ b/packages/core/src/platforms/jioHotstar.ts @@ -0,0 +1,30 @@ +import { DeepLinkHandler } from '../types'; +import { getUrlWithoutProtocol } from '../utils'; + +export const jioHotstarHandler: DeepLinkHandler = { + match: (url) => + getUrlWithoutProtocol(url).match( + /^(?:hotstar\.com|jiohotstar\.com|startv\.hotstar\.com)\/(?:in\/)?(?:shows|movies|live|tv|sport|play)(?:\/[a-zA-Z0-9_-]+)?\/([a-zA-Z0-9_-]+)(?:\/(?:[a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+))?(?:\/watch)?/, + ), + + build: (webUrl, match) => { + const contentId = match[1]; + const videoId = match[2]; + + if (videoId) { + return { + webUrl, + ios: `hotstar://content/${videoId}`, + android: `intent://${videoId}#Intent;scheme=hotstar;package=in.startv.hotstar;end`, + platform: 'jioHotstar', + }; + } + + return { + webUrl, + ios: `hotstar://content/${contentId}`, + android: `intent://${contentId}#Intent;scheme=hotstar;package=in.startv.hotstar;end`, + platform: 'jioHotstar', + }; + }, +}; diff --git a/packages/core/src/platforms/twitch.ts b/packages/core/src/platforms/twitch.ts index 56dc0d8..e12a2fb 100644 --- a/packages/core/src/platforms/twitch.ts +++ b/packages/core/src/platforms/twitch.ts @@ -1,4 +1,5 @@ import { DeepLinkHandler } from '../types'; +import { getUrlWithoutProtocol } from '../utils'; const PATTERNS: Array<[type: string, regex: RegExp]> = [ ['login', /^twitch\.tv\/login\/?$/], @@ -16,9 +17,6 @@ const PATTERNS: Array<[type: string, regex: RegExp]> = [ ], ]; -const getUrlWithoutProtocol = (url: string) => - url.replace(/^https?:\/\//, '').replace(/^www\./, ''); - export const twitchHandler: DeepLinkHandler = { match: (url) => { const urlWithoutProtocol = getUrlWithoutProtocol(url); @@ -49,7 +47,7 @@ export const twitchHandler: DeepLinkHandler = { return { webUrl, ios: iosDeepLink, - android: `intent://${matchUrl}#Intent;scheme=https;package=tv.twitch.android.app;S.browser_fallback_url=${encodeURIComponent(webUrl)};end`, + android: `intent://${matchUrl}#Intent;scheme=https;package=tv.twitch.android.app;end`, platform: 'twitch', }; }, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index a4ece09..8f40204 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -13,6 +13,7 @@ export type Platform = | 'twitch' | 'snapchat' | 'telegram' + | 'jioHotstar' | 'unknown'; export interface DeepLinkResult { diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index b4dcc30..9e6a70a 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -32,3 +32,6 @@ export function parseTimestampToSeconds(timestamp: string): number { return hours * 3600 + minutes * 60 + seconds; } + +export const getUrlWithoutProtocol = (url: string) => + url.replace(/^https?:\/\//, '').replace(/^www\./, ''); From 2c5bab98b8f6a266e810f151e27405e7d05b6aa2 Mon Sep 17 00:00:00 2001 From: Kishan Dev Date: Wed, 7 Jan 2026 22:38:40 +0530 Subject: [PATCH 2/5] fix: resolve merge conflicts with upstream main --- packages/core/src/platforms/index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/core/src/platforms/index.ts b/packages/core/src/platforms/index.ts index 86a6b00..ce80fa9 100644 --- a/packages/core/src/platforms/index.ts +++ b/packages/core/src/platforms/index.ts @@ -9,8 +9,8 @@ import { pinterestHandler } from './pinterest'; import { redditHandler } from './reddit'; import { snapchatHandler } from './snapchat'; import { spotifyHandler } from './spotify'; -import { telegramHandler } from './telegram'; import { substackHandler } from './substack'; +import { telegramHandler } from './telegram'; import { threadsHandler } from './threads'; import { twitchHandler } from './twitch'; import { unknownHandler } from './unknown'; @@ -29,12 +29,14 @@ export { redditHandler, snapchatHandler, spotifyHandler, + substackHandler, telegramHandler, threadsHandler, twitchHandler, + unknownHandler, whatsappHandler, youtubeHandler, - unknownHandler + zoomHandler }; export const handlers: DeepLinkHandler[] = [ @@ -48,9 +50,11 @@ export const handlers: DeepLinkHandler[] = [ redditHandler, snapchatHandler, spotifyHandler, + substackHandler, telegramHandler, threadsHandler, twitchHandler, whatsappHandler, youtubeHandler, + zoomHandler, ]; From 1f9ae35d09fcb12e936bd4fc0ba2e87560fa6d40 Mon Sep 17 00:00:00 2001 From: Kishan Dev Date: Wed, 7 Jan 2026 23:22:24 +0530 Subject: [PATCH 3/5] fix: coderabbit's suggestions --- apps/demo/index.html | 2 +- packages/core/README.md | 6 +++++- packages/core/src/platforms/jioHotstar.ts | 6 +++--- packages/core/src/types.ts | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/demo/index.html b/apps/demo/index.html index 1b329d6..ece8239 100644 --- a/apps/demo/index.html +++ b/apps/demo/index.html @@ -107,7 +107,7 @@

Try Example Links

data-url="https://www.hotstar.com/in/movies/sholay/1271513578/watch" target="_blank" > - Jio Hotstar + Jio Hotstar Jio Hotstar diff --git a/packages/core/README.md b/packages/core/README.md index 9dc526d..aba2a23 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -196,8 +196,12 @@ const result = generateDeepLink( ```typescript const result = generateDeepLink('https://www.hotstar.com/in/movies/sholay/1271513578/watch'); -// result.ios: 'hotstar://1271513578' +// result.ios: 'hotstar://content/1271513578' // result.android: 'intent://1271513578#Intent;scheme=hotstar;package=in.startv.hotstar;end' + +const result = generateDeepLink('https://www.hotstar.com/in/shows/mrs-deshpande/1271508620/takes-one-to-catch-one/1271513221/watch'); +// result.ios: 'hotstar://content/1271513221' +// result.android: 'intent://1271513221#Intent;scheme=hotstar;package=in.startv.hotstar;end' ``` ### Unknown URL diff --git a/packages/core/src/platforms/jioHotstar.ts b/packages/core/src/platforms/jioHotstar.ts index 1d7700e..7eb5151 100644 --- a/packages/core/src/platforms/jioHotstar.ts +++ b/packages/core/src/platforms/jioHotstar.ts @@ -4,7 +4,7 @@ import { getUrlWithoutProtocol } from '../utils'; export const jioHotstarHandler: DeepLinkHandler = { match: (url) => getUrlWithoutProtocol(url).match( - /^(?:hotstar\.com|jiohotstar\.com|startv\.hotstar\.com)\/(?:in\/)?(?:shows|movies|live|tv|sport|play)(?:\/[a-zA-Z0-9_-]+)?\/([a-zA-Z0-9_-]+)(?:\/(?:[a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+))?(?:\/watch)?/, + /^(?:hotstar\.com|jiohotstar\.com|startv\.hotstar\.com)\/(?:in\/)?(?:shows|movies|live|tv|sport|play)(?:\/[a-zA-Z0-9_-]+)?\/([a-zA-Z0-9_-]+)(?:\/(?:[a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+))?(?:\/watch)?$/, ), build: (webUrl, match) => { @@ -16,7 +16,7 @@ export const jioHotstarHandler: DeepLinkHandler = { webUrl, ios: `hotstar://content/${videoId}`, android: `intent://${videoId}#Intent;scheme=hotstar;package=in.startv.hotstar;end`, - platform: 'jioHotstar', + platform: 'jiohotstar', }; } @@ -24,7 +24,7 @@ export const jioHotstarHandler: DeepLinkHandler = { webUrl, ios: `hotstar://content/${contentId}`, android: `intent://${contentId}#Intent;scheme=hotstar;package=in.startv.hotstar;end`, - platform: 'jioHotstar', + platform: 'jiohotstar', }; }, }; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 2b624ec..a4999d5 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -13,7 +13,7 @@ export type Platform = | 'twitch' | 'snapchat' | 'telegram' - | 'jioHotstar' + | 'jiohotstar' | 'zoom' | 'substack' | 'unknown'; From ba2cc92bd3a47ae20820adae95951a844f80bfe7 Mon Sep 17 00:00:00 2001 From: Kishan Dev Date: Thu, 8 Jan 2026 00:09:10 +0530 Subject: [PATCH 4/5] fix: sports url not working --- packages/core/src/platforms/jioHotstar.ts | 31 ++++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/core/src/platforms/jioHotstar.ts b/packages/core/src/platforms/jioHotstar.ts index 7eb5151..fa2efab 100644 --- a/packages/core/src/platforms/jioHotstar.ts +++ b/packages/core/src/platforms/jioHotstar.ts @@ -1,11 +1,34 @@ import { DeepLinkHandler } from '../types'; import { getUrlWithoutProtocol } from '../utils'; +// Matches Hotstar URLs with patterns like: +// - hotstar.com/in/movies/{movie-name}/{movie-id} +// - hotstar.com/shows/{show-name}/{show-id} +// - hotstar.com/shows/{show-name}/{show-id}/episode/{episode-id} +// - jiohotstar.com/play/{id} +const PATTERNS: Array<[type: string, regex: RegExp]> = [ + [ + 'shows and movies', + /^(?:hotstar|jiohotstar|startv\.hotstar)(?:\.com)\/(?:in\/)?(?:shows|movies)(?:\/[a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)(?:\/(?:[a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+))?(?:\/watch)?$/, + ], + [ + 'sports', + /^(?:hotstar|jiohotstar|startv\.hotstar)(?:\.com)\/(?:in\/)?sports(?:\/[a-zA-Z0-9_-]+)(?:\/[a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)(?:\/video\/live)?(?:\/watch)?$/, + ], + ['play', /^(?:hotstar|jiohotstar|startv\.hotstar)(?:\.com)\/(?:in\/)?play\/([a-zA-Z0-9_-]+)$/], +]; + export const jioHotstarHandler: DeepLinkHandler = { - match: (url) => - getUrlWithoutProtocol(url).match( - /^(?:hotstar\.com|jiohotstar\.com|startv\.hotstar\.com)\/(?:in\/)?(?:shows|movies|live|tv|sport|play)(?:\/[a-zA-Z0-9_-]+)?\/([a-zA-Z0-9_-]+)(?:\/(?:[a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+))?(?:\/watch)?$/, - ), + match: (url) => { + const urlWithoutProtocol = getUrlWithoutProtocol(url); + + for (const [type, pattern] of PATTERNS) { + const match = urlWithoutProtocol.match(pattern); + if (match) return match; + } + + return null; + }, build: (webUrl, match) => { const contentId = match[1]; From 0d8fc8738d6b29f23afb739d754d02cb11932343 Mon Sep 17 00:00:00 2001 From: Kishan Dev Date: Thu, 8 Jan 2026 00:10:51 +0530 Subject: [PATCH 5/5] docs: added links docs --- packages/core/src/platforms/jioHotstar.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/src/platforms/jioHotstar.ts b/packages/core/src/platforms/jioHotstar.ts index fa2efab..76872c0 100644 --- a/packages/core/src/platforms/jioHotstar.ts +++ b/packages/core/src/platforms/jioHotstar.ts @@ -5,6 +5,8 @@ import { getUrlWithoutProtocol } from '../utils'; // - hotstar.com/in/movies/{movie-name}/{movie-id} // - hotstar.com/shows/{show-name}/{show-id} // - hotstar.com/shows/{show-name}/{show-id}/episode/{episode-id} +// - hotstar.com/sports/{sport-name}/{video-name}/{video-id} +// - hotstar.com/sports/{sport-name}/{video-name}/{video-id}/video/live/watch // - jiohotstar.com/play/{id} const PATTERNS: Array<[type: string, regex: RegExp]> = [ [