TelegramPWA/src/util/deeplink.ts
2023-01-28 02:21:33 +01:00

140 lines
3.8 KiB
TypeScript

import { getActions } from '../global';
import type { ApiChatType } from '../api/types';
import { API_CHAT_TYPES } from '../config';
import { IS_SAFARI } from './environment';
type DeepLinkMethod = 'resolve' | 'login' | 'passport' | 'settings' | 'join' | 'addstickers' | 'addemoji' |
'setlanguage' | 'addtheme' | 'confirmphone' | 'socks' | 'proxy' | 'privatepost' | 'bg' | 'share' | 'msg' | 'msg_url' |
'invoice';
export const processDeepLink = (url: string) => {
const {
protocol, searchParams, pathname, hostname,
} = new URL(url);
if (protocol !== 'tg:') return;
const {
openChatByInvite,
openChatByUsername,
openChatByPhoneNumber,
openStickerSet,
focusMessage,
joinVoiceChatByLink,
openInvoice,
processAttachBotParameters,
openChatWithDraft,
} = getActions();
// Safari thinks the path in tg://path links is hostname for some reason
const method = (IS_SAFARI ? hostname : pathname).replace(/^\/\//, '') as DeepLinkMethod;
const params = Object.fromEntries(searchParams);
switch (method) {
case 'resolve': {
const {
domain, phone, post, comment, voicechat, livestream, start, startattach, attach, thread, topic,
} = params;
const startAttach = params.hasOwnProperty('startattach') && !startattach ? true : startattach;
const choose = parseChooseParameter(params.choose);
const threadId = Number(thread) || Number(topic) || undefined;
if (domain !== 'telegrampassport') {
if (startAttach && choose) {
processAttachBotParameters({
username: domain,
filter: choose,
...(typeof startAttach === 'string' && { startParam: startAttach }),
});
} else if (params.hasOwnProperty('voicechat') || params.hasOwnProperty('livestream')) {
joinVoiceChatByLink({
username: domain,
inviteHash: voicechat || livestream,
});
} else if (phone) {
openChatByPhoneNumber({ phoneNumber: phone, startAttach, attach });
} else {
openChatByUsername({
username: domain,
messageId: post ? Number(post) : undefined,
commentId: comment ? Number(comment) : undefined,
startParam: start,
startAttach,
attach,
threadId,
});
}
}
break;
}
case 'privatepost': {
const {
post, channel,
} = params;
focusMessage({
chatId: `-${channel}`,
messageId: Number(post),
});
break;
}
case 'bg': {
// const {
// slug, color, rotation, mode, intensity, bg_color: bgColor, gradient,
// } = params;
break;
}
case 'join': {
const { invite } = params;
openChatByInvite({ hash: invite });
break;
}
case 'addemoji':
case 'addstickers': {
const { set } = params;
openStickerSet({
stickerSetInfo: {
shortName: set,
},
});
break;
}
case 'share':
case 'msg':
case 'msg_url': {
const { url: urlParam, text } = params;
openChatWithDraft({ text: formatShareText(urlParam, text) });
break;
}
case 'login': {
// const { code, token } = params;
break;
}
case 'invoice': {
const { slug } = params;
openInvoice({ slug });
break;
}
default:
// Unsupported deeplink
break;
}
};
export function parseChooseParameter(choose?: string) {
if (!choose) return undefined;
const types = choose.toLowerCase().split(' ');
return types.filter((type): type is ApiChatType => API_CHAT_TYPES.includes(type as ApiChatType));
}
export function formatShareText(url?: string, text?: string, title?: string): string {
return [url, title, text].filter(Boolean).join('\n');
}