diff --git a/apps/demo/index.html b/apps/demo/index.html index 672ad68..ece8239 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..aba2a23 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -189,7 +189,19 @@ 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://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/index.ts b/packages/core/src/index.ts index 813f4b4..5e38402 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,45 +1,9 @@ -import { - linkedinHandler, - youtubeHandler, - instagramHandler, - spotifyHandler, - substackHandler, - threadsHandler, - whatsappHandler, - facebookHandler, - redditHandler, - discordHandler, - githubHandler, - pinterestHandler, - twitchHandler, - snapchatHandler, - telegramHandler, - unknownHandler, - zoomHandler, -} 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, - substackHandler, - threadsHandler, - whatsappHandler, - snapchatHandler, - facebookHandler, - redditHandler, - discordHandler, - githubHandler, - pinterestHandler, - twitchHandler, - telegramHandler, - zoomHandler, -]; 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 af9e16e..ce80fa9 100644 --- a/packages/core/src/platforms/index.ts +++ b/packages/core/src/platforms/index.ts @@ -1,14 +1,16 @@ +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'; 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'; @@ -17,21 +19,42 @@ import { youtubeHandler } from './youtube'; import { zoomHandler } from './zoom'; export { - linkedinHandler, - youtubeHandler, + discordHandler, + facebookHandler, + githubHandler, instagramHandler, + jioHotstarHandler, + linkedinHandler, + pinterestHandler, + redditHandler, + snapchatHandler, spotifyHandler, substackHandler, + telegramHandler, threadsHandler, + twitchHandler, + unknownHandler, whatsappHandler, - facebookHandler, - redditHandler, + youtubeHandler, + zoomHandler +}; + +export const handlers: DeepLinkHandler[] = [ discordHandler, + facebookHandler, githubHandler, + instagramHandler, + jioHotstarHandler, + linkedinHandler, pinterestHandler, + redditHandler, snapchatHandler, + spotifyHandler, + substackHandler, telegramHandler, + threadsHandler, twitchHandler, - unknownHandler, + whatsappHandler, + youtubeHandler, zoomHandler, -}; +]; diff --git a/packages/core/src/platforms/jioHotstar.ts b/packages/core/src/platforms/jioHotstar.ts new file mode 100644 index 0000000..76872c0 --- /dev/null +++ b/packages/core/src/platforms/jioHotstar.ts @@ -0,0 +1,55 @@ +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} +// - 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]> = [ + [ + '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) => { + 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]; + 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 cea4ac6..a4999d5 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -13,6 +13,7 @@ export type Platform = | 'twitch' | 'snapchat' | 'telegram' + | 'jiohotstar' | 'zoom' | 'substack' | 'unknown'; 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\./, '');