Layer 186: Super Channels (#4885)

This commit is contained in:
zubiden 2024-08-29 15:52:39 +02:00 committed by Alexander Zinchuk
parent ee52eae6ac
commit 383a2d50b2
40 changed files with 614 additions and 241 deletions

View File

@ -110,7 +110,8 @@ function buildApiAttachMenuIcon(icon: GramJs.AttachMenuBotIcon): ApiAttachBotIco
export function buildApiBotInfo(botInfo: GramJs.BotInfo, chatId: string): ApiBotInfo {
const {
description, descriptionPhoto, descriptionDocument, userId, commands, menuButton, hasPreviewMedias,
description, descriptionPhoto, descriptionDocument, userId, commands, menuButton, privacyPolicyUrl,
hasPreviewMedias,
} = botInfo;
const botId = userId && buildApiPeerId(userId, 'user');
@ -125,6 +126,7 @@ export function buildApiBotInfo(botInfo: GramJs.BotInfo, chatId: string): ApiBot
gif,
photo,
menuButton: buildApiBotMenuButton(menuButton),
privacyPolicyUrl,
commands: commandsArray?.length ? commandsArray : undefined,
hasPreviewMedia: hasPreviewMedias,
};

View File

@ -51,7 +51,7 @@ function buildApiChatFieldsFromPeerEntity(
const hasVideoAvatar = 'photo' in peerEntity && peerEntity.photo && 'hasVideo' in peerEntity.photo
&& peerEntity.photo.hasVideo;
const avatarPhotoId = ('photo' in peerEntity) && peerEntity.photo ? buildAvatarPhotoId(peerEntity.photo) : undefined;
const isSignaturesShown = Boolean('signatures' in peerEntity && peerEntity.signatures);
const areSignaturesShown = Boolean('signatures' in peerEntity && peerEntity.signatures);
const hasPrivateLink = Boolean('hasLink' in peerEntity && peerEntity.hasLink);
const isScam = Boolean('scam' in peerEntity && peerEntity.scam);
const isFake = Boolean('fake' in peerEntity && peerEntity.fake);
@ -66,11 +66,13 @@ function buildApiChatFieldsFromPeerEntity(
const emojiStatus = ('emojiStatus' in peerEntity && peerEntity.emojiStatus)
? buildApiEmojiStatus(peerEntity.emojiStatus) : undefined;
const boostLevel = ('level' in peerEntity) ? peerEntity.level : undefined;
const areProfilesShown = Boolean('signatureProfiles' in peerEntity && peerEntity.signatureProfiles);
return omitUndefined<PeerEntityApiChatFields>({
isMin,
hasPrivateLink,
isSignaturesShown,
areSignaturesShown,
areProfilesShown,
usernames,
accessHash,
hasVideoAvatar,
@ -328,6 +330,7 @@ export function buildChatMember(
bannedRights: 'bannedRights' in member ? omitVirtualClassFields(member.bannedRights) : undefined,
adminRights: 'adminRights' in member ? omitVirtualClassFields(member.adminRights) : undefined,
customTitle: 'rank' in member ? member.rank : undefined,
isViaRequest: 'viaRequest' in member ? member.viaRequest : undefined,
...((member instanceof GramJs.ChannelParticipantAdmin || member instanceof GramJs.ChatParticipantAdmin) && {
isAdmin: true,
}),

View File

@ -205,7 +205,7 @@ export function buildApiMessageWithChatId(
isOutgoing,
content,
date: mtpMessage.date,
senderId: fromId || (mtpMessage.out && mtpMessage.post && currentUserId) || chatId,
senderId: fromId,
viewsCount: mtpMessage.views,
forwardsCount: mtpMessage.forwards,
isScheduled,

View File

@ -46,6 +46,7 @@ import {
buildApiMissingInvitedUser,
buildApiSponsoredMessageReportResult,
buildApiTopic,
buildChatMember,
buildChatMembers,
getPeerKey,
} from '../apiBuilders/chats';
@ -354,12 +355,12 @@ export async function fetchSavedChats({
}
export function fetchFullChat(chat: ApiChat) {
const { id, accessHash, adminRights } = chat;
const { id, accessHash } = chat;
const input = buildInputEntity(id, accessHash);
return input instanceof GramJs.InputChannel
? getFullChannelInfo(id, accessHash!, adminRights)
? getFullChannelInfo(chat)
: getFullChatInfo(id);
}
@ -598,10 +599,10 @@ async function getFullChatInfo(chatId: string): Promise<FullChatData | undefined
}
async function getFullChannelInfo(
id: string,
accessHash: string,
adminRights?: ApiChatAdminRights,
chat: ApiChat,
): Promise<FullChatData | undefined> {
const { id, adminRights } = chat;
const accessHash = chat.accessHash!;
const result = await invokeRequest(new GramJs.channels.GetFullChannel({
channel: buildInputEntity(id, accessHash) as GramJs.InputChannel,
}));
@ -659,14 +660,23 @@ async function getFullChannelInfo(
canViewParticipants && await fetchMembers(id, accessHash, 'admin')
) || {};
const botCommands = botInfo ? buildApiChatBotCommands(botInfo) : undefined;
const chats = result.chats.map((chat) => buildApiChatFromPreview(chat)).filter(Boolean);
const memberInfoRequest = !chat.isNotJoined && chat.type === 'chatTypeChannel'
? await fetchMember({ chat }) : undefined;
const memberInfo = memberInfoRequest?.member;
const joinInfo = memberInfo?.joinedDate ? {
joinedDate: memberInfo.joinedDate,
inviter: memberInfo.inviterId,
isViaRequest: memberInfo.isViaRequest,
} : undefined;
const chats = result.chats.map((c) => buildApiChatFromPreview(c)).filter(Boolean);
if (result?.chats?.length > 1) {
updateLocalDb(result);
const [, mtpLinkedChat] = result.chats;
const chat = buildApiChatFromPreview(mtpLinkedChat);
if (chat) {
const linkedChat = buildApiChatFromPreview(mtpLinkedChat);
if (linkedChat) {
onUpdate({
'@type': 'updateChat',
id: chat.id,
@ -676,7 +686,7 @@ async function getFullChannelInfo(
}
if (result.fullChat.pts) {
updateChannelState(id, result.fullChat.pts);
updateChannelState(chat.id, result.fullChat.pts);
}
const statusesById = {
@ -703,6 +713,7 @@ async function getFullChannelInfo(
canViewStatistics: canViewStats,
canViewMonetization,
isPreHistoryHidden: hiddenPrehistory,
joinInfo,
members,
kickedMembers,
adminMembersById: adminMembers ? buildCollectionByKey(adminMembers, 'userId') : undefined,
@ -1284,14 +1295,19 @@ export async function updateChatAbout(chat: ApiChat, about: string) {
}
export function toggleSignatures({
chat, isEnabled,
}: { chat: ApiChat; isEnabled: boolean }) {
chat, areSignaturesEnabled, areProfilesEnabled,
}: {
chat: ApiChat;
areSignaturesEnabled: boolean;
areProfilesEnabled: boolean;
}) {
const { id, accessHash } = chat;
const channel = buildInputEntity(id, accessHash);
return invokeRequest(new GramJs.channels.ToggleSignatures({
channel: channel as GramJs.InputChannel,
enabled: isEnabled,
signaturesEnabled: areSignaturesEnabled || undefined,
profilesEnabled: areProfilesEnabled || undefined,
}), {
shouldReturnTrue: true,
});
@ -1345,6 +1361,44 @@ export async function fetchMembers(
};
}
export async function fetchMember({
chat,
peer,
}: {
chat: ApiChat;
peer?: ApiPeer;
}) {
const participant = peer ? buildInputPeer(peer.id, peer.accessHash) : new GramJs.InputPeerSelf();
const result = await invokeRequest(new GramJs.channels.GetParticipant({
channel: buildInputEntity(chat.id, chat.accessHash) as GramJs.InputChannel,
participant,
}), {
abortControllerChatId: chat.id,
});
if (!result) {
return undefined;
}
updateLocalDb(result);
const { users, userStatusesById } = buildApiUsersAndStatuses(result.users);
const chats = result.chats.map((c) => buildApiChatFromPreview(c)).filter(Boolean);
const member = buildChatMember(result.participant);
if (!member) {
return undefined;
}
return {
member,
users,
userStatusesById,
chats,
};
}
export async function fetchGroupsForDiscussion() {
const result = await invokeRequest(new GramJs.channels.GetGroupsForDiscussion());

View File

@ -11,7 +11,7 @@ export {
export {
fetchChats, fetchFullChat, searchChats, requestChatUpdate, fetchChatSettings,
saveDraft, fetchChat, updateChatMutedState, updateTopicMutedState,
saveDraft, fetchChat, updateChatMutedState, updateTopicMutedState, fetchMember,
createChannel, joinChannel, deleteChatUser, deleteChat, leaveChannel, deleteChannel, createGroupChat, editChatPhoto,
toggleChatPinned, toggleChatArchived, toggleDialogUnread, setChatEnabledReactions,
fetchChatFolders, editChatFolder, deleteChatFolder, sortChatFolders, fetchRecommendedChatFolders,

View File

@ -23,6 +23,7 @@ import type {
ApiStory,
ApiStorySkipped,
ApiUser,
ApiUserStatus,
ApiVideo,
MediaContent,
OnApiUpdate,
@ -61,7 +62,7 @@ import {
buildUploadingMedia,
} from '../apiBuilders/messages';
import { getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
import { buildApiUser } from '../apiBuilders/users';
import { buildApiUser, buildApiUsersAndStatuses } from '../apiBuilders/users';
import {
buildInputEntity,
buildInputMediaDocument,
@ -106,6 +107,7 @@ type TranslateTextParams = ({
type SearchResults = {
messages: ApiMessage[];
users: ApiUser[];
userStatusesById: Record<number, ApiUserStatus>;
chats: ApiChat[];
totalCount: number;
nextOffsetRate?: number;
@ -1216,7 +1218,7 @@ export async function searchMessagesInChat({
updateLocalDb(result);
const chats = result.chats.map((c) => buildApiChatFromPreview(c)).filter(Boolean);
const users = result.users.map(buildApiUser).filter(Boolean);
const { users, userStatusesById } = buildApiUsersAndStatuses(result.users);
const messages = result.messages.map(buildApiMessage).filter(Boolean);
dispatchThreadInfoUpdates(result.messages);
@ -1233,6 +1235,7 @@ export async function searchMessagesInChat({
return {
chats,
users,
userStatusesById,
messages,
totalCount,
nextOffsetId,
@ -1304,7 +1307,7 @@ export async function searchMessagesGlobal({
updateLocalDb(result);
const chats = result.chats.map((c) => buildApiChatFromPreview(c)).filter(Boolean);
const users = result.users.map(buildApiUser).filter(Boolean);
const { users, userStatusesById } = buildApiUsersAndStatuses(result.users);
const messages = result.messages.map(buildApiMessage).filter(Boolean);
dispatchThreadInfoUpdates(result.messages);
@ -1323,6 +1326,7 @@ export async function searchMessagesGlobal({
return {
messages,
users,
userStatusesById,
chats,
totalCount,
nextOffsetRate,
@ -1356,7 +1360,7 @@ export async function searchHashtagPosts({
updateLocalDb(result);
const chats = result.chats.map((c) => buildApiChatFromPreview(c)).filter(Boolean);
const users = result.users.map(buildApiUser).filter(Boolean);
const { users, userStatusesById } = buildApiUsersAndStatuses(result.users);
const messages = result.messages.map(buildApiMessage).filter(Boolean);
dispatchThreadInfoUpdates(result.messages);
@ -1375,6 +1379,7 @@ export async function searchHashtagPosts({
return {
messages,
users,
userStatusesById,
chats,
totalCount,
nextOffsetRate,

View File

@ -453,7 +453,7 @@ export async function fetchStarsStatus() {
users,
chats,
nextOffset: result.nextOffset,
history: result.history.map(buildApiStarsTransaction),
history: result.history?.map(buildApiStarsTransaction),
balance: result.balance.toJSNumber(),
};
}
@ -488,7 +488,7 @@ export async function fetchStarsTransactions({
users,
chats,
nextOffset: result.nextOffset,
history: result.history.map(buildApiStarsTransaction),
history: result.history?.map(buildApiStarsTransaction),
balance: result.balance.toJSNumber(),
};
}

View File

@ -74,6 +74,7 @@ export interface ApiBotInfo {
photo?: ApiPhoto;
gif?: ApiVideo;
menuButton: ApiBotMenuButton;
privacyPolicyUrl?: string;
hasPreviewMedia?: true;
}

View File

@ -30,7 +30,8 @@ export interface ApiChat {
isVerified?: true;
isMuted?: boolean;
muteUntil?: number;
isSignaturesShown?: boolean;
areSignaturesShown?: boolean;
areProfilesShown?: boolean;
hasPrivateLink?: boolean;
accessHash?: string;
isMin?: boolean;
@ -120,6 +121,11 @@ export interface ApiChatFullInfo {
chatId: string;
maxMessageId?: number;
};
joinInfo?: {
joinedDate: number;
inviter?: string;
isViaRequest?: boolean;
};
linkedChatId?: string;
botCommands?: ApiBotCommand[];
enabledReactions?: ApiChatReactions;
@ -152,6 +158,7 @@ export interface ApiChatMember {
customTitle?: string;
isAdmin?: true;
isOwner?: true;
isViaRequest?: true;
}
export interface ApiChatAdminRights {

View File

@ -470,10 +470,11 @@ const Composer: FC<OwnProps & StateProps> = ({
}, [isReady, chatId, threadId, isInStoryViewer]);
useEffect(() => {
if (chatId && chat && !sendAsPeerIds && isReady && isChatSuperGroup(chat)) {
const isChannelWithProfiles = isChannel && chat?.areProfilesShown;
if (chatId && chat && !sendAsPeerIds && isReady && (isChatSuperGroup(chat) || isChannelWithProfiles)) {
loadSendAs({ chatId });
}
}, [chat, chatId, isReady, loadSendAs, sendAsPeerIds]);
}, [chat, chatId, isChannel, isReady, loadSendAs, sendAsPeerIds]);
const shouldAnimateSendAsButtonRef = useRef(false);
useSyncEffect(([prevChatId, prevSendAsPeerIds]) => {

View File

@ -60,10 +60,6 @@ const BOT_BUTTONS: Record<string, { icon: IconName; label: string }> = {
icon: 'bots',
label: 'BotSettings',
},
privacy: {
icon: 'info',
label: 'Privacy',
},
help: {
icon: 'help',
label: 'BotHelp',
@ -103,6 +99,7 @@ export type OwnProps = {
type StateProps = {
chat?: ApiChat;
botCommands?: ApiBotCommand[];
botPrivacyPolicyUrl?: string;
isPrivate?: boolean;
isMuted?: boolean;
isTopic?: boolean;
@ -135,6 +132,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
anchor,
isChannel,
botCommands,
botPrivacyPolicyUrl,
withForumActions,
isTopic,
isForum,
@ -195,6 +193,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
openCreateTopicPanel,
openEditTopicPanel,
openChat,
openUrl,
toggleManagement,
togglePeerTranslations,
blockUser,
@ -401,9 +400,10 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
const lang = useOldLang();
const botButtons = useMemo(() => {
return botCommands?.map(({ command }) => {
const commandButtons = botCommands?.map(({ command }) => {
const cmd = BOT_BUTTONS[command];
if (!cmd) return undefined;
const handleClick = () => {
sendBotCommand({ command: `/${command}` });
closeMenu();
@ -420,7 +420,28 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
</MenuItem>
);
});
}, [botCommands, closeMenu, lang, sendBotCommand]);
const hasPrivacyCommand = botCommands?.some(({ command }) => command === 'privacy');
const privacyButton = isBot && (
<MenuItem
icon="privacy-policy"
// eslint-disable-next-line react/jsx-no-bind
onClick={() => {
if (hasPrivacyCommand && !botPrivacyPolicyUrl) {
sendBotCommand({ command: '/privacy' });
} else {
openUrl({ url: botPrivacyPolicyUrl || lang('BotDefaultPrivacyPolicy') });
}
closeMenu();
}}
>
{lang('BotPrivacyPolicy')}
</MenuItem>
);
return [...commandButtons || [], privacyButton].filter(Boolean);
}, [botCommands, lang, botPrivacyPolicyUrl, isBot]);
const deleteTitle = useMemo(() => {
if (!chat) return undefined;
@ -766,6 +787,7 @@ export default memo(withGlobal<OwnProps>(
canGiftPremium,
hasLinkedChat: Boolean(chatFullInfo?.linkedChatId),
botCommands: chatBot ? userFullInfo?.botInfo?.commands : undefined,
botPrivacyPolicyUrl: chatBot ? userFullInfo?.botInfo?.privacyPolicyUrl : undefined,
isChatInfoShown: selectTabState(global).isChatInfoShown
&& currentChatId === chatId && currentThreadId === threadId,
canCreateTopic,

View File

@ -9,6 +9,7 @@ import { addExtraClass, removeExtraClass } from '../../lib/teact/teact-dom';
import { getActions, getGlobal, withGlobal } from '../../global';
import type {
ApiChatFullInfo,
ApiMessage, ApiRestrictionReason, ApiTopic,
} from '../../api/types';
import type { MessageListType } from '../../global/types';
@ -109,6 +110,7 @@ type StateProps = {
isRepliesChat?: boolean;
isAnonymousForwards?: boolean;
isCreator?: boolean;
isChannelWithAvatars?: boolean;
isBot?: boolean;
isSynced?: boolean;
messageIds?: number[];
@ -128,6 +130,7 @@ type StateProps = {
isForum?: boolean;
currentUserId: string;
areAdsEnabled?: boolean;
channelJoinInfo?: ApiChatFullInfo['joinInfo'];
};
const MESSAGE_REACTIONS_POLLING_INTERVAL = 20 * 1000;
@ -150,12 +153,11 @@ const MessageList: FC<OwnProps & StateProps> = ({
threadId,
type,
hasTools,
onScrollDownToggle,
onNotchToggle,
isChatLoaded,
isForum,
isChannelChat,
isGroupChat,
isChannelWithAvatars,
canPost,
isSynced,
isReady,
@ -183,9 +185,12 @@ const MessageList: FC<OwnProps & StateProps> = ({
isServiceNotificationsChat,
currentUserId,
getForceNextPinnedInHeader,
onPinnedIntersectionChange,
isContactRequirePremium,
areAdsEnabled,
channelJoinInfo,
onPinnedIntersectionChange,
onScrollDownToggle,
onNotchToggle,
}) => {
const {
loadViewportMessages, setScrollOffset, loadSponsoredMessages, loadMessageReactions, copyMessagesByIds,
@ -255,7 +260,59 @@ const MessageList: FC<OwnProps & StateProps> = ({
return undefined;
}
const listedMessages = messageIds.map((id) => messagesById[id]).filter(Boolean);
const listedMessages: ApiMessage[] = [];
messageIds.forEach((id, index, arr) => {
const prevMessage = listedMessages[listedMessages.length - 1];
const message = messagesById[id];
if (!message) {
return;
}
const { shouldAppendJoinMessage, shouldAppendJoinMessageAfterCurrent } = (() => {
if (!channelJoinInfo) return undefined;
if (prevMessage
&& prevMessage.date < channelJoinInfo.joinedDate && channelJoinInfo.joinedDate <= message.date) {
return { shouldAppendJoinMessage: true, shouldAppendJoinMessageAfterCurrent: false };
}
if (index === arr.length - 1 && message.date < channelJoinInfo.joinedDate) {
return {
shouldAppendJoinMessage: true,
shouldAppendJoinMessageAfterCurrent: true,
};
}
return undefined;
})() || {};
if (shouldAppendJoinMessageAfterCurrent) {
listedMessages.push(message);
}
if (shouldAppendJoinMessage) {
const lastMessageId = shouldAppendJoinMessageAfterCurrent ? message.id : (prevMessage?.id || (message.id - 1));
listedMessages.push({
id: generateChannelJoinMessageId(lastMessageId),
chatId: message.chatId,
date: channelJoinInfo!.joinedDate,
isOutgoing: false,
content: {
action: {
type: 'joinedChannel',
mediaType: 'action',
text: '',
translationValues: [],
targetChatId: message.chatId,
},
},
} satisfies ApiMessage);
}
if (!shouldAppendJoinMessageAfterCurrent) {
listedMessages.push(message);
}
});
// Service notifications have local IDs which may be not in sync with real message history
const orderRule: (keyof ApiMessage)[] = type === 'scheduled' || isServiceNotificationsChat
@ -270,7 +327,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
isChatWithSelf,
)
: undefined;
}, [messageIds, messagesById, type, isServiceNotificationsChat, isForum, threadId, isChatWithSelf]);
}, [messageIds, messagesById, type, isServiceNotificationsChat, isForum, threadId, isChatWithSelf, channelJoinInfo]);
useInterval(() => {
if (!messageIds || !messagesById || type === 'scheduled') return;
@ -576,9 +633,10 @@ const MessageList: FC<OwnProps & StateProps> = ({
}
}, [isSelectModeActive]);
const isPrivate = Boolean(chatId && isUserId(chatId));
const withUsers = Boolean((!isPrivate && !isChannelChat) || isChatWithSelf || isRepliesChat || isAnonymousForwards);
const noAvatars = Boolean(!withUsers || isChannelChat);
const isPrivate = isUserId(chatId);
const withUsers = Boolean((!isPrivate && !isChannelChat)
|| isChatWithSelf || isRepliesChat || isAnonymousForwards || isChannelWithAvatars);
const noAvatars = Boolean(!withUsers || (isChannelChat && !isChannelWithAvatars));
const shouldRenderGreeting = isUserId(chatId) && !isChatWithSelf && !isBot && !isAnonymousForwards
&& type === 'thread'
&& (
@ -728,6 +786,7 @@ export default memo(withGlobal<OwnProps>(
restrictionReason,
isChannelChat: isChatChannel(chat),
isGroupChat: isChatGroup(chat),
isChannelWithAvatars: chat.areProfilesShown,
isCreator: chat.isCreator,
isChatWithSelf: selectIsChatWithSelf(global, chatId),
isRepliesChat: isChatWithRepliesBot(chatId),
@ -741,6 +800,7 @@ export default memo(withGlobal<OwnProps>(
focusingId,
isSelectModeActive: selectIsInSelectMode(global),
hasLinkedChat: chatFullInfo ? Boolean(chatFullInfo.linkedChatId) : undefined,
channelJoinInfo: chatFullInfo?.joinInfo,
topic,
noMessageSendingAnimation: !selectPerformanceSettingsValue(global, 'messageSendingAnimations'),
isServiceNotificationsChat: chatId === SERVICE_NOTIFICATIONS_USER_ID,
@ -751,3 +811,7 @@ export default memo(withGlobal<OwnProps>(
};
},
)(MessageList));
function generateChannelJoinMessageId(lastMessageId: number) {
return lastMessageId + 10e-7; // Smaller than smallest possible id with `getNextLocalMessageId`
}

View File

@ -93,6 +93,7 @@ export function groupMessages(
nextMessage.id === firstUnreadId
|| message.senderId !== nextMessage.senderId
|| message.isOutgoing !== nextMessage.isOutgoing
|| message.postAuthorTitle !== nextMessage.postAuthorTitle
|| (isActionMessage(message) && !message.content.action?.phoneCall)
|| (isActionMessage(nextMessage) && !nextMessage.content.action?.phoneCall)
|| message.inlineButtons

View File

@ -816,7 +816,8 @@ const Message: FC<OwnProps & StateProps> = ({
const viaBusinessBotTitle = viaBusinessBot ? getSenderTitle(lang, viaBusinessBot) : undefined;
const signature = viaBusinessBotTitle || (isChannel && message.postAuthorTitle)
const canShowPostAuthor = !message.senderId;
const signature = viaBusinessBotTitle || (canShowPostAuthor && message.postAuthorTitle)
|| ((asForwarded || isChatWithSelf) && forwardInfo?.postAuthorTitle)
|| undefined;

View File

@ -41,6 +41,7 @@ type StateProps = {
shouldShowInChat?: boolean;
count: number;
isCurrentUserPremium: boolean;
isSynced?: boolean;
};
const SimilarChannels = ({
@ -49,9 +50,10 @@ const SimilarChannels = ({
shouldShowInChat,
count,
isCurrentUserPremium,
isSynced,
}: StateProps & OwnProps) => {
const lang = useOldLang();
const { toggleChannelRecommendations } = getActions();
const { toggleChannelRecommendations, loadChannelRecommendations } = getActions();
const [isShowing, markShowing, markNotShowing] = useFlag(false);
const [isHiding, markHiding, markNotHiding] = useFlag(false);
// eslint-disable-next-line no-null/no-null
@ -68,6 +70,7 @@ const SimilarChannels = ({
const [shoulRenderSkeleton, setShoulRenderSkeleton] = useState(!similarChannelIds);
const firstSimilarChannels = useMemo(() => similarChannels?.slice(0, SHOW_CHANNELS_NUMBER), [similarChannels]);
const areSimilarChannelsPresent = Boolean(firstSimilarChannels?.length);
useHorizontalScroll(ref, !areSimilarChannelsPresent || !shouldShowInChat || shoulRenderSkeleton, true);
const isAnimating = isHiding || isShowing;
const shouldRenderChannels = Boolean(
@ -76,6 +79,12 @@ const SimilarChannels = ({
&& areSimilarChannelsPresent,
);
useEffect(() => {
if (isSynced && !similarChannelIds) {
loadChannelRecommendations({ chatId });
}
}, [chatId, isSynced, similarChannelIds]);
useTimeout(() => setShoulRenderSkeleton(false), MAX_SKELETON_DELAY);
useEffect(() => {
@ -240,6 +249,7 @@ export default memo(
shouldShowInChat,
count,
isCurrentUserPremium,
isSynced: global.isSynced,
};
})(SimilarChannels),
);

View File

@ -143,6 +143,7 @@ type StateProps = {
isTopicInfo?: boolean;
isSavedDialog?: boolean;
forceScrollProfileTab?: boolean;
isSynced?: boolean;
};
type TabProps = {
@ -202,6 +203,7 @@ const Profile: FC<OwnProps & StateProps> = ({
isTopicInfo,
isSavedDialog,
forceScrollProfileTab,
isSynced,
}) => {
const {
setSharedMediaSearchType,
@ -293,10 +295,10 @@ const Profile: FC<OwnProps & StateProps> = ({
}, [chatId, botPreviewMedia, hasPreviewMediaTab]);
useEffect(() => {
if (isChannel && !similarChannels) {
if (isChannel && !similarChannels && isSynced) {
loadChannelRecommendations({ chatId });
}
}, [chatId, isChannel, similarChannels]);
}, [chatId, isChannel, similarChannels, isSynced]);
const renderingActiveTab = activeTab > tabs.length - 1 ? tabs.length - 1 : activeTab;
const tabType = tabs[renderingActiveTab].type as ProfileTabType;
@ -824,6 +826,7 @@ export default memo(withGlobal<OwnProps>(
isCurrentUserPremium,
isTopicInfo,
isSavedDialog,
isSynced: global.isSynced,
limitSimilarChannels: selectPremiumLimit(global, 'recommendedChannels'),
...(hasMembersTab && members && { members, adminMembersById }),
...(hasCommonChatsTab && user && { commonChatIds: user.commonChats?.ids }),

View File

@ -21,7 +21,6 @@ import useMedia from '../../../hooks/useMedia';
import useOldLang from '../../../hooks/useOldLang';
import AvatarEditable from '../../ui/AvatarEditable';
import Checkbox from '../../ui/Checkbox';
import ConfirmDialog from '../../ui/ConfirmDialog';
import FloatingActionButton from '../../ui/FloatingActionButton';
import InputText from '../../ui/InputText';
@ -42,10 +41,8 @@ type StateProps = {
chat: ApiChat;
chatFullInfo?: ApiChatFullInfo;
progress?: ManagementProgress;
isSignaturesShown: boolean;
canChangeInfo?: boolean;
canInvite?: boolean;
canPost?: boolean;
exportedInvites?: ApiExportedInvite[];
availableReactions?: ApiAvailableReaction[];
};
@ -58,10 +55,8 @@ const ManageChannel: FC<OwnProps & StateProps> = ({
chat,
chatFullInfo,
progress,
isSignaturesShown,
canChangeInfo,
canInvite,
canPost,
exportedInvites,
isActive,
availableReactions,
@ -70,7 +65,6 @@ const ManageChannel: FC<OwnProps & StateProps> = ({
}) => {
const {
updateChat,
toggleSignatures,
closeManagement,
leaveChannel,
deleteChannel,
@ -173,10 +167,6 @@ const ManageChannel: FC<OwnProps & StateProps> = ({
});
}, [about, chatId, photo, title, updateChat]);
const handleToggleSignatures = useCallback(() => {
toggleSignatures({ chatId, isEnabled: !isSignaturesShown });
}, [chatId, isSignaturesShown, toggleSignatures]);
const handleClickSubscribers = useCallback(() => {
onScreenSelect(ManagementScreens.ChannelSubscribers);
}, [onScreenSelect]);
@ -298,15 +288,6 @@ const ManageChannel: FC<OwnProps & StateProps> = ({
{chatReactionsDescription}
</span>
</ListItem>
{canPost && (
<div className="ListItem narrow">
<Checkbox
checked={isSignaturesShown}
label={lang('ChannelSignMessages')}
onChange={handleToggleSignatures}
/>
</div>
)}
</div>
<div className="section">
<ListItem
@ -369,17 +350,14 @@ export default memo(withGlobal<OwnProps>(
const chat = selectChat(global, chatId)!;
const { management } = selectTabState(global);
const { progress } = management;
const isSignaturesShown = Boolean(chat?.isSignaturesShown);
const { invites } = management.byChatId[chatId] || {};
return {
chat,
chatFullInfo: selectChatFullInfo(global, chatId),
progress,
isSignaturesShown,
canChangeInfo: getHasAdminRight(chat, 'changeInfo'),
canInvite: getHasAdminRight(chat, 'inviteUsers'),
canPost: getHasAdminRight(chat, 'postMessages'),
exportedInvites: invites,
availableReactions: global.reactions.availableReactions,
};

View File

@ -1,26 +1,29 @@
import type { FC } from '../../../lib/teact/teact';
import React, { memo, useCallback, useMemo } from '../../../lib/teact/teact';
import { getGlobal, withGlobal } from '../../../global';
import React, { memo, useMemo } from '../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../global';
import type { ApiChat, ApiChatMember } from '../../../api/types';
import { ManagementScreens } from '../../../types';
import { getUserFullName, isChatChannel } from '../../../global/helpers';
import { getHasAdminRight, getUserFullName, isChatChannel } from '../../../global/helpers';
import { selectChat, selectChatFullInfo } from '../../../global/selectors';
import { partition } from '../../../util/iteratees';
import useHistoryBack from '../../../hooks/useHistoryBack';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import PrivateChatInfo from '../../common/PrivateChatInfo';
import Checkbox from '../../ui/Checkbox';
import FloatingActionButton from '../../ui/FloatingActionButton';
import ListItem from '../../ui/ListItem';
type OwnProps = {
chatId: string;
isActive: boolean;
onScreenSelect: (screen: ManagementScreens) => void;
onChatMemberSelect: (memberId: string, isPromotedByCurrentUser?: boolean) => void;
onClose: NoneToVoidFunction;
isActive: boolean;
};
type StateProps = {
@ -31,6 +34,7 @@ type StateProps = {
};
const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
isActive,
chat,
isChannel,
currentUserId,
@ -38,8 +42,8 @@ const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
onScreenSelect,
onChatMemberSelect,
onClose,
isActive,
}) => {
const { toggleSignatures } = getActions();
const lang = useOldLang();
useHistoryBack({
@ -47,34 +51,48 @@ const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
onBack: onClose,
});
const canAddNewAdmins = Boolean(chat?.isCreator || chat?.adminRights?.addAdmins);
const areSignaturesEnabled = Boolean(chat?.areSignaturesShown);
const areProfilesEnabled = Boolean(chat?.areProfilesShown);
const canAddNewAdmins = Boolean(chat?.isCreator || (chat && getHasAdminRight(chat, 'addAdmins')));
const canToggleSignatures = isChannel && getHasAdminRight(chat!, 'postMessages');
const adminMembers = useMemo(() => {
if (!adminMembersById) {
return [];
}
return Object.values(adminMembersById).sort((a, b) => {
if (a.isOwner) {
return -1;
} else if (b.isOwner) {
return 1;
}
const [owner, admins] = partition(Object.values(adminMembersById), (member) => member.isOwner);
return 0;
});
return [...owner, ...admins];
}, [adminMembersById]);
const handleAdminMemberClick = useCallback((member: ApiChatMember) => {
const handleAdminMemberClick = useLastCallback((member: ApiChatMember) => {
onChatMemberSelect(member.userId, member.promotedByUserId === currentUserId);
onScreenSelect(ManagementScreens.ChatAdminRights);
}, [currentUserId, onChatMemberSelect, onScreenSelect]);
});
const handleAddAdminClick = useCallback(() => {
const handleToggleSignatures = useLastCallback(() => {
toggleSignatures({
chatId: chat!.id,
areProfilesEnabled,
areSignaturesEnabled: !areSignaturesEnabled,
});
});
const handleToggleProfiles = useLastCallback(() => {
toggleSignatures({
chatId: chat!.id,
areProfilesEnabled: !areProfilesEnabled,
areSignaturesEnabled,
});
});
const handleAddAdminClick = useLastCallback(() => {
onScreenSelect(ManagementScreens.GroupAddAdmins);
}, [onScreenSelect]);
});
const getMemberStatus = useCallback((member: ApiChatMember) => {
const getMemberStatus = useLastCallback((member: ApiChatMember) => {
if (member.isOwner) {
return lang('ChannelCreator');
}
@ -88,7 +106,7 @@ const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
}
return lang('ChannelAdmin');
}, [lang]);
});
return (
<div className="Management">
@ -106,9 +124,9 @@ const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
<div className="section" dir={lang.isRtl ? 'rtl' : undefined}>
<p className="text-muted" dir="auto">
{isChannel
? 'You can add administrators to help you manage your channel.'
: 'You can add administrators to help you manage your group.'}
{lang(isChannel
? 'Channel.Management.AddModeratorHelp'
: 'Group.Management.AddModeratorHelp')}
</p>
{adminMembers.map((member) => (
@ -134,6 +152,32 @@ const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
<i className="icon icon-add-user-filled" />
</FloatingActionButton>
</div>
{canToggleSignatures && (
<div className="section">
<div className="ListItem narrow">
<Checkbox
checked={areSignaturesEnabled}
label={lang('ChannelSignMessages')}
onChange={handleToggleSignatures}
/>
</div>
{areSignaturesEnabled && (
<>
<div className="ListItem narrow">
<Checkbox
checked={areProfilesEnabled}
label={lang('ChannelSignMessagesWithProfile')}
onChange={handleToggleProfiles}
/>
</div>
<p className="section-info">
{lang('ChannelSignProfilesInfo')}
</p>
</>
)}
</div>
)}
</div>
</div>
);
@ -142,7 +186,6 @@ const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => {
const chat = selectChat(global, chatId);
return {
chat,
currentUserId: global.currentUserId,

View File

@ -51,7 +51,7 @@ export const MEDIA_PROGRESSIVE_CACHE_DISABLED = false;
export const MEDIA_PROGRESSIVE_CACHE_NAME = 'tt-media-progressive';
export const MEDIA_CACHE_MAX_BYTES = 512 * 1024; // 512 KB
export const CUSTOM_BG_CACHE_NAME = 'tt-custom-bg';
export const LANG_CACHE_NAME = 'tt-lang-packs-v39';
export const LANG_CACHE_NAME = 'tt-lang-packs-v40';
export const ASSET_CACHE_NAME = 'tt-assets';
export const AUTODOWNLOAD_FILESIZE_MB_LIMITS = [1, 5, 10, 50, 100, 500];
export const DATA_BROADCAST_CHANNEL_NAME = 'tt-global';

View File

@ -238,7 +238,7 @@ addActionHandler('connectToActiveGroupCall', async (global, actions, payload): P
global = getGlobal();
const chat = selectChat(global, groupCall.chatId);
if (!chat) return;
await loadFullChat(global, actions, chat, tabId);
await loadFullChat(global, actions, chat);
}
});

View File

@ -547,7 +547,7 @@ addActionHandler('loadAllChats', async (global, actions, payload): Promise<void>
addActionHandler('loadFullChat', (global, actions, payload): ActionReturnType => {
const {
chatId, force, tabId = getCurrentTabId(), withPhotos,
chatId, force, withPhotos,
} = payload!;
const chat = selectChat(global, chatId);
if (!chat) {
@ -555,7 +555,7 @@ addActionHandler('loadFullChat', (global, actions, payload): ActionReturnType =>
}
const loadChat = async () => {
await loadFullChat(global, actions, chat, tabId);
await loadFullChat(global, actions, chat);
if (withPhotos) {
actions.loadMoreProfilePhotos({ peerId: chatId, shouldInvalidateCache: true });
}
@ -813,6 +813,8 @@ addActionHandler('leaveChannel', async (global, actions, payload): Promise<void>
global = deleteChatMessages(global, chatId, localMessageIds);
setGlobal(global);
}
actions.loadFullChat({ chatId, force: true });
});
addActionHandler('deleteChannel', (global, actions, payload): ActionReturnType => {
@ -1724,12 +1726,12 @@ addActionHandler('updateChat', async (global, actions, payload): Promise<void> =
setGlobal(global);
if (photo) {
actions.loadFullChat({ chatId, tabId, withPhotos: true });
actions.loadFullChat({ chatId, withPhotos: true });
}
});
addActionHandler('updateChatPhoto', async (global, actions, payload): Promise<void> => {
const { photo, chatId, tabId = getCurrentTabId() } = payload;
const { photo, chatId } = payload;
const chat = selectChat(global, chatId);
if (!chat) return;
@ -1738,11 +1740,11 @@ addActionHandler('updateChatPhoto', async (global, actions, payload): Promise<vo
accessHash: chat.accessHash,
photo,
});
actions.loadFullChat({ chatId, tabId, withPhotos: true });
actions.loadFullChat({ chatId, withPhotos: true });
});
addActionHandler('deleteChatPhoto', async (global, actions, payload): Promise<void> => {
const { photo, chatId, tabId = getCurrentTabId() } = payload;
const { photo, chatId } = payload;
const chat = selectChat(global, chatId);
if (!chat) return;
@ -1761,18 +1763,18 @@ addActionHandler('deleteChatPhoto', async (global, actions, payload): Promise<vo
global = deletePeerPhoto(global, chatId, photo.id);
setGlobal(global);
actions.loadFullChat({ chatId, tabId, withPhotos: true });
actions.loadFullChat({ chatId, withPhotos: true });
});
addActionHandler('toggleSignatures', (global, actions, payload): ActionReturnType => {
const { chatId, isEnabled } = payload;
const { chatId, areProfilesEnabled, areSignaturesEnabled } = payload;
const chat = selectChat(global, chatId);
if (!chat) {
return;
}
void callApi('toggleSignatures', { chat, isEnabled });
void callApi('toggleSignatures', { chat, areProfilesEnabled, areSignaturesEnabled });
});
addActionHandler('loadGroupsForDiscussion', async (global): Promise<void> => {
@ -1835,7 +1837,7 @@ addActionHandler('linkDiscussionGroup', async (global, actions, payload): Promis
});
addActionHandler('unlinkDiscussionGroup', async (global, actions, payload): Promise<void> => {
const { channelId, tabId = getCurrentTabId() } = payload;
const { channelId } = payload;
const channel = selectChat(global, channelId);
if (!channel) {
@ -1851,7 +1853,7 @@ addActionHandler('unlinkDiscussionGroup', async (global, actions, payload): Prom
await callApi('setDiscussionGroup', { channel });
if (chat) {
global = getGlobal();
loadFullChat(global, actions, chat, tabId);
loadFullChat(global, actions, chat);
}
});
@ -1928,11 +1930,11 @@ addActionHandler('addChatMembers', async (global, actions, payload): Promise<voi
}
actions.setNewChatMembersDialogState({ newChatMembersProgress: NewChatMembersProgress.Closed, tabId });
global = getGlobal();
loadFullChat(global, actions, chat, tabId);
loadFullChat(global, actions, chat);
});
addActionHandler('deleteChatMember', async (global, actions, payload): Promise<void> => {
const { chatId, userId, tabId = getCurrentTabId() } = payload;
const { chatId, userId } = payload;
const chat = selectChat(global, chatId);
const user = selectUser(global, userId);
@ -1942,7 +1944,7 @@ addActionHandler('deleteChatMember', async (global, actions, payload): Promise<v
await callApi('deleteChatMember', chat, user);
global = getGlobal();
loadFullChat(global, actions, chat, tabId);
loadFullChat(global, actions, chat);
});
addActionHandler('toggleIsProtected', (global, actions, payload): ActionReturnType => {
@ -1958,7 +1960,7 @@ addActionHandler('toggleIsProtected', (global, actions, payload): ActionReturnTy
addActionHandler('setChatEnabledReactions', async (global, actions, payload): Promise<void> => {
const {
chatId, enabledReactions, reactionsLimit, tabId = getCurrentTabId(),
chatId, enabledReactions, reactionsLimit,
} = payload;
const chat = selectChat(global, chatId);
if (!chat) return;
@ -1970,7 +1972,7 @@ addActionHandler('setChatEnabledReactions', async (global, actions, payload): Pr
});
global = getGlobal();
void loadFullChat(global, actions, chat, tabId);
void loadFullChat(global, actions, chat);
});
addActionHandler('fetchChat', (global, actions, payload): ActionReturnType => {
@ -2851,7 +2853,6 @@ async function loadChats(
export async function loadFullChat<T extends GlobalState>(
global: T, actions: RequiredGlobalActions, chat: ApiChat,
...[tabId = getCurrentTabId()]: TabArgs<T>
) {
const result = await callApi('fetchFullChat', chat);
if (!result) {
@ -2898,7 +2899,6 @@ export async function loadFullChat<T extends GlobalState>(
id: stickerSet.id,
accessHash: stickerSet.accessHash,
},
tabId,
});
}
@ -2910,7 +2910,6 @@ export async function loadFullChat<T extends GlobalState>(
id: emojiSet.id,
accessHash: emojiSet.accessHash,
},
tabId,
});
}
@ -3143,7 +3142,7 @@ export async function ensureIsSuperGroup<T extends GlobalState>(
return undefined;
}
actions.loadFullChat({ chatId: newChat.id, tabId });
actions.loadFullChat({ chatId: newChat.id });
actions.openChat({ id: newChat.id, tabId });
return newChat;

View File

@ -1,5 +1,6 @@
import type {
ApiChat, ApiGlobalMessageSearchType, ApiMessage, ApiTopic, ApiUser,
ApiUserStatus,
} from '../../../api/types';
import type { ActionReturnType, GlobalState, TabArgs } from '../../types';
@ -16,6 +17,7 @@ import {
addChats,
addMessages,
addUsers,
addUserStatuses,
updateGlobalSearch,
updateGlobalSearchFetchingStatus,
updateGlobalSearchResults,
@ -98,6 +100,11 @@ addActionHandler('searchMessagesGlobal', (global, actions, payload): ActionRetur
const offsetRate = (resultsByType?.[type])?.nextOffsetRate;
const offsetPeerId = (resultsByType?.[type])?.nextOffsetPeerId;
// Stop loading if we have all the messages
if (resultsByType?.[type]?.totalCount && resultsByType[type]!.totalCount! >= resultsByType[type]!.foundIds.length) {
return;
}
const chat = chatId ? selectChat(global, chatId) : undefined;
const offsetPeer = offsetPeerId ? selectChat(global, offsetPeerId) : undefined;
@ -161,6 +168,7 @@ async function searchMessagesGlobal<T extends GlobalState>(global: T, params: {
let result: {
messages: ApiMessage[];
users: ApiUser[];
userStatusesById?: Record<number, ApiUserStatus>;
chats: ApiChat[];
topics?: ApiTopic[];
totalTopicsCount?: number;
@ -241,7 +249,7 @@ async function searchMessagesGlobal<T extends GlobalState>(global: T, params: {
}
const {
messages, users, chats, totalCount, nextOffsetRate, nextOffsetId, nextOffsetPeerId,
messages, users, chats, userStatusesById, totalCount, nextOffsetRate, nextOffsetId, nextOffsetPeerId,
} = result;
if (chats.length) {
@ -252,6 +260,10 @@ async function searchMessagesGlobal<T extends GlobalState>(global: T, params: {
global = addUsers(global, buildCollectionByKey(users, 'id'));
}
if (userStatusesById) {
global = addUserStatuses(global, userStatusesById);
}
if (messages.length) {
global = addMessages(global, messages);
}

View File

@ -21,6 +21,7 @@ import {
addChats,
addMessages,
addUsers,
addUserStatuses,
initializeChatMediaSearchResults,
mergeWithChatMediaSearchSegment,
setChatMediaSearchLoading,
@ -125,7 +126,7 @@ addActionHandler('performMiddleSearch', async (global, actions, payload): Promis
}
const {
chats, users, messages, totalCount, nextOffsetId, nextOffsetRate, nextOffsetPeerId,
chats, users, userStatusesById, messages, totalCount, nextOffsetId, nextOffsetRate, nextOffsetPeerId,
} = result;
const newFoundIds = messages.map(getSearchResultKey);
@ -143,6 +144,7 @@ addActionHandler('performMiddleSearch', async (global, actions, payload): Promis
global = addChats(global, buildCollectionByKey(chats, 'id'));
global = addUsers(global, buildCollectionByKey(users, 'id'));
global = addUserStatuses(global, userStatusesById);
global = addMessages(global, messages);
global = updateMiddleSearch(global, resultChatId, threadId, {
fetchingQuery: undefined,

View File

@ -1018,7 +1018,9 @@ addActionHandler('loadStarStatus', async (global): Promise<void> => {
},
},
};
global = appendStarsTransactions(global, 'all', status.history, status.nextOffset);
if (status.history) {
global = appendStarsTransactions(global, 'all', status.history, status.nextOffset);
}
setGlobal(global);
});
@ -1044,6 +1046,8 @@ addActionHandler('loadStarsTransactions', async (global, actions, payload): Prom
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
global = updateStarsBalance(global, result.balance);
global = appendStarsTransactions(global, type, result.history, result.nextOffset);
if (result.history) {
global = appendStarsTransactions(global, type, result.history, result.nextOffset);
}
setGlobal(global);
});

View File

@ -760,7 +760,7 @@ addActionHandler('toggleUsername', async (global, actions, payload): Promise<voi
addActionHandler('toggleChatUsername', async (global, actions, payload): Promise<void> => {
const {
chatId, username, isActive, tabId = getCurrentTabId(),
chatId, username, isActive,
} = payload;
const chat = selectChat(global, chatId);
if (!chat?.usernames) {
@ -786,7 +786,7 @@ addActionHandler('toggleChatUsername', async (global, actions, payload): Promise
});
if (!result) {
actions.loadFullChat({ chatId, tabId });
actions.loadFullChat({ chatId });
}
});

View File

@ -68,8 +68,7 @@ addActionHandler('loadStickerSets', async (global, actions): Promise<void> => {
});
});
addActionHandler('loadAddedStickers', async (global, actions, payload): Promise<void> => {
const { tabId = getCurrentTabId() } = payload || {};
addActionHandler('loadAddedStickers', async (global, actions): Promise<void> => {
const {
added: {
setIds: addedSetIds = [],
@ -93,7 +92,6 @@ addActionHandler('loadAddedStickers', async (global, actions, payload): Promise<
}
actions.loadStickers({
stickerSetInfo: { id, accessHash: cached[id].accessHash },
tabId,
});
if (i % ADDED_SETS_THROTTLE_CHUNK === 0 && i > 0) {
@ -242,10 +240,10 @@ addActionHandler('loadDefaultStatusIcons', async (global): Promise<void> => {
});
addActionHandler('loadStickers', (global, actions, payload): ActionReturnType => {
const { stickerSetInfo, tabId = getCurrentTabId() } = payload;
const { stickerSetInfo } = payload;
const cachedSet = selectStickerSet(global, stickerSetInfo);
if (cachedSet && cachedSet.count === cachedSet?.stickers?.length) return; // Already fully loaded
void loadStickers(global, actions, stickerSetInfo, tabId);
void loadStickers(global, actions, stickerSetInfo);
});
addActionHandler('loadAnimatedEmojis', async (global): Promise<void> => {
@ -552,7 +550,6 @@ async function loadStickers<T extends GlobalState>(
global: T,
actions: RequiredGlobalActions,
stickerSetInfo: ApiStickerSetInfo,
...[tabId = getCurrentTabId()]: TabArgs<T>
) {
let stickerSet: { set: ApiStickerSet; stickers: ApiSticker[]; packs: Record<string, ApiSticker[]> } | undefined;
try {
@ -562,18 +559,20 @@ async function loadStickers<T extends GlobalState>(
);
} catch (error) {
if ((error as ApiError).message === 'STICKERSET_INVALID') {
actions.showNotification({
message: oldTranslate('StickerPack.ErrorNotFound'),
tabId,
});
Object.values(global.byTabId).forEach(({ id: tabId }) => {
actions.showNotification({
message: oldTranslate('StickerPack.ErrorNotFound'),
tabId,
});
if ('shortName' in stickerSetInfo
&& selectTabState(global, tabId).openedStickerSetShortName === stickerSetInfo.shortName) {
global = updateTabState(global, {
openedStickerSetShortName: undefined,
}, tabId);
setGlobal(global);
}
if ('shortName' in stickerSetInfo
&& selectTabState(global, tabId).openedStickerSetShortName === stickerSetInfo.shortName) {
global = updateTabState(global, {
openedStickerSetShortName: undefined,
}, tabId);
setGlobal(global);
}
});
return;
}
}
@ -747,7 +746,7 @@ addActionHandler('loadFeaturedEmojiStickers', async (global): Promise<void> => {
addActionHandler('openStickerSet', async (global, actions, payload): Promise<void> => {
const { stickerSetInfo, tabId = getCurrentTabId() } = payload;
if (!selectStickerSet(global, stickerSetInfo)) {
await loadStickers(global, actions, stickerSetInfo, tabId);
await loadStickers(global, actions, stickerSetInfo);
}
global = getGlobal();

View File

@ -6,7 +6,6 @@ import { ARCHIVED_FOLDER_ID, MAX_ACTIVE_PINNED_CHATS } from '../../../config';
import { buildCollectionByKey, omit } from '../../../util/iteratees';
import { isLocalMessageId } from '../../../util/keys/messageKey';
import { closeMessageNotifications, notifyAboutMessage } from '../../../util/notifications';
import { buildLocalMessage } from '../../../api/gramjs/apiBuilders/messages';
import { checkIfHasUnreadReactions, isChatChannel } from '../../helpers';
import {
addActionHandler, getGlobal, setGlobal,
@ -30,7 +29,6 @@ import { updateTabState } from '../../reducers/tabs';
import {
selectChat,
selectChatFullInfo,
selectChatLastMessageId,
selectChatListType,
selectChatMessages,
selectCommonBoxChatId,
@ -98,31 +96,7 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
case 'updateChatJoin': {
const listType = selectChatListType(global, update.id);
const chat = selectChat(global, update.id);
if (chat && isChatChannel(chat)) {
actions.loadChannelRecommendations({ chatId: chat.id });
const lastMessageId = selectChatLastMessageId(global, chat.id);
const localMessage = buildLocalMessage(chat, lastMessageId);
localMessage.content.action = {
mediaType: 'action',
text: 'you joined this channel',
translationValues: ['ChannelJoined'],
type: 'joinedChannel',
targetChatId: chat.id,
};
actions.apiUpdate({
'@type': 'newMessage',
id: localMessage.id,
chatId: chat.id,
message: localMessage,
});
}
if (!listType) {
return undefined;
}
global = updateChatListIds(global, listType, [update.id]);
global = updateChat(global, update.id, { isNotJoined: false });
setGlobal(global);
@ -130,6 +104,16 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
actions.requestChatUpdate({ chatId: chat.id });
}
actions.loadFullChat({ chatId: update.id, force: true });
if (!listType) {
return undefined;
}
global = getGlobal();
global = updateChatListIds(global, listType, [update.id]);
setGlobal(global);
return undefined;
}

View File

@ -463,7 +463,7 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
const tabId = getCurrentTabId();
global = deleteChatMessages(global, chatId, Object.keys(messagesById).map(Number));
setGlobal(global);
actions.loadFullChat({ chatId, force: true, tabId });
actions.loadFullChat({ chatId, force: true });
actions.loadViewportMessages({ chatId, threadId: MAIN_THREAD_ID, tabId });
}

View File

@ -228,7 +228,7 @@ addActionHandler('joinVoiceChatByLink', async (global, actions, payload): Promis
}
global = getGlobal();
const full = await loadFullChat(global, actions, chat, tabId);
const full = await loadFullChat(global, actions, chat);
if (full?.groupCall) {
actions.requestMasterAndJoinGroupCall({
@ -308,7 +308,7 @@ addActionHandler('joinGroupCall', async (global, actions, payload): Promise<void
if (!chat) return;
await loadFullChat(global, actions, chat, tabId);
await loadFullChat(global, actions, chat);
global = getGlobal();
groupCall = selectChatGroupCall(global, chatId);
} else if (!groupCall && id && accessHash) {

View File

@ -210,23 +210,6 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
cached.appConfig.limits = DEFAULT_LIMITS;
}
if (!cached.archiveSettings) {
cached.archiveSettings = initialState.archiveSettings;
}
if (!cached.stories) {
cached.stories = initialState.stories;
}
if (!cached.stories.stealthMode) {
cached.stories.stealthMode = initialState.stories.stealthMode;
}
if (!cached.stories.byPeerId) {
cached.stories.byPeerId = initialState.stories.byPeerId;
cached.stories.orderedPeerIds = initialState.stories.orderedPeerIds;
}
if (!cached.chats.similarChannelsById) {
cached.chats.similarChannelsById = initialState.chats.similarChannelsById;
}
@ -259,6 +242,9 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
if (!cached.chats.loadingParameters) {
cached.chats.loadingParameters = initialState.chats.loadingParameters;
}
if (!cached.topBotApps) {
cached.topBotApps = initialState.topBotApps;
}
}
function updateCache(force?: boolean) {

View File

@ -181,7 +181,7 @@ export function isServiceNotificationMessage(message: ApiMessage) {
}
export function isAnonymousOwnMessage(message: ApiMessage) {
return Boolean(message.senderId) && !isUserId(message.senderId!) && isOwnMessage(message);
return Boolean(message.senderId) && !isUserId(message.senderId) && isOwnMessage(message);
}
export function getSenderTitle(lang: LangFn, sender: ApiPeer) {

View File

@ -532,7 +532,6 @@ export function toggleSimilarChannels<T extends GlobalState>(
chatId: string,
) {
const similarChannels = global.chats.similarChannelsById[chatId];
const shouldShowInChat = !global.chats.similarChannelsById[chatId].shouldShowInChat;
return {
...global,
@ -542,7 +541,7 @@ export function toggleSimilarChannels<T extends GlobalState>(
...global.chats.similarChannelsById,
[chatId]: {
...similarChannels,
shouldShowInChat,
shouldShowInChat: !similarChannels.shouldShowInChat,
},
},
},

View File

@ -52,7 +52,18 @@ export function updateGlobalSearchResults<T extends GlobalState>(
(newId) => foundIdsForType.includes(getSearchResultKey(newFoundMessagesById[newId])),
)
) {
return updateGlobalSearchFetchingStatus(global, { messages: false }, tabId);
global = updateGlobalSearchFetchingStatus(global, { messages: false }, tabId);
return updateGlobalSearch(global, {
resultsByType: {
...(selectTabState(global, tabId).globalSearch || {}).resultsByType,
[type]: {
totalCount,
nextOffsetId,
nextOffsetRate,
nextOffsetPeerId,
},
},
}, tabId);
}
const prevFoundIds = foundIdsForType || [];

View File

@ -413,12 +413,12 @@ export function selectOutgoingStatus<T extends GlobalState>(
export function selectSender<T extends GlobalState>(global: T, message: ApiMessage): ApiPeer | undefined {
const { senderId } = message;
const chat = selectChat(global, message.chatId);
if (!senderId) {
return undefined;
return chat;
}
const chat = selectChat(global, message.chatId);
if (chat && isChatChannel(chat)) return chat;
if (chat && isChatChannel(chat) && !chat.areProfilesShown) return chat;
return selectPeer(global, senderId);
}

View File

@ -1423,7 +1423,7 @@ export interface ActionPayloads {
deleteChatMember: {
chatId: string;
userId: string;
} & WithTabId;
};
openPreviousChat: WithTabId | undefined;
editChatFolders: {
chatId: string;
@ -2094,7 +2094,8 @@ export interface ActionPayloads {
};
toggleSignatures: {
chatId: string;
isEnabled: boolean;
areSignaturesEnabled: boolean;
areProfilesEnabled: boolean;
};
loadGroupsForDiscussion: undefined;
linkDiscussionGroup: {
@ -2103,7 +2104,7 @@ export interface ActionPayloads {
} & WithTabId;
unlinkDiscussionGroup: {
channelId: string;
} & WithTabId;
};
openSavedDialog: {
chatId: string;
@ -2148,15 +2149,15 @@ export interface ActionPayloads {
chatId: string;
withPhotos?: boolean;
force?: boolean;
} & WithTabId;
};
updateChatPhoto: {
chatId: string;
photo: ApiPhoto;
} & WithTabId;
};
deleteChatPhoto: {
chatId: string;
photo: ApiPhoto;
} & WithTabId;
};
openChatWithDraft: {
chatId?: string;
threadId?: ThreadId;
@ -2389,7 +2390,7 @@ export interface ActionPayloads {
chatId: string;
enabledReactions?: ApiChatReactions;
reactionsLimit?: number;
} & WithTabId;
};
startActiveReaction: {
containerId: string;
@ -2740,7 +2741,7 @@ export interface ActionPayloads {
// Stickers
loadStickers: {
stickerSetInfo: ApiStickerSetInfo;
} & WithTabId;
};
loadAnimatedEmojis: undefined;
loadGreetingStickers: undefined;
loadGenericEmojiEffects: undefined;
@ -2759,7 +2760,7 @@ export interface ActionPayloads {
clearRecentStickers: undefined;
loadStickerSets: undefined;
loadAddedStickers: WithTabId | undefined;
loadAddedStickers: undefined;
loadRecentStickers: undefined;
loadFavoriteStickers: undefined;
loadFeaturedStickers: undefined;
@ -3005,7 +3006,7 @@ export interface ActionPayloads {
chatId: string;
username: string;
isActive: boolean;
} & WithTabId;
};
sortChatUsernames: {
chatId: string;
usernames: string[];

View File

@ -1,6 +1,6 @@
const api = require('./api');
const LAYER = 185;
const LAYER = 186;
const tlobjects = {};
for (const tl of Object.values(api)) {

File diff suppressed because one or more lines are too long

View File

@ -80,10 +80,10 @@ userStatusLastMonth#65899777 flags:# by_me:flags.0?true = UserStatus;
chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#6592a1a7 id:long title:string = Chat;
channel#aadfc8f flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int = Chat;
channel#fe4478bd flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
chatParticipantAdmin#a0933f5b user_id:long inviter_id:long date:int = ChatParticipant;
@ -508,10 +508,10 @@ account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:f
account.passwordInputSettings#c23727c9 flags:# new_algo:flags.0?PasswordKdfAlgo new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string new_secure_settings:flags.2?SecureSecretSettings = account.PasswordInputSettings;
auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage;
chatInviteExported#ab4a819 flags:# revoked:flags.0?true permanent:flags.5?true request_needed:flags.6?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int requested:flags.7?int title:flags.8?string = ExportedChatInvite;
chatInviteExported#a22cbd96 flags:# revoked:flags.0?true permanent:flags.5?true request_needed:flags.6?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int requested:flags.7?int subscription_expired:flags.10?int title:flags.8?string subscription_pricing:flags.9?StarsSubscriptionPricing = ExportedChatInvite;
chatInvitePublicJoinRequests#ed107ab7 = ExportedChatInvite;
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
chatInvite#cde0ec40 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true verified:flags.7?true scam:flags.8?true fake:flags.9?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector<User> color:int = ChatInvite;
chatInvite#fe65389d flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true verified:flags.7?true scam:flags.8?true fake:flags.9?true can_refulfill_subscription:flags.11?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector<User> color:int subscription_pricing:flags.10?StarsSubscriptionPricing subscription_form_id:flags.12?long = ChatInvite;
chatInvitePeek#61695cb0 chat:Chat expires:int = ChatInvite;
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
@ -528,7 +528,7 @@ stickerSet#2dd14edc flags:# archived:flags.1?true official:flags.2?true masks:fl
messages.stickerSet#6e153f16 set:StickerSet packs:Vector<StickerPack> keywords:Vector<StickerKeyword> documents:Vector<Document> = messages.StickerSet;
messages.stickerSetNotModified#d3f924eb = messages.StickerSet;
botCommand#c27ac8c7 command:string description:string = BotCommand;
botInfo#8f300b57 flags:# has_preview_medias:flags.6?true user_id:flags.0?long description:flags.1?string description_photo:flags.4?Photo description_document:flags.5?Document commands:flags.2?Vector<BotCommand> menu_button:flags.3?BotMenuButton = BotInfo;
botInfo#82437e74 flags:# has_preview_medias:flags.6?true user_id:flags.0?long description:flags.1?string description_photo:flags.4?Photo description_document:flags.5?Document commands:flags.2?Vector<BotCommand> menu_button:flags.3?BotMenuButton privacy_policy_url:flags.7?string = BotInfo;
keyboardButton#a2fa4880 text:string = KeyboardButton;
keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton;
keyboardButtonCallback#35bbdb6b flags:# requires_password:flags.0?true text:string data:bytes = KeyboardButton;
@ -582,8 +582,8 @@ updates.channelDifferenceTooLong#a4bcc6fe flags:# final:flags.0?true timeout:fla
updates.channelDifference#2064674e flags:# final:flags.0?true pts:int timeout:flags.1?int new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
channelMessagesFilter#cd77d957 flags:# exclude_new_messages:flags.1?true ranges:Vector<MessageRange> = ChannelMessagesFilter;
channelParticipant#c00c07c0 user_id:long date:int = ChannelParticipant;
channelParticipantSelf#35a8bfa7 flags:# via_request:flags.0?true user_id:long inviter_id:long date:int = ChannelParticipant;
channelParticipant#cb397619 flags:# user_id:long date:int subscription_until_date:flags.0?int = ChannelParticipant;
channelParticipantSelf#4f607bef flags:# via_request:flags.0?true user_id:long inviter_id:long date:int subscription_until_date:flags.1?int = ChannelParticipant;
channelParticipantCreator#2fe601d3 flags:# user_id:long admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant;
channelParticipantAdmin#34c3bb53 flags:# can_edit:flags.0?true self:flags.1?true user_id:long inviter_id:flags.1?long promoted_by:long date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant;
channelParticipantBanned#6df8014e flags:# left:flags.0?true peer:Peer kicked_by:long date:int banned_rights:ChatBannedRights = ChannelParticipant;
@ -829,6 +829,7 @@ channelAdminLogEventActionChangeProfilePeerColor#5e477b25 prev_value:PeerColor n
channelAdminLogEventActionChangeWallpaper#31bb5d52 prev_value:WallPaper new_value:WallPaper = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeEmojiStatus#3ea9feb1 prev_value:EmojiStatus new_value:EmojiStatus = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeEmojiStickerSet#46d840ab prev_stickerset:InputStickerSet new_stickerset:InputStickerSet = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleSignatureProfiles#60a79c79 new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
channels.adminLogResults#ed8af74d events:Vector<ChannelAdminLogEvent> chats:Vector<Chat> users:Vector<User> = channels.AdminLogResults;
channelAdminLogEventsFilter#ea107ae4 flags:# join:flags.0?true leave:flags.1?true invite:flags.2?true ban:flags.3?true unban:flags.4?true kick:flags.5?true unkick:flags.6?true promote:flags.7?true demote:flags.8?true info:flags.9?true settings:flags.10?true pinned:flags.11?true edit:flags.12?true delete:flags.13?true group_call:flags.14?true invites:flags.15?true send:flags.16?true forums:flags.17?true = ChannelAdminLogEventsFilter;
@ -1057,7 +1058,7 @@ botCommandScopePeerUser#a1321f3 peer:InputPeer user_id:InputUser = BotCommandSco
account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordResult;
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
sponsoredMessage#bdedf566 flags:# recommended:flags.5?true can_report:flags.12?true random_id:bytes url:string title:string message:string entities:flags.1?Vector<MessageEntity> photo:flags.6?Photo color:flags.13?PeerColor button_text:string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
sponsoredMessage#4d93a990 flags:# recommended:flags.5?true can_report:flags.12?true random_id:bytes url:string title:string message:string entities:flags.1?Vector<MessageEntity> photo:flags.6?Photo media:flags.14?MessageMedia color:flags.13?PeerColor button_text:string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
messages.sponsoredMessages#c9ee1d87 flags:# posts_between:flags.0?int messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;
messages.sponsoredMessagesEmpty#1839490f = messages.SponsoredMessages;
searchResultsCalendarPeriod#c9b0539f date:int min_msg_id:int max_msg_id:int count:int = SearchResultsCalendarPeriod;
@ -1069,7 +1070,7 @@ users.userFull#3b6d152e full_user:UserFull chats:Vector<Chat> users:Vector<User>
messages.peerSettings#6880b94d settings:PeerSettings chats:Vector<Chat> users:Vector<User> = messages.PeerSettings;
auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes = auth.LoggedOut;
reactionCount#a3d1cb80 flags:# chosen_order:flags.0?int reaction:Reaction count:int = ReactionCount;
messageReactions#4f2b9479 flags:# min:flags.0?true can_see_list:flags.2?true reactions_as_tags:flags.3?true results:Vector<ReactionCount> recent_reactions:flags.1?Vector<MessagePeerReaction> = MessageReactions;
messageReactions#a339f0b flags:# min:flags.0?true can_see_list:flags.2?true reactions_as_tags:flags.3?true results:Vector<ReactionCount> recent_reactions:flags.1?Vector<MessagePeerReaction> top_reactors:flags.4?Vector<MessageReactor> = MessageReactions;
messages.messageReactionsList#31bd492d flags:# count:int reactions:Vector<MessagePeerReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.MessageReactionsList;
availableReaction#c077ec01 flags:# inactive:flags.0?true premium:flags.2?true reaction:string title:string static_icon:Document appear_animation:Document select_animation:Document activate_animation:Document effect_animation:Document around_animation:flags.1?Document center_icon:flags.1?Document = AvailableReaction;
messages.availableReactionsNotModified#9f071957 = messages.AvailableReactions;
@ -1106,6 +1107,7 @@ inputInvoiceMessage#c5b56859 peer:InputPeer msg_id:int = InputInvoice;
inputInvoiceSlug#c326caef slug:string = InputInvoice;
inputInvoicePremiumGiftCode#98986c0d purpose:InputStorePaymentPurpose option:PremiumGiftCodeOption = InputInvoice;
inputInvoiceStars#65f00ce3 purpose:InputStorePaymentPurpose = InputInvoice;
inputInvoiceChatInviteSubscription#34e793f1 hash:string = InputInvoice;
payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
messages.transcribedAudio#cfb9d957 flags:# pending:flags.0?true transcription_id:long text:string trial_remains_num:flags.1?int trial_remains_until_date:flags.1?int = messages.TranscribedAudio;
help.premiumPromo#5334759c status_text:string status_entities:Vector<MessageEntity> video_sections:Vector<string> videos:Vector<Document> period_options:Vector<PremiumSubscriptionOption> users:Vector<User> = help.PremiumPromo;
@ -1125,6 +1127,7 @@ account.emojiStatuses#90c467d1 hash:long statuses:Vector<EmojiStatus> = account.
reactionEmpty#79f5d419 = Reaction;
reactionEmoji#1b2286b8 emoticon:string = Reaction;
reactionCustomEmoji#8935fc73 document_id:long = Reaction;
reactionPaid#523da4eb = Reaction;
chatReactionsNone#eafc32bc = ChatReactions;
chatReactionsAll#52928bca flags:# allow_custom:flags.0?true = ChatReactions;
chatReactionsSome#661d4037 reactions:Vector<Reaction> = ChatReactions;
@ -1320,8 +1323,8 @@ starsTransactionPeerFragment#e92fd902 = StarsTransactionPeer;
starsTransactionPeer#d80da15d peer:Peer = StarsTransactionPeer;
starsTransactionPeerAds#60682812 = StarsTransactionPeer;
starsTopupOption#bd915c0 flags:# extended:flags.1?true stars:long store_product:flags.0?string currency:string amount:long = StarsTopupOption;
starsTransaction#2db5418f flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true id:string stars:long date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector<MessageMedia> = StarsTransaction;
payments.starsStatus#8cf4ee60 flags:# balance:long history:Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
starsTransaction#433aeb2b flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true reaction:flags.11?true id:string stars:long date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector<MessageMedia> subscription_period:flags.12?int = StarsTransaction;
payments.starsStatus#bbfa316c flags:# balance:long subscriptions:flags.1?Vector<StarsSubscription> subscriptions_next_offset:flags.2?string subscriptions_missing_balance:flags.4?long history:flags.3?Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
foundStory#e87acbc0 peer:Peer story:StoryItem = FoundStory;
stories.foundStories#e2de7737 flags:# count:int stories:Vector<FoundStory> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = stories.FoundStories;
geoPointAddress#de4c5d93 flags:# country_iso2:string state:flags.0?string city:flags.1?string street:flags.2?string = GeoPointAddress;
@ -1334,6 +1337,9 @@ starsGiftOption#5e0589f1 flags:# extended:flags.1?true stars:long store_product:
bots.popularAppBots#1991b13b flags:# next_offset:flags.0?string users:Vector<User> = bots.PopularAppBots;
botPreviewMedia#23e91ba3 date:int media:MessageMedia = BotPreviewMedia;
bots.previewInfo#ca71d64 media:Vector<BotPreviewMedia> lang_codes:Vector<string> = bots.PreviewInfo;
starsSubscriptionPricing#5416d58 period:int amount:long = StarsSubscriptionPricing;
starsSubscription#538ecf18 flags:# canceled:flags.0?true can_refulfill:flags.1?true missing_balance:flags.2?true id:string peer:Peer until_date:int pricing:StarsSubscriptionPricing chat_invite_hash:flags.3?string = StarsSubscription;
messageReactor#4ba3a95a flags:# top:flags.0?true my:flags.1?true anonymous:flags.2?true peer_id:flags.3?Peer count:int = MessageReactor;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
initConnection#c1cd5ea9 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy params:flags.1?JSONValue query:!X = X;
@ -1437,7 +1443,7 @@ messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages
messages.getStickers#d5a5d3a1 emoticon:string hash:long = messages.Stickers;
messages.getAllStickers#b8a0a1a8 hash:long = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#a02ce5d5 flags:# legacy_revoke_permanent:flags.2?true request_needed:flags.3?true peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int title:flags.4?string = ExportedChatInvite;
messages.exportChatInvite#a455de90 flags:# legacy_revoke_permanent:flags.2?true request_needed:flags.3?true peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int title:flags.4?string subscription_pricing:flags.5?StarsSubscriptionPricing = ExportedChatInvite;
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
messages.importChatInvite#6c50051c hash:string = Updates;
messages.getStickerSet#c8a0ec74 stickerset:InputStickerSet hash:int = messages.StickerSet;
@ -1499,7 +1505,7 @@ messages.getExportedChatInvites#a2b5a3f6 flags:# revoked:flags.3?true peer:Input
messages.editExportedChatInvite#bdca2f75 flags:# revoked:flags.2?true peer:InputPeer link:string expire_date:flags.0?int usage_limit:flags.1?int request_needed:flags.3?Bool title:flags.4?string = messages.ExportedChatInvite;
messages.deleteRevokedExportedChatInvites#56987bd5 peer:InputPeer admin_id:InputUser = Bool;
messages.deleteExportedChatInvite#d464a42b peer:InputPeer link:string = Bool;
messages.getChatInviteImporters#df04dd4e flags:# requested:flags.0?true peer:InputPeer link:flags.1?string q:flags.2?string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
messages.getChatInviteImporters#df04dd4e flags:# requested:flags.0?true subscription_expired:flags.3?true peer:InputPeer link:flags.1?string q:flags.2?string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
messages.getMessageReadParticipants#31c1c44f peer:InputPeer msg_id:int = Vector<ReadParticipantDate>;
messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPeer user_id:InputUser = Updates;
messages.hideAllChatJoinRequests#e085f4ea flags:# approved:flags.0?true peer:InputPeer link:flags.1?string = Updates;
@ -1508,7 +1514,7 @@ messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;
messages.sendReaction#d30d78d4 flags:# big:flags.1?true add_to_recent:flags.2?true peer:InputPeer msg_id:int reaction:flags.0?Vector<Reaction> = Updates;
messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates;
messages.getMessageReactionsList#461b3f48 flags:# peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = messages.MessageReactionsList;
messages.setChatAvailableReactions#5a150bd4 flags:# peer:InputPeer available_reactions:ChatReactions reactions_limit:flags.0?int = Updates;
messages.setChatAvailableReactions#864b2581 flags:# peer:InputPeer available_reactions:ChatReactions reactions_limit:flags.0?int paid_enabled:flags.1?Bool = Updates;
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
messages.translateText#63183030 flags:# peer:flags.0?InputPeer id:flags.0?Vector<int> text:flags.1?Vector<TextWithEntities> to_lang:string = messages.TranslatedText;
@ -1587,7 +1593,7 @@ channels.leaveChannel#f836aa95 channel:InputChannel = Updates;
channels.inviteToChannel#c9e33d54 channel:InputChannel users:Vector<InputUser> = messages.InvitedUsers;
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
channels.exportMessageLink#e63fadeb flags:# grouped:flags.0?true thread:flags.1?true channel:InputChannel id:int = ExportedMessageLink;
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
channels.toggleSignatures#418d549c flags:# signatures_enabled:flags.0?true profiles_enabled:flags.1?true channel:InputChannel = Updates;
channels.editBanned#96e6cd81 channel:InputChannel participant:InputPeer banned_rights:ChatBannedRights = Updates;
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
@ -1632,7 +1638,7 @@ payments.getGiveawayInfo#f4239425 peer:InputPeer msg_id:int = payments.GiveawayI
payments.launchPrepaidGiveaway#5ff58f20 peer:InputPeer giveaway_id:long purpose:InputStorePaymentPurpose = Updates;
payments.getStarsTopupOptions#c00ec7d3 = Vector<StarsTopupOption>;
payments.getStarsStatus#104fcfa7 peer:InputPeer = payments.StarsStatus;
payments.getStarsTransactions#97938d5a flags:# inbound:flags.0?true outbound:flags.1?true ascending:flags.2?true peer:InputPeer offset:string limit:int = payments.StarsStatus;
payments.getStarsTransactions#69da4557 flags:# inbound:flags.0?true outbound:flags.1?true ascending:flags.2?true subscription_id:flags.3?string peer:InputPeer offset:string limit:int = payments.StarsStatus;
payments.sendStarsForm#2bb731d flags:# form_id:long invoice:InputInvoice = payments.PaymentResult;
payments.refundStarsCharge#25ae8f4a user_id:InputUser charge_id:string = Updates;
payments.getStarsTransactionsByID#27842d2e peer:InputPeer id:Vector<InputStarsTransaction> = payments.StarsStatus;

View File

@ -197,6 +197,7 @@
"channels.getMessages",
"channels.getParticipants",
"channels.getParticipant",
"channels.getParticipant",
"channels.getChannels",
"channels.getFullChannel",
"channels.createChannel",

View File

@ -99,11 +99,11 @@ userStatusLastMonth#65899777 flags:# by_me:flags.0?true = UserStatus;
chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#6592a1a7 id:long title:string = Chat;
channel#aadfc8f flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int = Chat;
channel#fe4478bd flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@ -605,11 +605,11 @@ auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage;
chatInviteExported#ab4a819 flags:# revoked:flags.0?true permanent:flags.5?true request_needed:flags.6?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int requested:flags.7?int title:flags.8?string = ExportedChatInvite;
chatInviteExported#a22cbd96 flags:# revoked:flags.0?true permanent:flags.5?true request_needed:flags.6?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int requested:flags.7?int subscription_expired:flags.10?int title:flags.8?string subscription_pricing:flags.9?StarsSubscriptionPricing = ExportedChatInvite;
chatInvitePublicJoinRequests#ed107ab7 = ExportedChatInvite;
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
chatInvite#cde0ec40 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true verified:flags.7?true scam:flags.8?true fake:flags.9?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector<User> color:int = ChatInvite;
chatInvite#fe65389d flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true verified:flags.7?true scam:flags.8?true fake:flags.9?true can_refulfill_subscription:flags.11?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector<User> color:int subscription_pricing:flags.10?StarsSubscriptionPricing subscription_form_id:flags.12?long = ChatInvite;
chatInvitePeek#61695cb0 chat:Chat expires:int = ChatInvite;
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
@ -631,7 +631,7 @@ messages.stickerSetNotModified#d3f924eb = messages.StickerSet;
botCommand#c27ac8c7 command:string description:string = BotCommand;
botInfo#8f300b57 flags:# has_preview_medias:flags.6?true user_id:flags.0?long description:flags.1?string description_photo:flags.4?Photo description_document:flags.5?Document commands:flags.2?Vector<BotCommand> menu_button:flags.3?BotMenuButton = BotInfo;
botInfo#82437e74 flags:# has_preview_medias:flags.6?true user_id:flags.0?long description:flags.1?string description_photo:flags.4?Photo description_document:flags.5?Document commands:flags.2?Vector<BotCommand> menu_button:flags.3?BotMenuButton privacy_policy_url:flags.7?string = BotInfo;
keyboardButton#a2fa4880 text:string = KeyboardButton;
keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton;
@ -695,8 +695,8 @@ updates.channelDifference#2064674e flags:# final:flags.0?true pts:int timeout:fl
channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
channelMessagesFilter#cd77d957 flags:# exclude_new_messages:flags.1?true ranges:Vector<MessageRange> = ChannelMessagesFilter;
channelParticipant#c00c07c0 user_id:long date:int = ChannelParticipant;
channelParticipantSelf#35a8bfa7 flags:# via_request:flags.0?true user_id:long inviter_id:long date:int = ChannelParticipant;
channelParticipant#cb397619 flags:# user_id:long date:int subscription_until_date:flags.0?int = ChannelParticipant;
channelParticipantSelf#4f607bef flags:# via_request:flags.0?true user_id:long inviter_id:long date:int subscription_until_date:flags.1?int = ChannelParticipant;
channelParticipantCreator#2fe601d3 flags:# user_id:long admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant;
channelParticipantAdmin#34c3bb53 flags:# can_edit:flags.0?true self:flags.1?true user_id:long inviter_id:flags.1?long promoted_by:long date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant;
channelParticipantBanned#6df8014e flags:# left:flags.0?true peer:Peer kicked_by:long date:int banned_rights:ChatBannedRights = ChannelParticipant;
@ -1012,6 +1012,7 @@ channelAdminLogEventActionChangeProfilePeerColor#5e477b25 prev_value:PeerColor n
channelAdminLogEventActionChangeWallpaper#31bb5d52 prev_value:WallPaper new_value:WallPaper = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeEmojiStatus#3ea9feb1 prev_value:EmojiStatus new_value:EmojiStatus = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeEmojiStickerSet#46d840ab prev_stickerset:InputStickerSet new_stickerset:InputStickerSet = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleSignatureProfiles#60a79c79 new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
@ -1377,7 +1378,7 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
sponsoredMessage#bdedf566 flags:# recommended:flags.5?true can_report:flags.12?true random_id:bytes url:string title:string message:string entities:flags.1?Vector<MessageEntity> photo:flags.6?Photo color:flags.13?PeerColor button_text:string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
sponsoredMessage#4d93a990 flags:# recommended:flags.5?true can_report:flags.12?true random_id:bytes url:string title:string message:string entities:flags.1?Vector<MessageEntity> photo:flags.6?Photo media:flags.14?MessageMedia color:flags.13?PeerColor button_text:string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
messages.sponsoredMessages#c9ee1d87 flags:# posts_between:flags.0?int messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;
messages.sponsoredMessagesEmpty#1839490f = messages.SponsoredMessages;
@ -1400,7 +1401,7 @@ auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes = auth.LoggedOut
reactionCount#a3d1cb80 flags:# chosen_order:flags.0?int reaction:Reaction count:int = ReactionCount;
messageReactions#4f2b9479 flags:# min:flags.0?true can_see_list:flags.2?true reactions_as_tags:flags.3?true results:Vector<ReactionCount> recent_reactions:flags.1?Vector<MessagePeerReaction> = MessageReactions;
messageReactions#a339f0b flags:# min:flags.0?true can_see_list:flags.2?true reactions_as_tags:flags.3?true results:Vector<ReactionCount> recent_reactions:flags.1?Vector<MessagePeerReaction> top_reactors:flags.4?Vector<MessageReactor> = MessageReactions;
messages.messageReactionsList#31bd492d flags:# count:int reactions:Vector<MessagePeerReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.MessageReactionsList;
@ -1457,6 +1458,7 @@ inputInvoiceMessage#c5b56859 peer:InputPeer msg_id:int = InputInvoice;
inputInvoiceSlug#c326caef slug:string = InputInvoice;
inputInvoicePremiumGiftCode#98986c0d purpose:InputStorePaymentPurpose option:PremiumGiftCodeOption = InputInvoice;
inputInvoiceStars#65f00ce3 purpose:InputStorePaymentPurpose = InputInvoice;
inputInvoiceChatInviteSubscription#34e793f1 hash:string = InputInvoice;
payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
@ -1485,6 +1487,7 @@ account.emojiStatuses#90c467d1 hash:long statuses:Vector<EmojiStatus> = account.
reactionEmpty#79f5d419 = Reaction;
reactionEmoji#1b2286b8 emoticon:string = Reaction;
reactionCustomEmoji#8935fc73 document_id:long = Reaction;
reactionPaid#523da4eb = Reaction;
chatReactionsNone#eafc32bc = ChatReactions;
chatReactionsAll#52928bca flags:# allow_custom:flags.0?true = ChatReactions;
@ -1811,9 +1814,9 @@ starsTransactionPeerAds#60682812 = StarsTransactionPeer;
starsTopupOption#bd915c0 flags:# extended:flags.1?true stars:long store_product:flags.0?string currency:string amount:long = StarsTopupOption;
starsTransaction#2db5418f flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true id:string stars:long date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector<MessageMedia> = StarsTransaction;
starsTransaction#433aeb2b flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true reaction:flags.11?true id:string stars:long date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector<MessageMedia> subscription_period:flags.12?int = StarsTransaction;
payments.starsStatus#8cf4ee60 flags:# balance:long history:Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
payments.starsStatus#bbfa316c flags:# balance:long subscriptions:flags.1?Vector<StarsSubscription> subscriptions_next_offset:flags.2?string subscriptions_missing_balance:flags.4?long history:flags.3?Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
foundStory#e87acbc0 peer:Peer story:StoryItem = FoundStory;
@ -1839,6 +1842,12 @@ botPreviewMedia#23e91ba3 date:int media:MessageMedia = BotPreviewMedia;
bots.previewInfo#ca71d64 media:Vector<BotPreviewMedia> lang_codes:Vector<string> = bots.PreviewInfo;
starsSubscriptionPricing#5416d58 period:int amount:long = StarsSubscriptionPricing;
starsSubscription#538ecf18 flags:# canceled:flags.0?true can_refulfill:flags.1?true missing_balance:flags.2?true id:string peer:Peer until_date:int pricing:StarsSubscriptionPricing chat_invite_hash:flags.3?string = StarsSubscription;
messageReactor#4ba3a95a flags:# top:flags.0?true my:flags.1?true anonymous:flags.2?true peer_id:flags.3?Peer count:int = MessageReactor;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -2058,7 +2067,7 @@ messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages
messages.getStickers#d5a5d3a1 emoticon:string hash:long = messages.Stickers;
messages.getAllStickers#b8a0a1a8 hash:long = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#a02ce5d5 flags:# legacy_revoke_permanent:flags.2?true request_needed:flags.3?true peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int title:flags.4?string = ExportedChatInvite;
messages.exportChatInvite#a455de90 flags:# legacy_revoke_permanent:flags.2?true request_needed:flags.3?true peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int title:flags.4?string subscription_pricing:flags.5?StarsSubscriptionPricing = ExportedChatInvite;
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
messages.importChatInvite#6c50051c hash:string = Updates;
messages.getStickerSet#c8a0ec74 stickerset:InputStickerSet hash:int = messages.StickerSet;
@ -2158,7 +2167,7 @@ messages.editExportedChatInvite#bdca2f75 flags:# revoked:flags.2?true peer:Input
messages.deleteRevokedExportedChatInvites#56987bd5 peer:InputPeer admin_id:InputUser = Bool;
messages.deleteExportedChatInvite#d464a42b peer:InputPeer link:string = Bool;
messages.getAdminsWithInvites#3920e6ef peer:InputPeer = messages.ChatAdminsWithInvites;
messages.getChatInviteImporters#df04dd4e flags:# requested:flags.0?true peer:InputPeer link:flags.1?string q:flags.2?string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
messages.getChatInviteImporters#df04dd4e flags:# requested:flags.0?true subscription_expired:flags.3?true peer:InputPeer link:flags.1?string q:flags.2?string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
messages.setHistoryTTL#b80e5fe4 peer:InputPeer period:int = Updates;
messages.checkHistoryImportPeer#5dc60f03 peer:InputPeer = messages.CheckedHistoryImportPeer;
messages.setChatTheme#e63be13f peer:InputPeer emoticon:string = Updates;
@ -2172,7 +2181,7 @@ messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;
messages.sendReaction#d30d78d4 flags:# big:flags.1?true add_to_recent:flags.2?true peer:InputPeer msg_id:int reaction:flags.0?Vector<Reaction> = Updates;
messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates;
messages.getMessageReactionsList#461b3f48 flags:# peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = messages.MessageReactionsList;
messages.setChatAvailableReactions#5a150bd4 flags:# peer:InputPeer available_reactions:ChatReactions reactions_limit:flags.0?int = Updates;
messages.setChatAvailableReactions#864b2581 flags:# peer:InputPeer available_reactions:ChatReactions reactions_limit:flags.0?int paid_enabled:flags.1?Bool = Updates;
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
messages.translateText#63183030 flags:# peer:flags.0?InputPeer id:flags.0?Vector<int> text:flags.1?Vector<TextWithEntities> to_lang:string = messages.TranslatedText;
@ -2235,6 +2244,8 @@ messages.editFactCheck#589ee75 peer:InputPeer msg_id:int text:TextWithEntities =
messages.deleteFactCheck#d1da940c peer:InputPeer msg_id:int = Updates;
messages.getFactCheck#b9cdc5ee peer:InputPeer msg_id:Vector<int> = Vector<FactCheck>;
messages.requestMainWebView#c9e01e7b flags:# compact:flags.7?true peer:InputPeer bot:InputUser start_param:flags.1?string theme_params:flags.0?DataJSON platform:string = WebViewResult;
messages.sendPaidReaction#25c8fe3e flags:# private:flags.0?true peer:InputPeer msg_id:int count:int random_id:long = Updates;
messages.togglePaidReactionPrivacy#849ad397 peer:InputPeer msg_id:int private:Bool = Bool;
updates.getState#edd4882a = updates.State;
updates.getDifference#19c2f763 flags:# pts:int pts_limit:flags.1?int pts_total_limit:flags.0?int date:int qts:int qts_limit:flags.2?int = updates.Difference;
@ -2300,7 +2311,7 @@ channels.leaveChannel#f836aa95 channel:InputChannel = Updates;
channels.inviteToChannel#c9e33d54 channel:InputChannel users:Vector<InputUser> = messages.InvitedUsers;
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
channels.exportMessageLink#e63fadeb flags:# grouped:flags.0?true thread:flags.1?true channel:InputChannel id:int = ExportedMessageLink;
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
channels.toggleSignatures#418d549c flags:# signatures_enabled:flags.0?true profiles_enabled:flags.1?true channel:InputChannel = Updates;
channels.getAdminedPublicChannels#f8b036af flags:# by_location:flags.0?true check_limit:flags.1?true for_personal:flags.2?true = messages.Chats;
channels.editBanned#96e6cd81 channel:InputChannel participant:InputPeer banned_rights:ChatBannedRights = Updates;
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
@ -2389,7 +2400,7 @@ payments.getGiveawayInfo#f4239425 peer:InputPeer msg_id:int = payments.GiveawayI
payments.launchPrepaidGiveaway#5ff58f20 peer:InputPeer giveaway_id:long purpose:InputStorePaymentPurpose = Updates;
payments.getStarsTopupOptions#c00ec7d3 = Vector<StarsTopupOption>;
payments.getStarsStatus#104fcfa7 peer:InputPeer = payments.StarsStatus;
payments.getStarsTransactions#97938d5a flags:# inbound:flags.0?true outbound:flags.1?true ascending:flags.2?true peer:InputPeer offset:string limit:int = payments.StarsStatus;
payments.getStarsTransactions#69da4557 flags:# inbound:flags.0?true outbound:flags.1?true ascending:flags.2?true subscription_id:flags.3?string peer:InputPeer offset:string limit:int = payments.StarsStatus;
payments.sendStarsForm#2bb731d flags:# form_id:long invoice:InputInvoice = payments.PaymentResult;
payments.refundStarsCharge#25ae8f4a user_id:InputUser charge_id:string = Updates;
payments.getStarsRevenueStats#d91ffad6 flags:# dark:flags.0?true peer:InputPeer = payments.StarsRevenueStats;
@ -2397,6 +2408,9 @@ payments.getStarsRevenueWithdrawalUrl#13bbe8b3 peer:InputPeer stars:long passwor
payments.getStarsRevenueAdsAccountUrl#d1d7efc5 peer:InputPeer = payments.StarsRevenueAdsAccountUrl;
payments.getStarsTransactionsByID#27842d2e peer:InputPeer id:Vector<InputStarsTransaction> = payments.StarsStatus;
payments.getStarsGiftOptions#d3c96bc8 flags:# user_id:flags.0?InputUser = Vector<StarsGiftOption>;
payments.getStarsSubscriptions#32512c5 flags:# missing_balance:flags.0?true peer:InputPeer offset:string = payments.StarsStatus;
payments.changeStarsSubscription#c7770878 flags:# peer:InputPeer subscription_id:string canceled:flags.0?Bool = Bool;
payments.fulfillStarsSubscription#cc5bebb3 peer:InputPeer subscription_id:string = Bool;
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;