diff --git a/src/components/common/SafeLink.tsx b/src/components/common/SafeLink.tsx index b3fab3874..dcf587eea 100644 --- a/src/components/common/SafeLink.tsx +++ b/src/components/common/SafeLink.tsx @@ -3,7 +3,7 @@ import { getDispatch } from '../../lib/teact/teactn'; import convertPunycode from '../../lib/punycode'; import { - DEBUG, RE_TG_LINK, RE_TME_ADDSTICKERS_LINK, RE_TME_INVITE_LINK, RE_TME_LINK, + DEBUG, RE_TG_LINK, RE_TME_LINK, } from '../../config'; import buildClassName from '../../util/buildClassName'; @@ -30,8 +30,7 @@ const SafeLink: FC = ({ const handleClick = useCallback((e: React.MouseEvent) => { if ( e.ctrlKey || e.altKey || e.shiftKey || e.metaKey - || !url || (!url.match(RE_TME_LINK) && !url.match(RE_TME_INVITE_LINK) && !url.match(RE_TG_LINK) - && !url.match(RE_TME_ADDSTICKERS_LINK)) + || !url || (!url.match(RE_TME_LINK) && !url.match(RE_TG_LINK)) ) { if (isNotSafe) { toggleSafeLinkModal({ url }); diff --git a/src/config.ts b/src/config.ts index 08c916895..19e9ad138 100644 --- a/src/config.ts +++ b/src/config.ts @@ -140,10 +140,7 @@ export const CONTENT_TYPES_WITH_PREVIEW = new Set([ export const RE_LINK_TEMPLATE = '((ftp|https?):\\/\\/)?((www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,63})\\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)'; export const RE_MENTION_TEMPLATE = '(@[\\w\\d_-]+)'; export const RE_TG_LINK = /^tg:(\/\/)?([?=&\d\w_-]+)?/gm; -// eslint-disable-next-line max-len -export const RE_TME_LINK = /^(?:https?:\/\/)?(?:t\.me\/)([\d\w_]+)(?:\/([\d]+))?(?:\/([\d]+)(?:\?([\w]+)=([\d]+))?)?$/gm; -export const RE_TME_INVITE_LINK = /^(?:https?:\/\/)?(?:t\.me\/joinchat\/)([\d\w_-]+)?$/gm; -export const RE_TME_ADDSTICKERS_LINK = /^(?:https?:\/\/)?(?:t\.me\/addstickers\/)([\d\w_-]+)$/gm; +export const RE_TME_LINK = /^(?:https?:\/\/)?(?:t\.me\/)/gm; // MTProto constants export const SERVICE_NOTIFICATIONS_USER_ID = 777000; diff --git a/src/modules/actions/api/bots.ts b/src/modules/actions/api/bots.ts index a85f30611..5352336a0 100644 --- a/src/modules/actions/api/bots.ts +++ b/src/modules/actions/api/bots.ts @@ -6,7 +6,7 @@ import { ApiChat } from '../../../api/types'; import { InlineBotSettings } from '../../../types'; import { - RE_TG_LINK, RE_TME_ADDSTICKERS_LINK, RE_TME_INVITE_LINK, RE_TME_LINK, + RE_TG_LINK, RE_TME_LINK, } from '../../../config'; import { callApi } from '../../../api/gramjs'; import { @@ -30,8 +30,7 @@ addReducer('clickInlineButton', (global, actions, payload) => { actions.sendBotCommand({ command: button.value }); break; case 'url': - if (button.value.match(RE_TME_INVITE_LINK) || button.value.match(RE_TME_LINK) || button.value.match(RE_TG_LINK) - || button.value.match(RE_TME_ADDSTICKERS_LINK)) { + if (button.value.match(RE_TME_LINK) || button.value.match(RE_TG_LINK)) { actions.openTelegramLink({ url: button.value }); } else { actions.toggleSafeLinkModal({ url: button.value }); diff --git a/src/modules/actions/api/chats.ts b/src/modules/actions/api/chats.ts index 595834f3a..5c89c1abc 100644 --- a/src/modules/actions/api/chats.ts +++ b/src/modules/actions/api/chats.ts @@ -12,10 +12,8 @@ import { ARCHIVED_FOLDER_ID, TOP_CHAT_MESSAGES_PRELOAD_LIMIT, CHAT_LIST_LOAD_SLICE, - RE_TME_INVITE_LINK, - RE_TME_LINK, TIPS_USERNAME, - LOCALIZED_TIPS, RE_TG_LINK, RE_TME_ADDSTICKERS_LINK, SERVICE_NOTIFICATIONS_USER_ID, + LOCALIZED_TIPS, RE_TG_LINK, SERVICE_NOTIFICATIONS_USER_ID, } from '../../../config'; import { callApi } from '../../../api/gramjs'; import { @@ -534,42 +532,50 @@ addReducer('openChatByInvite', (global, actions, payload) => { addReducer('openTelegramLink', (global, actions, payload) => { const { url } = payload!; - const stickersMatch = RE_TME_ADDSTICKERS_LINK.exec(url); - if (stickersMatch) { - actions.openStickerSetShortName({ - stickerSetShortName: stickersMatch[1], - }); - } else if (url.match(RE_TG_LINK)) { + if (url.match(RE_TG_LINK)) { processDeepLink(url.match(RE_TG_LINK)[0]); + return; + } + + const uri = new URL(url.startsWith('http') ? url : `https://${url}`); + const [part1, part2, part3] = uri.pathname.split('/').filter(Boolean).map((l) => decodeURI(l)); + const params = Object.fromEntries(uri.searchParams); + + let hash: string | undefined; + if (part1 === 'joinchat') { + hash = part2; + } + + if (part1.startsWith(' ') || part1.startsWith('+')) { + hash = part1.substr(1, part1.length - 1); + } + + if (hash) { + actions.openChatByInvite({ hash }); + return; + } + + if (part1 === 'addstickers') { + actions.openStickerSetShortName({ + stickerSetShortName: part2, + }); + return; + } + + const chatOrChannelPostId = part2 ? Number(part2) : undefined; + const messageId = part3 ? Number(part3) : undefined; + const commentId = params.comment ? Number(params.comment) : undefined; + if (part1 === 'c' && chatOrChannelPostId && messageId) { + actions.focusMessage({ + chatId: -chatOrChannelPostId, + messageId, + }); } else { - let match = RE_TME_INVITE_LINK.exec(url); - - if (match) { - const hash = match[1]; - - actions.openChatByInvite({ hash }); - } else { - match = RE_TME_LINK.exec(url)!; - - const username = match[1]; - const chatOrChannelPostId = match[2] ? Number(match[2]) : undefined; - const messageId = match[3] ? Number(match[3]) : undefined; - const commentId = match[4] === 'comment' && match[5] ? Number(match[5]) : undefined; - - // Open message in private group - if (username === 'c' && chatOrChannelPostId && messageId) { - actions.focusMessage({ - chatId: -chatOrChannelPostId, - messageId, - }); - } else { - actions.openChatByUsername({ - username, - messageId: messageId || chatOrChannelPostId, - commentId, - }); - } - } + actions.openChatByUsername({ + username: part1, + messageId: messageId || chatOrChannelPostId, + commentId, + }); } }); diff --git a/tsconfig.json b/tsconfig.json index 48637f4fb..fdd661dd1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,8 +4,9 @@ "target": "esnext", "lib": [ "dom", + "dom.iterable", "webworker", - "es7" + "es2019" ], "allowJs": true, "skipLibCheck": true,