Support t.me/joinchat (#1035)
This commit is contained in:
parent
851619349c
commit
fc69c603a3
@ -885,6 +885,22 @@ export async function migrateChat(chat: ApiChat) {
|
|||||||
return buildApiChatFromPreview(result.chats[1]);
|
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(
|
function preparePeers(
|
||||||
result: GramJs.messages.Dialogs | GramJs.messages.DialogsSlice | GramJs.messages.PeerDialogs,
|
result: GramJs.messages.Dialogs | GramJs.messages.DialogsSlice | GramJs.messages.PeerDialogs,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export {
|
|||||||
fetchChatFolders, editChatFolder, deleteChatFolder, fetchRecommendedChatFolders,
|
fetchChatFolders, editChatFolder, deleteChatFolder, fetchRecommendedChatFolders,
|
||||||
getChatByUsername, togglePreHistoryHidden, updateChatDefaultBannedRights, updateChatMemberBannedRights,
|
getChatByUsername, togglePreHistoryHidden, updateChatDefaultBannedRights, updateChatMemberBannedRights,
|
||||||
updateChatTitle, updateChatAbout, toggleSignatures, updateChatAdmin, fetchGroupsForDiscussion, setDiscussionGroup,
|
updateChatTitle, updateChatAbout, toggleSignatures, updateChatAdmin, fetchGroupsForDiscussion, setDiscussionGroup,
|
||||||
migrateChat,
|
migrateChat, openChatByInvite,
|
||||||
} from './chats';
|
} from './chats';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { withGlobal } from '../../lib/teact/teactn';
|
|||||||
import convertPunycode from '../../lib/punycode';
|
import convertPunycode from '../../lib/punycode';
|
||||||
import { GlobalActions } from '../../global/types';
|
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 { pick } from '../../util/iteratees';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ const SafeLink: FC<OwnProps & DispatchProps> = ({
|
|||||||
const handleClick = useCallback((e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
const handleClick = useCallback((e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
||||||
if (
|
if (
|
||||||
e.ctrlKey || e.altKey || e.shiftKey || e.metaKey
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { formatPastTimeShort } from '../../util/dateFormat';
|
|||||||
|
|
||||||
import Media from './Media';
|
import Media from './Media';
|
||||||
import Link from '../ui/Link';
|
import Link from '../ui/Link';
|
||||||
|
import SafeLink from './SafeLink';
|
||||||
|
|
||||||
import './WebLink.scss';
|
import './WebLink.scss';
|
||||||
|
|
||||||
@ -75,9 +76,13 @@ const WebLink: FC<OwnProps> = ({ message, senderTitle, onMessageClick }) => {
|
|||||||
{truncatedDescription && (
|
{truncatedDescription && (
|
||||||
<Link className="site-description" onClick={handleMessageClick}>{renderText(truncatedDescription)}</Link>
|
<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}
|
{url.replace('mailto:', '') || displayUrl}
|
||||||
</a>
|
</SafeLink>
|
||||||
{senderTitle && <div className="sender-name">{renderText(senderTitle)}</div>}
|
{senderTitle && <div className="sender-name">{renderText(senderTitle)}</div>}
|
||||||
</div>
|
</div>
|
||||||
{senderTitle && (
|
{senderTitle && (
|
||||||
|
|||||||
@ -106,6 +106,7 @@ export const CONTENT_TYPES_FOR_QUICK_UPLOAD = 'image/png,image/gif,image/jpeg,vi
|
|||||||
// eslint-disable-next-line max-len
|
// 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_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_LINK = /^(?:https?:\/\/)?(?:t\.me\/)([\d\w_]+)(?:\/([\d]+))?$/gm;
|
||||||
|
export const RE_TME_INVITE_LINK = /^(?:https?:\/\/)?(?:t\.me\/joinchat\/)([\d\w_]+)?$/gm;
|
||||||
|
|
||||||
// MTProto constants
|
// MTProto constants
|
||||||
export const SERVICE_NOTIFICATIONS_USER_ID = 777000;
|
export const SERVICE_NOTIFICATIONS_USER_ID = 777000;
|
||||||
|
|||||||
@ -901,6 +901,8 @@ messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
|
|||||||
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
||||||
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
||||||
messages.exportChatInvite#df7534c peer:InputPeer = ExportedChatInvite;
|
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.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
|
||||||
messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
|
messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
|
||||||
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
|
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
|
||||||
|
|||||||
@ -901,6 +901,8 @@ messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
|
|||||||
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
||||||
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
||||||
messages.exportChatInvite#df7534c peer:InputPeer = ExportedChatInvite;
|
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.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
|
||||||
messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
|
messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
|
||||||
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
|
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { addReducer, getDispatch } from '../../../lib/teact/teactn';
|
|||||||
|
|
||||||
import { ApiChat } from '../../../api/types';
|
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 { callApi } from '../../../api/gramjs';
|
||||||
import { selectChatMessage, selectCurrentChat } from '../../selectors';
|
import { selectChatMessage, selectCurrentChat } from '../../selectors';
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ addReducer('clickInlineButton', (global, actions, payload) => {
|
|||||||
actions.sendBotCommand({ command: button.value });
|
actions.sendBotCommand({ command: button.value });
|
||||||
break;
|
break;
|
||||||
case 'url':
|
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 });
|
actions.openTelegramLink({ url: button.value });
|
||||||
} else {
|
} else {
|
||||||
window.open(button.value);
|
window.open(button.value);
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import {
|
|||||||
ARCHIVED_FOLDER_ID,
|
ARCHIVED_FOLDER_ID,
|
||||||
TOP_CHAT_MESSAGES_PRELOAD_LIMIT,
|
TOP_CHAT_MESSAGES_PRELOAD_LIMIT,
|
||||||
CHAT_LIST_LOAD_SLICE,
|
CHAT_LIST_LOAD_SLICE,
|
||||||
|
RE_TME_INVITE_LINK,
|
||||||
RE_TME_LINK,
|
RE_TME_LINK,
|
||||||
TIPS_USERNAME,
|
TIPS_USERNAME,
|
||||||
} from '../../../config';
|
} from '../../../config';
|
||||||
@ -380,12 +381,28 @@ addReducer('toggleChatUnread', (global, actions, payload) => {
|
|||||||
|
|
||||||
addReducer('openTelegramLink', (global, actions, payload) => {
|
addReducer('openTelegramLink', (global, actions, payload) => {
|
||||||
const { url } = payload!;
|
const { url } = payload!;
|
||||||
const match = RE_TME_LINK.exec(url)!;
|
let match = RE_TME_INVITE_LINK.exec(url);
|
||||||
|
|
||||||
const username = match[1];
|
if (match) {
|
||||||
const channelPostId = match[2] ? Number(match[2]) : undefined;
|
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) => {
|
addReducer('openChatByUsername', (global, actions, payload) => {
|
||||||
|
|||||||
@ -55,6 +55,11 @@ const READABLE_ERROR_MESSAGES: Record<string, string> = {
|
|||||||
USER_KICKED: 'This user was kicked from this supergroup/channel',
|
USER_KICKED: 'This user was kicked from this supergroup/channel',
|
||||||
USER_NOT_MUTUAL_CONTACT: 'The provided user is not a mutual contact',
|
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',
|
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) {
|
export default function getReadableErrorText(error: ApiError) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user