Update to layer 133 (#1525)

This commit is contained in:
Alexander Zinchuk 2021-11-05 21:56:58 +03:00
parent d4d11b7d4b
commit 1e60003f5a
177 changed files with 2202 additions and 2040 deletions

View File

@ -11,7 +11,7 @@
"deploy:production": "npm run build:production && git add -A && git commit -a -m '[Build]' --no-verify && git push", "deploy:production": "npm run build:production && git add -A && git commit -a -m '[Build]' --no-verify && git push",
"inc_version": "echo $((`cat .patch-version` + 1)) > .patch-version && echo \"$(node -p -e \"require('./package.json').version.match(/^\\d+\\.\\d+/)[0]\").$(cat .patch-version)\"", "inc_version": "echo $((`cat .patch-version` + 1)) > .patch-version && echo \"$(node -p -e \"require('./package.json').version.match(/^\\d+\\.\\d+/)[0]\").$(cat .patch-version)\"",
"perf:serve": "cross-env APP_ENV=perf parcel src/index-perf.html", "perf:serve": "cross-env APP_ENV=perf parcel src/index-perf.html",
"lint": "eslint . --ext .ts,.tsx --ignore-pattern src/lib/gramjs", "lint": "tsc && eslint . --ext .ts,.tsx --ignore-pattern src/lib/gramjs",
"lint:fix": "npm run lint -- --fix", "lint:fix": "npm run lint -- --fix",
"gramjs:tl": "node ./src/lib/gramjs/tl/generateModules.js", "gramjs:tl": "node ./src/lib/gramjs/tl/generateModules.js",
"gramjs:lint:fix": "eslint ./src/lib/gramjs --ignore-path=src/lib/gramjs/.eslintignore --fix", "gramjs:lint:fix": "eslint ./src/lib/gramjs --ignore-path=src/lib/gramjs/.eslintignore --fix",

View File

@ -1,3 +1,4 @@
import BigInt from 'big-integer';
import { Api as GramJs } from '../../../lib/gramjs'; import { Api as GramJs } from '../../../lib/gramjs';
import { import {
ApiChat, ApiChat,
@ -10,7 +11,7 @@ import {
} from '../../types'; } from '../../types';
import { pick, pickTruthy } from '../../../util/iteratees'; import { pick, pickTruthy } from '../../../util/iteratees';
import { import {
isInputPeerChannel, isInputPeerChat, isInputPeerUser, isPeerChat, isPeerUser, buildApiPeerId, getApiChatIdFromMtpPeer, isPeerChat, isPeerUser,
} from './peers'; } from './peers';
import { omitVirtualClassFields } from './helpers'; import { omitVirtualClassFields } from './helpers';
import { getServerTime } from '../../../util/serverTime'; import { getServerTime } from '../../../util/serverTime';
@ -93,11 +94,13 @@ function buildApiChatPermissions(peerEntity: GramJs.TypeUser | GramJs.TypeChat):
} }
return { return {
adminRights: omitVirtualClassFields(peerEntity.adminRights), adminRights: peerEntity.adminRights ? omitVirtualClassFields(peerEntity.adminRights) : undefined,
currentUserBannedRights: peerEntity instanceof GramJs.Channel currentUserBannedRights: peerEntity instanceof GramJs.Channel && peerEntity.bannedRights
? omitVirtualClassFields(peerEntity.bannedRights) ? omitVirtualClassFields(peerEntity.bannedRights)
: undefined, : undefined,
defaultBannedRights: omitVirtualClassFields(peerEntity.defaultBannedRights), defaultBannedRights: peerEntity.defaultBannedRights
? omitVirtualClassFields(peerEntity.defaultBannedRights)
: undefined,
}; };
} }
@ -146,7 +149,7 @@ function buildApiChatRestrictions(peerEntity: GramJs.TypeUser | GramJs.TypeChat)
function buildApiChatMigrationInfo(peerEntity: GramJs.TypeChat): { function buildApiChatMigrationInfo(peerEntity: GramJs.TypeChat): {
migratedTo?: { migratedTo?: {
chatId: number; chatId: string;
accessHash?: string; accessHash?: string;
}; };
} { } {
@ -159,7 +162,7 @@ function buildApiChatMigrationInfo(peerEntity: GramJs.TypeChat): {
migratedTo: { migratedTo: {
chatId: getApiChatIdFromMtpPeer(peerEntity.migratedTo), chatId: getApiChatIdFromMtpPeer(peerEntity.migratedTo),
...(peerEntity.migratedTo instanceof GramJs.InputChannel && { ...(peerEntity.migratedTo instanceof GramJs.InputChannel && {
accessHash: peerEntity.migratedTo.accessHash.toString(), accessHash: String(peerEntity.migratedTo.accessHash),
}), }),
}, },
}; };
@ -200,34 +203,13 @@ export function buildApiChatFromPreview(
} }
return { return {
id: preview instanceof GramJs.User ? preview.id : -preview.id, id: buildApiPeerId(preview.id, preview instanceof GramJs.User ? 'user' : 'chat'),
type: getApiChatTypeFromPeerEntity(preview), type: getApiChatTypeFromPeerEntity(preview),
title: preview instanceof GramJs.User ? getUserName(preview) : preview.title, title: preview instanceof GramJs.User ? getUserName(preview) : preview.title,
...buildApiChatFieldsFromPeerEntity(preview, isSupport), ...buildApiChatFieldsFromPeerEntity(preview, isSupport),
}; };
} }
export function getApiChatIdFromMtpPeer(peer: GramJs.TypePeer): number {
if (isPeerUser(peer)) {
return peer.userId;
} else if (isPeerChat(peer)) {
return -peer.chatId;
} else {
return -peer.channelId;
}
}
export function getApiChatIdFromInputMtpPeer(peer: GramJs.TypeInputPeer): number | undefined {
if (isInputPeerUser(peer)) {
return peer.userId;
} else if (isInputPeerChat(peer)) {
return -peer.chatId;
} else if (isInputPeerChannel(peer)) {
return -peer.channelId;
}
return undefined;
}
export function getApiChatTypeFromPeerEntity(peerEntity: GramJs.TypeChat | GramJs.TypeUser) { export function getApiChatTypeFromPeerEntity(peerEntity: GramJs.TypeChat | GramJs.TypeUser) {
if (peerEntity instanceof GramJs.User || peerEntity instanceof GramJs.UserEmpty) { if (peerEntity instanceof GramJs.User || peerEntity instanceof GramJs.UserEmpty) {
return 'chatTypePrivate'; return 'chatTypePrivate';
@ -268,7 +250,7 @@ function getUserName(user: GramJs.User) {
export function buildAvatarHash(photo: GramJs.TypeUserProfilePhoto | GramJs.TypeChatPhoto) { export function buildAvatarHash(photo: GramJs.TypeUserProfilePhoto | GramJs.TypeChatPhoto) {
if ('photoId' in photo) { if ('photoId' in photo) {
return photo.photoId.toString(); return String(photo.photoId);
} }
return undefined; return undefined;
@ -279,14 +261,14 @@ export function buildChatMember(
): ApiChatMember | undefined { ): ApiChatMember | undefined {
const userId = (member instanceof GramJs.ChannelParticipantBanned || member instanceof GramJs.ChannelParticipantLeft) const userId = (member instanceof GramJs.ChannelParticipantBanned || member instanceof GramJs.ChannelParticipantLeft)
? getApiChatIdFromMtpPeer(member.peer) ? getApiChatIdFromMtpPeer(member.peer)
: member.userId; : buildApiPeerId(member.userId, 'user');
return { return {
userId, userId,
inviterId: 'inviterId' in member ? member.inviterId : undefined, inviterId: 'inviterId' in member ? buildApiPeerId(member.inviterId as BigInt.BigInteger, 'user') : undefined,
joinedDate: 'date' in member ? member.date : undefined, joinedDate: 'date' in member ? member.date : undefined,
kickedByUserId: 'kickedBy' in member ? member.kickedBy : undefined, kickedByUserId: 'kickedBy' in member ? buildApiPeerId(member.kickedBy, 'user') : undefined,
promotedByUserId: 'promotedBy' in member ? member.promotedBy : undefined, promotedByUserId: 'promotedBy' in member ? buildApiPeerId(member.promotedBy, 'user') : undefined,
bannedRights: 'bannedRights' in member ? omitVirtualClassFields(member.bannedRights) : undefined, bannedRights: 'bannedRights' in member ? omitVirtualClassFields(member.bannedRights) : undefined,
adminRights: 'adminRights' in member ? omitVirtualClassFields(member.adminRights) : undefined, adminRights: 'adminRights' in member ? omitVirtualClassFields(member.adminRights) : undefined,
customTitle: 'rank' in member ? member.rank : undefined, customTitle: 'rank' in member ? member.rank : undefined,
@ -362,9 +344,9 @@ export function buildApiChatFolder(filter: GramJs.DialogFilter): ApiChatFolder {
'excludeMuted', 'excludeRead', 'excludeArchived', 'excludeMuted', 'excludeRead', 'excludeArchived',
]), ]),
channels: filter.broadcasts, channels: filter.broadcasts,
pinnedChatIds: filter.pinnedPeers.map(getApiChatIdFromInputMtpPeer).filter<number>(Boolean as any), pinnedChatIds: filter.pinnedPeers.map(getApiChatIdFromMtpPeer).filter<string>(Boolean as any),
includedChatIds: filter.includePeers.map(getApiChatIdFromInputMtpPeer).filter<number>(Boolean as any), includedChatIds: filter.includePeers.map(getApiChatIdFromMtpPeer).filter<string>(Boolean as any),
excludedChatIds: filter.excludePeers.map(getApiChatIdFromInputMtpPeer).filter<number>(Boolean as any), excludedChatIds: filter.excludePeers.map(getApiChatIdFromMtpPeer).filter<string>(Boolean as any),
}; };
} }
@ -382,8 +364,10 @@ export function buildApiChatFolderFromSuggested({
export function buildApiChatBotCommands(botInfos: GramJs.BotInfo[]) { export function buildApiChatBotCommands(botInfos: GramJs.BotInfo[]) {
return botInfos.reduce((botCommands, botInfo) => { return botInfos.reduce((botCommands, botInfo) => {
const botId = buildApiPeerId(botInfo.userId, 'user');
botCommands = botCommands.concat(botInfo.commands.map((mtpCommand) => ({ botCommands = botCommands.concat(botInfo.commands.map((mtpCommand) => ({
botId: botInfo.userId, botId,
...omitVirtualClassFields(mtpCommand), ...omitVirtualClassFields(mtpCommand),
}))); })));

View File

@ -1,20 +1,29 @@
import { Api as GramJs } from '../../../lib/gramjs';
type VirtualFields =
'flags'
| 'CONSTRUCTOR_ID'
| 'SUBCLASS_OF_ID'
| 'className'
| 'classType'
| 'getBytes';
export function bytesToDataUri(bytes: Buffer, shouldOmitPrefix = false, mimeType: string = 'image/jpeg') { export function bytesToDataUri(bytes: Buffer, shouldOmitPrefix = false, mimeType: string = 'image/jpeg') {
const prefix = shouldOmitPrefix ? '' : `data:${mimeType};base64,`; const prefix = shouldOmitPrefix ? '' : `data:${mimeType};base64,`;
return `${prefix}${btoa(String.fromCharCode(...bytes))}`; return `${prefix}${btoa(String.fromCharCode(...bytes))}`;
} }
export function omitVirtualClassFields(instance: any) { export function omitVirtualClassFields<T extends GramJs.VirtualClass<T> & { flags?: any }>(
if (!instance) { instance: T,
return undefined; ): Omit<T, VirtualFields> {
}
const { const {
flags, flags,
CONSTRUCTOR_ID, CONSTRUCTOR_ID,
SUBCLASS_OF_ID, SUBCLASS_OF_ID,
className, className,
classType, classType,
getBytes,
...rest ...rest
} = instance; } = instance;

View File

@ -32,21 +32,20 @@ import {
VIDEO_MOV_TYPE, VIDEO_MOV_TYPE,
} from '../../../config'; } from '../../../config';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
import { getApiChatIdFromMtpPeer } from './chats';
import { buildStickerFromDocument } from './symbols'; import { buildStickerFromDocument } from './symbols';
import { buildApiPhoto, buildApiPhotoSize, buildApiThumbnailFromStripped } from './common'; import { buildApiPhoto, buildApiPhotoSize, buildApiThumbnailFromStripped } from './common';
import { interpolateArray } from '../../../util/waveform'; import { interpolateArray } from '../../../util/waveform';
import { buildPeer } from '../gramjsBuilders'; import { buildPeer } from '../gramjsBuilders';
import { addPhotoToLocalDb, resolveMessageApiChatId } from '../helpers'; import { addPhotoToLocalDb, resolveMessageApiChatId } from '../helpers';
import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers';
const LOCAL_IMAGE_UPLOADING_TEMP_ID = 'temp'; const LOCAL_MEDIA_UPLOADING_TEMP_ID = 'temp';
const LOCAL_VIDEO_UPLOADING_TEMP_ID = 'temp';
const INPUT_WAVEFORM_LENGTH = 63; const INPUT_WAVEFORM_LENGTH = 63;
let localMessageCounter = LOCAL_MESSAGE_ID_BASE; let localMessageCounter = LOCAL_MESSAGE_ID_BASE;
let currentUserId!: number; let currentUserId!: string;
export function setMessageBuilderCurrentUserId(_currentUserId: number) { export function setMessageBuilderCurrentUserId(_currentUserId: string) {
currentUserId = _currentUserId; currentUserId = _currentUserId;
} }
@ -62,20 +61,20 @@ export function buildApiMessage(mtpMessage: GramJs.TypeMessage): ApiMessage | un
} }
export function buildApiMessageFromShort(mtpMessage: GramJs.UpdateShortMessage): ApiMessage { export function buildApiMessageFromShort(mtpMessage: GramJs.UpdateShortMessage): ApiMessage {
const chatId = getApiChatIdFromMtpPeer({ userId: mtpMessage.userId } as GramJs.TypePeer); const chatId = buildApiPeerId(mtpMessage.userId, 'user');
return buildApiMessageWithChatId(chatId, { return buildApiMessageWithChatId(chatId, {
...mtpMessage, ...mtpMessage,
fromId: buildPeer(mtpMessage.out ? currentUserId : mtpMessage.userId), fromId: buildPeer(mtpMessage.out ? currentUserId : buildApiPeerId(mtpMessage.userId, 'user')),
}); });
} }
export function buildApiMessageFromShortChat(mtpMessage: GramJs.UpdateShortChatMessage): ApiMessage { export function buildApiMessageFromShortChat(mtpMessage: GramJs.UpdateShortChatMessage): ApiMessage {
const chatId = getApiChatIdFromMtpPeer({ chatId: mtpMessage.chatId } as GramJs.TypePeer); const chatId = buildApiPeerId(mtpMessage.chatId, 'chat');
return buildApiMessageWithChatId(chatId, { return buildApiMessageWithChatId(chatId, {
...mtpMessage, ...mtpMessage,
fromId: buildPeer(mtpMessage.fromId), fromId: buildPeer(buildApiPeerId(mtpMessage.fromId, 'user')),
}); });
} }
@ -117,7 +116,7 @@ type UniversalMessage = (
)> )>
); );
export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalMessage): ApiMessage { export function buildApiMessageWithChatId(chatId: string, mtpMessage: UniversalMessage): ApiMessage {
const fromId = mtpMessage.fromId ? getApiChatIdFromMtpPeer(mtpMessage.fromId) : undefined; const fromId = mtpMessage.fromId ? getApiChatIdFromMtpPeer(mtpMessage.fromId) : undefined;
const peerId = mtpMessage.peerId ? getApiChatIdFromMtpPeer(mtpMessage.peerId) : undefined; const peerId = mtpMessage.peerId ? getApiChatIdFromMtpPeer(mtpMessage.peerId) : undefined;
const isChatWithSelf = !fromId && chatId === currentUserId; const isChatWithSelf = !fromId && chatId === currentUserId;
@ -151,7 +150,7 @@ export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalM
} = buildReplyButtons(mtpMessage) || {}; } = buildReplyButtons(mtpMessage) || {};
const forwardInfo = mtpMessage.fwdFrom && buildApiMessageForwardInfo(mtpMessage.fwdFrom, isChatWithSelf); const forwardInfo = mtpMessage.fwdFrom && buildApiMessageForwardInfo(mtpMessage.fwdFrom, isChatWithSelf);
const { replies, mediaUnread: isMediaUnread, postAuthor } = mtpMessage; const { replies, mediaUnread: isMediaUnread, postAuthor } = mtpMessage;
const groupedId = mtpMessage.groupedId && mtpMessage.groupedId.toString(); const groupedId = mtpMessage.groupedId && String(mtpMessage.groupedId);
const isInAlbum = Boolean(groupedId) && !(content.document || content.audio); const isInAlbum = Boolean(groupedId) && !(content.document || content.audio);
const shouldHideKeyboardButtons = mtpMessage.replyMarkup instanceof GramJs.ReplyKeyboardHide; const shouldHideKeyboardButtons = mtpMessage.replyMarkup instanceof GramJs.ReplyKeyboardHide;
@ -179,7 +178,7 @@ export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalM
inlineButtons, inlineButtons,
...(keyboardButtons && { keyboardButtons, keyboardPlaceholder, isKeyboardSingleUse }), ...(keyboardButtons && { keyboardButtons, keyboardPlaceholder, isKeyboardSingleUse }),
...(shouldHideKeyboardButtons && { shouldHideKeyboardButtons }), ...(shouldHideKeyboardButtons && { shouldHideKeyboardButtons }),
...(mtpMessage.viaBotId && { viaBotId: mtpMessage.viaBotId }), ...(mtpMessage.viaBotId && { viaBotId: buildApiPeerId(mtpMessage.viaBotId, 'user') }),
...(replies?.comments && { threadInfo: buildThreadInfo(replies, mtpMessage.id, chatId) }), ...(replies?.comments && { threadInfo: buildThreadInfo(replies, mtpMessage.id, chatId) }),
...(postAuthor && { adminTitle: postAuthor }), ...(postAuthor && { adminTitle: postAuthor }),
}; };
@ -463,12 +462,13 @@ function buildContact(media: GramJs.TypeMessageMedia): ApiContact | undefined {
return undefined; return undefined;
} }
return pick(media, [ const {
'firstName', firstName, lastName, phoneNumber, userId,
'lastName', } = media;
'phoneNumber',
'userId', return {
]); firstName, lastName, phoneNumber, userId: buildApiPeerId(userId, 'user'),
};
} }
function buildPollFromMedia(media: GramJs.TypeMessageMedia): ApiPoll | undefined { function buildPollFromMedia(media: GramJs.TypeMessageMedia): ApiPoll | undefined {
@ -495,7 +495,7 @@ export function buildPoll(poll: GramJs.Poll, pollResults: GramJs.PollResults): A
})); }));
return { return {
id: id.toString(), id: String(id),
summary: { summary: {
isPublic: poll.publicVoters, isPublic: poll.publicVoters,
...pick(poll, [ ...pick(poll, [
@ -543,7 +543,7 @@ export function buildPollResults(pollResults: GramJs.PollResults): ApiPoll['resu
return { return {
totalVoters, totalVoters,
recentVoterIds: recentVoters, recentVoterIds: recentVoters?.map((id) => buildApiPeerId(id, 'user')),
results, results,
solution, solution,
...(entities && { solutionEntities: entities.map(buildApiMessageEntity) }), ...(entities && { solutionEntities: entities.map(buildApiMessageEntity) }),
@ -584,8 +584,8 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef
function buildAction( function buildAction(
action: GramJs.TypeMessageAction, action: GramJs.TypeMessageAction,
senderId: number | undefined, senderId: string | undefined,
targetPeerId: number | undefined, targetPeerId: string | undefined,
isChannelPost: boolean, isChannelPost: boolean,
isOutgoing: boolean, isOutgoing: boolean,
): ApiAction | undefined { ): ApiAction | undefined {
@ -601,9 +601,9 @@ function buildAction(
let photo: ApiPhoto | undefined; let photo: ApiPhoto | undefined;
const targetUserIds = 'users' in action const targetUserIds = 'users' in action
? action.users && action.users ? action.users && action.users.map((id) => buildApiPeerId(id, 'user'))
: ('userId' in action && [action.userId]) || []; : ('userId' in action && [buildApiPeerId(action.userId, 'user')]) || [];
let targetChatId: number | undefined; let targetChatId: string | undefined;
if (action instanceof GramJs.MessageActionChatCreate) { if (action instanceof GramJs.MessageActionChatCreate) {
text = 'Notification.CreatedChatWithTitle'; text = 'Notification.CreatedChatWithTitle';
@ -908,7 +908,7 @@ function buildUploadingMedia(
if (mimeType.startsWith('image/')) { if (mimeType.startsWith('image/')) {
return { return {
photo: { photo: {
id: LOCAL_IMAGE_UPLOADING_TEMP_ID, id: LOCAL_MEDIA_UPLOADING_TEMP_ID,
sizes: [], sizes: [],
thumbnail: { width, height, dataUri: '' }, // Used only for dimensions thumbnail: { width, height, dataUri: '' }, // Used only for dimensions
blobUrl, blobUrl,
@ -917,7 +917,7 @@ function buildUploadingMedia(
} else { } else {
return { return {
video: { video: {
id: LOCAL_VIDEO_UPLOADING_TEMP_ID, id: LOCAL_MEDIA_UPLOADING_TEMP_ID,
mimeType, mimeType,
duration: duration || 0, duration: duration || 0,
fileName, fileName,
@ -962,7 +962,7 @@ function buildUploadingMedia(
function buildNewPoll(poll: ApiNewPoll, localId: number) { function buildNewPoll(poll: ApiNewPoll, localId: number) {
return { return {
poll: { poll: {
id: localId.toString(), id: String(localId),
summary: pick(poll.summary, ['question', 'answers']), summary: pick(poll.summary, ['question', 'answers']),
results: {}, results: {},
}, },
@ -981,22 +981,26 @@ function buildApiMessageEntity(entity: GramJs.TypeMessageEntity): ApiMessageEnti
} }
function buildThreadInfo( function buildThreadInfo(
messageReplies: GramJs.TypeMessageReplies, messageId: number, chatId: number, messageReplies: GramJs.TypeMessageReplies, messageId: number, chatId: string,
): ApiThreadInfo | undefined { ): ApiThreadInfo | undefined {
const { const {
channelId, replies, maxId, readMaxId, recentRepliers, channelId, replies, maxId, readMaxId, recentRepliers,
} = messageReplies; } = messageReplies;
if (!channelId) {
if (channelId === DELETED_COMMENTS_CHANNEL_ID) {
return undefined; return undefined;
} }
const isPostThread = chatId !== channelId; const apiChannelId = buildApiPeerId(channelId, 'channel');
if (apiChannelId === DELETED_COMMENTS_CHANNEL_ID) {
return undefined;
}
const isPostThread = chatId !== apiChannelId;
return { return {
threadId: messageId, threadId: messageId,
...(isPostThread ? { ...(isPostThread ? {
chatId: getApiChatIdFromMtpPeer({ channelId } as GramJs.TypePeer), chatId: apiChannelId,
originChannelId: chatId, originChannelId: chatId,
} : { } : {
chatId, chatId,

View File

@ -4,7 +4,7 @@ import { ApiCountry, ApiSession, ApiWallpaper } from '../../types';
import { ApiPrivacySettings, ApiPrivacyKey, PrivacyVisibility } from '../../../types'; import { ApiPrivacySettings, ApiPrivacyKey, PrivacyVisibility } from '../../../types';
import { buildApiDocument } from './messages'; import { buildApiDocument } from './messages';
import { getApiChatIdFromMtpPeer } from './chats'; import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers';
import { flatten, pick } from '../../../util/iteratees'; import { flatten, pick } from '../../../util/iteratees';
import { getServerTime } from '../../../util/serverTime'; import { getServerTime } from '../../../util/serverTime';
@ -60,10 +60,10 @@ export function buildPrivacyKey(key: GramJs.TypePrivacyKey): ApiPrivacyKey | und
export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySettings { export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySettings {
let visibility: PrivacyVisibility | undefined; let visibility: PrivacyVisibility | undefined;
let allowUserIds: number[] | undefined; let allowUserIds: string[] | undefined;
let allowChatIds: number[] | undefined; let allowChatIds: string[] | undefined;
let blockUserIds: number[] | undefined; let blockUserIds: string[] | undefined;
let blockChatIds: number[] | undefined; let blockChatIds: string[] | undefined;
rules.forEach((rule) => { rules.forEach((rule) => {
if (rule instanceof GramJs.PrivacyValueAllowAll) { if (rule instanceof GramJs.PrivacyValueAllowAll) {
@ -75,13 +75,13 @@ export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySe
} else if (rule instanceof GramJs.PrivacyValueDisallowAll) { } else if (rule instanceof GramJs.PrivacyValueDisallowAll) {
visibility = visibility || 'nobody'; visibility = visibility || 'nobody';
} else if (rule instanceof GramJs.PrivacyValueAllowUsers) { } else if (rule instanceof GramJs.PrivacyValueAllowUsers) {
allowUserIds = rule.users; allowUserIds = rule.users.map((chatId) => buildApiPeerId(chatId, 'user'));
} else if (rule instanceof GramJs.PrivacyValueDisallowUsers) { } else if (rule instanceof GramJs.PrivacyValueDisallowUsers) {
blockUserIds = rule.users; blockUserIds = rule.users.map((chatId) => buildApiPeerId(chatId, 'user'));
} else if (rule instanceof GramJs.PrivacyValueAllowChatParticipants) { } else if (rule instanceof GramJs.PrivacyValueAllowChatParticipants) {
allowChatIds = rule.chats.map((id) => -id); allowChatIds = rule.chats.map((chatId) => buildApiPeerId(chatId, 'chat'));
} else if (rule instanceof GramJs.PrivacyValueDisallowChatParticipants) { } else if (rule instanceof GramJs.PrivacyValueDisallowChatParticipants) {
blockChatIds = rule.chats.map((id) => -id); blockChatIds = rule.chats.map((chatId) => buildApiPeerId(chatId, 'chat'));
} }
}); });
@ -113,6 +113,7 @@ export function buildApiNotifyException(
...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }), ...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }),
}; };
} }
function buildApiCountry(country: GramJs.help.Country, code?: GramJs.help.CountryCode) { function buildApiCountry(country: GramJs.help.Country, code?: GramJs.help.CountryCode) {
const { const {
hidden, iso2, defaultName, name, hidden, iso2, defaultName, name,

View File

@ -96,7 +96,7 @@ export function buildPaymentForm(form: GramJs.payments.PaymentForm) {
canSaveCredentials, canSaveCredentials,
passwordMissing, passwordMissing,
formId: String(formId), formId: String(formId),
providerId, providerId: String(providerId),
nativeProvider, nativeProvider,
savedInfo, savedInfo,
invoice: { invoice: {

View File

@ -1,25 +1,29 @@
import BigInt from 'big-integer';
import { Api as GramJs } from '../../../lib/gramjs'; import { Api as GramJs } from '../../../lib/gramjs';
export function isPeerUser(peer: GramJs.TypePeer): peer is GramJs.PeerUser { export function isPeerUser(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerUser {
return peer.hasOwnProperty('userId'); return peer.hasOwnProperty('userId');
} }
export function isPeerChat(peer: GramJs.TypePeer): peer is GramJs.PeerChat { export function isPeerChat(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerChat {
return peer.hasOwnProperty('chatId'); return peer.hasOwnProperty('chatId');
} }
export function isPeerChannel(peer: GramJs.TypePeer): peer is GramJs.PeerChannel { export function isPeerChannel(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerChannel {
return peer.hasOwnProperty('channelId'); return peer.hasOwnProperty('channelId');
} }
export function isInputPeerUser(peer: GramJs.TypeInputPeer): peer is GramJs.InputPeerUser { export function buildApiPeerId(id: BigInt.BigInteger, type: 'user' | 'chat' | 'channel') {
return peer.hasOwnProperty('userId'); return type === 'user' ? String(id) : `-${id}`;
} }
export function isInputPeerChat(peer: GramJs.TypeInputPeer): peer is GramJs.InputPeerChat { export function getApiChatIdFromMtpPeer(peer: GramJs.TypePeer | GramJs.TypeInputPeer) {
return peer.hasOwnProperty('chatId'); if (isPeerUser(peer)) {
} return buildApiPeerId(peer.userId, 'user');
} else if (isPeerChat(peer)) {
export function isInputPeerChannel(peer: GramJs.TypeInputPeer): peer is GramJs.InputPeerChannel { return buildApiPeerId(peer.chatId, 'chat');
return peer.hasOwnProperty('channelId'); } else {
return buildApiPeerId((peer as GramJs.InputPeerChannel).channelId, 'channel');
}
} }

View File

@ -72,7 +72,6 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet {
title, title,
thumbs, thumbs,
count, count,
hash,
shortName, shortName,
} = set; } = set;
@ -85,7 +84,6 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet {
title, title,
hasThumbnail: Boolean(thumbs?.length), hasThumbnail: Boolean(thumbs?.length),
count, count,
hash,
shortName, shortName,
}; };
} }

View File

@ -2,21 +2,24 @@ import { Api as GramJs } from '../../../lib/gramjs';
import { import {
ApiBotCommand, ApiUser, ApiUserStatus, ApiUserType, ApiBotCommand, ApiUser, ApiUserStatus, ApiUserType,
} from '../../types'; } from '../../types';
import { buildApiPeerId } from './peers';
export function buildApiUserFromFull(mtpUserFull: GramJs.UserFull): ApiUser { export function buildApiUserFromFull(mtpUserFull: GramJs.UserFull): ApiUser {
const { const {
about, commonChatsCount, pinnedMsgId, botInfo, blocked, about, commonChatsCount, pinnedMsgId, botInfo, blocked,
} = mtpUserFull; } = mtpUserFull;
const user = buildApiUser(mtpUserFull.user)!;
return { return {
...(buildApiUser(mtpUserFull.user) as ApiUser), ...user,
fullInfo: { fullInfo: {
bio: about, bio: about,
commonChatsCount, commonChatsCount,
pinnedMessageId: pinnedMsgId, pinnedMessageId: pinnedMsgId,
isBlocked: Boolean(blocked), isBlocked: Boolean(blocked),
...(botInfo && { botDescription: botInfo.description }), ...(botInfo && { botDescription: botInfo.description }),
...(botInfo && botInfo.commands.length && { botCommands: buildApiBotCommands(mtpUserFull.user.id, botInfo) }), ...(botInfo && botInfo.commands.length && { botCommands: buildApiBotCommands(user.id, botInfo) }),
}, },
}; };
} }
@ -33,7 +36,7 @@ export function buildApiUser(mtpUser: GramJs.TypeUser): ApiUser | undefined {
const userType = buildApiUserType(mtpUser); const userType = buildApiUserType(mtpUser);
return { return {
id, id: buildApiPeerId(id, 'user'),
isMin: Boolean(mtpUser.min), isMin: Boolean(mtpUser.min),
...(mtpUser.self && { isSelf: true }), ...(mtpUser.self && { isSelf: true }),
...(mtpUser.verified && { isVerified: true }), ...(mtpUser.verified && { isVerified: true }),
@ -78,7 +81,7 @@ export function buildApiUserStatus(mtpStatus?: GramJs.TypeUserStatus): ApiUserSt
} }
} }
function buildApiBotCommands(botId: number, botInfo: GramJs.BotInfo) { function buildApiBotCommands(botId: string, botInfo: GramJs.BotInfo) {
return botInfo.commands.map(({ command, description }) => ({ return botInfo.commands.map(({ command, description }) => ({
botId, botId,
command, command,

View File

@ -18,7 +18,24 @@ import {
import localDb from '../localDb'; import localDb from '../localDb';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
export function getEntityTypeById(chatOrUserId: number) { const CHANNEL_ID_MIN_LENGTH = 11; // Example: -1000000000
export function getEntityTypeById(chatOrUserId: string) {
if (typeof chatOrUserId === 'number') {
return getEntityTypeByDeprecatedId(chatOrUserId);
}
if (!chatOrUserId.startsWith('-')) {
return 'user';
} else if (chatOrUserId.length >= CHANNEL_ID_MIN_LENGTH) {
return 'channel';
} else {
return 'chat';
}
}
// Workaround for old-fashioned IDs stored locally
export function getEntityTypeByDeprecatedId(chatOrUserId: number) {
if (chatOrUserId > 0) { if (chatOrUserId > 0) {
return 'user'; return 'user';
} else if (chatOrUserId <= -1000000000) { } else if (chatOrUserId <= -1000000000) {
@ -28,81 +45,78 @@ export function getEntityTypeById(chatOrUserId: number) {
} }
} }
export function buildPeer(chatOrUserId: number): GramJs.TypePeer { export function buildPeer(chatOrUserId: string): GramJs.TypePeer {
if (chatOrUserId > 0) { const type = getEntityTypeById(chatOrUserId);
if (type === 'user') {
return new GramJs.PeerUser({ return new GramJs.PeerUser({
userId: chatOrUserId, userId: buildMtpPeerId(chatOrUserId, 'user'),
}); });
} else if (chatOrUserId <= -1000000000) { } else if (type === 'channel') {
return new GramJs.PeerChannel({ return new GramJs.PeerChannel({
channelId: -chatOrUserId, channelId: buildMtpPeerId(chatOrUserId, 'channel'),
}); });
} else { } else {
return new GramJs.PeerChat({ return new GramJs.PeerChat({
chatId: -chatOrUserId, chatId: buildMtpPeerId(chatOrUserId, 'chat'),
}); });
} }
} }
export function buildInputPeer(chatOrUserId: number, accessHash?: string): GramJs.TypeInputPeer { export function buildInputPeer(chatOrUserId: string, accessHash?: string): GramJs.TypeInputPeer {
if (chatOrUserId > 0 || chatOrUserId <= -1000000000) { const type = getEntityTypeById(chatOrUserId);
return chatOrUserId > 0
? new GramJs.InputPeerUser({ if (type === 'user') {
userId: chatOrUserId, return new GramJs.InputPeerUser({
accessHash: BigInt(accessHash!), userId: buildMtpPeerId(chatOrUserId, 'user'),
}) accessHash: BigInt(accessHash!),
: new GramJs.InputPeerChannel({ });
channelId: -chatOrUserId, } else if (type === 'channel') {
accessHash: BigInt(accessHash!), return new GramJs.InputPeerChannel({
}); channelId: buildMtpPeerId(chatOrUserId, 'channel'),
accessHash: BigInt(accessHash!),
});
} else { } else {
return new GramJs.InputPeerChat({ return new GramJs.InputPeerChat({
chatId: -chatOrUserId, chatId: buildMtpPeerId(chatOrUserId, 'chat'),
}); });
} }
} }
export function buildInputPeerFromLocalDb(chatOrUserId: number): GramJs.TypeInputPeer | undefined { export function buildInputPeerFromLocalDb(chatOrUserId: string): GramJs.TypeInputPeer | undefined {
if (chatOrUserId > 0) { const type = getEntityTypeById(chatOrUserId);
const { accessHash } = localDb.users[chatOrUserId] || {}; let accessHash: BigInt.BigInteger | undefined;
return accessHash if (type === 'user') {
? new GramJs.InputPeerUser({ accessHash = localDb.users[chatOrUserId]?.accessHash;
userId: chatOrUserId, if (!accessHash) {
accessHash, return undefined;
}) }
: undefined; } else if (type === 'channel') {
accessHash = (localDb.chats[chatOrUserId] as GramJs.Channel)?.accessHash;
if (!accessHash) {
return undefined;
}
} }
if (chatOrUserId <= -1000000000) { return buildInputPeer(chatOrUserId, String(accessHash));
const { accessHash } = (localDb.chats[-chatOrUserId] as GramJs.Channel) || {};
return accessHash
? new GramJs.InputPeerChannel({
channelId: -chatOrUserId,
accessHash,
})
: undefined;
}
return new GramJs.InputPeerChat({
chatId: -chatOrUserId,
});
} }
export function buildInputEntity(chatOrUserId: number, accessHash?: string) { export function buildInputEntity(chatOrUserId: string, accessHash?: string) {
if (chatOrUserId > 0) { const type = getEntityTypeById(chatOrUserId);
if (type === 'user') {
return new GramJs.InputUser({ return new GramJs.InputUser({
userId: chatOrUserId, userId: buildMtpPeerId(chatOrUserId, 'user'),
accessHash: BigInt(accessHash!), accessHash: BigInt(accessHash!),
}); });
} else if (chatOrUserId <= -1000000000) { } else if (type === 'channel') {
return new GramJs.InputChannel({ return new GramJs.InputChannel({
channelId: -chatOrUserId, channelId: buildMtpPeerId(chatOrUserId, 'channel'),
accessHash: BigInt(accessHash!), accessHash: BigInt(accessHash!),
}); });
} else { } else {
return -chatOrUserId; return buildMtpPeerId(chatOrUserId, 'chat');
} }
} }
@ -225,7 +239,7 @@ export function generateRandomBigInt() {
export function buildMessageFromUpdate( export function buildMessageFromUpdate(
id: number, id: number,
chatId: number, chatId: string,
update: GramJs.UpdateShortSentMessage | GramJs.UpdateServiceNotification, update: GramJs.UpdateShortSentMessage | GramJs.UpdateServiceNotification,
) { ) {
// This is not a proper message, but we only need these fields for downloading media through `localDb`. // This is not a proper message, but we only need these fields for downloading media through `localDb`.
@ -269,24 +283,13 @@ export function buildMtpMessageEntity(entity: ApiMessageEntity): GramJs.TypeMess
return new GramJs.InputMessageEntityMentionName({ return new GramJs.InputMessageEntityMentionName({
offset, offset,
length, length,
userId: new GramJs.InputUser({ userId: userId!, accessHash: user!.accessHash! }), userId: new GramJs.InputUser({ userId: BigInt(userId!), accessHash: user!.accessHash! }),
}); });
default: default:
return new GramJs.MessageEntityUnknown({ offset, length }); return new GramJs.MessageEntityUnknown({ offset, length });
} }
} }
// TODO: This formula is taken from API docs, but doesn't seem to calculate hash correctly
export function calculateResultHash(ids: number[]) {
let hash = 0;
ids.forEach((id) => {
// eslint-disable-next-line no-bitwise
hash = (((hash * 0x4F25) & 0x7FFFFFFF) + id) & 0x7FFFFFFF;
});
return hash;
}
export function isMessageWithMedia(message: GramJs.Message | GramJs.UpdateServiceNotification) { export function isMessageWithMedia(message: GramJs.Message | GramJs.UpdateServiceNotification) {
const { media } = message; const { media } = message;
if (!media) { if (!media) {
@ -412,3 +415,12 @@ export function buildInputReportReason(reason: ApiReportReason) {
return undefined; return undefined;
} }
function buildMtpPeerId(id: string, type: 'user' | 'chat' | 'channel') {
// Workaround for old-fashioned IDs stored locally
if (typeof id === 'number') {
return BigInt(Math.abs(id));
}
return type === 'user' ? BigInt(id) : BigInt(id.slice(1));
}

View File

@ -1,6 +1,6 @@
import { Api as GramJs } from '../../lib/gramjs'; import { Api as GramJs } from '../../lib/gramjs';
import localDb from './localDb'; import localDb from './localDb';
import { getApiChatIdFromMtpPeer } from './apiBuilders/chats'; import { getApiChatIdFromMtpPeer } from './apiBuilders/peers';
export function resolveMessageApiChatId(mtpMessage: GramJs.TypeMessage) { export function resolveMessageApiChatId(mtpMessage: GramJs.TypeMessage) {
if (!(mtpMessage instanceof GramJs.Message || mtpMessage instanceof GramJs.MessageService)) { if (!(mtpMessage instanceof GramJs.Message || mtpMessage instanceof GramJs.MessageService)) {

View File

@ -4,8 +4,8 @@ import { ApiMessage } from '../types';
interface LocalDb { interface LocalDb {
localMessages: Record<string, ApiMessage>; localMessages: Record<string, ApiMessage>;
// Used for loading avatars and media through in-memory Gram JS instances. // Used for loading avatars and media through in-memory Gram JS instances.
chats: Record<number, GramJs.Chat | GramJs.Channel>; chats: Record<string, GramJs.Chat | GramJs.Channel>;
users: Record<number, GramJs.User>; users: Record<string, GramJs.User>;
messages: Record<string, GramJs.Message | GramJs.MessageService>; messages: Record<string, GramJs.Message | GramJs.MessageService>;
documents: Record<string, GramJs.Document>; documents: Record<string, GramJs.Document>;
stickerSets: Record<string, GramJs.StickerSet>; stickerSets: Record<string, GramJs.StickerSet>;

View File

@ -5,10 +5,11 @@ import { ApiChat, ApiUser } from '../../types';
import localDb from '../localDb'; import localDb from '../localDb';
import { invokeRequest } from './client'; import { invokeRequest } from './client';
import { buildInputPeer, calculateResultHash, generateRandomBigInt } from '../gramjsBuilders'; import { buildInputPeer, generateRandomBigInt } from '../gramjsBuilders';
import { buildApiUser } from '../apiBuilders/users'; import { buildApiUser } from '../apiBuilders/users';
import { buildApiBotInlineMediaResult, buildApiBotInlineResult, buildBotSwitchPm } from '../apiBuilders/bots'; import { buildApiBotInlineMediaResult, buildApiBotInlineResult, buildBotSwitchPm } from '../apiBuilders/bots';
import { buildApiChatFromPreview } from '../apiBuilders/chats'; import { buildApiChatFromPreview } from '../apiBuilders/chats';
import { buildApiPeerId } from '../apiBuilders/peers';
export function init() { export function init() {
} }
@ -17,7 +18,7 @@ export function answerCallbackButton(
{ {
chatId, accessHash, messageId, data, chatId, accessHash, messageId, data,
}: { }: {
chatId: number; accessHash?: string; messageId: number; data: string; chatId: string; accessHash?: string; messageId: number; data: string;
}, },
) { ) {
return invokeRequest(new GramJs.messages.GetBotCallbackAnswer({ return invokeRequest(new GramJs.messages.GetBotCallbackAnswer({
@ -27,9 +28,8 @@ export function answerCallbackButton(
})); }));
} }
export async function fetchTopInlineBots({ hash = 0 }: { hash?: number }) { export async function fetchTopInlineBots() {
const topPeers = await invokeRequest(new GramJs.contacts.GetTopPeers({ const topPeers = await invokeRequest(new GramJs.contacts.GetTopPeers({
hash,
botsInline: true, botsInline: true,
})); }));
@ -41,7 +41,6 @@ export async function fetchTopInlineBots({ hash = 0 }: { hash?: number }) {
const ids = users.map(({ id }) => id); const ids = users.map(({ id }) => id);
return { return {
hash: calculateResultHash(ids),
ids, ids,
users, users,
}; };
@ -160,7 +159,7 @@ function getInlineBotResultsNextOffset(username: string, nextOffset?: string) {
} }
function addUserToLocalDb(user: GramJs.User) { function addUserToLocalDb(user: GramJs.User) {
localDb.users[user.id] = user; localDb.users[buildApiPeerId(user.id, 'user')] = user;
} }
function addDocumentToLocalDb(document: GramJs.Document) { function addDocumentToLocalDb(document: GramJs.Document) {

View File

@ -1,3 +1,4 @@
import BigInt from 'big-integer';
import { Api as GramJs } from '../../../lib/gramjs'; import { Api as GramJs } from '../../../lib/gramjs';
import { import {
OnApiUpdate, OnApiUpdate,
@ -21,7 +22,6 @@ import {
getPeerKey, getPeerKey,
buildChatMembers, buildChatMembers,
buildApiChatFromPreview, buildApiChatFromPreview,
getApiChatIdFromMtpPeer,
buildApiChatFolder, buildApiChatFolder,
buildApiChatFolderFromSuggested, buildApiChatFolderFromSuggested,
buildApiChatBotCommands, buildApiChatBotCommands,
@ -40,6 +40,7 @@ import {
buildChatAdminRights, buildChatAdminRights,
} from '../gramjsBuilders'; } from '../gramjsBuilders';
import { addMessageToLocalDb } from '../helpers'; import { addMessageToLocalDb } from '../helpers';
import { buildApiPeerId, getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
const MAX_INT_32 = 2 ** 31 - 1; const MAX_INT_32 = 2 ** 31 - 1;
let onUpdate: OnApiUpdate; let onUpdate: OnApiUpdate;
@ -96,12 +97,12 @@ export async function fetchChats({
...preparePeers(result), ...preparePeers(result),
}; };
const chats: ApiChat[] = []; const chats: ApiChat[] = [];
const draftsById: Record<number, ApiFormattedText> = {}; const draftsById: Record<string, ApiFormattedText> = {};
const replyingToById: Record<number, number> = {}; const replyingToById: Record<string, number> = {};
const dialogs = (resultPinned ? resultPinned.dialogs : []).concat(result.dialogs); const dialogs = (resultPinned ? resultPinned.dialogs : []).concat(result.dialogs);
const orderedPinnedIds: number[] = []; const orderedPinnedIds: string[] = [];
dialogs.forEach((dialog) => { dialogs.forEach((dialog) => {
if ( if (
@ -325,12 +326,12 @@ export function clearDraft(chat: ApiChat) {
})); }));
} }
async function getFullChatInfo(chatId: number): Promise<{ async function getFullChatInfo(chatId: string): Promise<{
fullInfo: ApiChatFullInfo; fullInfo: ApiChatFullInfo;
users?: ApiUser[]; users?: ApiUser[];
} | undefined> { } | undefined> {
const result = await invokeRequest(new GramJs.messages.GetFullChat({ const result = await invokeRequest(new GramJs.messages.GetFullChat({
chatId: buildInputEntity(chatId) as number, chatId: buildInputEntity(chatId) as BigInt.BigInteger,
})); }));
if (!result || !(result.fullChat instanceof GramJs.ChatFull)) { if (!result || !(result.fullChat instanceof GramJs.ChatFull)) {
@ -366,7 +367,7 @@ async function getFullChatInfo(chatId: number): Promise<{
} }
async function getFullChannelInfo( async function getFullChannelInfo(
id: number, id: string,
accessHash: string, accessHash: string,
adminRights?: ApiChatAdminRights, adminRights?: ApiChatAdminRights,
) { ) {
@ -430,7 +431,7 @@ async function getFullChannelInfo(
nextSendDate: slowmodeNextSendDate, nextSendDate: slowmodeNextSendDate,
} : undefined, } : undefined,
migratedFrom: migratedFromChatId ? { migratedFrom: migratedFromChatId ? {
chatId: getApiChatIdFromMtpPeer({ chatId: migratedFromChatId } as GramJs.TypePeer), chatId: buildApiPeerId(migratedFromChatId, 'chat'),
maxMessageId: migratedFromMaxId, maxMessageId: migratedFromMaxId,
} : undefined, } : undefined,
canViewMembers: canViewParticipants, canViewMembers: canViewParticipants,
@ -438,8 +439,8 @@ async function getFullChannelInfo(
members, members,
kickedMembers, kickedMembers,
adminMembers, adminMembers,
groupCallId: call ? call.id.toString() : undefined, groupCallId: call ? String(call.id) : undefined,
linkedChatId: linkedChatId ? getApiChatIdFromMtpPeer({ chatId: linkedChatId } as GramJs.TypePeer) : undefined, linkedChatId: linkedChatId ? buildApiPeerId(linkedChatId, 'chat') : undefined,
botCommands, botCommands,
}, },
users: [...(users || []), ...(bannedUsers || []), ...(adminUsers || [])], users: [...(users || []), ...(bannedUsers || []), ...(adminUsers || [])],
@ -515,7 +516,7 @@ export async function createChannel({
export function joinChannel({ export function joinChannel({
channelId, accessHash, channelId, accessHash,
}: { }: {
channelId: number; accessHash: string; channelId: string; accessHash: string;
}) { }) {
return invokeRequest(new GramJs.channels.JoinChannel({ return invokeRequest(new GramJs.channels.JoinChannel({
channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel, channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel,
@ -529,7 +530,7 @@ export function deleteChatUser({
}) { }) {
if (chat.type !== 'chatTypeBasicGroup') return undefined; if (chat.type !== 'chatTypeBasicGroup') return undefined;
return invokeRequest(new GramJs.messages.DeleteChatUser({ return invokeRequest(new GramJs.messages.DeleteChatUser({
chatId: buildInputEntity(chat.id, chat.accessHash) as number, chatId: buildInputEntity(chat.id, chat.accessHash) as BigInt.BigInteger,
userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser, userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser,
}), true); }), true);
} }
@ -537,17 +538,17 @@ export function deleteChatUser({
export function deleteChat({ export function deleteChat({
chatId, chatId,
}: { }: {
chatId: number; chatId: string;
}) { }) {
return invokeRequest(new GramJs.messages.DeleteChat({ return invokeRequest(new GramJs.messages.DeleteChat({
chatId: buildInputEntity(chatId) as number, chatId: buildInputEntity(chatId) as BigInt.BigInteger,
}), true); }), true);
} }
export function leaveChannel({ export function leaveChannel({
channelId, accessHash, channelId, accessHash,
}: { }: {
channelId: number; accessHash: string; channelId: string; accessHash: string;
}) { }) {
return invokeRequest(new GramJs.channels.LeaveChannel({ return invokeRequest(new GramJs.channels.LeaveChannel({
channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel, channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel,
@ -557,7 +558,7 @@ export function leaveChannel({
export function deleteChannel({ export function deleteChannel({
channelId, accessHash, channelId, accessHash,
}: { }: {
channelId: number; accessHash: string; channelId: string; accessHash: string;
}) { }) {
return invokeRequest(new GramJs.channels.DeleteChannel({ return invokeRequest(new GramJs.channels.DeleteChannel({
channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel, channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel,
@ -600,7 +601,7 @@ export async function createGroupChat({
export async function editChatPhoto({ export async function editChatPhoto({
chatId, accessHash, photo, chatId, accessHash, photo,
}: { }: {
chatId: number; accessHash?: string; photo: File; chatId: string; accessHash?: string; photo: File;
}) { }) {
const uploadedPhoto = await uploadFile(photo); const uploadedPhoto = await uploadFile(photo);
const inputEntity = buildInputEntity(chatId, accessHash); const inputEntity = buildInputEntity(chatId, accessHash);
@ -614,7 +615,7 @@ export async function editChatPhoto({
}), }),
}) })
: new GramJs.messages.EditChatPhoto({ : new GramJs.messages.EditChatPhoto({
chatId: inputEntity as number, chatId: inputEntity as BigInt.BigInteger,
photo: new GramJs.InputChatUploadedPhoto({ photo: new GramJs.InputChatUploadedPhoto({
file: uploadedPhoto, file: uploadedPhoto,
}), }),
@ -837,7 +838,7 @@ export async function updateChatTitle(chat: ApiChat, title: string) {
channel: inputEntity as GramJs.InputChannel, channel: inputEntity as GramJs.InputChannel,
title, title,
}) : new GramJs.messages.EditChatTitle({ }) : new GramJs.messages.EditChatTitle({
chatId: inputEntity as number, chatId: inputEntity as BigInt.BigInteger,
title, title,
}), }),
true, true,
@ -881,7 +882,7 @@ type ChannelMembersFilter =
| 'recent'; | 'recent';
export async function fetchMembers( export async function fetchMembers(
chatId: number, chatId: string,
accessHash: string, accessHash: string,
memberFilter: ChannelMembersFilter = 'recent', memberFilter: ChannelMembersFilter = 'recent',
offset?: number, offset?: number,
@ -946,7 +947,7 @@ export function setDiscussionGroup({
export async function migrateChat(chat: ApiChat) { export async function migrateChat(chat: ApiChat) {
const result = await invokeRequest( const result = await invokeRequest(
new GramJs.messages.MigrateChat({ chatId: buildInputEntity(chat.id) as number }), true, new GramJs.messages.MigrateChat({ chatId: buildInputEntity(chat.id) as BigInt.BigInteger }), true,
); );
// `migrateChat` can return a lot of different update types according to docs, // `migrateChat` can return a lot of different update types according to docs,
@ -1014,7 +1015,7 @@ export function addChatMembers(chat: ApiChat, users: ApiUser[]) {
return Promise.all(users.map((user) => { return Promise.all(users.map((user) => {
return invokeRequest(new GramJs.messages.AddChatUser({ return invokeRequest(new GramJs.messages.AddChatUser({
chatId: buildInputEntity(chat.id) as number, chatId: buildInputEntity(chat.id) as BigInt.BigInteger,
userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser, userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser,
}), true); }), true);
})); }));
@ -1043,7 +1044,7 @@ export function deleteChatMember(chat: ApiChat, user: ApiUser) {
}); });
} else { } else {
return invokeRequest(new GramJs.messages.DeleteChatUser({ return invokeRequest(new GramJs.messages.DeleteChatUser({
chatId: buildInputEntity(chat.id) as number, chatId: buildInputEntity(chat.id) as BigInt.BigInteger,
userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser, userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser,
}), true); }), true);
} }
@ -1074,7 +1075,7 @@ function updateLocalDb(result: (
if ('users' in result) { if ('users' in result) {
result.users.forEach((user) => { result.users.forEach((user) => {
if (user instanceof GramJs.User) { if (user instanceof GramJs.User) {
localDb.users[user.id] = user; localDb.users[buildApiPeerId(user.id, 'user')] = user;
} }
}); });
} }
@ -1082,7 +1083,7 @@ function updateLocalDb(result: (
if ('chats' in result) { if ('chats' in result) {
result.chats.forEach((chat) => { result.chats.forEach((chat) => {
if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) { if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) {
localDb.chats[chat.id] = chat; localDb.chats[buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel')] = chat;
} }
}); });
} }
@ -1102,7 +1103,5 @@ export async function importChatInvite({ hash }: { hash: string }) {
return undefined; return undefined;
} }
const chat = buildApiChatFromPreview(updates.chats[0]); return buildApiChatFromPreview(updates.chats[0]);
return chat;
} }

View File

@ -24,6 +24,7 @@ import { setMessageBuilderCurrentUserId } from '../apiBuilders/messages';
import downloadMediaWithClient from './media'; import downloadMediaWithClient from './media';
import { buildApiUserFromFull } from '../apiBuilders/users'; import { buildApiUserFromFull } from '../apiBuilders/users';
import localDb from '../localDb'; import localDb from '../localDb';
import { buildApiPeerId } from '../apiBuilders/peers';
const DEFAULT_USER_AGENT = 'Unknown UserAgent'; const DEFAULT_USER_AGENT = 'Unknown UserAgent';
const APP_CODE_NAME = 'Z'; const APP_CODE_NAME = 'Z';
@ -254,7 +255,7 @@ export async function fetchCurrentUser() {
return; return;
} }
localDb.users[userFull.user.id] = userFull.user; localDb.users[buildApiPeerId(userFull.user.id, 'user')] = userFull.user;
const currentUser = buildApiUserFromFull(userFull); const currentUser = buildApiUserFromFull(userFull);
setMessageBuilderCurrentUserId(currentUser.id); setMessageBuilderCurrentUserId(currentUser.id);

View File

@ -91,16 +91,16 @@ async function download(
} }
let entityType: EntityType; let entityType: EntityType;
let entityId: string | number = mediaMatch[2]; const entityId: string | number = mediaMatch[2];
const sizeType = mediaMatch[3] ? mediaMatch[3].replace('?size=', '') : undefined; const sizeType = mediaMatch[3] ? mediaMatch[3].replace('?size=', '') : undefined;
let entity: ( let entity: (
GramJs.User | GramJs.Chat | GramJs.Channel | GramJs.Photo | GramJs.User | GramJs.Chat | GramJs.Channel | GramJs.Photo |
GramJs.Message | GramJs.Document | GramJs.StickerSet | GramJs.TypeWebDocument | undefined GramJs.Message | GramJs.MessageService |
GramJs.Document | GramJs.StickerSet | GramJs.TypeWebDocument | undefined
); );
if (mediaMatch[1] === 'avatar' || mediaMatch[1] === 'profile') { if (mediaMatch[1] === 'avatar' || mediaMatch[1] === 'profile') {
entityType = getEntityTypeById(Number(entityId)); entityType = getEntityTypeById(entityId);
entityId = Math.abs(Number(entityId));
} else { } else {
entityType = mediaMatch[1] as 'msg' | 'sticker' | 'wallpaper' | 'gif' | 'stickerSet' | 'photo' | 'webDocument'; entityType = mediaMatch[1] as 'msg' | 'sticker' | 'wallpaper' | 'gif' | 'stickerSet' | 'photo' | 'webDocument';
} }
@ -108,27 +108,27 @@ async function download(
switch (entityType) { switch (entityType) {
case 'channel': case 'channel':
case 'chat': case 'chat':
entity = localDb.chats[entityId as number]; entity = localDb.chats[entityId];
break; break;
case 'user': case 'user':
entity = localDb.users[entityId as number]; entity = localDb.users[entityId];
break; break;
case 'msg': case 'msg':
entity = localDb.messages[entityId as string]; entity = localDb.messages[entityId];
break; break;
case 'sticker': case 'sticker':
case 'gif': case 'gif':
case 'wallpaper': case 'wallpaper':
entity = localDb.documents[entityId as string]; entity = localDb.documents[entityId];
break; break;
case 'photo': case 'photo':
entity = localDb.photos[entityId as string]; entity = localDb.photos[entityId];
break; break;
case 'stickerSet': case 'stickerSet':
entity = localDb.stickerSets[entityId as string]; entity = localDb.stickerSets[entityId];
break; break;
case 'webDocument': case 'webDocument':
entity = localDb.webDocuments[entityId as string]; entity = localDb.webDocuments[entityId];
break; break;
} }

View File

@ -43,7 +43,6 @@ import {
buildMtpMessageEntity, buildMtpMessageEntity,
isMessageWithMedia, isMessageWithMedia,
isServiceMessageWithMedia, isServiceMessageWithMedia,
calculateResultHash,
buildInputReportReason, buildInputReportReason,
} from '../gramjsBuilders'; } from '../gramjsBuilders';
import localDb from '../localDb'; import localDb from '../localDb';
@ -52,6 +51,7 @@ import { fetchFile } from '../../../util/files';
import { addMessageToLocalDb, resolveMessageApiChatId } from '../helpers'; import { addMessageToLocalDb, resolveMessageApiChatId } from '../helpers';
import { interpolateArray } from '../../../util/waveform'; import { interpolateArray } from '../../../util/waveform';
import { requestChatUpdate } from './chats'; import { requestChatUpdate } from './chats';
import { buildApiPeerId } from '../apiBuilders/peers';
const FAST_SEND_TIMEOUT = 1000; const FAST_SEND_TIMEOUT = 1000;
const INPUT_WAVEFORM_LENGTH = 63; const INPUT_WAVEFORM_LENGTH = 63;
@ -238,7 +238,7 @@ export function sendMessage(
}, FAST_SEND_TIMEOUT); }, FAST_SEND_TIMEOUT);
const randomId = generateRandomBigInt(); const randomId = generateRandomBigInt();
localDb.localMessages[randomId.toString()] = localMessage; localDb.localMessages[String(randomId)] = localMessage;
if (groupedId) { if (groupedId) {
return sendGroupedMedia({ return sendGroupedMedia({
@ -1078,12 +1078,11 @@ export async function findFirstMessageIdAfterDate({
return result.messages[0].id; return result.messages[0].id;
} }
export async function fetchScheduledHistory({ chat, hash = 0 }: { chat: ApiChat; hash?: number }) { export async function fetchScheduledHistory({ chat }: { chat: ApiChat }) {
const { id, accessHash } = chat; const { id, accessHash } = chat;
const result = await invokeRequest(new GramJs.messages.GetScheduledHistory({ const result = await invokeRequest(new GramJs.messages.GetScheduledHistory({
peer: buildInputPeer(id, accessHash), peer: buildInputPeer(id, accessHash),
hash,
})); }));
if ( if (
@ -1100,7 +1099,6 @@ export async function fetchScheduledHistory({ chat, hash = 0 }: { chat: ApiChat;
return { return {
messages, messages,
hash: calculateResultHash(messages.map((message) => message.id)),
}; };
} }
@ -1119,13 +1117,13 @@ function updateLocalDb(result: (
)) { )) {
result.users.forEach((user) => { result.users.forEach((user) => {
if (user instanceof GramJs.User) { if (user instanceof GramJs.User) {
localDb.users[user.id] = user; localDb.users[buildApiPeerId(user.id, 'user')] = user;
} }
}); });
result.chats.forEach((chat) => { result.chats.forEach((chat) => {
if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) { if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) {
localDb.chats[chat.id] = chat; localDb.chats[buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel')] = chat;
} }
}); });

View File

@ -4,7 +4,7 @@ import { Api as GramJs } from '../../../lib/gramjs';
import { import {
ApiChat, ApiLangString, ApiLanguage, ApiNotifyException, ApiUser, ApiWallpaper, ApiChat, ApiLangString, ApiLanguage, ApiNotifyException, ApiUser, ApiWallpaper,
} from '../../types'; } from '../../types';
import { ApiPrivacyKey, IInputPrivacyRules } from '../../../types'; import { ApiPrivacyKey, InputPrivacyRules } from '../../../types';
import { BLOCKED_LIST_LIMIT, DEFAULT_LANG_PACK, LANG_PACKS } from '../../../config'; import { BLOCKED_LIST_LIMIT, DEFAULT_LANG_PACK, LANG_PACKS } from '../../../config';
import { import {
@ -12,13 +12,14 @@ import {
} from '../apiBuilders/misc'; } from '../apiBuilders/misc';
import { buildApiUser } from '../apiBuilders/users'; import { buildApiUser } from '../apiBuilders/users';
import { buildApiChatFromPreview, getApiChatIdFromMtpPeer } from '../apiBuilders/chats'; import { buildApiChatFromPreview } from '../apiBuilders/chats';
import { buildInputPrivacyKey, buildInputPeer } from '../gramjsBuilders'; import { buildInputPrivacyKey, buildInputPeer, buildInputEntity } from '../gramjsBuilders';
import { invokeRequest, uploadFile, getClient } from './client'; import { invokeRequest, uploadFile, getClient } from './client';
import { omitVirtualClassFields } from '../apiBuilders/helpers'; import { omitVirtualClassFields } from '../apiBuilders/helpers';
import { buildCollectionByKey } from '../../../util/iteratees'; import { buildCollectionByKey } from '../../../util/iteratees';
import localDb from '../localDb'; import localDb from '../localDb';
import { getServerTime } from '../../../util/serverTime'; import { getServerTime } from '../../../util/serverTime';
import { buildApiPeerId, getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
const MAX_INT_32 = 2 ** 31 - 1; const MAX_INT_32 = 2 ** 31 - 1;
const BETA_LANG_CODES = ['ar', 'fa', 'id', 'ko', 'uz']; const BETA_LANG_CODES = ['ar', 'fa', 'id', 'ko', 'uz'];
@ -61,8 +62,8 @@ export async function uploadProfilePhoto(file: File) {
})); }));
} }
export async function fetchWallpapers(hash: number) { export async function fetchWallpapers() {
const result = await invokeRequest(new GramJs.account.GetWallPapers({ hash })); const result = await invokeRequest(new GramJs.account.GetWallPapers({ hash: BigInt('0') }));
if (!result || result instanceof GramJs.account.WallPapersNotModified) { if (!result || result instanceof GramJs.account.WallPapersNotModified) {
return undefined; return undefined;
@ -84,7 +85,6 @@ export async function fetchWallpapers(hash: number) {
}); });
return { return {
hash: result.hash,
wallpapers: filteredWallpapers.map(buildApiWallpaper).filter<ApiWallpaper>(Boolean as any), wallpapers: filteredWallpapers.map(buildApiWallpaper).filter<ApiWallpaper>(Boolean as any),
}; };
} }
@ -130,13 +130,13 @@ export async function fetchBlockedContacts() {
}; };
} }
export function blockContact(chatOrUserId: number, accessHash?: string) { export function blockContact(chatOrUserId: string, accessHash?: string) {
return invokeRequest(new GramJs.contacts.Block({ return invokeRequest(new GramJs.contacts.Block({
id: buildInputPeer(chatOrUserId, accessHash), id: buildInputPeer(chatOrUserId, accessHash),
})); }));
} }
export function unblockContact(chatOrUserId: number, accessHash?: string) { export function unblockContact(chatOrUserId: string, accessHash?: string) {
return invokeRequest(new GramJs.contacts.Unblock({ return invokeRequest(new GramJs.contacts.Unblock({
id: buildInputPeer(chatOrUserId, accessHash), id: buildInputPeer(chatOrUserId, accessHash),
})); }));
@ -353,29 +353,29 @@ export function unregisterDevice(token: string) {
} }
export async function setPrivacySettings( export async function setPrivacySettings(
privacyKey: ApiPrivacyKey, rules: IInputPrivacyRules, privacyKey: ApiPrivacyKey, rules: InputPrivacyRules,
) { ) {
const key = buildInputPrivacyKey(privacyKey); const key = buildInputPrivacyKey(privacyKey);
const privacyRules: GramJs.TypeInputPrivacyRule[] = []; const privacyRules: GramJs.TypeInputPrivacyRule[] = [];
if (rules.allowedUsers) { if (rules.allowedUsers) {
privacyRules.push(new GramJs.InputPrivacyValueAllowUsers({ privacyRules.push(new GramJs.InputPrivacyValueAllowUsers({
users: rules.allowedUsers.map(({ id, accessHash }) => buildInputPeer(id, accessHash)), users: rules.allowedUsers.map(({ id, accessHash }) => buildInputEntity(id, accessHash) as GramJs.InputUser),
})); }));
} }
if (rules.allowedChats) { if (rules.allowedChats) {
privacyRules.push(new GramJs.InputPrivacyValueAllowChatParticipants({ privacyRules.push(new GramJs.InputPrivacyValueAllowChatParticipants({
chats: rules.allowedChats.map(({ id }) => -id), chats: rules.allowedChats.map(({ id }) => buildInputEntity(id) as BigInt.BigInteger),
})); }));
} }
if (rules.blockedUsers) { if (rules.blockedUsers) {
privacyRules.push(new GramJs.InputPrivacyValueDisallowUsers({ privacyRules.push(new GramJs.InputPrivacyValueDisallowUsers({
users: rules.blockedUsers.map(({ id, accessHash }) => buildInputPeer(id, accessHash)), users: rules.blockedUsers.map(({ id, accessHash }) => buildInputEntity(id, accessHash) as GramJs.InputUser),
})); }));
} }
if (rules.blockedChats) { if (rules.blockedChats) {
privacyRules.push(new GramJs.InputPrivacyValueDisallowChatParticipants({ privacyRules.push(new GramJs.InputPrivacyValueDisallowChatParticipants({
chats: rules.blockedChats.map(({ id }) => -id), chats: rules.blockedChats.map(({ id }) => buildInputEntity(id) as BigInt.BigInteger),
})); }));
} }
switch (rules.visibility) { switch (rules.visibility) {
@ -437,13 +437,13 @@ function updateLocalDb(
) { ) {
result.users.forEach((user) => { result.users.forEach((user) => {
if (user instanceof GramJs.User) { if (user instanceof GramJs.User) {
localDb.users[user.id] = user; localDb.users[buildApiPeerId(user.id, 'user')] = user;
} }
}); });
result.chats.forEach((chat) => { result.chats.forEach((chat) => {
if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) { if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) {
localDb.chats[chat.id] = chat; localDb.chats[buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel')] = chat;
} }
}); });
} }

View File

@ -1,3 +1,4 @@
import BigInt from 'big-integer';
import { Api as GramJs } from '../../../lib/gramjs'; import { Api as GramJs } from '../../../lib/gramjs';
import { ApiSticker, ApiVideo, OnApiUpdate } from '../../types'; import { ApiSticker, ApiVideo, OnApiUpdate } from '../../types';
@ -15,8 +16,8 @@ export function init(_onUpdate: OnApiUpdate) {
onUpdate = _onUpdate; onUpdate = _onUpdate;
} }
export async function fetchStickerSets({ hash }: { hash: number }) { export async function fetchStickerSets({ hash = '0' }: { hash?: string }) {
const allStickers = await invokeRequest(new GramJs.messages.GetAllStickers({ hash })); const allStickers = await invokeRequest(new GramJs.messages.GetAllStickers({ hash: BigInt(hash) }));
if (!allStickers || allStickers instanceof GramJs.messages.AllStickersNotModified) { if (!allStickers || allStickers instanceof GramJs.messages.AllStickersNotModified) {
return undefined; return undefined;
@ -29,46 +30,46 @@ export async function fetchStickerSets({ hash }: { hash: number }) {
}); });
return { return {
hash: allStickers.hash, hash: String(allStickers.hash),
sets: allStickers.sets.map(buildStickerSet), sets: allStickers.sets.map(buildStickerSet),
}; };
} }
export async function fetchRecentStickers({ hash }: { hash: number }) { export async function fetchRecentStickers({ hash = '0' }: { hash?: string }) {
const result = await invokeRequest(new GramJs.messages.GetRecentStickers({ hash })); const result = await invokeRequest(new GramJs.messages.GetRecentStickers({ hash: BigInt(hash) }));
if (!result || result instanceof GramJs.messages.RecentStickersNotModified) { if (!result || result instanceof GramJs.messages.RecentStickersNotModified) {
return undefined; return undefined;
} }
return { return {
hash: result.hash, hash: String(result.hash),
stickers: processStickerResult(result.stickers.slice(0, RECENT_STICKERS_LIMIT)), stickers: processStickerResult(result.stickers.slice(0, RECENT_STICKERS_LIMIT)),
}; };
} }
export async function fetchFavoriteStickers({ hash }: { hash: number }) { export async function fetchFavoriteStickers({ hash = '0' }: { hash?: string }) {
const result = await invokeRequest(new GramJs.messages.GetFavedStickers({ hash })); const result = await invokeRequest(new GramJs.messages.GetFavedStickers({ hash: BigInt(hash) }));
if (!result || result instanceof GramJs.messages.FavedStickersNotModified) { if (!result || result instanceof GramJs.messages.FavedStickersNotModified) {
return undefined; return undefined;
} }
return { return {
hash: result.hash, hash: String(result.hash),
stickers: processStickerResult(result.stickers), stickers: processStickerResult(result.stickers),
}; };
} }
export async function fetchFeaturedStickers({ hash }: { hash: number }) { export async function fetchFeaturedStickers({ hash = '0' }: { hash?: string }) {
const result = await invokeRequest(new GramJs.messages.GetFeaturedStickers({ hash })); const result = await invokeRequest(new GramJs.messages.GetFeaturedStickers({ hash: BigInt(hash) }));
if (!result || result instanceof GramJs.messages.FeaturedStickersNotModified) { if (!result || result instanceof GramJs.messages.FeaturedStickersNotModified) {
return undefined; return undefined;
} }
return { return {
hash: result.hash, hash: String(result.hash),
sets: result.sets.map(buildStickerSetCovered), sets: result.sets.map(buildStickerSetCovered),
}; };
} }
@ -93,8 +94,10 @@ export async function faveSticker({
} }
} }
export async function fetchStickers({ stickerSetShortName, stickerSetId, accessHash }: export async function fetchStickers(
{ stickerSetShortName?: string; stickerSetId?: string; accessHash: string }) { { stickerSetShortName, stickerSetId, accessHash }:
{ stickerSetShortName?: string; stickerSetId?: string; accessHash: string },
) {
const result = await invokeRequest(new GramJs.messages.GetStickerSet({ const result = await invokeRequest(new GramJs.messages.GetStickerSet({
stickerset: stickerSetId stickerset: stickerSetId
? buildInputStickerSet(stickerSetId, accessHash) ? buildInputStickerSet(stickerSetId, accessHash)
@ -127,10 +130,10 @@ export async function fetchAnimatedEmojis() {
}; };
} }
export async function searchStickers({ query, hash }: { query: string; hash: number }) { export async function searchStickers({ query, hash = '0' }: { query: string; hash?: string }) {
const result = await invokeRequest(new GramJs.messages.SearchStickerSets({ const result = await invokeRequest(new GramJs.messages.SearchStickerSets({
q: query, q: query,
hash, hash: BigInt(hash),
})); }));
if (!result || result instanceof GramJs.messages.FoundStickerSetsNotModified) { if (!result || result instanceof GramJs.messages.FoundStickerSetsNotModified) {
@ -138,20 +141,20 @@ export async function searchStickers({ query, hash }: { query: string; hash: num
} }
return { return {
hash: result.hash, hash: String(result.hash),
sets: result.sets.map(buildStickerSetCovered), sets: result.sets.map(buildStickerSetCovered),
}; };
} }
export async function fetchSavedGifs({ hash }: { hash: number }) { export async function fetchSavedGifs({ hash = '0' }: { hash?: string }) {
const result = await invokeRequest(new GramJs.messages.GetSavedGifs({ hash })); const result = await invokeRequest(new GramJs.messages.GetSavedGifs({ hash: BigInt(hash) }));
if (!result || result instanceof GramJs.messages.SavedGifsNotModified) { if (!result || result instanceof GramJs.messages.SavedGifsNotModified) {
return undefined; return undefined;
} }
return { return {
hash: result.hash, hash: String(result.hash),
gifs: processGifResult(result.gifs), gifs: processGifResult(result.gifs),
}; };
} }
@ -233,11 +236,11 @@ export async function searchGifs({ query, offset = '' }: { query: string; offset
} }
export async function fetchStickersForEmoji({ export async function fetchStickersForEmoji({
emoji, hash = 0, emoji, hash = '0',
}: { emoji: string; hash?: number }) { }: { emoji: string; hash?: string }) {
const result = await invokeRequest(new GramJs.messages.GetStickers({ const result = await invokeRequest(new GramJs.messages.GetStickers({
emoticon: emoji, emoticon: emoji,
hash, hash: BigInt(hash),
})); }));
if (!result || result instanceof GramJs.messages.StickersNotModified) { if (!result || result instanceof GramJs.messages.StickersNotModified) {
@ -246,7 +249,7 @@ export async function fetchStickersForEmoji({
return { return {
stickers: processStickerResult(result.stickers), stickers: processStickerResult(result.stickers),
hash: result.hash, hash: String(result.hash),
}; };
} }

View File

@ -10,7 +10,6 @@ import { invokeRequest } from './client';
import { searchMessagesLocal } from './messages'; import { searchMessagesLocal } from './messages';
import { import {
buildInputEntity, buildInputEntity,
calculateResultHash,
buildInputPeer, buildInputPeer,
buildInputContact, buildInputContact,
} from '../gramjsBuilders'; } from '../gramjsBuilders';
@ -20,6 +19,7 @@ import { buildApiPhoto } from '../apiBuilders/common';
import localDb from '../localDb'; import localDb from '../localDb';
import { addPhotoToLocalDb } from '../helpers'; import { addPhotoToLocalDb } from '../helpers';
import { buildApiCountryList } from '../apiBuilders/misc'; import { buildApiCountryList } from '../apiBuilders/misc';
import { buildApiPeerId } from '../apiBuilders/peers';
let onUpdate: OnApiUpdate; let onUpdate: OnApiUpdate;
@ -31,7 +31,7 @@ export async function fetchFullUser({
id, id,
accessHash, accessHash,
}: { }: {
id: number; id: string;
accessHash?: string; accessHash?: string;
}) { }) {
const input = buildInputEntity(id, accessHash); const input = buildInputEntity(id, accessHash);
@ -73,9 +73,8 @@ export async function fetchCountryList({ langCode = 'en' }: { langCode?: LangCod
return buildApiCountryList(countryList.countries); return buildApiCountryList(countryList.countries);
} }
export async function fetchTopUsers({ hash = 0 }: { hash?: number }) { export async function fetchTopUsers() {
const topPeers = await invokeRequest(new GramJs.contacts.GetTopPeers({ const topPeers = await invokeRequest(new GramJs.contacts.GetTopPeers({
hash,
correspondents: true, correspondents: true,
})); }));
if (!(topPeers instanceof GramJs.contacts.TopPeers)) { if (!(topPeers instanceof GramJs.contacts.TopPeers)) {
@ -86,29 +85,24 @@ export async function fetchTopUsers({ hash = 0 }: { hash?: number }) {
const ids = users.map(({ id }) => id); const ids = users.map(({ id }) => id);
return { return {
hash: calculateResultHash(ids),
ids, ids,
users, users,
}; };
} }
export async function fetchContactList({ hash = 0 }: { hash?: number }) { export async function fetchContactList() {
const result = await invokeRequest(new GramJs.contacts.GetContacts({ hash })); const result = await invokeRequest(new GramJs.contacts.GetContacts({ hash: BigInt('0') }));
if (!result || result instanceof GramJs.contacts.ContactsNotModified) { if (!result || result instanceof GramJs.contacts.ContactsNotModified) {
return undefined; return undefined;
} }
result.users.forEach((user) => { result.users.forEach((user) => {
if (user instanceof GramJs.User) { if (user instanceof GramJs.User) {
localDb.users[user.id] = user; localDb.users[buildApiPeerId(user.id, 'user')] = user;
} }
}); });
return { return {
hash: calculateResultHash([
result.savedCount,
...result.contacts.map(({ userId }) => userId),
]),
users: result.users.map(buildApiUser).filter<ApiUser>(Boolean as any), users: result.users.map(buildApiUser).filter<ApiUser>(Boolean as any),
chats: result.users.map((user) => buildApiChatFromPreview(user)).filter<ApiChat>(Boolean as any), chats: result.users.map((user) => buildApiChatFromPreview(user)).filter<ApiChat>(Boolean as any),
}; };
@ -124,7 +118,7 @@ export async function fetchUsers({ users }: { users: ApiUser[] }) {
result.forEach((user) => { result.forEach((user) => {
if (user instanceof GramJs.User) { if (user instanceof GramJs.User) {
localDb.users[user.id] = user; localDb.users[buildApiPeerId(user.id, 'user')] = user;
} }
}); });
@ -156,7 +150,7 @@ export function addContact({
firstName = '', firstName = '',
lastName = '', lastName = '',
}: { }: {
id: number; id: string;
accessHash?: string; accessHash?: string;
phoneNumber?: string; phoneNumber?: string;
firstName?: string; firstName?: string;
@ -174,7 +168,7 @@ export async function deleteUser({
id, id,
accessHash, accessHash,
}: { }: {
id: number; id: string;
accessHash?: string; accessHash?: string;
}) { }) {
const input = buildInputEntity(id, accessHash); const input = buildInputEntity(id, accessHash);

View File

@ -14,14 +14,12 @@ import {
buildMessageDraft, buildMessageDraft,
} from './apiBuilders/messages'; } from './apiBuilders/messages';
import { import {
getApiChatIdFromMtpPeer,
buildChatMember, buildChatMember,
buildChatMembers, buildChatMembers,
buildChatTypingStatus, buildChatTypingStatus,
buildAvatarHash, buildAvatarHash,
buildApiChatFromPreview, buildApiChatFromPreview,
buildApiChatFolder, buildApiChatFolder,
getApiChatIdFromInputMtpPeer,
} from './apiBuilders/chats'; } from './apiBuilders/chats';
import { buildApiUser, buildApiUserStatus } from './apiBuilders/users'; import { buildApiUser, buildApiUserStatus } from './apiBuilders/users';
import { import {
@ -35,6 +33,7 @@ import { DEBUG } from '../../config';
import { addMessageToLocalDb, addPhotoToLocalDb, resolveMessageApiChatId } from './helpers'; import { addMessageToLocalDb, addPhotoToLocalDb, resolveMessageApiChatId } from './helpers';
import { buildApiNotifyException, buildPrivacyKey, buildPrivacyRules } from './apiBuilders/misc'; import { buildApiNotifyException, buildPrivacyKey, buildPrivacyRules } from './apiBuilders/misc';
import { buildApiPhoto } from './apiBuilders/common'; import { buildApiPhoto } from './apiBuilders/common';
import { buildApiPeerId, getApiChatIdFromMtpPeer } from './apiBuilders/peers';
type Update = ( type Update = (
(GramJs.TypeUpdate | GramJs.TypeUpdates) & { _entities?: (GramJs.TypeUser | GramJs.TypeChat)[] } (GramJs.TypeUpdate | GramJs.TypeUpdates) & { _entities?: (GramJs.TypeUser | GramJs.TypeChat)[] }
@ -178,7 +177,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
const photo = buildChatPhotoForLocalDb(action.photo); const photo = buildChatPhotoForLocalDb(action.photo);
const avatarHash = buildAvatarHash(photo); const avatarHash = buildAvatarHash(photo);
const localDbChatId = Math.abs(resolveMessageApiChatId(update.message)!); const localDbChatId = resolveMessageApiChatId(update.message)!;
if (localDb.chats[localDbChatId]) { if (localDb.chats[localDbChatId]) {
localDb.chats[localDbChatId].photo = photo; localDb.chats[localDbChatId].photo = photo;
} }
@ -195,7 +194,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
}); });
} }
} else if (action instanceof GramJs.MessageActionChatDeletePhoto) { } else if (action instanceof GramJs.MessageActionChatDeletePhoto) {
const localDbChatId = Math.abs(resolveMessageApiChatId(update.message)!); const localDbChatId = resolveMessageApiChatId(update.message)!;
if (localDb.chats[localDbChatId]) { if (localDb.chats[localDbChatId]) {
localDb.chats[localDbChatId].photo = new GramJs.ChatPhotoEmpty(); localDb.chats[localDbChatId].photo = new GramJs.ChatPhotoEmpty();
} }
@ -270,10 +269,10 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
onUpdate({ onUpdate({
'@type': 'deleteScheduledMessages', '@type': 'deleteScheduledMessages',
ids: update.messages, ids: update.messages,
chatId: getApiChatIdFromInputMtpPeer(update.peer), chatId: getApiChatIdFromMtpPeer(update.peer),
}); });
} else if (update instanceof GramJs.UpdateDeleteChannelMessages) { } else if (update instanceof GramJs.UpdateDeleteChannelMessages) {
const chatId = getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel); const chatId = buildApiPeerId(update.channelId, 'channel');
const ids = update.messages; const ids = update.messages;
const existingIds = ids.filter((id) => localDb.messages[`${chatId}-${id}`]); const existingIds = ids.filter((id) => localDb.messages[`${chatId}-${id}`]);
const missingIds = ids.filter((id) => !localDb.messages[`${chatId}-${id}`]); const missingIds = ids.filter((id) => !localDb.messages[`${chatId}-${id}`]);
@ -339,7 +338,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
randomId = originRequest.randomId; randomId = originRequest.randomId;
} }
const localMessage = randomId && localDb.localMessages[randomId.toString()]; const localMessage = randomId && localDb.localMessages[String(randomId)];
if (!localMessage) { if (!localMessage) {
throw new Error('Local message not found'); throw new Error('Local message not found');
} }
@ -400,7 +399,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
} else if (update instanceof GramJs.UpdateChannelReadMessagesContents) { } else if (update instanceof GramJs.UpdateChannelReadMessagesContents) {
onUpdate({ onUpdate({
'@type': 'updateChannelMessages', '@type': 'updateChannelMessages',
channelId: update.channelId, channelId: buildApiPeerId(update.channelId, 'channel'),
ids: update.messages, ids: update.messages,
messageUpdate: { messageUpdate: {
hasUnreadMention: false, hasUnreadMention: false,
@ -414,28 +413,28 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
onUpdate({ onUpdate({
'@type': 'updateMessagePoll', '@type': 'updateMessagePoll',
pollId: pollId.toString(), pollId: String(pollId),
pollUpdate: apiPoll, pollUpdate: apiPoll,
}); });
} else { } else {
const pollResults = buildPollResults(results); const pollResults = buildPollResults(results);
onUpdate({ onUpdate({
'@type': 'updateMessagePoll', '@type': 'updateMessagePoll',
pollId: pollId.toString(), pollId: String(pollId),
pollUpdate: { results: pollResults }, pollUpdate: { results: pollResults },
}); });
} }
} else if (update instanceof GramJs.UpdateMessagePollVote) { } else if (update instanceof GramJs.UpdateMessagePollVote) {
onUpdate({ onUpdate({
'@type': 'updateMessagePollVote', '@type': 'updateMessagePollVote',
pollId: update.pollId.toString(), pollId: String(update.pollId),
userId: update.userId, userId: buildApiPeerId(update.userId, 'user'),
options: update.options.map((option) => String.fromCharCode(...option)), options: update.options.map((option) => String.fromCharCode(...option)),
}); });
} else if (update instanceof GramJs.UpdateChannelMessageViews) { } else if (update instanceof GramJs.UpdateChannelMessageViews) {
onUpdate({ onUpdate({
'@type': 'updateMessage', '@type': 'updateMessage',
chatId: getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel), chatId: buildApiPeerId(update.channelId, 'channel'),
id: update.id, id: update.id,
message: { views: update.views }, message: { views: update.views },
}); });
@ -461,7 +460,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
} else if (update instanceof GramJs.UpdateReadChannelInbox) { } else if (update instanceof GramJs.UpdateReadChannelInbox) {
onUpdate({ onUpdate({
'@type': 'updateChat', '@type': 'updateChat',
id: getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel), id: buildApiPeerId(update.channelId, 'channel'),
chat: { chat: {
lastReadInboxMessageId: update.maxId, lastReadInboxMessageId: update.maxId,
unreadCount: update.stillUnreadCount, unreadCount: update.stillUnreadCount,
@ -470,7 +469,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
} else if (update instanceof GramJs.UpdateReadChannelOutbox) { } else if (update instanceof GramJs.UpdateReadChannelOutbox) {
onUpdate({ onUpdate({
'@type': 'updateChat', '@type': 'updateChat',
id: getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel), id: buildApiPeerId(update.channelId, 'channel'),
chat: { chat: {
lastReadOutboxMessageId: update.maxId, lastReadOutboxMessageId: update.maxId,
}, },
@ -525,7 +524,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
onUpdate({ onUpdate({
'@type': 'updateChatMembers', '@type': 'updateChatMembers',
id: getApiChatIdFromMtpPeer({ chatId: update.participants.chatId } as GramJs.TypePeer), id: buildApiPeerId(update.participants.chatId, 'chat'),
replacedMembers, replacedMembers,
}); });
} else if (update instanceof GramJs.UpdateChatParticipantAdd) { } else if (update instanceof GramJs.UpdateChatParticipantAdd) {
@ -535,25 +534,22 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
onUpdate({ onUpdate({
'@type': 'updateChatMembers', '@type': 'updateChatMembers',
id: getApiChatIdFromMtpPeer({ chatId: update.chatId } as GramJs.PeerChat), id: buildApiPeerId(update.chatId, 'chat'),
addedMember, addedMember,
}); });
} else if (update instanceof GramJs.UpdateChatParticipantDelete) { } else if (update instanceof GramJs.UpdateChatParticipantDelete) {
const { userId: deletedMemberId } = update;
onUpdate({ onUpdate({
'@type': 'updateChatMembers', '@type': 'updateChatMembers',
id: getApiChatIdFromMtpPeer({ chatId: update.chatId } as GramJs.PeerChat), id: buildApiPeerId(update.chatId, 'chat'),
deletedMemberId, deletedMemberId: buildApiPeerId(update.userId, 'user'),
}); });
} else if ( } else if (
update instanceof GramJs.UpdatePinnedMessages update instanceof GramJs.UpdatePinnedMessages
|| update instanceof GramJs.UpdatePinnedChannelMessages || update instanceof GramJs.UpdatePinnedChannelMessages
) { ) {
const peer = update instanceof GramJs.UpdatePinnedMessages const chatId = update instanceof GramJs.UpdatePinnedMessages
? update.peer ? getApiChatIdFromMtpPeer(update.peer)
: { channelId: update.channelId } as GramJs.PeerChannel; : buildApiPeerId(update.channelId, 'channel');
const chatId = getApiChatIdFromMtpPeer(peer);
onUpdate({ onUpdate({
'@type': 'updatePinnedIds', '@type': 'updatePinnedIds',
@ -574,8 +570,8 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
|| update instanceof GramJs.UpdateChatUserTyping || update instanceof GramJs.UpdateChatUserTyping
) { ) {
const id = update instanceof GramJs.UpdateUserTyping const id = update instanceof GramJs.UpdateUserTyping
? update.userId ? buildApiPeerId(update.userId, 'user')
: getApiChatIdFromMtpPeer({ chatId: update.chatId } as GramJs.PeerChat); : buildApiPeerId(update.chatId, 'chat');
onUpdate({ onUpdate({
'@type': 'updateChatTypingStatus', '@type': 'updateChatTypingStatus',
@ -583,7 +579,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
typingStatus: buildChatTypingStatus(update, serverTimeOffset), typingStatus: buildChatTypingStatus(update, serverTimeOffset),
}); });
} else if (update instanceof GramJs.UpdateChannelUserTyping) { } else if (update instanceof GramJs.UpdateChannelUserTyping) {
const id = getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel); const id = buildApiPeerId(update.channelId, 'channel');
onUpdate({ onUpdate({
'@type': 'updateChatTypingStatus', '@type': 'updateChatTypingStatus',
@ -612,11 +608,11 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
onUpdate({ onUpdate({
'@type': chat.isNotJoined ? 'updateChatLeave' : 'updateChatJoin', '@type': chat.isNotJoined ? 'updateChatLeave' : 'updateChatJoin',
id: getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel), id: buildApiPeerId(update.channelId, 'channel'),
}); });
} }
} else if (channel instanceof GramJs.ChannelForbidden) { } else if (channel instanceof GramJs.ChannelForbidden) {
const chatId = getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel); const chatId = buildApiPeerId(update.channelId, 'channel');
onUpdate({ onUpdate({
'@type': 'updateChat', '@type': 'updateChat',
@ -635,7 +631,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
// No corresponding update available at this moment https://core.telegram.org/type/Updates // No corresponding update available at this moment https://core.telegram.org/type/Updates
onUpdate({ onUpdate({
'@type': 'resetMessages', '@type': 'resetMessages',
id: getApiChatIdFromMtpPeer({ chatId: update.channelId } as GramJs.PeerChat), id: buildApiPeerId(update.channelId, 'channel'),
}); });
} }
} else if ( } else if (
@ -660,35 +656,35 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
// Users // Users
} else if (update instanceof GramJs.UpdateUserStatus) { } else if (update instanceof GramJs.UpdateUserStatus) {
const { userId, status } = update;
onUpdate({ onUpdate({
'@type': 'updateUserStatus', '@type': 'updateUserStatus',
userId, userId: buildApiPeerId(update.userId, 'user'),
status: buildApiUserStatus(status), status: buildApiUserStatus(update.status),
}); });
} else if (update instanceof GramJs.UpdateUserName) { } else if (update instanceof GramJs.UpdateUserName) {
const updatedUser = localDb.users[update.userId]; const apiUserId = buildApiPeerId(update.userId, 'user');
const updatedUser = localDb.users[apiUserId];
const user = updatedUser?.mutualContact && !updatedUser.self const user = updatedUser?.mutualContact && !updatedUser.self
? pick(update, ['username']) ? pick(update, ['username'])
: pick(update, ['firstName', 'lastName', 'username']); : pick(update, ['firstName', 'lastName', 'username']);
onUpdate({ onUpdate({
'@type': 'updateUser', '@type': 'updateUser',
id: update.userId, id: apiUserId,
user, user,
}); });
} else if (update instanceof GramJs.UpdateUserPhoto) { } else if (update instanceof GramJs.UpdateUserPhoto) {
const { userId, photo } = update; const { userId, photo } = update;
const apiUserId = buildApiPeerId(userId, 'user');
const avatarHash = buildAvatarHash(photo); const avatarHash = buildAvatarHash(photo);
if (localDb.users[userId]) { if (localDb.users[apiUserId]) {
localDb.users[userId].photo = photo; localDb.users[apiUserId].photo = photo;
} }
onUpdate({ onUpdate({
'@type': 'updateUser', '@type': 'updateUser',
id: userId, id: apiUserId,
user: { avatarHash }, user: { avatarHash },
}); });
} else if (update instanceof GramJs.UpdateUserPhone) { } else if (update instanceof GramJs.UpdateUserPhone) {
@ -696,7 +692,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
onUpdate({ onUpdate({
'@type': 'updateUser', '@type': 'updateUser',
id: userId, id: buildApiPeerId(userId, 'user'),
user: { phoneNumber: phone }, user: { phoneNumber: phone },
}); });
} else if (update instanceof GramJs.UpdatePeerSettings) { } else if (update instanceof GramJs.UpdatePeerSettings) {
@ -712,7 +708,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
.forEach((user) => { .forEach((user) => {
onUpdate({ onUpdate({
'@type': 'deleteUser', '@type': 'deleteUser',
id: user.id, id: buildApiPeerId(user.id, 'user'),
}); });
}); });

View File

@ -40,7 +40,7 @@ export interface ApiBotInlineSwitchPm {
} }
export interface ApiBotCommand { export interface ApiBotCommand {
botId: number; botId: string;
command: string; command: string;
description: string; description: string;
} }

View File

@ -8,7 +8,7 @@ type ApiChatType = (
); );
export interface ApiChat { export interface ApiChat {
id: number; id: string;
folderId?: number; folderId?: number;
type: ApiChatType; type: ApiChatType;
title?: string; title?: string;
@ -47,7 +47,7 @@ export interface ApiChat {
defaultBannedRights?: ApiChatBannedRights; defaultBannedRights?: ApiChatBannedRights;
migratedTo?: { migratedTo?: {
chatId: number; chatId: string;
accessHash?: string; accessHash?: string;
}; };
@ -58,26 +58,11 @@ export interface ApiChat {
} }
export interface ApiTypingStatus { export interface ApiTypingStatus {
userId?: number; userId?: string;
action: string; action: string;
timestamp: number; timestamp: number;
} }
export interface ApiTypeGroupCall {
joinMuted?: true;
canChangeJoinMuted?: true;
joinDateAsc?: true;
scheduleStartSubscribed?: true;
id: number;
participantsCount: number;
params?: any;
title?: string;
streamDcId?: number;
recordStartDate?: number;
scheduleDate?: number;
version: number;
}
export interface ApiChatFullInfo { export interface ApiChatFullInfo {
about?: string; about?: string;
onlineCount?: number; onlineCount?: number;
@ -93,19 +78,19 @@ export interface ApiChatFullInfo {
nextSendDate?: number; nextSendDate?: number;
}; };
migratedFrom?: { migratedFrom?: {
chatId: number; chatId: string;
maxMessageId?: number; maxMessageId?: number;
}; };
linkedChatId?: number; linkedChatId?: string;
botCommands?: ApiBotCommand[]; botCommands?: ApiBotCommand[];
} }
export interface ApiChatMember { export interface ApiChatMember {
userId: number; userId: string;
inviterId?: number; inviterId?: string;
joinedDate?: number; joinedDate?: number;
kickedByUserId?: number; kickedByUserId?: string;
promotedByUserId?: number; promotedByUserId?: string;
bannedRights?: ApiChatBannedRights; bannedRights?: ApiChatBannedRights;
adminRights?: ApiChatAdminRights; adminRights?: ApiChatAdminRights;
customTitle?: string; customTitle?: string;
@ -159,7 +144,7 @@ export interface ApiChatFolder {
excludeMuted?: true; excludeMuted?: true;
excludeRead?: true; excludeRead?: true;
excludeArchived?: true; excludeArchived?: true;
pinnedChatIds?: number[]; pinnedChatIds?: string[];
includedChatIds: number[]; includedChatIds: string[];
excludedChatIds: number[]; excludedChatIds: string[];
} }

View File

@ -39,7 +39,6 @@ export interface ApiStickerSet {
title: string; title: string;
hasThumbnail?: boolean; hasThumbnail?: boolean;
count: number; count: number;
hash: number;
stickers?: ApiSticker[]; stickers?: ApiSticker[];
packs?: Record<string, ApiSticker[]>; packs?: Record<string, ApiSticker[]>;
covers?: ApiSticker[]; covers?: ApiSticker[];
@ -92,7 +91,7 @@ export interface ApiContact {
firstName: string; firstName: string;
lastName: string; lastName: string;
phoneNumber: string; phoneNumber: string;
userId: number; userId: string;
} }
export interface ApiPollAnswer { export interface ApiPollAnswer {
@ -122,7 +121,7 @@ export interface ApiPoll {
results: { results: {
results?: ApiPollResult[]; results?: ApiPollResult[];
totalVoters?: number; totalVoters?: number;
recentVoterIds?: number[]; recentVoterIds?: string[];
solution?: string; solution?: string;
solutionEntities?: ApiMessageEntity[]; solutionEntities?: ApiMessageEntity[];
}; };
@ -149,8 +148,8 @@ export type ApiNewPoll = {
export interface ApiAction { export interface ApiAction {
text: string; text: string;
targetUserIds?: number[]; targetUserIds?: string[];
targetChatId?: number; targetChatId?: string;
type: 'historyClear' | 'contactSignUp' | 'chatCreate' | 'other'; type: 'historyClear' | 'contactSignUp' | 'chatCreate' | 'other';
photo?: ApiPhoto; photo?: ApiPhoto;
amount?: number; amount?: number;
@ -176,8 +175,8 @@ export interface ApiMessageForwardInfo {
isChannelPost: boolean; isChannelPost: boolean;
channelPostId?: number; channelPostId?: number;
isLinkedChannelPost?: boolean; isLinkedChannelPost?: boolean;
fromChatId?: number; fromChatId?: string;
senderUserId?: number; senderUserId?: string;
fromMessageId?: number; fromMessageId?: number;
hiddenUserName?: string; hiddenUserName?: string;
adminTitle?: string; adminTitle?: string;
@ -187,7 +186,7 @@ export interface ApiMessageEntity {
type: string; type: string;
offset: number; offset: number;
length: number; length: number;
userId?: number; userId?: string;
url?: string; url?: string;
} }
@ -218,7 +217,7 @@ export interface ApiFormattedText {
export interface ApiMessage { export interface ApiMessage {
id: number; id: number;
chatId: number; chatId: string;
content: { content: {
text?: ApiFormattedText; text?: ApiFormattedText;
photo?: ApiPhoto; photo?: ApiPhoto;
@ -235,8 +234,8 @@ export interface ApiMessage {
}; };
date: number; date: number;
isOutgoing: boolean; isOutgoing: boolean;
senderId?: number; senderId?: string;
replyToChatId?: number; replyToChatId?: string;
replyToMessageId?: number; replyToMessageId?: number;
replyToTopMessageId?: number; replyToTopMessageId?: number;
sendingState?: 'messageSendingStatePending' | 'messageSendingStateFailed'; sendingState?: 'messageSendingStatePending' | 'messageSendingStateFailed';
@ -254,7 +253,7 @@ export interface ApiMessage {
keyboardButtons?: ApiKeyboardButtons; keyboardButtons?: ApiKeyboardButtons;
keyboardPlaceholder?: string; keyboardPlaceholder?: string;
isKeyboardSingleUse?: boolean; isKeyboardSingleUse?: boolean;
viaBotId?: number; viaBotId?: string;
threadInfo?: ApiThreadInfo; threadInfo?: ApiThreadInfo;
adminTitle?: string; adminTitle?: string;
isScheduled?: boolean; isScheduled?: boolean;
@ -264,13 +263,13 @@ export interface ApiMessage {
export interface ApiThreadInfo { export interface ApiThreadInfo {
threadId: number; threadId: number;
chatId: number; chatId: string;
topMessageId?: number; topMessageId?: number;
originChannelId?: number; originChannelId?: string;
messagesCount: number; messagesCount: number;
lastMessageId?: number; lastMessageId?: number;
lastReadInboxMessageId?: number; lastReadInboxMessageId?: number;
recentReplierIds?: number[]; recentReplierIds?: string[];
} }
export type ApiMessageOutgoingStatus = 'read' | 'succeeded' | 'pending' | 'failed'; export type ApiMessageOutgoingStatus = 'read' | 'succeeded' | 'pending' | 'failed';

View File

@ -64,7 +64,7 @@ export interface ApiSessionData {
} }
export type ApiNotifyException = { export type ApiNotifyException = {
chatId: number; chatId: string;
isMuted: boolean; isMuted: boolean;
isSilent?: boolean; isSilent?: boolean;
shouldShowPreviews?: boolean; shouldShowPreviews?: boolean;

View File

@ -17,7 +17,7 @@ export interface ApiPaymentSavedInfo {
export interface ApiPaymentForm { export interface ApiPaymentForm {
canSaveCredentials?: boolean; canSaveCredentials?: boolean;
passwordMissing?: boolean; passwordMissing?: boolean;
providerId: number; providerId: string;
nativeProvider?: string; nativeProvider?: string;
savedInfo: any; savedInfo: any;
invoice: { invoice: {

View File

@ -65,7 +65,7 @@ export type ApiUpdateCurrentUser = {
export type ApiUpdateChat = { export type ApiUpdateChat = {
'@type': 'updateChat'; '@type': 'updateChat';
id: number; id: string;
chat: Partial<ApiChat>; chat: Partial<ApiChat>;
newProfilePhoto?: ApiPhoto; newProfilePhoto?: ApiPhoto;
noTopChatsRequest?: boolean; noTopChatsRequest?: boolean;
@ -73,7 +73,7 @@ export type ApiUpdateChat = {
export type ApiUpdateChatJoin = { export type ApiUpdateChatJoin = {
'@type': 'updateChatJoin'; '@type': 'updateChatJoin';
id: number; id: string;
}; };
export type ApiUpdateShowInvite = { export type ApiUpdateShowInvite = {
@ -83,50 +83,50 @@ export type ApiUpdateShowInvite = {
export type ApiUpdateChatLeave = { export type ApiUpdateChatLeave = {
'@type': 'updateChatLeave'; '@type': 'updateChatLeave';
id: number; id: string;
}; };
export type ApiUpdateChatInbox = { export type ApiUpdateChatInbox = {
'@type': 'updateChatInbox'; '@type': 'updateChatInbox';
id: number; id: string;
chat: Partial<ApiChat>; chat: Partial<ApiChat>;
}; };
export type ApiUpdateChatTypingStatus = { export type ApiUpdateChatTypingStatus = {
'@type': 'updateChatTypingStatus'; '@type': 'updateChatTypingStatus';
id: number; id: string;
typingStatus: ApiTypingStatus | undefined; typingStatus: ApiTypingStatus | undefined;
}; };
export type ApiUpdateChatFullInfo = { export type ApiUpdateChatFullInfo = {
'@type': 'updateChatFullInfo'; '@type': 'updateChatFullInfo';
id: number; id: string;
fullInfo: Partial<ApiChatFullInfo>; fullInfo: Partial<ApiChatFullInfo>;
}; };
export type ApiUpdateChatMembers = { export type ApiUpdateChatMembers = {
'@type': 'updateChatMembers'; '@type': 'updateChatMembers';
id: number; id: string;
replacedMembers?: ApiChatMember[]; replacedMembers?: ApiChatMember[];
addedMember?: ApiChatMember; addedMember?: ApiChatMember;
deletedMemberId?: number; deletedMemberId?: string;
}; };
export type ApiUpdatePinnedChatIds = { export type ApiUpdatePinnedChatIds = {
'@type': 'updatePinnedChatIds'; '@type': 'updatePinnedChatIds';
ids: number[]; ids: string[];
folderId?: number; folderId?: number;
}; };
export type ApiUpdateChatListType = { export type ApiUpdateChatListType = {
'@type': 'updateChatListType'; '@type': 'updateChatListType';
id: number; id: string;
folderId: number; folderId: number;
}; };
export type ApiUpdateChatPinned = { export type ApiUpdateChatPinned = {
'@type': 'updateChatPinned'; '@type': 'updateChatPinned';
id: number; id: string;
isPinned: boolean; isPinned: boolean;
}; };
@ -148,14 +148,14 @@ export type ApiUpdateRecommendedChatFolders = {
export type ApiUpdateNewScheduledMessage = { export type ApiUpdateNewScheduledMessage = {
'@type': 'newScheduledMessage'; '@type': 'newScheduledMessage';
chatId: number; chatId: string;
id: number; id: number;
message: Partial<ApiMessage>; message: Partial<ApiMessage>;
}; };
export type ApiUpdateNewMessage = { export type ApiUpdateNewMessage = {
'@type': 'newMessage'; '@type': 'newMessage';
chatId: number; chatId: string;
id: number; id: number;
message: Partial<ApiMessage>; message: Partial<ApiMessage>;
shouldForceReply?: boolean; shouldForceReply?: boolean;
@ -163,28 +163,28 @@ export type ApiUpdateNewMessage = {
export type ApiUpdateMessage = { export type ApiUpdateMessage = {
'@type': 'updateMessage'; '@type': 'updateMessage';
chatId: number; chatId: string;
id: number; id: number;
message: Partial<ApiMessage>; message: Partial<ApiMessage>;
}; };
export type ApiUpdateScheduledMessage = { export type ApiUpdateScheduledMessage = {
'@type': 'updateScheduledMessage'; '@type': 'updateScheduledMessage';
chatId: number; chatId: string;
id: number; id: number;
message: Partial<ApiMessage>; message: Partial<ApiMessage>;
}; };
export type ApiUpdatePinnedMessageIds = { export type ApiUpdatePinnedMessageIds = {
'@type': 'updatePinnedIds'; '@type': 'updatePinnedIds';
chatId: number; chatId: string;
isPinned?: boolean; isPinned?: boolean;
messageIds: number[]; messageIds: number[];
}; };
export type ApiUpdateThreadInfo = { export type ApiUpdateThreadInfo = {
'@type': 'updateThreadInfo'; '@type': 'updateThreadInfo';
chatId: number; chatId: string;
threadId: number; threadId: number;
threadInfo: Partial<ApiThreadInfo>; threadInfo: Partial<ApiThreadInfo>;
firstMessageId?: number; firstMessageId?: number;
@ -192,21 +192,21 @@ export type ApiUpdateThreadInfo = {
export type ApiUpdateScheduledMessageSendSucceeded = { export type ApiUpdateScheduledMessageSendSucceeded = {
'@type': 'updateScheduledMessageSendSucceeded'; '@type': 'updateScheduledMessageSendSucceeded';
chatId: number; chatId: string;
localId: number; localId: number;
message: ApiMessage; message: ApiMessage;
}; };
export type ApiUpdateMessageSendSucceeded = { export type ApiUpdateMessageSendSucceeded = {
'@type': 'updateMessageSendSucceeded'; '@type': 'updateMessageSendSucceeded';
chatId: number; chatId: string;
localId: number; localId: number;
message: ApiMessage; message: ApiMessage;
}; };
export type ApiUpdateMessageSendFailed = { export type ApiUpdateMessageSendFailed = {
'@type': 'updateMessageSendFailed'; '@type': 'updateMessageSendFailed';
chatId: number; chatId: string;
localId: number; localId: number;
sendingState: { sendingState: {
'@type': 'messageSendingStateFailed'; '@type': 'messageSendingStateFailed';
@ -221,7 +221,7 @@ export type ApiUpdateCommonBoxMessages = {
export type ApiUpdateChannelMessages = { export type ApiUpdateChannelMessages = {
'@type': 'updateChannelMessages'; '@type': 'updateChannelMessages';
channelId: number; channelId: string;
ids: number[]; ids: number[];
messageUpdate: Partial<ApiMessage>; messageUpdate: Partial<ApiMessage>;
}; };
@ -235,7 +235,7 @@ export type ApiUpdateMessagePoll = {
export type ApiUpdateMessagePollVote = { export type ApiUpdateMessagePollVote = {
'@type': 'updateMessagePollVote'; '@type': 'updateMessagePollVote';
pollId: string; pollId: string;
userId: number; userId: string;
options: string[]; options: string[];
}; };
@ -247,34 +247,34 @@ export type ApiUpdateServiceNotification = {
export type ApiUpdateDeleteMessages = { export type ApiUpdateDeleteMessages = {
'@type': 'deleteMessages'; '@type': 'deleteMessages';
ids: number[]; ids: number[];
chatId?: number; chatId?: string;
}; };
export type ApiUpdateDeleteScheduledMessages = { export type ApiUpdateDeleteScheduledMessages = {
'@type': 'deleteScheduledMessages'; '@type': 'deleteScheduledMessages';
ids: number[]; ids: number[];
chatId?: number; chatId?: string;
}; };
export type ApiUpdateDeleteHistory = { export type ApiUpdateDeleteHistory = {
'@type': 'deleteHistory'; '@type': 'deleteHistory';
chatId: number; chatId: string;
}; };
export type ApiUpdateDeleteProfilePhotos = { export type ApiUpdateDeleteProfilePhotos = {
'@type': 'deleteProfilePhotos'; '@type': 'deleteProfilePhotos';
ids: string[]; ids: string[];
chatId: number; chatId: string;
}; };
export type ApiUpdateResetMessages = { export type ApiUpdateResetMessages = {
'@type': 'resetMessages'; '@type': 'resetMessages';
id: number; id: string;
}; };
export type ApiUpdateDraftMessage = { export type ApiUpdateDraftMessage = {
'@type': 'draftMessage'; '@type': 'draftMessage';
chatId: number; chatId: string;
formattedText?: ApiFormattedText; formattedText?: ApiFormattedText;
date?: number; date?: number;
replyingToId?: number; replyingToId?: number;
@ -282,30 +282,30 @@ export type ApiUpdateDraftMessage = {
export type ApiDeleteUser = { export type ApiDeleteUser = {
'@type': 'deleteUser'; '@type': 'deleteUser';
id: number; id: string;
}; };
export type ApiUpdateUser = { export type ApiUpdateUser = {
'@type': 'updateUser'; '@type': 'updateUser';
id: number; id: string;
user: Partial<ApiUser>; user: Partial<ApiUser>;
}; };
export type ApiUpdateUserStatus = { export type ApiUpdateUserStatus = {
'@type': 'updateUserStatus'; '@type': 'updateUserStatus';
userId: number; userId: string;
status: ApiUserStatus; status: ApiUserStatus;
}; };
export type ApiUpdateUserFullInfo = { export type ApiUpdateUserFullInfo = {
'@type': 'updateUserFullInfo'; '@type': 'updateUserFullInfo';
id: number; id: string;
fullInfo: Partial<ApiUserFullInfo>; fullInfo: Partial<ApiUserFullInfo>;
}; };
export type ApiUpdateAvatar = { export type ApiUpdateAvatar = {
'@type': 'updateAvatar'; '@type': 'updateAvatar';
chatId: number; chatId: string;
dataUri: string; dataUri: string;
}; };
@ -357,7 +357,7 @@ export type ApiUpdateTwoFaStateWaitCode = {
export type ApiUpdatePeerBlocked = { export type ApiUpdatePeerBlocked = {
'@type': 'updatePeerBlocked'; '@type': 'updatePeerBlocked';
id: number; id: string;
isBlocked: boolean; isBlocked: boolean;
}; };
@ -366,10 +366,10 @@ export type ApiUpdatePrivacy = {
key: 'phoneNumber' | 'lastSeen' | 'profilePhoto' | 'forwards' | 'chatInvite'; key: 'phoneNumber' | 'lastSeen' | 'profilePhoto' | 'forwards' | 'chatInvite';
rules: { rules: {
visibility: 'everybody' | 'contacts' | 'nonContacts' | 'nobody'; visibility: 'everybody' | 'contacts' | 'nonContacts' | 'nobody';
allowUserIds: number[]; allowUserIds: string[];
allowChatIds: number[]; allowChatIds: string[];
blockUserIds: number[]; blockUserIds: string[];
blockChatIds: number[]; blockChatIds: string[];
}; };
}; };

View File

@ -2,7 +2,7 @@ import { ApiPhoto } from './messages';
import { ApiBotCommand } from './bots'; import { ApiBotCommand } from './bots';
export interface ApiUser { export interface ApiUser {
id: number; id: string;
isMin: boolean; isMin: boolean;
isSelf?: true; isSelf?: true;
isVerified?: true; isVerified?: true;

View File

@ -51,10 +51,10 @@ type OwnProps = {
isSelectable?: boolean; isSelectable?: boolean;
isSelected?: boolean; isSelected?: boolean;
isDownloading: boolean; isDownloading: boolean;
onPlay: (messageId: number, chatId: number) => void; onPlay: (messageId: number, chatId: string) => void;
onReadMedia?: () => void; onReadMedia?: () => void;
onCancelUpload?: () => void; onCancelUpload?: () => void;
onDateClick?: (messageId: number, chatId: number) => void; onDateClick?: (messageId: number, chatId: string) => void;
}; };
const AVG_VOICE_DURATION = 10; const AVG_VOICE_DURATION = 10;

View File

@ -9,7 +9,7 @@ import {
getChatTitle, getChatTitle,
getUserColorKey, getUserColorKey,
getUserFullName, getUserFullName,
isChatPrivate, isUserId,
isChatWithRepliesBot, isChatWithRepliesBot,
isDeletedUser, isDeletedUser,
isUserOnline, isUserOnline,
@ -78,7 +78,7 @@ const Avatar: FC<OwnProps> = ({
content = userFullName ? getFirstLetters(userFullName, 2) : undefined; content = userFullName ? getFirstLetters(userFullName, 2) : undefined;
} else if (chat) { } else if (chat) {
const title = getChatTitle(lang, chat); const title = getChatTitle(lang, chat);
content = title && getFirstLetters(title, isChatPrivate(chat.id) ? 2 : 1); content = title && getFirstLetters(title, isUserId(chat.id) ? 2 : 1);
} else if (text) { } else if (text) {
content = getFirstLetters(text, 2); content = getFirstLetters(text, 2);
} }

View File

@ -10,7 +10,7 @@ import {
selectChat, selectNotifyExceptions, selectNotifySettings, selectUser, selectChat, selectNotifyExceptions, selectNotifySettings, selectUser,
} from '../../modules/selectors'; } from '../../modules/selectors';
import { import {
getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isChatPrivate, isUserRightBanned, selectIsChatMuted, getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isUserId, isUserRightBanned, selectIsChatMuted,
} from '../../modules/helpers'; } from '../../modules/helpers';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
@ -22,7 +22,7 @@ import ListItem from '../ui/ListItem';
import Switcher from '../ui/Switcher'; import Switcher from '../ui/Switcher';
type OwnProps = { type OwnProps = {
chatOrUserId: number; chatOrUserId: string;
forceShowSelf?: boolean; forceShowSelf?: boolean;
}; };
@ -140,7 +140,7 @@ export default memo(withGlobal<OwnProps>(
const { lastSyncTime, countryList: { phoneCodes: phoneCodeList } } = global; const { lastSyncTime, countryList: { phoneCodes: phoneCodeList } } = global;
const chat = chatOrUserId ? selectChat(global, chatOrUserId) : undefined; const chat = chatOrUserId ? selectChat(global, chatOrUserId) : undefined;
const user = isChatPrivate(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined; const user = isUserId(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined;
const isMuted = chat && selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global)); const isMuted = chat && selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global));
const canInviteUsers = chat && !user && ( const canInviteUsers = chat && !user && (

View File

@ -10,7 +10,7 @@ import Link from '../ui/Link';
type OwnProps = { type OwnProps = {
className?: string; className?: string;
chatId?: number; chatId?: string;
children: any; children: any;
}; };

View File

@ -7,7 +7,7 @@ import useInfiniteScroll from '../../hooks/useInfiniteScroll';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import useKeyboardListNavigation from '../../hooks/useKeyboardListNavigation'; import useKeyboardListNavigation from '../../hooks/useKeyboardListNavigation';
import useInputFocusOnOpen from '../../hooks/useInputFocusOnOpen'; import useInputFocusOnOpen from '../../hooks/useInputFocusOnOpen';
import { isChatPrivate } from '../../modules/helpers'; import { isUserId } from '../../modules/helpers';
import Loading from '../ui/Loading'; import Loading from '../ui/Loading';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
@ -21,15 +21,15 @@ import PrivateChatInfo from './PrivateChatInfo';
import './ChatOrUserPicker.scss'; import './ChatOrUserPicker.scss';
export type OwnProps = { export type OwnProps = {
currentUserId?: number; currentUserId?: string;
chatOrUserIds: number[]; chatOrUserIds: string[];
isOpen: boolean; isOpen: boolean;
filterRef: RefObject<HTMLInputElement>; filterRef: RefObject<HTMLInputElement>;
filterPlaceholder: string; filterPlaceholder: string;
filter: string; filter: string;
onFilterChange: (filter: string) => void; onFilterChange: (filter: string) => void;
loadMore: NoneToVoidFunction; loadMore: NoneToVoidFunction;
onSelectChatOrUser: (chatOrUserId: number) => void; onSelectChatOrUser: (chatOrUserId: string) => void;
onClose: NoneToVoidFunction; onClose: NoneToVoidFunction;
}; };
@ -104,7 +104,7 @@ const ChatOrUserPicker: FC<OwnProps> = ({
className="chat-item-clickable force-rounded-corners" className="chat-item-clickable force-rounded-corners"
onClick={() => onSelectChatOrUser(id)} onClick={() => onSelectChatOrUser(id)}
> >
{isChatPrivate(id) ? ( {isUserId(id) ? (
<PrivateChatInfo status={id === currentUserId ? lang('SavedMessagesInfo') : undefined} userId={id} /> <PrivateChatInfo status={id === currentUserId ? lang('SavedMessagesInfo') : undefined} userId={id} />
) : ( ) : (
<GroupChatInfo chatId={id} /> <GroupChatInfo chatId={id} />

View File

@ -6,7 +6,7 @@ import { GlobalActions } from '../../global/types';
import { selectIsChatWithSelf, selectUser } from '../../modules/selectors'; import { selectIsChatWithSelf, selectUser } from '../../modules/selectors';
import { import {
isChatPrivate, isUserId,
isUserBot, isUserBot,
getUserFirstOrLastName, getUserFirstOrLastName,
getPrivateChatUserId, getPrivateChatUserId,
@ -39,7 +39,7 @@ type StateProps = {
isPrivateChat: boolean; isPrivateChat: boolean;
isBasicGroup: boolean; isBasicGroup: boolean;
isSuperGroup: boolean; isSuperGroup: boolean;
currentUserId: number | undefined; currentUserId: string | undefined;
canDeleteForAll?: boolean; canDeleteForAll?: boolean;
contactName?: string; contactName?: string;
}; };
@ -196,7 +196,7 @@ const DeleteChatModal: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { chat }): StateProps => { (global, { chat }): StateProps => {
const isPrivateChat = isChatPrivate(chat.id); const isPrivateChat = isUserId(chat.id);
const isChatWithSelf = selectIsChatWithSelf(global, chat.id); const isChatWithSelf = selectIsChatWithSelf(global, chat.id);
const user = isPrivateChat && selectUser(global, getPrivateChatUserId(chat)!); const user = isPrivateChat && selectUser(global, getPrivateChatUserId(chat)!);
const isBot = user && isUserBot(user) && !chat.isSupport; const isBot = user && isUserBot(user) && !chat.isSupport;

View File

@ -13,7 +13,7 @@ import {
selectUser, selectUser,
} from '../../modules/selectors'; } from '../../modules/selectors';
import { import {
isChatPrivate, isUserId,
getUserFirstOrLastName, getUserFirstOrLastName,
getPrivateChatUserId, getPrivateChatUserId,
isChatBasicGroup, isChatBasicGroup,
@ -115,7 +115,7 @@ export default memo(withGlobal<OwnProps>(
const { threadId } = selectCurrentMessageList(global) || {}; const { threadId } = selectCurrentMessageList(global) || {};
const { canDeleteForAll } = (threadId && selectAllowedMessageActions(global, message, threadId)) || {}; const { canDeleteForAll } = (threadId && selectAllowedMessageActions(global, message, threadId)) || {};
const chat = selectChat(global, message.chatId); const chat = selectChat(global, message.chatId);
const contactName = chat && isChatPrivate(chat.id) const contactName = chat && isUserId(chat.id)
? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!))
: undefined; : undefined;

View File

@ -32,7 +32,7 @@ type OwnProps = {
isDownloading: boolean; isDownloading: boolean;
onCancelUpload?: () => void; onCancelUpload?: () => void;
onMediaClick?: () => void; onMediaClick?: () => void;
onDateClick?: (messageId: number, chatId: number) => void; onDateClick?: (messageId: number, chatId: string) => void;
}; };
const Document: FC<OwnProps> = ({ const Document: FC<OwnProps> = ({

View File

@ -23,7 +23,7 @@ import VerifiedIcon from './VerifiedIcon';
import TypingStatus from './TypingStatus'; import TypingStatus from './TypingStatus';
type OwnProps = { type OwnProps = {
chatId: number; chatId: string;
typingStatus?: ApiTypingStatus; typingStatus?: ApiTypingStatus;
avatarSize?: 'small' | 'medium' | 'large' | 'jumbo'; avatarSize?: 'small' | 'medium' | 'large' | 'jumbo';
withMediaViewer?: boolean; withMediaViewer?: boolean;

View File

@ -16,7 +16,7 @@ import './Media.scss';
type OwnProps = { type OwnProps = {
message: ApiMessage; message: ApiMessage;
idPrefix?: string; idPrefix?: string;
onClick?: (messageId: number, chatId: number) => void; onClick?: (messageId: number, chatId: string) => void;
}; };
const Media: FC<OwnProps> = ({ message, idPrefix = 'shared-media', onClick }) => { const Media: FC<OwnProps> = ({ message, idPrefix = 'shared-media', onClick }) => {

View File

@ -2,7 +2,7 @@ import React, {
FC, useCallback, useRef, useEffect, memo, FC, useCallback, useRef, useEffect, memo,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { isChatPrivate } from '../../modules/helpers'; import { isUserId } from '../../modules/helpers';
import InfiniteScroll from '../ui/InfiniteScroll'; import InfiniteScroll from '../ui/InfiniteScroll';
import Checkbox from '../ui/Checkbox'; import Checkbox from '../ui/Checkbox';
@ -19,15 +19,15 @@ import Loading from '../ui/Loading';
import './Picker.scss'; import './Picker.scss';
type OwnProps = { type OwnProps = {
itemIds: number[]; itemIds: string[];
selectedIds: number[]; selectedIds: string[];
filterValue?: string; filterValue?: string;
filterPlaceholder?: string; filterPlaceholder?: string;
notFoundText?: string; notFoundText?: string;
searchInputId?: string; searchInputId?: string;
isLoading?: boolean; isLoading?: boolean;
noScrollRestore?: boolean; noScrollRestore?: boolean;
onSelectedIdsChange: (ids: number[]) => void; onSelectedIdsChange: (ids: string[]) => void;
onFilterChange: (value: string) => void; onFilterChange: (value: string) => void;
onLoadMore?: () => void; onLoadMore?: () => void;
}; };
@ -63,7 +63,7 @@ const Picker: FC<OwnProps> = ({
}, FOCUS_DELAY_MS); }, FOCUS_DELAY_MS);
}, []); }, []);
const handleItemClick = useCallback((id: number) => { const handleItemClick = useCallback((id: string) => {
const newSelectedIds = [...selectedIds]; const newSelectedIds = [...selectedIds];
if (newSelectedIds.includes(id)) { if (newSelectedIds.includes(id)) {
newSelectedIds.splice(newSelectedIds.indexOf(id), 1); newSelectedIds.splice(newSelectedIds.indexOf(id), 1);
@ -119,7 +119,7 @@ const Picker: FC<OwnProps> = ({
ripple ripple
> >
<Checkbox label="" checked={selectedIds.includes(id)} /> <Checkbox label="" checked={selectedIds.includes(id)} />
{isChatPrivate(id) ? ( {isUserId(id) ? (
<PrivateChatInfo userId={id} /> <PrivateChatInfo userId={id} />
) : ( ) : (
<GroupChatInfo chatId={id} /> <GroupChatInfo chatId={id} />

View File

@ -4,7 +4,7 @@ import { withGlobal } from '../../lib/teact/teactn';
import { ApiChat, ApiUser } from '../../api/types'; import { ApiChat, ApiUser } from '../../api/types';
import { selectChat, selectUser } from '../../modules/selectors'; import { selectChat, selectUser } from '../../modules/selectors';
import { getChatTitle, getUserFirstOrLastName, isChatPrivate } from '../../modules/helpers'; import { getChatTitle, getUserFirstOrLastName, isUserId } from '../../modules/helpers';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -14,7 +14,7 @@ import Avatar from './Avatar';
import './PickerSelectedItem.scss'; import './PickerSelectedItem.scss';
type OwnProps = { type OwnProps = {
chatOrUserId?: number; chatOrUserId?: string;
icon?: string; icon?: string;
title?: string; title?: string;
isMinimized?: boolean; isMinimized?: boolean;
@ -106,7 +106,7 @@ export default memo(withGlobal<OwnProps>(
} }
const chat = chatOrUserId ? selectChat(global, chatOrUserId) : undefined; const chat = chatOrUserId ? selectChat(global, chatOrUserId) : undefined;
const user = isChatPrivate(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined; const user = isUserId(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined;
return { return {
chat, chat,

View File

@ -5,7 +5,7 @@ import { GlobalActions } from '../../global/types';
import { selectChat, selectIsChatWithSelf, selectUser } from '../../modules/selectors'; import { selectChat, selectIsChatWithSelf, selectUser } from '../../modules/selectors';
import { import {
isChatPrivate, isUserId,
getUserFirstOrLastName, getUserFirstOrLastName,
getPrivateChatUserId, getPrivateChatUserId,
isChatBasicGroup, isChatBasicGroup,
@ -21,7 +21,7 @@ import Button from '../ui/Button';
export type OwnProps = { export type OwnProps = {
isOpen: boolean; isOpen: boolean;
chatId: number; chatId: string;
messageId: number; messageId: number;
onClose: () => void; onClose: () => void;
}; };
@ -103,14 +103,14 @@ const PinMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => { (global, { chatId }): StateProps => {
const isPrivateChat = isChatPrivate(chatId); const isPrivateChat = isUserId(chatId);
const isChatWithSelf = selectIsChatWithSelf(global, chatId); const isChatWithSelf = selectIsChatWithSelf(global, chatId);
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
const isChannel = !!chat && isChatChannel(chat); const isChannel = !!chat && isChatChannel(chat);
const isGroup = !!chat && isChatBasicGroup(chat); const isGroup = !!chat && isChatBasicGroup(chat);
const isSuperGroup = !!chat && isChatSuperGroup(chat); const isSuperGroup = !!chat && isChatSuperGroup(chat);
const canPinForAll = (isPrivateChat && !isChatWithSelf) || isSuperGroup || isGroup; const canPinForAll = (isPrivateChat && !isChatWithSelf) || isSuperGroup || isGroup;
const contactName = chat && isChatPrivate(chat.id) const contactName = chat && isUserId(chat.id)
? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!))
: undefined; : undefined;

View File

@ -19,7 +19,7 @@ import VerifiedIcon from './VerifiedIcon';
import TypingStatus from './TypingStatus'; import TypingStatus from './TypingStatus';
type OwnProps = { type OwnProps = {
userId: number; userId: string;
typingStatus?: ApiTypingStatus; typingStatus?: ApiTypingStatus;
avatarSize?: 'tiny' | 'small' | 'medium' | 'large' | 'jumbo'; avatarSize?: 'tiny' | 'small' | 'medium' | 'large' | 'jumbo';
forceShowSelf?: boolean; forceShowSelf?: boolean;

View File

@ -26,7 +26,7 @@ import Transition from '../ui/Transition';
import './ProfileInfo.scss'; import './ProfileInfo.scss';
type OwnProps = { type OwnProps = {
userId: number; userId: string;
forceShowSelf?: boolean; forceShowSelf?: boolean;
}; };

View File

@ -9,7 +9,7 @@ import {
getChatTitle, getChatTitle,
getUserColorKey, getUserColorKey,
getUserFullName, getUserFullName,
isChatPrivate, isUserId,
isChatWithRepliesBot, isChatWithRepliesBot,
isDeletedUser, isDeletedUser,
} from '../../modules/helpers'; } from '../../modules/helpers';
@ -87,7 +87,7 @@ const ProfilePhoto: FC<OwnProps> = ({
content = userFullName ? getFirstLetters(userFullName, 2) : undefined; content = userFullName ? getFirstLetters(userFullName, 2) : undefined;
} else if (!imageSrc && chat) { } else if (!imageSrc && chat) {
const title = getChatTitle(lang, chat); const title = getChatTitle(lang, chat);
content = title && getFirstLetters(title, isChatPrivate(chat.id) ? 2 : 1); content = title && getFirstLetters(title, isUserId(chat.id) ? 2 : 1);
} else { } else {
content = ( content = (
<div className="spinner-wrapper"> <div className="spinner-wrapper">

View File

@ -7,7 +7,7 @@ import Button from '../ui/Button';
export type OwnProps = { export type OwnProps = {
isOpen: boolean; isOpen: boolean;
chatId?: number; chatId?: string;
pinnedMessagesCount?: number; pinnedMessagesCount?: number;
onClose: () => void; onClose: () => void;
onUnpin: () => void; onUnpin: () => void;

View File

@ -20,7 +20,7 @@ const MAX_TEXT_LENGTH = 170; // symbols
type OwnProps = { type OwnProps = {
message: ApiMessage; message: ApiMessage;
senderTitle?: string; senderTitle?: string;
onMessageClick: (messageId: number, chatId: number) => void; onMessageClick: (messageId: number, chatId: string) => void;
}; };
const WebLink: FC<OwnProps> = ({ const WebLink: FC<OwnProps> = ({

View File

@ -7,7 +7,7 @@ import {
getMessageContent, getMessageContent,
getMessageSummaryText, getMessageSummaryText,
getUserFullName, getUserFullName,
isChatPrivate, isUserId,
} from '../../../modules/helpers'; } from '../../../modules/helpers';
import trimText from '../../../util/trimText'; import trimText from '../../../util/trimText';
import { formatCurrency } from '../../../util/formatCurrency'; import { formatCurrency } from '../../../util/formatCurrency';
@ -32,7 +32,7 @@ export function renderActionMessageText(
actionOrigin?: ApiUser | ApiChat, actionOrigin?: ApiUser | ApiChat,
targetUsers?: ApiUser[], targetUsers?: ApiUser[],
targetMessage?: ApiMessage, targetMessage?: ApiMessage,
targetChatId?: number, targetChatId?: string,
options: ActionMessageTextOptions = {}, options: ActionMessageTextOptions = {},
) { ) {
if (!message.content.action) { if (!message.content.action) {
@ -167,7 +167,7 @@ function renderMessageContent(lang: LangFn, message: ApiMessage, options: Action
} }
function renderOriginContent(lang: LangFn, origin: ApiUser | ApiChat, asPlain?: boolean) { function renderOriginContent(lang: LangFn, origin: ApiUser | ApiChat, asPlain?: boolean) {
return isChatPrivate(origin.id) return isUserId(origin.id)
? renderUserContent(origin as ApiUser, asPlain) ? renderUserContent(origin as ApiUser, asPlain)
: renderChatContent(lang, origin as ApiChat, asPlain); : renderChatContent(lang, origin as ApiChat, asPlain);
} }
@ -192,7 +192,7 @@ function renderChatContent(lang: LangFn, chat: ApiChat, asPlain?: boolean): stri
return <ChatLink className="action-link" chatId={chat.id}>{chat && renderText(text!)}</ChatLink>; return <ChatLink className="action-link" chatId={chat.id}>{chat && renderText(text!)}</ChatLink>;
} }
function renderMigratedContent(chatId: number, asPlain?: boolean): string | TextPart | undefined { function renderMigratedContent(chatId: string, asPlain?: boolean): string | TextPart | undefined {
const text = 'another chat'; const text = 'another chat';
if (asPlain) { if (asPlain) {

View File

@ -15,7 +15,7 @@ import CheckboxGroup from '../ui/CheckboxGroup';
export type OwnProps = { export type OwnProps = {
isOpen: boolean; isOpen: boolean;
chatId: number; chatId: string;
onClose: () => void; onClose: () => void;
onCloseAnimationEnd?: () => void; onCloseAnimationEnd?: () => void;
}; };
@ -63,8 +63,8 @@ const ChatFolderModal: FC<OwnProps & StateProps & DispatchProps> = ({
}, [folderOrderedIds, foldersById]); }, [folderOrderedIds, foldersById]);
const handleSubmit = useCallback(() => { const handleSubmit = useCallback(() => {
const idsToRemove = initialSelectedFolderIds.filter((id) => !selectedFolderIds.includes(id)).map(Number); const idsToRemove = initialSelectedFolderIds.filter((id) => !selectedFolderIds.includes(id));
const idsToAdd = selectedFolderIds.filter((id) => !initialSelectedFolderIds.includes(id)).map(Number); const idsToAdd = selectedFolderIds.filter((id) => !initialSelectedFolderIds.includes(id));
editChatFolders({ chatId, idsToRemove, idsToAdd }); editChatFolders({ chatId, idsToRemove, idsToAdd });
onClose(); onClose();

View File

@ -14,7 +14,7 @@ import { ANIMATION_END_DELAY } from '../../../config';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { import {
getChatTitle, getChatTitle,
isChatPrivate, isUserId,
isActionMessage, isActionMessage,
getPrivateChatUserId, getPrivateChatUserId,
getMessageAction, getMessageAction,
@ -56,7 +56,7 @@ import './Chat.scss';
type OwnProps = { type OwnProps = {
style?: string; style?: string;
chatId: number; chatId: string;
folderId?: number; folderId?: number;
orderDiff: number; orderDiff: number;
animationType: ChatAnimationTypes; animationType: ChatAnimationTypes;
@ -67,10 +67,10 @@ type StateProps = {
chat?: ApiChat; chat?: ApiChat;
isMuted?: boolean; isMuted?: boolean;
privateChatUser?: ApiUser; privateChatUser?: ApiUser;
actionTargetUserIds?: number[]; actionTargetUserIds?: string[];
usersById?: Record<number, ApiUser>; usersById?: Record<string, ApiUser>;
actionTargetMessage?: ApiMessage; actionTargetMessage?: ApiMessage;
actionTargetChatId?: number; actionTargetChatId?: string;
lastMessageSender?: ApiUser; lastMessageSender?: ApiUser;
lastMessageOutgoingStatus?: ApiMessageOutgoingStatus; lastMessageOutgoingStatus?: ApiMessageOutgoingStatus;
draft?: ApiFormattedText; draft?: ApiFormattedText;
@ -264,7 +264,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
const className = buildClassName( const className = buildClassName(
'Chat chat-item-clickable', 'Chat chat-item-clickable',
isChatPrivate(chatId) ? 'private' : 'group', isUserId(chatId) ? 'private' : 'group',
isSelected && 'selected', isSelected && 'selected',
); );

View File

@ -30,14 +30,14 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
chatFoldersById: Record<number, ApiChatFolder>; chatFoldersById: Record<number, ApiChatFolder>;
notifySettings: NotifySettings; notifySettings: NotifySettings;
notifyExceptions?: Record<number, NotifyException>; notifyExceptions?: Record<number, NotifyException>;
orderedFolderIds?: number[]; orderedFolderIds?: number[];
activeChatFolder: number; activeChatFolder: number;
currentUserId?: number; currentUserId?: string;
lastSyncTime?: number; lastSyncTime?: number;
shouldSkipHistoryAnimations?: boolean; shouldSkipHistoryAnimations?: boolean;
}; };
@ -86,7 +86,7 @@ const ChatFolders: FC<OwnProps & StateProps & DispatchProps> = ({
return undefined; return undefined;
} }
const chatIds = Object.keys(chatsById).map(Number); const chatIds = Object.keys(chatsById);
const counters = displayedFolders.map((folder) => { const counters = displayedFolders.map((folder) => {
const { const {
unreadDialogsCount, hasActiveDialogs, unreadDialogsCount, hasActiveDialogs,

View File

@ -35,11 +35,11 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
chatFolder?: ApiChatFolder; chatFolder?: ApiChatFolder;
listIds?: number[]; listIds?: string[];
orderedPinnedIds?: number[]; orderedPinnedIds?: string[];
lastSyncTime?: number; lastSyncTime?: number;
notifySettings: NotifySettings; notifySettings: NotifySettings;
notifyExceptions?: Record<number, NotifyException>; notifyExceptions?: Record<number, NotifyException>;

View File

@ -26,8 +26,8 @@ export type OwnProps = {
}; };
type StateProps = { type StateProps = {
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
contactIds?: number[]; contactIds?: string[];
serverTimeOffset: number; serverTimeOffset: number;
}; };
@ -49,12 +49,9 @@ const ContactList: FC<OwnProps & StateProps & DispatchProps> = ({
useHistoryBack(isActive, onReset); useHistoryBack(isActive, onReset);
const handleClick = useCallback( const handleClick = useCallback((id: string) => {
(id: number) => { openChat({ id, shouldReplaceHistory: true });
openChat({ id, shouldReplaceHistory: true }); }, [openChat]);
},
[openChat],
);
const listIds = useMemo(() => { const listIds = useMemo(() => {
if (!contactIds) { if (!contactIds) {

View File

@ -43,12 +43,12 @@ type OwnProps = {
type StateProps = { type StateProps = {
searchQuery?: string; searchQuery?: string;
isLoading: boolean; isLoading: boolean;
currentUserId?: number; currentUserId?: string;
globalSearchChatId?: number; globalSearchChatId?: string;
searchDate?: number; searchDate?: number;
theme: ISettings['theme']; theme: ISettings['theme'];
animationLevel: 0 | 1 | 2; animationLevel: 0 | 1 | 2;
chatsById?: Record<number, ApiChat>; chatsById?: Record<string, ApiChat>;
}; };
type DispatchProps = Pick<GlobalActions, ( type DispatchProps = Pick<GlobalActions, (

View File

@ -6,15 +6,15 @@ export enum ChatAnimationTypes {
None, None,
} }
export function useChatAnimationType(orderDiffById: Record<number, number>) { export function useChatAnimationType(orderDiffById: Record<string, number>) {
const movesUp = useCallback((id: number) => orderDiffById[id] < 0, [orderDiffById]); const movesUp = useCallback((id: string) => orderDiffById[id] < 0, [orderDiffById]);
const movesDown = useCallback((id: number) => orderDiffById[id] > 0, [orderDiffById]); const movesDown = useCallback((id: string) => orderDiffById[id] > 0, [orderDiffById]);
const orderDiffIds = Object.keys(orderDiffById).map(Number); const orderDiffIds = Object.keys(orderDiffById);
const numberOfUp = orderDiffIds.filter(movesUp).length; const numberOfUp = orderDiffIds.filter(movesUp).length;
const numberOfDown = orderDiffIds.filter(movesDown).length; const numberOfDown = orderDiffIds.filter(movesDown).length;
return useCallback((chatId: number): ChatAnimationTypes => { return useCallback((chatId: string): ChatAnimationTypes => {
const orderDiff = orderDiffById[chatId]; const orderDiff = orderDiffById[chatId];
if (orderDiff === 0) { if (orderDiff === 0) {

View File

@ -29,7 +29,7 @@ const NewChat: FC<OwnProps> = ({
onContentChange, onContentChange,
onReset, onReset,
}) => { }) => {
const [newChatMemberIds, setNewChatMemberIds] = useState<number[]>([]); const [newChatMemberIds, setNewChatMemberIds] = useState<string[]>([]);
const handleNextStep = useCallback(() => { const handleNextStep = useCallback(() => {
onContentChange(isChannel ? LeftColumnContent.NewChannelStep2 : LeftColumnContent.NewGroupStep2); onContentChange(isChannel ? LeftColumnContent.NewChannelStep2 : LeftColumnContent.NewGroupStep2);

View File

@ -20,21 +20,21 @@ import Button from '../../ui/Button';
export type OwnProps = { export type OwnProps = {
isChannel?: boolean; isChannel?: boolean;
isActive: boolean; isActive: boolean;
selectedMemberIds: number[]; selectedMemberIds: string[];
onSelectedMemberIdsChange: (ids: number[]) => void; onSelectedMemberIdsChange: (ids: string[]) => void;
onNextStep: () => void; onNextStep: () => void;
onReset: () => void; onReset: () => void;
}; };
type StateProps = { type StateProps = {
currentUserId?: number; currentUserId?: string;
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
localContactIds?: number[]; localContactIds?: string[];
searchQuery?: string; searchQuery?: string;
isSearching?: boolean; isSearching?: boolean;
localUserIds?: number[]; localUserIds?: string[];
globalUserIds?: number[]; globalUserIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, 'loadContactList' | 'setGlobalSearchQuery'>; type DispatchProps = Pick<GlobalActions, 'loadContactList' | 'setGlobalSearchQuery'>;

View File

@ -21,7 +21,7 @@ import PrivateChatInfo from '../../common/PrivateChatInfo';
export type OwnProps = { export type OwnProps = {
isChannel?: boolean; isChannel?: boolean;
isActive: boolean; isActive: boolean;
memberIds: number[]; memberIds: string[];
onReset: (forceReturnToChatList?: boolean) => void; onReset: (forceReturnToChatList?: boolean) => void;
}; };

View File

@ -66,17 +66,17 @@ const AudioResults: FC<OwnProps & StateProps & DispatchProps> = ({
} }
return foundIds.map((id) => { return foundIds.map((id) => {
const [chatId, messageId] = id.split('_').map(Number); const [chatId, messageId] = id.split('_');
return globalMessagesByChatId[chatId]?.byId[messageId]; return globalMessagesByChatId[chatId]?.byId[Number(messageId)];
}).filter(Boolean); }).filter(Boolean);
}, [globalMessagesByChatId, foundIds]); }, [globalMessagesByChatId, foundIds]);
const handleMessageFocus = useCallback((messageId: number, chatId: number) => { const handleMessageFocus = useCallback((messageId: number, chatId: string) => {
focusMessage({ chatId, messageId }); focusMessage({ chatId, messageId });
}, [focusMessage]); }, [focusMessage]);
const handlePlayAudio = useCallback((messageId: number, chatId: number) => { const handlePlayAudio = useCallback((messageId: number, chatId: string) => {
openAudioPlayer({ chatId, messageId, origin: AudioOrigin.Search }); openAudioPlayer({ chatId, messageId, origin: AudioOrigin.Search });
}, [openAudioPlayer]); }, [openAudioPlayer]);

View File

@ -36,7 +36,7 @@ import './ChatMessage.scss';
type OwnProps = { type OwnProps = {
searchQuery?: string; searchQuery?: string;
message: ApiMessage; message: ApiMessage;
chatId: number; chatId: string;
}; };
type StateProps = { type StateProps = {

View File

@ -26,10 +26,10 @@ export type OwnProps = {
}; };
type StateProps = { type StateProps = {
currentUserId?: number; currentUserId?: string;
foundIds?: string[]; foundIds?: string[];
globalMessagesByChatId?: Record<number, { byId: Record<number, ApiMessage> }>; globalMessagesByChatId?: Record<string, { byId: Record<number, ApiMessage> }>;
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
fetchingStatus?: { chats?: boolean; messages?: boolean }; fetchingStatus?: { chats?: boolean; messages?: boolean };
lastSyncTime?: number; lastSyncTime?: number;
}; };
@ -70,9 +70,9 @@ const ChatMessageResults: FC<OwnProps & StateProps & DispatchProps> = ({
return foundIds return foundIds
.map((id) => { .map((id) => {
const [chatId, messageId] = id.split('_').map(Number); const [chatId, messageId] = id.split('_');
return globalMessagesByChatId?.[chatId]?.byId[messageId]; return globalMessagesByChatId?.[chatId]?.byId[Number(messageId)];
}) })
.filter<ApiMessage>(Boolean as any) .filter<ApiMessage>(Boolean as any)
.sort((a, b) => b.date - a.date); .sort((a, b) => b.date - a.date);

View File

@ -33,16 +33,16 @@ export type OwnProps = {
}; };
type StateProps = { type StateProps = {
currentUserId?: number; currentUserId?: string;
localContactIds?: number[]; localContactIds?: string[];
localChatIds?: number[]; localChatIds?: string[];
localUserIds?: number[]; localUserIds?: string[];
globalChatIds?: number[]; globalChatIds?: string[];
globalUserIds?: number[]; globalUserIds?: string[];
foundIds?: string[]; foundIds?: string[];
globalMessagesByChatId?: Record<number, { byId: Record<number, ApiMessage> }>; globalMessagesByChatId?: Record<string, { byId: Record<number, ApiMessage> }>;
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
fetchingStatus?: { chats?: boolean; messages?: boolean }; fetchingStatus?: { chats?: boolean; messages?: boolean };
lastSyncTime?: number; lastSyncTime?: number;
}; };
@ -79,7 +79,7 @@ const ChatResults: FC<OwnProps & StateProps & DispatchProps> = ({
}, [lastSyncTime, searchMessagesGlobal, searchQuery]); }, [lastSyncTime, searchMessagesGlobal, searchQuery]);
const handleChatClick = useCallback( const handleChatClick = useCallback(
(id: number) => { (id: string) => {
openChat({ id, shouldReplaceHistory: true }); openChat({ id, shouldReplaceHistory: true });
if (id !== currentUserId) { if (id !== currentUserId) {
@ -93,7 +93,7 @@ const ChatResults: FC<OwnProps & StateProps & DispatchProps> = ({
[currentUserId, openChat, addRecentlyFoundChatId, onReset], [currentUserId, openChat, addRecentlyFoundChatId, onReset],
); );
const handlePickerItemClick = useCallback((id: number) => { const handlePickerItemClick = useCallback((id: string) => {
setGlobalSearchChatId({ id }); setGlobalSearchChatId({ id });
}, [setGlobalSearchChatId]); }, [setGlobalSearchChatId]);
@ -142,9 +142,9 @@ const ChatResults: FC<OwnProps & StateProps & DispatchProps> = ({
return foundIds return foundIds
.map((id) => { .map((id) => {
const [chatId, messageId] = id.split('_').map(Number); const [chatId, messageId] = id.split('_');
return globalMessagesByChatId?.[chatId]?.byId[messageId]; return globalMessagesByChatId?.[chatId]?.byId[Number(messageId)];
}) })
.filter<ApiMessage>(Boolean as any) .filter<ApiMessage>(Boolean as any)
.sort((a, b) => b.date - a.date); .sort((a, b) => b.date - a.date);

View File

@ -64,14 +64,14 @@ const FileResults: FC<OwnProps & StateProps & DispatchProps> = ({
} }
return foundIds.map((id) => { return foundIds.map((id) => {
const [chatId, messageId] = id.split('_').map(Number); const [chatId, messageId] = id.split('_');
const message = globalMessagesByChatId[chatId]?.byId[messageId]; const message = globalMessagesByChatId[chatId]?.byId[Number(messageId)];
return message && getMessageDocument(message) ? message : undefined; return message && getMessageDocument(message) ? message : undefined;
}).filter(Boolean) as ApiMessage[]; }).filter(Boolean) as ApiMessage[];
}, [globalMessagesByChatId, foundIds]); }, [globalMessagesByChatId, foundIds]);
const handleMessageFocus = useCallback((messageId: number, chatId: number) => { const handleMessageFocus = useCallback((messageId: number, chatId: string) => {
focusMessage({ chatId, messageId }); focusMessage({ chatId, messageId });
}, [focusMessage]); }, [focusMessage]);

View File

@ -32,7 +32,7 @@ export type OwnProps = {
type StateProps = { type StateProps = {
currentContent?: GlobalSearchContent; currentContent?: GlobalSearchContent;
chatId?: number; chatId?: string;
}; };
type DispatchProps = Pick<GlobalActions, ('setGlobalSearchContent' | 'setGlobalSearchDate')>; type DispatchProps = Pick<GlobalActions, ('setGlobalSearchContent' | 'setGlobalSearchDate')>;

View File

@ -7,7 +7,7 @@ import { ApiChat, ApiUser } from '../../../api/types';
import useChatContextActions from '../../../hooks/useChatContextActions'; import useChatContextActions from '../../../hooks/useChatContextActions';
import useFlag from '../../../hooks/useFlag'; import useFlag from '../../../hooks/useFlag';
import { isChatPrivate, getPrivateChatUserId, selectIsChatMuted } from '../../../modules/helpers'; import { isUserId, getPrivateChatUserId, selectIsChatMuted } from '../../../modules/helpers';
import { import {
selectChat, selectUser, selectIsChatPinned, selectNotifySettings, selectNotifyExceptions, selectChat, selectUser, selectIsChatPinned, selectNotifySettings, selectNotifyExceptions,
} from '../../../modules/selectors'; } from '../../../modules/selectors';
@ -20,9 +20,9 @@ import ListItem from '../../ui/ListItem';
import ChatFolderModal from '../ChatFolderModal.async'; import ChatFolderModal from '../ChatFolderModal.async';
type OwnProps = { type OwnProps = {
chatId: number; chatId: string;
withUsername?: boolean; withUsername?: boolean;
onClick: (id: number) => void; onClick: (id: string) => void;
}; };
type StateProps = { type StateProps = {
@ -70,7 +70,7 @@ const LeftSearchResultChat: FC<OwnProps & StateProps> = ({
contextActions={contextActions} contextActions={contextActions}
buttonRef={buttonRef} buttonRef={buttonRef}
> >
{isChatPrivate(chatId) ? ( {isUserId(chatId) ? (
<PrivateChatInfo userId={chatId} withUsername={withUsername} avatarSize="large" /> <PrivateChatInfo userId={chatId} withUsername={withUsername} avatarSize="large" />
) : ( ) : (
<GroupChatInfo chatId={chatId} withUsername={withUsername} avatarSize="large" /> <GroupChatInfo chatId={chatId} withUsername={withUsername} avatarSize="large" />

View File

@ -61,13 +61,13 @@ const LinkResults: FC<OwnProps & StateProps & DispatchProps> = ({
} }
return foundIds.map((id) => { return foundIds.map((id) => {
const [chatId, messageId] = id.split('_').map(Number); const [chatId, messageId] = id.split('_');
return globalMessagesByChatId[chatId]?.byId[messageId]; return globalMessagesByChatId[chatId]?.byId[Number(messageId)];
}).filter(Boolean); }).filter(Boolean);
}, [globalMessagesByChatId, foundIds]); }, [globalMessagesByChatId, foundIds]);
const handleMessageFocus = useCallback((messageId: number, chatId: number) => { const handleMessageFocus = useCallback((messageId: number, chatId: string) => {
focusMessage({ chatId, messageId }); focusMessage({ chatId, messageId });
}, [focusMessage]); }, [focusMessage]);

View File

@ -60,13 +60,13 @@ const MediaResults: FC<OwnProps & StateProps & DispatchProps> = ({
} }
return foundIds.map((id) => { return foundIds.map((id) => {
const [chatId, messageId] = id.split('_').map(Number); const [chatId, messageId] = id.split('_');
return globalMessagesByChatId[chatId]?.byId[messageId]; return globalMessagesByChatId[chatId]?.byId[Number(messageId)];
}).filter(Boolean); }).filter(Boolean);
}, [globalMessagesByChatId, foundIds]); }, [globalMessagesByChatId, foundIds]);
const handleSelectMedia = useCallback((messageId: number, chatId: number) => { const handleSelectMedia = useCallback((messageId: number, chatId: string) => {
openMediaViewer({ openMediaViewer({
chatId, chatId,
messageId, messageId,

View File

@ -24,9 +24,9 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
topUserIds?: number[]; topUserIds?: string[];
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
recentlyFoundChatIds?: number[]; recentlyFoundChatIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, ( type DispatchProps = Pick<GlobalActions, (
@ -58,16 +58,13 @@ const RecentContacts: FC<OwnProps & StateProps & DispatchProps> = ({
useHorizontalScroll(topUsersRef.current, !topUserIds); useHorizontalScroll(topUsersRef.current, !topUserIds);
const handleClick = useCallback( const handleClick = useCallback((id: string) => {
(id: number) => { openChat({ id, shouldReplaceHistory: true });
openChat({ id, shouldReplaceHistory: true }); onReset();
onReset(); setTimeout(() => {
setTimeout(() => { addRecentlyFoundChatId({ id });
addRecentlyFoundChatId({ id }); }, SEARCH_CLOSE_TIMEOUT_MS);
}, SEARCH_CLOSE_TIMEOUT_MS); }, [openChat, addRecentlyFoundChatId, onReset]);
},
[openChat, addRecentlyFoundChatId, onReset],
);
const lang = useLang(); const lang = useLang();

View File

@ -9,13 +9,13 @@ import { selectTheme } from '../../../../modules/selectors';
export type StateProps = { export type StateProps = {
theme: ISettings['theme']; theme: ISettings['theme'];
isLoading?: boolean; isLoading?: boolean;
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
globalMessagesByChatId?: Record<number, { byId: Record<number, ApiMessage> }>; globalMessagesByChatId?: Record<string, { byId: Record<number, ApiMessage> }>;
foundIds?: string[]; foundIds?: string[];
lastSyncTime?: number; lastSyncTime?: number;
searchChatId?: number; searchChatId?: string;
activeDownloads: Record<number, number[]>; activeDownloads: Record<string, number[]>;
}; };
export function createMapStateToProps(type: ApiGlobalMessageSearchType) { export function createMapStateToProps(type: ApiGlobalMessageSearchType) {

View File

@ -2,26 +2,26 @@ import { ApiChat, ApiMessage, ApiUser } from '../../../../api/types';
import { import {
getChatTitle, getChatTitle,
getSenderTitle, getSenderTitle,
isChatPrivate, isUserId,
isChatGroup, isChatGroup,
} from '../../../../modules/helpers'; } from '../../../../modules/helpers';
import { LangFn } from '../../../../hooks/useLang'; import { LangFn } from '../../../../hooks/useLang';
export function getSenderName( export function getSenderName(
lang: LangFn, message: ApiMessage, chatsById: Record<number, ApiChat>, usersById: Record<number, ApiUser>, lang: LangFn, message: ApiMessage, chatsById: Record<string, ApiChat>, usersById: Record<string, ApiUser>,
) { ) {
const { senderId } = message; const { senderId } = message;
if (!senderId) { if (!senderId) {
return undefined; return undefined;
} }
const sender = isChatPrivate(senderId) ? usersById[senderId] : chatsById[senderId]; const sender = isUserId(senderId) ? usersById[senderId] : chatsById[senderId];
let senderName = getSenderTitle(lang, sender); let senderName = getSenderTitle(lang, sender);
const chat = chatsById[message.chatId]; const chat = chatsById[message.chatId];
if (chat) { if (chat) {
if (isChatPrivate(senderId) && (sender as ApiUser).isSelf) { if (isUserId(senderId) && (sender as ApiUser).isSelf) {
senderName = `${lang('FromYou')}${getChatTitle(lang, chat)}`; senderName = `${lang('FromYou')}${getChatTitle(lang, chat)}`;
} else if (isChatGroup(chat)) { } else if (isChatGroup(chat)) {
senderName += `${getChatTitle(lang, chat)}`; senderName += `${getChatTitle(lang, chat)}`;

View File

@ -19,11 +19,11 @@ export type OwnProps = {
}; };
type StateProps = { type StateProps = {
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
blockedIds: number[]; blockedIds: string[];
contactIds?: number[]; contactIds?: string[];
localContactIds?: number[]; localContactIds?: string[];
currentUserId?: number; currentUserId?: string;
}; };
type DispatchProps = Pick<GlobalActions, 'loadContactList' | 'setUserSearchQuery' | 'blockContact'>; type DispatchProps = Pick<GlobalActions, 'loadContactList' | 'setUserSearchQuery' | 'blockContact'>;
@ -54,7 +54,7 @@ const BlockUserModal: FC<OwnProps & StateProps & DispatchProps> = ({
return !blockedIds.includes(contactId) && contactId !== currentUserId; return !blockedIds.includes(contactId) && contactId !== currentUserId;
}); });
return unique(availableContactsId).reduce((acc, contactId) => { return unique(availableContactsId).reduce<string[]>((acc, contactId) => {
if ( if (
!filter !filter
|| !usersById[contactId] || !usersById[contactId]
@ -65,7 +65,7 @@ const BlockUserModal: FC<OwnProps & StateProps & DispatchProps> = ({
} }
return acc; return acc;
}, [] as number[]) }, [])
.sort((firstId, secondId) => { .sort((firstId, secondId) => {
const firstName = getUserFullName(usersById[firstId]) || ''; const firstName = getUserFullName(usersById[firstId]) || '';
const secondName = getUserFullName(usersById[secondId]) || ''; const secondName = getUserFullName(usersById[secondId]) || '';
@ -74,7 +74,7 @@ const BlockUserModal: FC<OwnProps & StateProps & DispatchProps> = ({
}); });
}, [blockedIds, contactIds, currentUserId, filter, localContactIds, usersById]); }, [blockedIds, contactIds, currentUserId, filter, localContactIds, usersById]);
const handleRemoveUser = useCallback((userId: number) => { const handleRemoveUser = useCallback((userId: string) => {
const { id: contactId, accessHash } = usersById[userId] || {}; const { id: contactId, accessHash } = usersById[userId] || {};
if (!contactId || !accessHash) { if (!contactId || !accessHash) {
return; return;

View File

@ -11,7 +11,7 @@ import { CHAT_HEIGHT_PX } from '../../../config';
import { formatPhoneNumberWithCode } from '../../../util/phoneNumber'; import { formatPhoneNumberWithCode } from '../../../util/phoneNumber';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
import { import {
getChatTitle, getUserFullName, isChatPrivate, getChatTitle, getUserFullName, isUserId,
} from '../../../modules/helpers'; } from '../../../modules/helpers';
import renderText from '../../common/helpers/renderText'; import renderText from '../../common/helpers/renderText';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
@ -32,9 +32,9 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
chatsByIds: Record<number, ApiChat>; chatsByIds: Record<string, ApiChat>;
usersByIds: Record<number, ApiUser>; usersByIds: Record<string, ApiUser>;
blockedIds: number[]; blockedIds: string[];
phoneCodeList: ApiCountryCode[]; phoneCodeList: ApiCountryCode[];
}; };
@ -52,14 +52,14 @@ const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps & DispatchProps> = (
}) => { }) => {
const lang = useLang(); const lang = useLang();
const [isBlockUserModalOpen, openBlockUserModal, closeBlockUserModal] = useFlag(); const [isBlockUserModalOpen, openBlockUserModal, closeBlockUserModal] = useFlag();
const handleUnblockClick = useCallback((contactId: number) => { const handleUnblockClick = useCallback((contactId: string) => {
unblockContact({ contactId }); unblockContact({ contactId });
}, [unblockContact]); }, [unblockContact]);
useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.PrivacyBlockedUsers); useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.PrivacyBlockedUsers);
function renderContact(contactId: number, i: number, viewportOffset: number) { function renderContact(contactId: string, i: number, viewportOffset: number) {
const isPrivate = isChatPrivate(contactId); const isPrivate = isUserId(contactId);
const user = isPrivate ? usersByIds[contactId] : undefined; const user = isPrivate ? usersByIds[contactId] : undefined;
const chat = !isPrivate ? chatsByIds[contactId] : undefined; const chat = !isPrivate ? chatsByIds[contactId] : undefined;

View File

@ -23,8 +23,8 @@ type OwnProps = {
}; };
type StateProps = Partial<ApiPrivacySettings> & { type StateProps = Partial<ApiPrivacySettings> & {
chatsById?: Record<number, ApiChat>; chatsById?: Record<string, ApiChat>;
usersById?: Record<number, ApiUser>; usersById?: Record<string, ApiUser>;
}; };
type DispatchProps = Pick<GlobalActions, 'setPrivacyVisibility'>; type DispatchProps = Pick<GlobalActions, 'setPrivacyVisibility'>;

View File

@ -12,7 +12,7 @@ import { pick } from '../../../util/iteratees';
import searchWords from '../../../util/searchWords'; import searchWords from '../../../util/searchWords';
import { getPrivacyKey } from './helper/privacy'; import { getPrivacyKey } from './helper/privacy';
import { import {
getChatTitle, isChatGroup, isChatPrivate, prepareChatList, getChatTitle, isChatGroup, isUserId, prepareChatList,
} from '../../../modules/helpers'; } from '../../../modules/helpers';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
@ -28,12 +28,12 @@ export type OwnProps = {
}; };
type StateProps = { type StateProps = {
currentUserId?: number; currentUserId?: string;
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
listIds?: number[]; listIds?: string[];
orderedPinnedIds?: number[]; orderedPinnedIds?: string[];
archivedListIds?: number[]; archivedListIds?: string[];
archivedPinnedIds?: number[]; archivedPinnedIds?: string[];
settings?: ApiPrivacySettings; settings?: ApiPrivacySettings;
}; };
@ -69,7 +69,7 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps & Dispatc
}, [isAllowList, settings]); }, [isAllowList, settings]);
const [searchQuery, setSearchQuery] = useState<string>(''); const [searchQuery, setSearchQuery] = useState<string>('');
const [isSubmitShown, setIsSubmitShown] = useState<boolean>(false); const [isSubmitShown, setIsSubmitShown] = useState<boolean>(false);
const [newSelectedContactIds, setNewSelectedContactIds] = useState<number[]>(selectedContactIds); const [newSelectedContactIds, setNewSelectedContactIds] = useState<string[]>(selectedContactIds);
const chats = useMemo(() => { const chats = useMemo(() => {
const activeChatArrays = listIds const activeChatArrays = listIds
@ -102,7 +102,7 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps & Dispatc
return chats return chats
.filter((chat) => ( .filter((chat) => (
((isChatPrivate(chat.id) && chat.id !== currentUserId) || isChatGroup(chat)) ((isUserId(chat.id) && chat.id !== currentUserId) || isChatGroup(chat))
&& ( && (
!searchQuery !searchQuery
|| searchWords(getChatTitle(lang, chat), searchQuery) || searchWords(getChatTitle(lang, chat), searchQuery)
@ -112,7 +112,7 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps & Dispatc
.map(({ id }) => id); .map(({ id }) => id);
}, [chats, currentUserId, lang, searchQuery, selectedContactIds]); }, [chats, currentUserId, lang, searchQuery, selectedContactIds]);
const handleSelectedContactIdsChange = useCallback((value: number[]) => { const handleSelectedContactIdsChange = useCallback((value: string[]) => {
setNewSelectedContactIds(value); setNewSelectedContactIds(value);
setIsSubmitShown(true); setIsSubmitShown(true);
}, []); }, []);

View File

@ -32,11 +32,11 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
listIds?: number[]; listIds?: string[];
orderedPinnedIds?: number[]; orderedPinnedIds?: string[];
archivedListIds?: number[]; archivedListIds?: string[];
archivedPinnedIds?: number[]; archivedPinnedIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, 'loadMoreChats'>; type DispatchProps = Pick<GlobalActions, 'loadMoreChats'>;
@ -101,7 +101,7 @@ const SettingsFoldersChatFilters: FC<OwnProps & StateProps & DispatchProps> = ({
}); });
}, [dispatch]); }, [dispatch]);
const handleSelectedIdsChange = useCallback((ids: number[]) => { const handleSelectedIdsChange = useCallback((ids: string[]) => {
if (mode === 'included') { if (mode === 'included') {
dispatch({ dispatch({
type: 'setIncludeFilters', type: 'setIncludeFilters',

View File

@ -2,7 +2,7 @@ import React, {
FC, useCallback, useRef, useEffect, memo, FC, useCallback, useRef, useEffect, memo,
} from '../../../../lib/teact/teact'; } from '../../../../lib/teact/teact';
import { isChatPrivate } from '../../../../modules/helpers'; import { isUserId } from '../../../../modules/helpers';
import { import {
INCLUDED_CHAT_TYPES, INCLUDED_CHAT_TYPES,
EXCLUDED_CHAT_TYPES, EXCLUDED_CHAT_TYPES,
@ -25,11 +25,11 @@ import './SettingsFoldersChatsPicker.scss';
type OwnProps = { type OwnProps = {
mode: 'included' | 'excluded'; mode: 'included' | 'excluded';
chatIds: number[]; chatIds: string[];
selectedIds: number[]; selectedIds: string[];
selectedChatTypes: string[]; selectedChatTypes: string[];
filterValue?: string; filterValue?: string;
onSelectedIdsChange: (ids: number[]) => void; onSelectedIdsChange: (ids: string[]) => void;
onSelectedChatTypesChange: (types: string[]) => void; onSelectedChatTypesChange: (types: string[]) => void;
onFilterChange: (value: string) => void; onFilterChange: (value: string) => void;
onLoadMore: () => void; onLoadMore: () => void;
@ -67,7 +67,7 @@ const SettingsFoldersChatsPicker: FC<OwnProps> = ({
}, FOCUS_DELAY_MS); }, FOCUS_DELAY_MS);
}, []); }, []);
const handleItemClick = useCallback((id: number) => { const handleItemClick = useCallback((id: string) => {
const newSelectedIds = [...selectedIds]; const newSelectedIds = [...selectedIds];
if (newSelectedIds.includes(id)) { if (newSelectedIds.includes(id)) {
newSelectedIds.splice(newSelectedIds.indexOf(id), 1); newSelectedIds.splice(newSelectedIds.indexOf(id), 1);
@ -131,7 +131,7 @@ const SettingsFoldersChatsPicker: FC<OwnProps> = ({
); );
} }
function renderItem(id: number) { function renderItem(id: string) {
const isSelected = selectedIds.includes(id); const isSelected = selectedIds.includes(id);
return ( return (
@ -142,7 +142,7 @@ const SettingsFoldersChatsPicker: FC<OwnProps> = ({
ripple ripple
disabled={!isSelected && hasMaxChats} disabled={!isSelected && hasMaxChats}
> >
{isChatPrivate(id) ? ( {isUserId(id) ? (
<PrivateChatInfo userId={id} /> <PrivateChatInfo userId={id} />
) : ( ) : (
<GroupChatInfo chatId={id} withChatType /> <GroupChatInfo chatId={id} withChatType />

View File

@ -8,7 +8,7 @@ import { SettingsScreens } from '../../../../types';
import { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config'; import { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config';
import { findIntersectionWithSet, pick } from '../../../../util/iteratees'; import { findIntersectionWithSet, pick } from '../../../../util/iteratees';
import { isChatPrivate } from '../../../../modules/helpers'; import { isUserId } from '../../../../modules/helpers';
import getAnimationData from '../../../common/helpers/animatedAssets'; import getAnimationData from '../../../common/helpers/animatedAssets';
import { import {
EXCLUDED_CHAT_TYPES, EXCLUDED_CHAT_TYPES,
@ -41,8 +41,8 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
loadedActiveChatIds?: number[]; loadedActiveChatIds?: string[];
loadedArchivedChatIds?: number[]; loadedArchivedChatIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, 'editChatFolder' | 'addChatFolder' | 'loadMoreChats'>; type DispatchProps = Pick<GlobalActions, 'editChatFolder' | 'addChatFolder' | 'loadMoreChats'>;
@ -212,7 +212,7 @@ const SettingsFoldersEdit: FC<OwnProps & StateProps & DispatchProps> = ({
narrow narrow
inactive inactive
> >
{isChatPrivate(id) ? ( {isUserId(id) ? (
<PrivateChatInfo avatarSize="small" userId={id} /> <PrivateChatInfo avatarSize="small" userId={id} />
) : ( ) : (
<GroupChatInfo avatarSize="small" chatId={id} /> <GroupChatInfo avatarSize="small" chatId={id} />

View File

@ -30,8 +30,8 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
orderedFolderIds?: number[]; orderedFolderIds?: number[];
foldersById: Record<number, ApiChatFolder>; foldersById: Record<number, ApiChatFolder>;
recommendedChatFolders?: ApiChatFolder[]; recommendedChatFolders?: ApiChatFolder[];
@ -104,7 +104,7 @@ const SettingsFoldersMain: FC<OwnProps & StateProps & DispatchProps> = ({
return undefined; return undefined;
} }
const chatIds = Object.keys(chatsById).map(Number); const chatIds = Object.keys(chatsById);
return orderedFolderIds.map((id) => { return orderedFolderIds.map((id) => {
const folder = foldersById[id]; const folder = foldersById[id];

View File

@ -18,12 +18,12 @@ export type OwnProps = {
}; };
type StateProps = { type StateProps = {
chatsById: Record<number, ApiChat>; chatsById: Record<string, ApiChat>;
pinnedIds?: number[]; pinnedIds?: string[];
activeListIds?: number[]; activeListIds?: string[];
archivedListIds?: number[]; archivedListIds?: string[];
orderedPinnedIds?: number[]; orderedPinnedIds?: string[];
currentUserId?: number; currentUserId?: string;
}; };
type DispatchProps = Pick<GlobalActions, 'setForwardChatId' | 'exitForwardMode' | 'loadMoreChats'>; type DispatchProps = Pick<GlobalActions, 'setForwardChatId' | 'exitForwardMode' | 'loadMoreChats'>;
@ -75,7 +75,7 @@ const ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({
], chatsById, undefined, priorityIds); ], chatsById, undefined, priorityIds);
}, [activeListIds, archivedListIds, chatsById, currentUserId, filter, lang, pinnedIds]); }, [activeListIds, archivedListIds, chatsById, currentUserId, filter, lang, pinnedIds]);
const handleSelectUser = useCallback((userId: number) => { const handleSelectUser = useCallback((userId: string) => {
setForwardChatId({ id: userId }); setForwardChatId({ id: userId });
}, [setForwardChatId]); }, [setForwardChatId]);

View File

@ -74,10 +74,10 @@ import PanZoom from './PanZoom';
import './MediaViewer.scss'; import './MediaViewer.scss';
type StateProps = { type StateProps = {
chatId?: number; chatId?: string;
threadId?: number; threadId?: number;
messageId?: number; messageId?: number;
senderId?: number; senderId?: string;
origin?: MediaViewerOrigin; origin?: MediaViewerOrigin;
avatarOwner?: ApiChat | ApiUser; avatarOwner?: ApiChat | ApiUser;
profilePhotoIndex?: number; profilePhotoIndex?: number;
@ -139,7 +139,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
/* Animation */ /* Animation */
const animationKey = useRef<number>(); const animationKey = useRef<number>();
const prevSenderId = usePrevious<number | undefined>(senderId); const prevSenderId = usePrevious<string | undefined>(senderId);
if (isOpen && (!prevSenderId || prevSenderId !== senderId || !animationKey.current)) { if (isOpen && (!prevSenderId || prevSenderId !== senderId || !animationKey.current)) {
animationKey.current = selectedMediaMessageIndex; animationKey.current = selectedMediaMessageIndex;
} }

View File

@ -4,7 +4,7 @@ import { withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types'; import { GlobalActions } from '../../global/types';
import { ApiChat, ApiMessage, ApiUser } from '../../api/types'; import { ApiChat, ApiMessage, ApiUser } from '../../api/types';
import { getSenderTitle, isChatPrivate } from '../../modules/helpers'; import { getSenderTitle, isUserId } from '../../modules/helpers';
import { formatMediaDateTime } from '../../util/dateFormat'; import { formatMediaDateTime } from '../../util/dateFormat';
import renderText from '../common/helpers/renderText'; import renderText from '../common/helpers/renderText';
import { import {
@ -21,7 +21,7 @@ import Avatar from '../common/Avatar';
import './SenderInfo.scss'; import './SenderInfo.scss';
type OwnProps = { type OwnProps = {
chatId?: number; chatId?: string;
messageId?: number; messageId?: number;
isAvatar?: boolean; isAvatar?: boolean;
}; };
@ -53,15 +53,14 @@ const SenderInfo: FC<OwnProps & StateProps & DispatchProps> = ({
return undefined; return undefined;
} }
const isFromChat = sender.id < 0;
const senderTitle = getSenderTitle(lang, sender); const senderTitle = getSenderTitle(lang, sender);
return ( return (
<div className="SenderInfo" onClick={handleFocusMessage}> <div className="SenderInfo" onClick={handleFocusMessage}>
{isFromChat ? ( {isUserId(sender.id) ? (
<Avatar key={sender.id} size="medium" chat={sender as ApiChat} />
) : (
<Avatar key={sender.id} size="medium" user={sender as ApiUser} /> <Avatar key={sender.id} size="medium" user={sender as ApiUser} />
) : (
<Avatar key={sender.id} size="medium" chat={sender as ApiChat} />
)} )}
<div className="meta"> <div className="meta">
<div className="title" dir="auto"> <div className="title" dir="auto">
@ -81,7 +80,7 @@ export default withGlobal<OwnProps>(
(global, { chatId, messageId, isAvatar }): StateProps => { (global, { chatId, messageId, isAvatar }): StateProps => {
if (isAvatar && chatId) { if (isAvatar && chatId) {
return { return {
sender: isChatPrivate(chatId) ? selectUser(global, chatId) : selectChat(global, chatId), sender: isUserId(chatId) ? selectUser(global, chatId) : selectChat(global, chatId),
}; };
} }

View File

@ -36,11 +36,11 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
sender?: ApiUser | ApiChat; sender?: ApiUser | ApiChat;
targetUserIds?: number[]; targetUserIds?: string[];
targetMessage?: ApiMessage; targetMessage?: ApiMessage;
targetChatId?: number; targetChatId?: string;
isFocused: boolean; isFocused: boolean;
focusDirection?: FocusDirection; focusDirection?: FocusDirection;
noFocusHighlight?: boolean; noFocusHighlight?: boolean;

View File

@ -10,13 +10,14 @@ import { pick } from '../../util/iteratees';
import { selectChat } from '../../modules/selectors'; import { selectChat } from '../../modules/selectors';
import { useIntersectionObserver } from '../../hooks/useIntersectionObserver'; import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import { getUserIdDividend } from '../../modules/helpers';
import StickerButton from '../common/StickerButton'; import StickerButton from '../common/StickerButton';
import './ContactGreeting.scss'; import './ContactGreeting.scss';
type OwnProps = { type OwnProps = {
userId: number; userId: string;
}; };
type StateProps = { type StateProps = {
@ -94,7 +95,8 @@ const ContactGreeting: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { userId }): StateProps => { (global, { userId }): StateProps => {
const { stickers } = global.stickers.greeting; const { stickers } = global.stickers.greeting;
const sticker = stickers?.length ? stickers[userId % stickers.length] : undefined; const dividend = getUserIdDividend(userId) + getUserIdDividend(global.currentUserId!);
const sticker = stickers?.length ? stickers[dividend % stickers.length] : undefined;
const chat = selectChat(global, userId); const chat = selectChat(global, userId);
if (!chat) { if (!chat) {
return {}; return {};
@ -111,5 +113,4 @@ export default memo(withGlobal<OwnProps>(
(setGlobal, actions): DispatchProps => pick(actions, [ (setGlobal, actions): DispatchProps => pick(actions, [
'loadGreetingStickers', 'sendMessage', 'markMessageListRead', 'loadGreetingStickers', 'sendMessage', 'markMessageListRead',
]), ]),
)(ContactGreeting)); )(ContactGreeting));

View File

@ -7,7 +7,7 @@ import { GlobalActions } from '../../global/types';
import { selectCanDeleteSelectedMessages, selectCurrentChat, selectUser } from '../../modules/selectors'; import { selectCanDeleteSelectedMessages, selectCurrentChat, selectUser } from '../../modules/selectors';
import { import {
isChatPrivate, isUserId,
getUserFirstOrLastName, getUserFirstOrLastName,
getPrivateChatUserId, getPrivateChatUserId,
isChatBasicGroup, isChatBasicGroup,
@ -115,7 +115,7 @@ export default memo(withGlobal<OwnProps>(
const { messageIds: selectedMessageIds } = global.selectedMessages || {}; const { messageIds: selectedMessageIds } = global.selectedMessages || {};
const { canDeleteForAll } = selectCanDeleteSelectedMessages(global); const { canDeleteForAll } = selectCanDeleteSelectedMessages(global);
const chat = selectCurrentChat(global); const chat = selectCurrentChat(global);
const contactName = chat && isChatPrivate(chat.id) const contactName = chat && isUserId(chat.id)
? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!))
: undefined; : undefined;

View File

@ -29,7 +29,7 @@ import Button from '../ui/Button';
import HeaderMenuContainer from './HeaderMenuContainer.async'; import HeaderMenuContainer from './HeaderMenuContainer.async';
interface OwnProps { interface OwnProps {
chatId: number; chatId: string;
threadId: number; threadId: number;
messageListType: MessageListType; messageListType: MessageListType;
} }

View File

@ -14,7 +14,7 @@ import {
} from '../../modules/selectors'; } from '../../modules/selectors';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
import { import {
isChatPrivate, getCanDeleteChat, selectIsChatMuted, getCanAddContact, isUserId, getCanDeleteChat, selectIsChatMuted, getCanAddContact,
} from '../../modules/helpers'; } from '../../modules/helpers';
import useShowTransition from '../../hooks/useShowTransition'; import useShowTransition from '../../hooks/useShowTransition';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -31,7 +31,7 @@ type DispatchProps = Pick<GlobalActions, (
)>; )>;
export type OwnProps = { export type OwnProps = {
chatId: number; chatId: string;
threadId: number; threadId: number;
isOpen: boolean; isOpen: boolean;
anchor: IAnchorPosition; anchor: IAnchorPosition;
@ -253,7 +253,7 @@ export default memo(withGlobal<OwnProps>(
if (!chat || chat.isRestricted) { if (!chat || chat.isRestricted) {
return {}; return {};
} }
const isPrivate = isChatPrivate(chat.id); const isPrivate = isUserId(chat.id);
const user = isPrivate ? selectUser(global, chatId) : undefined; const user = isPrivate ? selectUser(global, chatId) : undefined;
const canAddContact = user && getCanAddContact(user); const canAddContact = user && getCanAddContact(user);

View File

@ -28,7 +28,7 @@ import {
} from '../../modules/selectors'; } from '../../modules/selectors';
import { import {
isChatChannel, isChatChannel,
isChatPrivate, isUserId,
isChatWithRepliesBot, isChatWithRepliesBot,
isChatGroup, isChatGroup,
} from '../../modules/helpers'; } from '../../modules/helpers';
@ -56,7 +56,7 @@ import NoMessages from './NoMessages';
import './MessageList.scss'; import './MessageList.scss';
type OwnProps = { type OwnProps = {
chatId: number; chatId: string;
threadId: number; threadId: number;
type: MessageListType; type: MessageListType;
canPost: boolean; canPost: boolean;
@ -447,10 +447,10 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
const lang = useLang(); const lang = useLang();
const isPrivate = Boolean(chatId && isChatPrivate(chatId)); const isPrivate = Boolean(chatId && isUserId(chatId));
const withUsers = Boolean((!isPrivate && !isChannelChat) || isChatWithSelf || isRepliesChat); const withUsers = Boolean((!isPrivate && !isChannelChat) || isChatWithSelf || isRepliesChat);
const noAvatars = Boolean(!withUsers || isChannelChat); const noAvatars = Boolean(!withUsers || isChannelChat);
const shouldRenderGreeting = isChatPrivate(chatId) && !isChatWithSelf && !isBot const shouldRenderGreeting = isUserId(chatId) && !isChatWithSelf && !isBot
&& ( && (
( (
!messageGroups && !lastMessage && messageIds !messageGroups && !lastMessage && messageIds

View File

@ -37,7 +37,7 @@ import {
selectPinnedIds, selectPinnedIds,
selectTheme, selectTheme,
} from '../../modules/selectors'; } from '../../modules/selectors';
import { getCanPostInChat, getMessageSendingRestrictionReason, isChatPrivate } from '../../modules/helpers'; import { getCanPostInChat, getMessageSendingRestrictionReason, isUserId } from '../../modules/helpers';
import captureEscKeyListener from '../../util/captureEscKeyListener'; import captureEscKeyListener from '../../util/captureEscKeyListener';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
@ -64,7 +64,7 @@ import ReceiptModal from '../payment/ReceiptModal.async';
import './MiddleColumn.scss'; import './MiddleColumn.scss';
type StateProps = { type StateProps = {
chatId?: number; chatId?: string;
threadId?: number; threadId?: number;
messageListType?: MessageListType; messageListType?: MessageListType;
isPrivate?: boolean; isPrivate?: boolean;
@ -477,7 +477,7 @@ export default memo(withGlobal(
chatId, chatId,
threadId, threadId,
messageListType, messageListType,
isPrivate: isChatPrivate(chatId), isPrivate: isUserId(chatId),
canPost: !isPinnedMessageList && (!chat || canPost) && !isBotNotStarted, canPost: !isPinnedMessageList && (!chat || canPost) && !isBotNotStarted,
isPinnedMessageList, isPinnedMessageList,
isScheduledMessageList, isScheduledMessageList,

View File

@ -23,7 +23,7 @@ import {
} from '../../config'; } from '../../config';
import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../util/environment';
import { import {
isChatPrivate, isUserId,
getMessageKey, getMessageKey,
getChatTitle, getChatTitle,
getSenderTitle, getSenderTitle,
@ -68,7 +68,7 @@ const ANIMATION_DURATION = 350;
const BACK_BUTTON_INACTIVE_TIME = 450; const BACK_BUTTON_INACTIVE_TIME = 450;
type OwnProps = { type OwnProps = {
chatId: number; chatId: string;
threadId: number; threadId: number;
messageListType: MessageListType; messageListType: MessageListType;
isReady?: boolean; isReady?: boolean;
@ -85,7 +85,7 @@ type StateProps = {
isLeftColumnShown?: boolean; isLeftColumnShown?: boolean;
isRightColumnShown?: boolean; isRightColumnShown?: boolean;
audioMessage?: ApiMessage; audioMessage?: ApiMessage;
chatsById?: Record<number, ApiChat>; chatsById?: Record<string, ApiChat>;
messagesCount?: number; messagesCount?: number;
isChatWithSelf?: boolean; isChatWithSelf?: boolean;
isChatWithBot?: boolean; isChatWithBot?: boolean;
@ -348,7 +348,7 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
<> <>
{(isLeftColumnHideable || currentTransitionKey > 0) && renderBackButton(shouldShowCloseButton, true)} {(isLeftColumnHideable || currentTransitionKey > 0) && renderBackButton(shouldShowCloseButton, true)}
<div className="chat-info-wrapper" onClick={handleHeaderClick}> <div className="chat-info-wrapper" onClick={handleHeaderClick}>
{isChatPrivate(chatId) ? ( {isUserId(chatId) ? (
<PrivateChatInfo <PrivateChatInfo
userId={chatId} userId={chatId}
typingStatus={typingStatus} typingStatus={typingStatus}

View File

@ -7,7 +7,7 @@ import useLang, { LangFn } from '../../hooks/useLang';
import './NoMessages.scss'; import './NoMessages.scss';
type OwnProps = { type OwnProps = {
chatId: number; chatId: string;
isChatWithSelf?: boolean; isChatWithSelf?: boolean;
type: MessageListType; type: MessageListType;
isGroupChatJustCreated?: boolean; isGroupChatJustCreated?: boolean;

View File

@ -31,9 +31,9 @@ export type OwnProps = {
attachments: ApiAttachment[]; attachments: ApiAttachment[];
caption: string; caption: string;
isReady?: boolean; isReady?: boolean;
currentUserId?: number; currentUserId?: string;
groupChatMembers?: ApiChatMember[]; groupChatMembers?: ApiChatMember[];
usersById?: Record<number, ApiUser>; usersById?: Record<string, ApiUser>;
recentEmojis: string[]; recentEmojis: string[];
baseEmojiKeywords?: Record<string, string[]>; baseEmojiKeywords?: Record<string, string[]>;
emojiKeywords?: Record<string, string[]>; emojiKeywords?: Record<string, string[]>;

View File

@ -26,7 +26,7 @@ export type OwnProps = {
}; };
type StateProps = { type StateProps = {
usersById: Record<number, ApiUser>; usersById: Record<string, ApiUser>;
}; };
type DispatchProps = Pick<GlobalActions, 'sendBotCommand'>; type DispatchProps = Pick<GlobalActions, 'sendBotCommand'>;

View File

@ -41,7 +41,7 @@ import {
import { import {
getAllowedAttachmentOptions, getAllowedAttachmentOptions,
getChatSlowModeOptions, getChatSlowModeOptions,
isChatPrivate, isUserId,
isChatAdmin, isChatAdmin,
} from '../../../modules/helpers'; } from '../../../modules/helpers';
import { formatMediaDuration, formatVoiceRecordDuration, getDayStartAt } from '../../../util/dateFormat'; import { formatMediaDuration, formatVoiceRecordDuration, getDayStartAt } from '../../../util/dateFormat';
@ -98,7 +98,7 @@ import CalendarModal from '../../common/CalendarModal.async';
import './Composer.scss'; import './Composer.scss';
type OwnProps = { type OwnProps = {
chatId: number; chatId: string;
threadId: number; threadId: number;
messageListType: MessageListType; messageListType: MessageListType;
dropAreaState: string; dropAreaState: string;
@ -123,8 +123,8 @@ type StateProps = {
canScheduleUntilOnline?: boolean; canScheduleUntilOnline?: boolean;
stickersForEmoji?: ApiSticker[]; stickersForEmoji?: ApiSticker[];
groupChatMembers?: ApiChatMember[]; groupChatMembers?: ApiChatMember[];
currentUserId?: number; currentUserId?: string;
usersById?: Record<number, ApiUser>; usersById?: Record<string, ApiUser>;
recentEmojis: string[]; recentEmojis: string[];
lastSyncTime?: number; lastSyncTime?: number;
contentToBeScheduled?: GlobalState['messages']['contentToBeScheduled']; contentToBeScheduled?: GlobalState['messages']['contentToBeScheduled'];
@ -132,7 +132,7 @@ type StateProps = {
baseEmojiKeywords?: Record<string, string[]>; baseEmojiKeywords?: Record<string, string[]>;
emojiKeywords?: Record<string, string[]>; emojiKeywords?: Record<string, string[]>;
serverTimeOffset: number; serverTimeOffset: number;
topInlineBotIds?: number[]; topInlineBotIds?: string[];
isInlineBotLoading: boolean; isInlineBotLoading: boolean;
inlineBots?: Record<string, false | InlineBotSettings>; inlineBots?: Record<string, false | InlineBotSettings>;
botCommands?: ApiBotCommand[] | false; botCommands?: ApiBotCommand[] | false;
@ -1069,7 +1069,7 @@ export default memo(withGlobal<OwnProps>(
isChatWithSelf, isChatWithSelf,
canScheduleUntilOnline: ( canScheduleUntilOnline: (
!isChatWithSelf && !isChatWithBot !isChatWithSelf && !isChatWithBot
&& (chat && chatUser && isChatPrivate(chatId) && chatUser.status && Boolean(chatUser.status.wasOnline)) && (chat && chatUser && isUserId(chatId) && chatUser.status && Boolean(chatUser.status.wasOnline))
), ),
isRightColumnShown: selectIsRightColumnShown(global), isRightColumnShown: selectIsRightColumnShown(global),
isSelectModeActive: selectIsInSelectMode(global), isSelectModeActive: selectIsInSelectMode(global),

View File

@ -23,7 +23,7 @@ import { pick } from '../../../util/iteratees';
import useAsyncRendering from '../../right/hooks/useAsyncRendering'; import useAsyncRendering from '../../right/hooks/useAsyncRendering';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { isChatPrivate } from '../../../modules/helpers'; import { isUserId } from '../../../modules/helpers';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import EmbeddedMessage from '../../common/EmbeddedMessage'; import EmbeddedMessage from '../../common/EmbeddedMessage';
@ -154,7 +154,7 @@ export default memo(withGlobal(
sender = selectSender(global, message); sender = selectSender(global, message);
} }
} else if (isForwarding) { } else if (isForwarding) {
sender = isChatPrivate(fromChatId!) ? selectUser(global, fromChatId!) : selectChat(global, fromChatId!); sender = isUserId(fromChatId!) ? selectUser(global, fromChatId!) : selectChat(global, fromChatId!);
} }
return { return {

View File

@ -32,7 +32,7 @@ const runThrottled = throttle((cb) => cb(), 500, true);
export type OwnProps = { export type OwnProps = {
isOpen: boolean; isOpen: boolean;
botId?: number; botId?: string;
isGallery?: boolean; isGallery?: boolean;
allowedAttachmentOptions: IAllowedAttachmentOptions; allowedAttachmentOptions: IAllowedAttachmentOptions;
inlineBotResults?: (ApiBotInlineResult | ApiBotInlineMediaResult)[]; inlineBotResults?: (ApiBotInlineResult | ApiBotInlineMediaResult)[];

View File

@ -20,7 +20,7 @@ export type OwnProps = {
onClose: () => void; onClose: () => void;
onInsertUserName: (user: ApiUser, forceFocus?: boolean) => void; onInsertUserName: (user: ApiUser, forceFocus?: boolean) => void;
filteredUsers?: ApiUser[]; filteredUsers?: ApiUser[];
usersById?: Record<number, ApiUser>; usersById?: Record<string, ApiUser>;
}; };
const MentionTooltip: FC<OwnProps> = ({ const MentionTooltip: FC<OwnProps> = ({
@ -34,7 +34,7 @@ const MentionTooltip: FC<OwnProps> = ({
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false); const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
const handleUserSelect = useCallback((userId: number, forceFocus = false) => { const handleUserSelect = useCallback((userId: string, forceFocus = false) => {
const user = usersById?.[userId]; const user = usersById?.[userId];
if (!user) { if (!user) {
return; return;

View File

@ -47,7 +47,7 @@ type OwnProps = {
}; };
type StateProps = { type StateProps = {
currentChatId?: number; currentChatId?: string;
replyingToId?: number; replyingToId?: number;
noTabCapture?: boolean; noTabCapture?: boolean;
messageSendKeyCombo?: ISettings['messageSendKeyCombo']; messageSendKeyCombo?: ISettings['messageSendKeyCombo'];

View File

@ -22,7 +22,7 @@ import Button from '../../ui/Button';
import './WebPagePreview.scss'; import './WebPagePreview.scss';
type OwnProps = { type OwnProps = {
chatId: number; chatId: string;
threadId: number; threadId: number;
messageText: string; messageText: string;
disabled?: boolean; disabled?: boolean;

View File

@ -14,12 +14,12 @@ import useBeforeUnload from '../../../../hooks/useBeforeUnload';
import { IS_TOUCH_ENV } from '../../../../util/environment'; import { IS_TOUCH_ENV } from '../../../../util/environment';
// Used to avoid running debounced callbacks when chat changes. // Used to avoid running debounced callbacks when chat changes.
let currentChatId: number | undefined; let currentChatId: string | undefined;
let currentThreadId: number | undefined; let currentThreadId: number | undefined;
export default ( export default (
draft: ApiFormattedText | undefined, draft: ApiFormattedText | undefined,
chatId: number, chatId: string,
threadId: number, threadId: number,
html: string, html: string,
htmlRef: { current: string }, htmlRef: { current: string },
@ -28,7 +28,7 @@ export default (
saveDraft: GlobalActions['saveDraft'], saveDraft: GlobalActions['saveDraft'],
clearDraft: GlobalActions['clearDraft'], clearDraft: GlobalActions['clearDraft'],
) => { ) => {
const updateDraft = useCallback((draftChatId: number, draftThreadId: number) => { const updateDraft = useCallback((draftChatId: string, draftThreadId: number) => {
if (htmlRef.current.length && !editedMessage) { if (htmlRef.current.length && !editedMessage) {
saveDraft({ chatId: draftChatId, threadId: draftThreadId, draft: parseMessageInput(htmlRef.current!) }); saveDraft({ chatId: draftChatId, threadId: draftThreadId, draft: parseMessageInput(htmlRef.current!) });
} else { } else {

View File

@ -10,7 +10,7 @@ const HAS_NEW_LINE = /^@([a-z0-9_]{1,32})[\u00A0\u0020]+\n{2,}/i;
export default function useInlineBotTooltip( export default function useInlineBotTooltip(
isAllowed: boolean, isAllowed: boolean,
chatId: number, chatId: string,
html: string, html: string,
inlineBots?: Record<string, false | InlineBotSettings>, inlineBots?: Record<string, false | InlineBotSettings>,
) { ) {

View File

@ -28,9 +28,9 @@ export default function useMentionTooltip(
onUpdateHtml: (html: string) => void, onUpdateHtml: (html: string) => void,
inputId: string = EDITABLE_INPUT_ID, inputId: string = EDITABLE_INPUT_ID,
groupChatMembers?: ApiChatMember[], groupChatMembers?: ApiChatMember[],
topInlineBotIds?: number[], topInlineBotIds?: string[],
currentUserId?: number, currentUserId?: string,
usersById?: Record<number, ApiUser>, usersById?: Record<string, ApiUser>,
) { ) {
const [isOpen, markIsOpen, unmarkIsOpen] = useFlag(); const [isOpen, markIsOpen, unmarkIsOpen] = useFlag();
const [usersToMention, setUsersToMention] = useState<ApiUser[] | undefined>(); const [usersToMention, setUsersToMention] = useState<ApiUser[] | undefined>();

Some files were not shown because too many files have changed in this diff Show More