Support t.me/joinchat (#1035)

This commit is contained in:
Alexander Zinchuk 2021-04-20 18:19:58 +03:00
parent 851619349c
commit fc69c603a3
10 changed files with 59 additions and 11 deletions

View File

@ -885,6 +885,22 @@ export async function migrateChat(chat: ApiChat) {
return buildApiChatFromPreview(result.chats[1]);
}
export async function openChatByInvite(hash: string) {
const result = await invokeRequest(new GramJs.messages.CheckChatInvite({ hash }));
if (!result) {
return undefined;
}
if (result instanceof GramJs.ChatInvite) {
await invokeRequest(new GramJs.messages.ImportChatInvite({ hash }), true);
return undefined;
} else {
return buildApiChatFromPreview(result.chat);
}
}
function preparePeers(
result: GramJs.messages.Dialogs | GramJs.messages.DialogsSlice | GramJs.messages.PeerDialogs,
) {

View File

@ -12,7 +12,7 @@ export {
fetchChatFolders, editChatFolder, deleteChatFolder, fetchRecommendedChatFolders,
getChatByUsername, togglePreHistoryHidden, updateChatDefaultBannedRights, updateChatMemberBannedRights,
updateChatTitle, updateChatAbout, toggleSignatures, updateChatAdmin, fetchGroupsForDiscussion, setDiscussionGroup,
migrateChat,
migrateChat, openChatByInvite,
} from './chats';
export {

View File

@ -3,7 +3,7 @@ import { withGlobal } from '../../lib/teact/teactn';
import convertPunycode from '../../lib/punycode';
import { GlobalActions } from '../../global/types';
import { DEBUG, RE_TME_LINK } from '../../config';
import { DEBUG, RE_TME_INVITE_LINK, RE_TME_LINK } from '../../config';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName';
@ -26,7 +26,7 @@ const SafeLink: FC<OwnProps & DispatchProps> = ({
const handleClick = useCallback((e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
if (
e.ctrlKey || e.altKey || e.shiftKey || e.metaKey
|| !url || !url.match(RE_TME_LINK)
|| !url || (!url.match(RE_TME_LINK) && !url.match(RE_TME_INVITE_LINK))
) {
return true;
}

View File

@ -10,6 +10,7 @@ import { formatPastTimeShort } from '../../util/dateFormat';
import Media from './Media';
import Link from '../ui/Link';
import SafeLink from './SafeLink';
import './WebLink.scss';
@ -75,9 +76,13 @@ const WebLink: FC<OwnProps> = ({ message, senderTitle, onMessageClick }) => {
{truncatedDescription && (
<Link className="site-description" onClick={handleMessageClick}>{renderText(truncatedDescription)}</Link>
)}
<a href={url} target="_blank" rel="noopener noreferrer" className="site-name">
<SafeLink
url={url}
className="site-name"
text=""
>
{url.replace('mailto:', '') || displayUrl}
</a>
</SafeLink>
{senderTitle && <div className="sender-name">{renderText(senderTitle)}</div>}
</div>
{senderTitle && (

View File

@ -106,6 +106,7 @@ export const CONTENT_TYPES_FOR_QUICK_UPLOAD = 'image/png,image/gif,image/jpeg,vi
// eslint-disable-next-line max-len
export const RE_LINK_TEMPLATE = '((ftp|https?):\\/\\/)?((www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6})\\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)';
export const RE_TME_LINK = /^(?:https?:\/\/)?(?:t\.me\/)([\d\w_]+)(?:\/([\d]+))?$/gm;
export const RE_TME_INVITE_LINK = /^(?:https?:\/\/)?(?:t\.me\/joinchat\/)([\d\w_]+)?$/gm;
// MTProto constants
export const SERVICE_NOTIFICATIONS_USER_ID = 777000;

View File

@ -901,6 +901,8 @@ messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#df7534c peer:InputPeer = ExportedChatInvite;
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
messages.importChatInvite#6c50051c hash:string = Updates;
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;

View File

@ -901,6 +901,8 @@ messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#df7534c peer:InputPeer = ExportedChatInvite;
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
messages.importChatInvite#6c50051c hash:string = Updates;
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;

View File

@ -2,7 +2,7 @@ import { addReducer, getDispatch } from '../../../lib/teact/teactn';
import { ApiChat } from '../../../api/types';
import { RE_TME_LINK } from '../../../config';
import { RE_TME_INVITE_LINK, RE_TME_LINK } from '../../../config';
import { callApi } from '../../../api/gramjs';
import { selectChatMessage, selectCurrentChat } from '../../selectors';
@ -14,7 +14,7 @@ addReducer('clickInlineButton', (global, actions, payload) => {
actions.sendBotCommand({ command: button.value });
break;
case 'url':
if (button.value.match(RE_TME_LINK)) {
if (button.value.match(RE_TME_INVITE_LINK) || button.value.match(RE_TME_LINK)) {
actions.openTelegramLink({ url: button.value });
} else {
window.open(button.value);

View File

@ -12,6 +12,7 @@ import {
ARCHIVED_FOLDER_ID,
TOP_CHAT_MESSAGES_PRELOAD_LIMIT,
CHAT_LIST_LOAD_SLICE,
RE_TME_INVITE_LINK,
RE_TME_LINK,
TIPS_USERNAME,
} from '../../../config';
@ -380,12 +381,28 @@ addReducer('toggleChatUnread', (global, actions, payload) => {
addReducer('openTelegramLink', (global, actions, payload) => {
const { url } = payload!;
const match = RE_TME_LINK.exec(url)!;
let match = RE_TME_INVITE_LINK.exec(url);
const username = match[1];
const channelPostId = match[2] ? Number(match[2]) : undefined;
if (match) {
const hash = match[1];
void openChatByUsername(actions, username, channelPostId);
(async () => {
const chat = await callApi('openChatByInvite', hash);
if (!chat) {
return;
}
actions.openChat({ id: chat.id });
})();
} else {
match = RE_TME_LINK.exec(url)!;
const username = match[1];
const channelPostId = match[2] ? Number(match[2]) : undefined;
void openChatByUsername(actions, username, channelPostId);
}
});
addReducer('openChatByUsername', (global, actions, payload) => {

View File

@ -55,6 +55,11 @@ const READABLE_ERROR_MESSAGES: Record<string, string> = {
USER_KICKED: 'This user was kicked from this supergroup/channel',
USER_NOT_MUTUAL_CONTACT: 'The provided user is not a mutual contact',
USER_PRIVACY_RESTRICTED: 'The user\'s privacy settings do not allow you to do this',
INVITE_HASH_EMPTY: 'The invite hash is empty',
INVITE_HASH_EXPIRED: 'The invite link has expired',
INVITE_HASH_INVALID: 'The invite hash is invalid',
CHANNELS_TOO_MUCH: 'You have joined too many channels/supergroups',
USER_ALREADY_PARTICIPANT: 'You already in the group',
};
export default function getReadableErrorText(error: ApiError) {