[Refactoring] Remove big-integer library (#6294)
This commit is contained in:
parent
8ab7da8c8a
commit
1be16bf765
10
package-lock.json
generated
10
package-lock.json
generated
@ -16,7 +16,7 @@
|
||||
"@tauri-apps/plugin-shell": "^2.3.1",
|
||||
"@tauri-apps/plugin-updater": "^2.9.0",
|
||||
"async-mutex": "^0.5.0",
|
||||
"big-integer": "github:painor/BigInteger.js",
|
||||
"browserslist-config-baseline": "^0.5.0",
|
||||
"emoji-data-ios": "git+https://github.com/korenskoy/emoji-data-ios#443f1c9d7b16a82e7ee53f7f226d7d9a9920a105",
|
||||
"idb-keyval": "^6.2.2",
|
||||
"lowlight": "^3.3.0",
|
||||
@ -7330,14 +7330,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/big-integer": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "git+ssh://git@github.com/painor/BigInteger.js.git#4e2a4f1c1e4bd1d7c5d65e08aab51ac9ec939601",
|
||||
"license": "Unlicense",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
|
||||
@ -132,7 +132,7 @@
|
||||
"@tauri-apps/plugin-shell": "^2.3.1",
|
||||
"@tauri-apps/plugin-updater": "^2.9.0",
|
||||
"async-mutex": "^0.5.0",
|
||||
"big-integer": "github:painor/BigInteger.js",
|
||||
"browserslist-config-baseline": "^0.5.0",
|
||||
"emoji-data-ios": "git+https://github.com/korenskoy/emoji-data-ios#443f1c9d7b16a82e7ee53f7f226d7d9a9920a105",
|
||||
"idb-keyval": "^6.2.2",
|
||||
"lowlight": "^3.3.0",
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type { ApiAppConfig, ApiLimitType, ApiPremiumSection } from '../../types';
|
||||
@ -131,7 +130,7 @@ function buildEmojiSounds(appConfig: GramJsAppConfig) {
|
||||
dcId: 1,
|
||||
mimeType: 'audio/ogg',
|
||||
fileReference: Buffer.alloc(0),
|
||||
size: BigInt(0),
|
||||
size: 0n,
|
||||
} as GramJs.Document);
|
||||
|
||||
acc[key] = l.id;
|
||||
|
||||
@ -24,6 +24,7 @@ import type {
|
||||
|
||||
import { numberToHexColor } from '../../../util/colors';
|
||||
import { pick } from '../../../util/iteratees';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { addDocumentToLocalDb } from '../helpers/localDb';
|
||||
import { serializeBytes } from '../helpers/misc';
|
||||
import { buildApiMessageEntity, buildApiPhoto } from './common';
|
||||
@ -252,7 +253,7 @@ export function buildBotInlineMessage(
|
||||
description: sendMessage.description,
|
||||
photo: buildApiWebDocument(sendMessage.photo),
|
||||
currency: sendMessage.currency,
|
||||
amount: sendMessage.totalAmount.toJSNumber(),
|
||||
amount: toJSNumber(sendMessage.totalAmount),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ import type {
|
||||
} from '../../types';
|
||||
|
||||
import { pickTruthy } from '../../../util/iteratees';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { getServerTimeOffset } from '../../../util/serverTime';
|
||||
import { addPhotoToLocalDb, addUserToLocalDb } from '../helpers/localDb';
|
||||
import { serializeBytes } from '../helpers/misc';
|
||||
@ -113,7 +114,8 @@ function buildApiChatFieldsFromPeerEntity(
|
||||
isJoinRequest: channel?.joinRequest,
|
||||
isForum: channel?.forum,
|
||||
isMonoforum: channel?.monoforum,
|
||||
linkedMonoforumId: channel?.linkedMonoforumId && buildApiPeerId(channel.linkedMonoforumId, 'channel'),
|
||||
linkedMonoforumId: channel?.linkedMonoforumId !== undefined
|
||||
? buildApiPeerId(channel.linkedMonoforumId, 'channel') : undefined,
|
||||
areChannelMessagesAllowed: channel?.broadcastMessagesAllowed,
|
||||
areStoriesHidden,
|
||||
maxStoryId,
|
||||
@ -123,7 +125,7 @@ function buildApiChatFieldsFromPeerEntity(
|
||||
botVerificationIconId,
|
||||
hasGeo: channel?.hasGeo,
|
||||
subscriptionUntil: channel?.subscriptionUntilDate,
|
||||
paidMessagesStars: paidMessagesStars?.toJSNumber(),
|
||||
paidMessagesStars: toJSNumber(paidMessagesStars),
|
||||
level: channel?.level,
|
||||
hasAutoTranslation: channel?.autotranslation,
|
||||
withForumTabs: channel?.forumTabs,
|
||||
@ -713,7 +715,7 @@ export function buildApiStarsSubscriptionPricing(
|
||||
): ApiStarsSubscriptionPricing {
|
||||
return {
|
||||
period: pricing.period,
|
||||
amount: pricing.amount.toJSNumber(),
|
||||
amount: toJSNumber(pricing.amount),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import bigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type {
|
||||
@ -14,6 +13,7 @@ import type {
|
||||
} from '../../types';
|
||||
|
||||
import { numberToHexColor } from '../../../util/colors';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
||||
import { addDocumentToLocalDb } from '../helpers/localDb';
|
||||
import { buildApiFormattedText } from './common';
|
||||
@ -47,7 +47,7 @@ export function buildApiStarGift(starGift: GramJs.TypeStarGift): ApiStarGift {
|
||||
requirePremium,
|
||||
resaleTonOnly,
|
||||
valueCurrency,
|
||||
valueAmount: valueAmount?.toJSNumber(),
|
||||
valueAmount: toJSNumber(valueAmount),
|
||||
regularGiftId: giftId.toString(),
|
||||
};
|
||||
}
|
||||
@ -67,19 +67,19 @@ export function buildApiStarGift(starGift: GramJs.TypeStarGift): ApiStarGift {
|
||||
id: id.toString(),
|
||||
isLimited: limited,
|
||||
sticker,
|
||||
stars: stars.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
availabilityRemains,
|
||||
availabilityTotal,
|
||||
starsToConvert: convertStars.toJSNumber(),
|
||||
starsToConvert: toJSNumber(convertStars),
|
||||
firstSaleDate,
|
||||
lastSaleDate,
|
||||
isSoldOut: soldOut,
|
||||
isBirthday: birthday,
|
||||
upgradeStars: upgradeStars?.toJSNumber(),
|
||||
upgradeStars: upgradeStars !== undefined ? toJSNumber(upgradeStars) : undefined,
|
||||
title,
|
||||
resellMinStars: resellMinStars?.toJSNumber(),
|
||||
resellMinStars: resellMinStars !== undefined ? toJSNumber(resellMinStars) : undefined,
|
||||
releasedByPeerId: releasedBy && getApiChatIdFromMtpPeer(releasedBy),
|
||||
availabilityResale: availabilityResale?.toJSNumber(),
|
||||
availabilityResale: availabilityResale !== undefined ? toJSNumber(availabilityResale) : undefined,
|
||||
requirePremium,
|
||||
limitedPerUser,
|
||||
perUserTotal,
|
||||
@ -168,15 +168,15 @@ export function buildApiSavedStarGift(userStarGift: GramJs.SavedStarGift, peerId
|
||||
return {
|
||||
gift: buildApiStarGift(gift),
|
||||
date,
|
||||
starsToConvert: convertStars?.toJSNumber(),
|
||||
starsToConvert: toJSNumber(convertStars),
|
||||
fromId: fromId && getApiChatIdFromMtpPeer(fromId),
|
||||
message: message && buildApiFormattedText(message),
|
||||
messageId: msgId,
|
||||
isNameHidden: nameHidden,
|
||||
isUnsaved: unsaved,
|
||||
canUpgrade,
|
||||
alreadyPaidUpgradeStars: upgradeStars?.toJSNumber(),
|
||||
transferStars: transferStars?.toJSNumber(),
|
||||
alreadyPaidUpgradeStars: toJSNumber(upgradeStars),
|
||||
transferStars: toJSNumber(transferStars),
|
||||
inputGift,
|
||||
savedId: savedId?.toString(),
|
||||
canExportAt,
|
||||
@ -279,16 +279,19 @@ GramJs.TypeStarGiftAttributeId[] {
|
||||
return attributes.map((attr) => {
|
||||
switch (attr.type) {
|
||||
case 'model':
|
||||
return new GramJs.StarGiftAttributeIdModel({ documentId: bigInt(attr.documentId) });
|
||||
return new GramJs.StarGiftAttributeIdModel({ documentId: BigInt(attr.documentId) });
|
||||
|
||||
case 'pattern':
|
||||
return new GramJs.StarGiftAttributeIdPattern({ documentId: bigInt(attr.documentId) });
|
||||
return new GramJs.StarGiftAttributeIdPattern({ documentId: BigInt(attr.documentId) });
|
||||
|
||||
case 'backdrop':
|
||||
return new GramJs.StarGiftAttributeIdBackdrop({ backdropId: attr.backdropId });
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown attribute type: ${(attr as any).type}`);
|
||||
default: {
|
||||
// Exhaustive check
|
||||
const _exhaustive: never = attr;
|
||||
return _exhaustive;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import type { ApiPhoneCallDiscardReason } from '../../types';
|
||||
import type { ApiMessageAction } from '../../types/messageActions';
|
||||
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { buildApiBotApp } from './bots';
|
||||
import { buildApiFormattedText, buildApiPhoto } from './common';
|
||||
import { buildApiStarGift } from './gifts';
|
||||
@ -128,7 +129,7 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
isRecurringInit: recurringInit,
|
||||
isRecurringUsed: recurringUsed,
|
||||
currency,
|
||||
totalAmount: totalAmount.toJSNumber(),
|
||||
totalAmount: toJSNumber(totalAmount),
|
||||
invoiceSlug,
|
||||
subscriptionUntilDate,
|
||||
};
|
||||
@ -254,10 +255,10 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
mediaType: 'action',
|
||||
type: 'giftPremium',
|
||||
currency,
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
months,
|
||||
cryptoCurrency,
|
||||
cryptoAmount: cryptoAmount?.toJSNumber(),
|
||||
cryptoAmount: toJSNumber(cryptoAmount),
|
||||
message: message && buildApiFormattedText(message),
|
||||
};
|
||||
}
|
||||
@ -308,9 +309,9 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
months,
|
||||
slug,
|
||||
currency,
|
||||
amount: amount?.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
cryptoCurrency,
|
||||
cryptoAmount: cryptoAmount?.toJSNumber(),
|
||||
cryptoAmount: toJSNumber(cryptoAmount),
|
||||
message: message && buildApiFormattedText(message),
|
||||
};
|
||||
}
|
||||
@ -319,7 +320,7 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
return {
|
||||
mediaType: 'action',
|
||||
type: 'giveawayLaunch',
|
||||
stars: stars?.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
};
|
||||
}
|
||||
if (action instanceof GramJs.MessageActionGiveawayResults) {
|
||||
@ -341,7 +342,7 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
type: 'paymentRefunded',
|
||||
peerId: getApiChatIdFromMtpPeer(peer),
|
||||
currency,
|
||||
totalAmount: totalAmount.toJSNumber(),
|
||||
totalAmount: toJSNumber(totalAmount),
|
||||
};
|
||||
}
|
||||
if (action instanceof GramJs.MessageActionGiftStars) {
|
||||
@ -352,10 +353,10 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
mediaType: 'action',
|
||||
type: 'giftStars',
|
||||
currency,
|
||||
amount: amount.toJSNumber(),
|
||||
stars: stars.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
stars: toJSNumber(stars),
|
||||
cryptoCurrency,
|
||||
cryptoAmount: cryptoAmount?.toJSNumber(),
|
||||
cryptoAmount: toJSNumber(cryptoAmount),
|
||||
transactionId,
|
||||
};
|
||||
}
|
||||
@ -367,9 +368,9 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
mediaType: 'action',
|
||||
type: 'giftTon',
|
||||
currency,
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
cryptoCurrency,
|
||||
cryptoAmount: cryptoAmount.toJSNumber(),
|
||||
cryptoAmount: toJSNumber(cryptoAmount),
|
||||
transactionId,
|
||||
};
|
||||
}
|
||||
@ -381,7 +382,7 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
mediaType: 'action',
|
||||
type: 'prizeStars',
|
||||
isUnclaimed: unclaimed,
|
||||
stars: stars.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
transactionId,
|
||||
boostPeerId: getApiChatIdFromMtpPeer(boostPeer),
|
||||
giveawayMsgId,
|
||||
@ -407,12 +408,12 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
canUpgrade,
|
||||
gift: starGift,
|
||||
message: message && buildApiFormattedText(message),
|
||||
starsToConvert: convertStars?.toJSNumber(),
|
||||
starsToConvert: toJSNumber(convertStars),
|
||||
upgradeMsgId,
|
||||
alreadyPaidUpgradeStars: upgradeStars?.toJSNumber(),
|
||||
alreadyPaidUpgradeStars: toJSNumber(upgradeStars),
|
||||
fromId: fromId && getApiChatIdFromMtpPeer(fromId),
|
||||
peerId: peer && getApiChatIdFromMtpPeer(peer),
|
||||
savedId: savedId && buildApiPeerId(savedId, 'user'),
|
||||
savedId: savedId !== undefined ? buildApiPeerId(savedId, 'user') : undefined,
|
||||
};
|
||||
}
|
||||
if (action instanceof GramJs.MessageActionStarGiftUnique) {
|
||||
@ -433,10 +434,10 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
isRefunded: refunded,
|
||||
gift: starGift,
|
||||
canExportAt,
|
||||
transferStars: transferStars?.toJSNumber(),
|
||||
transferStars: toJSNumber(transferStars),
|
||||
fromId: fromId && getApiChatIdFromMtpPeer(fromId),
|
||||
peerId: peer && getApiChatIdFromMtpPeer(peer),
|
||||
savedId: savedId && buildApiPeerId(savedId, 'user'),
|
||||
savedId: savedId !== undefined ? buildApiPeerId(savedId, 'user') : undefined,
|
||||
resaleAmount: resaleAmount ? buildApiCurrencyAmount(resaleAmount) : undefined,
|
||||
};
|
||||
}
|
||||
@ -448,7 +449,7 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
mediaType: 'action',
|
||||
type: 'paidMessagesPrice',
|
||||
isAllowedInChannel: broadcastMessagesAllowed,
|
||||
stars: stars.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
};
|
||||
}
|
||||
if (action instanceof GramJs.MessageActionPaidMessagesRefunded) {
|
||||
@ -458,7 +459,7 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
return {
|
||||
mediaType: 'action',
|
||||
type: 'paidMessagesRefunded',
|
||||
stars: stars.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
count,
|
||||
};
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ import { SUPPORTED_PHOTO_CONTENT_TYPES, SUPPORTED_VIDEO_CONTENT_TYPES, VIDEO_WEB
|
||||
import { addTimestampEntities } from '../../../util/dates/timestamp';
|
||||
import { generateWaveform } from '../../../util/generateWaveform';
|
||||
import { pick } from '../../../util/iteratees';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import {
|
||||
addMediaToLocalDb, addStoryToLocalDb, addWebPageMediaToLocalDb, type MediaRepairContext,
|
||||
} from '../helpers/localDb';
|
||||
@ -260,7 +261,7 @@ export function buildVideoFromDocument(document: GramJs.Document, params?: {
|
||||
isRound,
|
||||
isGif: Boolean(gifAttr),
|
||||
thumbnail: buildApiThumbnailFromStripped(thumbs),
|
||||
size: size.toJSNumber(),
|
||||
size: toJSNumber(size),
|
||||
isSpoiler,
|
||||
timestamp,
|
||||
hasVideoPreview,
|
||||
@ -300,7 +301,7 @@ export function buildAudioFromDocument(document: GramJs.Document): ApiAudio | un
|
||||
fileName: getFilenameFromDocument(document, 'audio'),
|
||||
title,
|
||||
performer,
|
||||
size: size.toJSNumber(),
|
||||
size: toJSNumber(size),
|
||||
};
|
||||
}
|
||||
|
||||
@ -359,7 +360,7 @@ function buildAudio(media: GramJs.TypeMessageMedia): ApiAudio | undefined {
|
||||
id: String(media.document.id),
|
||||
fileName: getFilenameFromDocument(media.document, 'audio'),
|
||||
thumbnailSizes,
|
||||
size: media.document.size.toJSNumber(),
|
||||
size: toJSNumber(media.document.size),
|
||||
...pick(media.document, ['mimeType']),
|
||||
...pick(audioAttribute, ['duration', 'performer', 'title']),
|
||||
};
|
||||
@ -402,7 +403,7 @@ function buildVoice(media: GramJs.TypeMessageMedia): ApiVoice | undefined {
|
||||
return {
|
||||
mediaType: 'voice',
|
||||
id: String(media.document.id),
|
||||
size: media.document.size.toJSNumber(),
|
||||
size: toJSNumber(media.document.size),
|
||||
duration,
|
||||
waveform: waveform ? Array.from(waveform) : undefined,
|
||||
};
|
||||
@ -475,7 +476,7 @@ export function buildApiDocument(document: GramJs.TypeDocument): ApiDocument | u
|
||||
return {
|
||||
mediaType: 'document',
|
||||
id: String(id),
|
||||
size: size.toJSNumber(),
|
||||
size: toJSNumber(size),
|
||||
mimeType,
|
||||
timestamp: date,
|
||||
fileName: getFilenameFromDocument(document),
|
||||
@ -644,7 +645,7 @@ function buildGiveaway(media: GramJs.MessageMediaGiveaway): ApiGiveaway | undefi
|
||||
mediaType: 'giveaway',
|
||||
channelIds,
|
||||
months,
|
||||
stars: stars?.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
quantity,
|
||||
untilDate,
|
||||
countries: countriesIso2,
|
||||
@ -770,7 +771,7 @@ export function buildMediaInvoice(media: GramJs.MessageMediaInvoice): ApiMediaIn
|
||||
description,
|
||||
photo: buildApiWebDocument(photo),
|
||||
receiptMessageId: receiptMsgId,
|
||||
amount: totalAmount.toJSNumber(),
|
||||
amount: toJSNumber(totalAmount),
|
||||
currency,
|
||||
isTest: test,
|
||||
extendedMedia: preview,
|
||||
@ -932,7 +933,7 @@ function buildPaidMedia(media: GramJs.TypeMessageMedia): ApiPaidMedia | undefine
|
||||
if (isBought) {
|
||||
return {
|
||||
mediaType: 'paidMedia',
|
||||
starsAmount: starsAmount.toJSNumber(),
|
||||
starsAmount: toJSNumber(starsAmount),
|
||||
isBought,
|
||||
extendedMedia: buildBoughtMediaContent(extendedMedia)!,
|
||||
};
|
||||
@ -940,7 +941,7 @@ function buildPaidMedia(media: GramJs.TypeMessageMedia): ApiPaidMedia | undefine
|
||||
|
||||
return {
|
||||
mediaType: 'paidMedia',
|
||||
starsAmount: starsAmount.toJSNumber(),
|
||||
starsAmount: toJSNumber(starsAmount),
|
||||
extendedMedia: extendedMedia
|
||||
.filter((paidMedia): paidMedia is GramJs.MessageExtendedMediaPreview => (
|
||||
paidMedia instanceof GramJs.MessageExtendedMediaPreview
|
||||
|
||||
@ -45,6 +45,7 @@ import {
|
||||
import { getEmojiOnlyCountForMessage } from '../../../global/helpers/getEmojiOnlyCountForMessage';
|
||||
import { addTimestampEntities } from '../../../util/dates/timestamp';
|
||||
import { omitUndefined, pick } from '../../../util/iteratees';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { getServerTime, getServerTimeOffset } from '../../../util/serverTime';
|
||||
import { interpolateArray } from '../../../util/waveform';
|
||||
import {
|
||||
@ -218,7 +219,7 @@ export function buildApiMessageWithChatId(
|
||||
mtpMessage.media instanceof GramJs.MessageMediaInvoice ? mtpMessage.media.receiptMsgId : undefined,
|
||||
) || {};
|
||||
const { mediaUnread: isMediaUnread, postAuthor } = mtpMessage;
|
||||
const groupedId = mtpMessage.groupedId && String(mtpMessage.groupedId);
|
||||
const groupedId = mtpMessage.groupedId !== undefined ? String(mtpMessage.groupedId) : undefined;
|
||||
const isInAlbum = Boolean(groupedId) && !(content.document || content.audio || content.sticker);
|
||||
const shouldHideKeyboardButtons = mtpMessage.replyMarkup instanceof GramJs.ReplyKeyboardHide;
|
||||
const isHideKeyboardSelective = mtpMessage.replyMarkup instanceof GramJs.ReplyKeyboardHide
|
||||
@ -285,7 +286,7 @@ export function buildApiMessageWithChatId(
|
||||
isInvertedMedia,
|
||||
isVideoProcessingPending,
|
||||
reportDeliveryUntilDate: mtpMessage.reportDeliveryUntilDate,
|
||||
paidMessageStars: mtpMessage.paidMessageStars?.toJSNumber(),
|
||||
paidMessageStars: toJSNumber(mtpMessage.paidMessageStars),
|
||||
restrictionReasons,
|
||||
};
|
||||
}
|
||||
@ -835,6 +836,6 @@ export function buildApiSearchPostsFlood(
|
||||
totalDaily: searchFlood.totalDaily,
|
||||
remains: searchFlood.remains,
|
||||
waitTill: searchFlood.waitTill,
|
||||
starsAmount: searchFlood.starsAmount.toJSNumber(),
|
||||
starsAmount: toJSNumber(searchFlood.starsAmount),
|
||||
};
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import { numberToHexColor } from '../../../util/colors';
|
||||
import {
|
||||
buildCollectionByCallback, omit, omitUndefined, pick,
|
||||
} from '../../../util/iteratees';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { addUserToLocalDb } from '../helpers/localDb';
|
||||
import { omitVirtualClassFields } from './helpers';
|
||||
import { buildApiDocument, buildMessageTextContent } from './messageContent';
|
||||
@ -362,9 +363,9 @@ export function buildApiCollectibleInfo(info: GramJs.fragment.TypeCollectibleInf
|
||||
} = info;
|
||||
|
||||
return {
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
currency,
|
||||
cryptoAmount: cryptoAmount.toJSNumber(),
|
||||
cryptoAmount: toJSNumber(cryptoAmount),
|
||||
cryptoCurrency,
|
||||
purchaseDate,
|
||||
url,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import bigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type {
|
||||
@ -31,6 +30,7 @@ import type {
|
||||
} from '../../types';
|
||||
|
||||
import { STARS_CURRENCY_CODE, TON_CURRENCY_CODE } from '../../../config';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { addWebDocumentToLocalDb } from '../helpers/localDb';
|
||||
import { buildApiStarsSubscriptionPricing } from './chats';
|
||||
import { buildApiMessageEntity } from './common';
|
||||
@ -45,15 +45,16 @@ export function buildShippingOptions(shippingOptions: GramJs.ShippingOption[] |
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Object.values(shippingOptions).map((option) => {
|
||||
return shippingOptions.map((option) => {
|
||||
return {
|
||||
id: option.id,
|
||||
title: option.title,
|
||||
amount: option.prices.reduce((ac, cur) => ac + cur.amount.toJSNumber(), 0),
|
||||
|
||||
amount: option.prices.reduce((ac, cur) => ac + toJSNumber(cur.amount), 0),
|
||||
prices: option.prices.map(({ label, amount }) => {
|
||||
return {
|
||||
label,
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
};
|
||||
}),
|
||||
};
|
||||
@ -79,7 +80,7 @@ export function buildApiReceipt(receipt: GramJs.payments.TypePaymentReceipt): Ap
|
||||
botId: buildApiPeerId(botId, 'user'),
|
||||
description,
|
||||
title,
|
||||
totalAmount: -totalAmount.toJSNumber(),
|
||||
totalAmount: -toJSNumber(totalAmount),
|
||||
transactionId,
|
||||
photo: buildApiWebDocument(photo),
|
||||
invoice: buildApiInvoice(invoice),
|
||||
@ -110,7 +111,7 @@ export function buildApiReceipt(receipt: GramJs.payments.TypePaymentReceipt): Ap
|
||||
shippingPrices = shipping.prices.map(({ label, amount }) => {
|
||||
return {
|
||||
label,
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
};
|
||||
});
|
||||
shippingMethod = shipping.title;
|
||||
@ -119,13 +120,13 @@ export function buildApiReceipt(receipt: GramJs.payments.TypePaymentReceipt): Ap
|
||||
return {
|
||||
type: 'regular',
|
||||
info: { shippingAddress, phone, name },
|
||||
totalAmount: totalAmount.toJSNumber(),
|
||||
totalAmount: toJSNumber(totalAmount),
|
||||
currency,
|
||||
date,
|
||||
credentialsTitle,
|
||||
shippingPrices,
|
||||
shippingMethod,
|
||||
tipAmount: tipAmount ? tipAmount.toJSNumber() : 0,
|
||||
tipAmount: toJSNumber(tipAmount) || 0,
|
||||
title,
|
||||
description,
|
||||
botId: buildApiPeerId(botId, 'user'),
|
||||
@ -240,10 +241,10 @@ export function buildApiInvoice(invoice: GramJs.Invoice): ApiInvoice {
|
||||
|
||||
const mappedPrices: ApiLabeledPrice[] = prices.map(({ label, amount }) => ({
|
||||
label,
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
}));
|
||||
|
||||
const totalAmount = prices.reduce((acc, cur) => acc.add(cur.amount), bigInt(0)).toJSNumber();
|
||||
const totalAmount = prices.reduce((acc, cur) => acc + toJSNumber(cur.amount), 0);
|
||||
|
||||
return {
|
||||
totalAmount,
|
||||
@ -252,8 +253,8 @@ export function buildApiInvoice(invoice: GramJs.Invoice): ApiInvoice {
|
||||
isRecurring: recurring,
|
||||
termsUrl,
|
||||
prices: mappedPrices,
|
||||
maxTipAmount: maxTipAmount?.toJSNumber(),
|
||||
suggestedTipAmounts: suggestedTipAmounts?.map((tip) => tip.toJSNumber()),
|
||||
maxTipAmount: toJSNumber(maxTipAmount),
|
||||
suggestedTipAmounts: suggestedTipAmounts?.map((tip) => toJSNumber(tip)),
|
||||
isEmailRequested: emailRequested,
|
||||
isEmailSentToProvider: emailToProvider,
|
||||
isNameRequested: nameRequested,
|
||||
@ -288,7 +289,7 @@ function buildApiPremiumSubscriptionOption(option: GramJs.PremiumSubscriptionOpt
|
||||
isCurrent: current,
|
||||
canPurchaseUpgrade,
|
||||
currency,
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
botUrl,
|
||||
months,
|
||||
};
|
||||
@ -314,7 +315,7 @@ export function buildPrepaidGiveaway(
|
||||
return {
|
||||
type: 'starsGiveaway',
|
||||
id: interaction.id.toString(),
|
||||
stars: interaction.stars.toJSNumber(),
|
||||
stars: toJSNumber(interaction.stars),
|
||||
quantity: interaction.quantity,
|
||||
boosts: interaction.boosts,
|
||||
date: interaction.date,
|
||||
@ -336,8 +337,8 @@ export function buildApiBoostsStatus(boostStatus: GramJs.premium.BoostsStatus):
|
||||
boostUrl,
|
||||
giftBoosts,
|
||||
nextLevelBoosts,
|
||||
...(premiumAudience && { premiumSubscribers: buildStatisticsPercentage(premiumAudience) }),
|
||||
...(prepaidGiveaways && { prepaidGiveaways: prepaidGiveaways.map((m) => buildPrepaidGiveaway(m)) }),
|
||||
premiumSubscribers: premiumAudience && buildStatisticsPercentage(premiumAudience),
|
||||
prepaidGiveaways: prepaidGiveaways?.map((m) => buildPrepaidGiveaway(m)),
|
||||
};
|
||||
}
|
||||
|
||||
@ -352,12 +353,12 @@ export function buildApiBoost(boost: GramJs.Boost): ApiBoost {
|
||||
} = boost;
|
||||
|
||||
return {
|
||||
userId: userId && buildApiPeerId(userId, 'user'),
|
||||
userId: userId !== undefined ? buildApiPeerId(userId, 'user') : undefined,
|
||||
multiplier,
|
||||
expires,
|
||||
isFromGiveaway: giveaway,
|
||||
isGift: gift,
|
||||
stars: stars?.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
};
|
||||
}
|
||||
|
||||
@ -390,7 +391,8 @@ export function buildApiGiveawayInfo(info: GramJs.payments.TypeGiveawayInfo): Ap
|
||||
type: 'active',
|
||||
startDate,
|
||||
isParticipating: participating,
|
||||
adminDisallowedChatId: adminDisallowedChatId && buildApiPeerId(adminDisallowedChatId, 'channel'),
|
||||
adminDisallowedChatId: adminDisallowedChatId !== undefined
|
||||
? buildApiPeerId(adminDisallowedChatId, 'channel') : undefined,
|
||||
disallowedCountry,
|
||||
joinedTooEarlyDate,
|
||||
isPreparingResults: preparingResults,
|
||||
@ -416,7 +418,7 @@ export function buildApiGiveawayInfo(info: GramJs.payments.TypeGiveawayInfo): Ap
|
||||
giftCodeSlug,
|
||||
isRefunded: refunded,
|
||||
isWinner: winner,
|
||||
starsPrize: starsPrize?.toJSNumber(),
|
||||
starsPrize: toJSNumber(starsPrize),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -429,7 +431,7 @@ export function buildApiCheckedGiftCode(giftcode: GramJs.payments.TypeCheckedGif
|
||||
return {
|
||||
date,
|
||||
months,
|
||||
toId: toId && buildApiPeerId(toId, 'user'),
|
||||
toId: toId !== undefined ? buildApiPeerId(toId, 'user') : undefined,
|
||||
fromId: fromId && getApiChatIdFromMtpPeer(fromId),
|
||||
usedAt: usedDate,
|
||||
isFromGiveaway: viaGiveaway,
|
||||
@ -443,7 +445,7 @@ export function buildApiPremiumGiftCodeOption(option: GramJs.PremiumGiftCodeOpti
|
||||
} = option;
|
||||
|
||||
return {
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
currency,
|
||||
months,
|
||||
users,
|
||||
@ -457,17 +459,17 @@ export function buildApiStarsGiftOptions(option: GramJs.StarsGiftOption): ApiSta
|
||||
|
||||
return {
|
||||
isExtended: extended,
|
||||
stars: stars.toJSNumber(),
|
||||
amount: amount.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
amount: toJSNumber(amount),
|
||||
currency,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildApiCurrencyAmount(amount: GramJs.TypeStarsAmount): ApiTypeCurrencyAmount | undefined {
|
||||
export function buildApiCurrencyAmount(amount: GramJs.TypeStarsAmount): ApiTypeCurrencyAmount {
|
||||
if (amount instanceof GramJs.StarsAmount) {
|
||||
return {
|
||||
currency: STARS_CURRENCY_CODE,
|
||||
amount: amount.amount.toJSNumber(),
|
||||
amount: toJSNumber(amount.amount),
|
||||
nanos: amount.nanos,
|
||||
};
|
||||
}
|
||||
@ -475,11 +477,12 @@ export function buildApiCurrencyAmount(amount: GramJs.TypeStarsAmount): ApiTypeC
|
||||
if (amount instanceof GramJs.StarsTonAmount) {
|
||||
return {
|
||||
currency: TON_CURRENCY_CODE,
|
||||
amount: amount.amount.toJSNumber(),
|
||||
amount: toJSNumber(amount.amount),
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
const _exhaustive: never = amount;
|
||||
return _exhaustive;
|
||||
}
|
||||
|
||||
export function buildApiStarsGiveawayWinnersOption(
|
||||
@ -492,7 +495,7 @@ export function buildApiStarsGiveawayWinnersOption(
|
||||
return {
|
||||
isDefault,
|
||||
users,
|
||||
perUserStars: perUserStars.toJSNumber(),
|
||||
perUserStars: toJSNumber(perUserStars),
|
||||
};
|
||||
}
|
||||
|
||||
@ -507,8 +510,8 @@ export function buildApiStarsGiveawayOptions(option: GramJs.StarsGiveawayOption)
|
||||
isExtended: extended,
|
||||
isDefault,
|
||||
yearlyBoosts,
|
||||
stars: stars.toJSNumber(),
|
||||
amount: amount.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
amount: toJSNumber(amount),
|
||||
currency,
|
||||
winners: winnerList,
|
||||
};
|
||||
@ -625,9 +628,9 @@ export function buildApiStarTopupOption(option: GramJs.TypeStarsTopupOption): Ap
|
||||
} = option;
|
||||
|
||||
return {
|
||||
amount: amount.toJSNumber(),
|
||||
amount: toJSNumber(amount),
|
||||
currency,
|
||||
stars: stars.toJSNumber(),
|
||||
stars: toJSNumber(stars),
|
||||
isExtended: extended,
|
||||
};
|
||||
}
|
||||
@ -644,14 +647,14 @@ export function buildApiUniqueStarGiftValueInfo(
|
||||
isLastSaleOnFragment: lastSaleOnFragment,
|
||||
isValueAverage: valueIsAverage,
|
||||
currency,
|
||||
value: value.toJSNumber(),
|
||||
value: toJSNumber(value),
|
||||
initialSaleDate,
|
||||
initialSaleStars: initialSaleStars.toJSNumber(),
|
||||
initialSalePrice: initialSalePrice.toJSNumber(),
|
||||
initialSaleStars: toJSNumber(initialSaleStars),
|
||||
initialSalePrice: toJSNumber(initialSalePrice),
|
||||
lastSaleDate,
|
||||
lastSalePrice: lastSalePrice?.toJSNumber(),
|
||||
floorPrice: floorPrice?.toJSNumber(),
|
||||
averagePrice: averagePrice?.toJSNumber(),
|
||||
lastSalePrice: toJSNumber(lastSalePrice),
|
||||
floorPrice: toJSNumber(floorPrice),
|
||||
averagePrice: toJSNumber(averagePrice),
|
||||
listedCount,
|
||||
fragmentListedCount,
|
||||
fragmentListedUrl,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import type BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type { ApiEmojiStatusType, ApiPeerColor } from '../../types';
|
||||
@ -20,16 +19,16 @@ export function isMtpPeerChannel(peer: TypePeerOrInput): peer is GramJs.PeerChan
|
||||
return peer.hasOwnProperty('channelId');
|
||||
}
|
||||
|
||||
export function buildApiPeerId(id: BigInt.BigInteger, type: 'user' | 'chat' | 'channel') {
|
||||
export function buildApiPeerId(id: bigint, type: 'user' | 'chat' | 'channel') {
|
||||
if (type === 'user') {
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
if (type === 'channel') {
|
||||
return id.add(CHANNEL_ID_BASE).negate().toString();
|
||||
return ((id + CHANNEL_ID_BASE) * -1n).toString();
|
||||
}
|
||||
|
||||
return id.negate().toString();
|
||||
return (id * -1n).toString();
|
||||
}
|
||||
|
||||
export function getApiChatIdFromMtpPeer(peer: TypePeerOrInput) {
|
||||
|
||||
@ -17,10 +17,9 @@ import type {
|
||||
} from '../../types';
|
||||
|
||||
import { buildApiUsernames, buildAvatarPhotoId } from './common';
|
||||
import { buildApiCurrencyAmount } from './payments';
|
||||
import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers';
|
||||
|
||||
const DECIMALS = 10 ** 9;
|
||||
|
||||
export function buildChannelStatistics(stats: GramJs.stats.BroadcastStats): ApiChannelStatistics {
|
||||
return {
|
||||
type: 'channel',
|
||||
@ -275,16 +274,16 @@ function buildApiMessagePublicForward(message: GramJs.TypeMessage, chats: GramJs
|
||||
};
|
||||
}
|
||||
|
||||
function buildChannelMonetizationBalances({
|
||||
currentBalance,
|
||||
availableBalance,
|
||||
overallRevenue,
|
||||
withdrawalEnabled,
|
||||
}: GramJs.StarsRevenueStatus): ChannelMonetizationBalances {
|
||||
function buildChannelMonetizationBalances(revenueStatus: GramJs.StarsRevenueStatus): ChannelMonetizationBalances {
|
||||
const currentBalance = buildApiCurrencyAmount(revenueStatus.currentBalance);
|
||||
const availableBalance = buildApiCurrencyAmount(revenueStatus.availableBalance);
|
||||
const overallRevenue = buildApiCurrencyAmount(revenueStatus.overallRevenue);
|
||||
const withdrawalEnabled = revenueStatus.withdrawalEnabled;
|
||||
|
||||
return {
|
||||
currentBalance: Number(currentBalance) / DECIMALS,
|
||||
availableBalance: Number(availableBalance) / DECIMALS,
|
||||
overallRevenue: Number(overallRevenue) / DECIMALS,
|
||||
currentBalance,
|
||||
availableBalance,
|
||||
overallRevenue,
|
||||
isWithdrawalEnabled: withdrawalEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet {
|
||||
const hasStaticThumb = thumbs?.some((thumb) => thumb.type === 's');
|
||||
const hasAnimatedThumb = thumbs?.some((thumb) => thumb.type === 'a');
|
||||
const hasVideoThumb = thumbs?.some((thumb) => thumb.type === 'v');
|
||||
const thumbCustomEmojiId = thumbDocumentId && String(thumbDocumentId);
|
||||
const thumbCustomEmojiId = thumbDocumentId !== undefined ? String(thumbDocumentId) : undefined;
|
||||
|
||||
const hasThumbnail = hasStaticThumb || hasAnimatedThumb || hasVideoThumb || Boolean(thumbCustomEmojiId);
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import type {
|
||||
ApiUserType,
|
||||
} from '../../types';
|
||||
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { buildApiBotInfo } from './bots';
|
||||
import { buildApiBusinessIntro, buildApiBusinessLocation, buildApiBusinessWorkHours } from './business';
|
||||
import {
|
||||
@ -54,7 +55,8 @@ export function buildApiUserFullInfo(mtpUserFull: GramJs.users.UserFull): ApiUse
|
||||
businessLocation: businessLocation && buildApiBusinessLocation(businessLocation),
|
||||
businessWorkHours: businessWorkHours && buildApiBusinessWorkHours(businessWorkHours),
|
||||
businessIntro: businessIntro && buildApiBusinessIntro(businessIntro),
|
||||
personalChannelId: personalChannelId && buildApiPeerId(personalChannelId, 'channel'),
|
||||
personalChannelId: personalChannelId !== undefined
|
||||
? buildApiPeerId(personalChannelId, 'channel') : undefined,
|
||||
personalChannelMessageId: personalChannelMessage,
|
||||
botVerification: botVerification && buildApiBotVerification(botVerification),
|
||||
areAdsEnabled: sponsoredEnabled,
|
||||
@ -64,7 +66,7 @@ export function buildApiUserFullInfo(mtpUserFull: GramJs.users.UserFull): ApiUse
|
||||
starsMyPendingRatingDate,
|
||||
isBotCanManageEmojiStatus: botCanManageEmojiStatus,
|
||||
hasScheduledMessages: hasScheduled,
|
||||
paidMessagesStars: sendPaidMessagesStars?.toJSNumber(),
|
||||
paidMessagesStars: toJSNumber(sendPaidMessagesStars),
|
||||
settings: buildApiPeerSettings(settings),
|
||||
};
|
||||
}
|
||||
@ -89,7 +91,7 @@ export function buildApiPeerSettings({
|
||||
phoneCountry,
|
||||
nameChangeDate,
|
||||
photoChangeDate,
|
||||
chargedPaidMessageStars: chargePaidMessageStars?.toJSNumber(),
|
||||
chargedPaidMessageStars: toJSNumber(chargePaidMessageStars),
|
||||
};
|
||||
}
|
||||
|
||||
@ -143,7 +145,7 @@ export function buildApiUser(mtpUser: GramJs.TypeUser): ApiUser | undefined {
|
||||
botVerificationIconId: botVerificationIcon?.toString(),
|
||||
color: mtpUser.color && buildApiPeerColor(mtpUser.color),
|
||||
profileColor: profileColor && buildApiPeerColor(profileColor),
|
||||
paidMessagesStars: sendPaidMessagesStars?.toJSNumber(),
|
||||
paidMessagesStars: toJSNumber(sendPaidMessagesStars),
|
||||
};
|
||||
}
|
||||
|
||||
@ -193,8 +195,8 @@ export function buildApiBirthday(birthday: GramJs.TypeBirthday): ApiBirthday {
|
||||
export function buildApiStarsRating(starsRating: GramJs.StarsRating): ApiStarsRating {
|
||||
return {
|
||||
level: starsRating.level,
|
||||
currentLevelStars: starsRating.currentLevelStars.toJSNumber(),
|
||||
stars: starsRating.stars.toJSNumber(),
|
||||
nextLevelStars: starsRating.nextLevelStars?.toJSNumber(),
|
||||
currentLevelStars: toJSNumber(starsRating.currentLevelStars),
|
||||
stars: toJSNumber(starsRating.stars),
|
||||
nextLevelStars: toJSNumber(starsRating.nextLevelStars),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import { generateRandomBytes, readBigIntFromBuffer } from '../../../lib/gramjs/Helpers';
|
||||
import { generateRandomBigInt, generateRandomBytes, readBigIntFromBuffer } from '../../../lib/gramjs/Helpers';
|
||||
|
||||
import type {
|
||||
ApiBotApp,
|
||||
@ -47,13 +46,13 @@ import localDb from '../localDb';
|
||||
|
||||
export const DEFAULT_PRIMITIVES = {
|
||||
INT: 0,
|
||||
BIGINT: BigInt(0),
|
||||
BIGINT: 0n,
|
||||
STRING: '',
|
||||
} as const;
|
||||
|
||||
export function getEntityTypeById(peerId: string) {
|
||||
const n = Number(peerId);
|
||||
if (n > 0) {
|
||||
const n = BigInt(peerId);
|
||||
if (n > 0n) {
|
||||
return 'user';
|
||||
}
|
||||
|
||||
@ -143,7 +142,7 @@ export function buildInputPaidReactionPrivacy(isPrivate?: boolean, peerId?: stri
|
||||
|
||||
export function buildInputPeerFromLocalDb(chatOrUserId: string): GramJs.TypeInputPeer | undefined {
|
||||
const type = getEntityTypeById(chatOrUserId);
|
||||
let accessHash: BigInt.BigInteger | undefined;
|
||||
let accessHash: bigint | undefined;
|
||||
|
||||
if (type === 'user') {
|
||||
accessHash = localDb.users[chatOrUserId]?.accessHash;
|
||||
@ -207,7 +206,7 @@ export function buildInputMediaDocument(media: ApiSticker | ApiVideo) {
|
||||
return new GramJs.InputMediaDocument({ id: inputDocument });
|
||||
}
|
||||
|
||||
export function buildInputPoll(pollParams: ApiNewPoll, randomId: BigInt.BigInteger) {
|
||||
export function buildInputPoll(pollParams: ApiNewPoll, randomId: bigint) {
|
||||
const { summary, quiz } = pollParams;
|
||||
|
||||
const poll = new GramJs.Poll({
|
||||
@ -359,10 +358,6 @@ export function buildInputStory(story: ApiStory | ApiStorySkipped) {
|
||||
});
|
||||
}
|
||||
|
||||
export function generateRandomBigInt() {
|
||||
return readBigIntFromBuffer(generateRandomBytes(8), true, true);
|
||||
}
|
||||
|
||||
export function generateRandomTimestampedBigInt() {
|
||||
// 32 bits for timestamp, 32 bits are random
|
||||
const buffer = generateRandomBytes(8);
|
||||
@ -372,10 +367,6 @@ export function generateRandomTimestampedBigInt() {
|
||||
return readBigIntFromBuffer(buffer, true, true);
|
||||
}
|
||||
|
||||
export function generateRandomInt() {
|
||||
return readBigIntFromBuffer(generateRandomBytes(4), true, true).toJSNumber();
|
||||
}
|
||||
|
||||
export function buildMessageFromUpdate(
|
||||
id: number,
|
||||
chatId: string,
|
||||
@ -470,7 +461,7 @@ export function buildInputContact({
|
||||
lastName: string;
|
||||
}) {
|
||||
return new GramJs.InputPhoneContact({
|
||||
clientId: BigInt(1),
|
||||
clientId: 1n,
|
||||
phone,
|
||||
firstName,
|
||||
lastName,
|
||||
@ -597,17 +588,16 @@ export function buildInputThemeParams(params: ApiThemeParameters) {
|
||||
}
|
||||
|
||||
export function buildMtpPeerId(id: string, type: 'user' | 'chat' | 'channel') {
|
||||
const n = BigInt(id);
|
||||
if (type === 'user') {
|
||||
return BigInt(id);
|
||||
return n;
|
||||
}
|
||||
|
||||
const n = Number(id);
|
||||
|
||||
if (type === 'channel') {
|
||||
return BigInt(-n - CHANNEL_ID_BASE);
|
||||
return -n - CHANNEL_ID_BASE;
|
||||
}
|
||||
|
||||
return BigInt(n * -1);
|
||||
return n * -1n;
|
||||
}
|
||||
|
||||
export function buildInputGroupCall(groupCall: Partial<ApiGroupCall>) {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../lib/gramjs';
|
||||
|
||||
import { DEBUG } from '../../config';
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import { generateRandomBigInt } from '../../../lib/gramjs/Helpers';
|
||||
|
||||
import type {
|
||||
ApiBotApp,
|
||||
@ -33,7 +33,6 @@ import {
|
||||
buildInputThemeParams,
|
||||
buildInputUser,
|
||||
DEFAULT_PRIMITIVES,
|
||||
generateRandomBigInt,
|
||||
} from '../gramjsBuilders';
|
||||
import {
|
||||
addDocumentToLocalDb,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import { generateRandomInt32 } from '../../../lib/gramjs/Helpers';
|
||||
|
||||
import type { JoinGroupCallPayload } from '../../../lib/secret-sauce';
|
||||
import type {
|
||||
@ -13,7 +13,7 @@ import {
|
||||
buildPhoneCall,
|
||||
} from '../apiBuilders/calls';
|
||||
import {
|
||||
buildInputGroupCall, buildInputPeer, buildInputPhoneCall, buildInputUser, DEFAULT_PRIMITIVES, generateRandomInt,
|
||||
buildInputGroupCall, buildInputPeer, buildInputPhoneCall, buildInputUser, DEFAULT_PRIMITIVES,
|
||||
} from '../gramjsBuilders';
|
||||
import { sendApiUpdate } from '../updates/apiUpdateEmitter';
|
||||
import { invokeRequest, invokeRequestBeacon } from './client';
|
||||
@ -182,7 +182,7 @@ export async function createGroupCall({
|
||||
}: {
|
||||
peer: ApiChat;
|
||||
}) {
|
||||
const randomId = generateRandomInt();
|
||||
const randomId = generateRandomInt32();
|
||||
const result = await invokeRequest(new GramJs.phone.CreateGroupCall({
|
||||
peer: buildInputPeer(peer.id, peer.accessHash),
|
||||
randomId,
|
||||
@ -284,7 +284,7 @@ export async function requestCall({
|
||||
user: ApiUser; gAHash: number[]; isVideo?: boolean;
|
||||
}) {
|
||||
const result = await invokeRequest(new GramJs.phone.RequestCall({
|
||||
randomId: generateRandomInt(),
|
||||
randomId: generateRandomInt32(),
|
||||
userId: buildInputUser(user.id, user.accessHash),
|
||||
gAHash: Buffer.from(gAHash),
|
||||
...(isVideo && { video: true }),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import { RPCError } from '../../../lib/gramjs/errors';
|
||||
import { generateRandomBigInt } from '../../../lib/gramjs/Helpers';
|
||||
|
||||
import type { ChatListType } from '../../../types';
|
||||
import type {
|
||||
@ -71,7 +71,6 @@ import {
|
||||
buildInputUser,
|
||||
buildMtpMessageEntity,
|
||||
DEFAULT_PRIMITIVES,
|
||||
generateRandomBigInt,
|
||||
getEntityTypeById,
|
||||
} from '../gramjsBuilders';
|
||||
import {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import bigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type { SizeType, TelegramClient } from '../../../lib/gramjs';
|
||||
@ -15,6 +14,7 @@ import {
|
||||
MEDIA_CACHE_NAME_AVATARS,
|
||||
} from '../../../config';
|
||||
import * as cacheApi from '../../../util/cacheApi';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { getEntityTypeById } from '../gramjsBuilders';
|
||||
import localDb from '../localDb';
|
||||
|
||||
@ -89,7 +89,7 @@ async function download(
|
||||
} = parsed;
|
||||
|
||||
if (entityType === 'staticMap') {
|
||||
const accessHash = bigInt(entityId);
|
||||
const accessHash = BigInt(entityId);
|
||||
const parsedParams = new URLSearchParams(params);
|
||||
const long = Number(parsedParams.get('long'));
|
||||
const lat = Number(parsedParams.get('lat'));
|
||||
@ -162,7 +162,7 @@ async function download(
|
||||
fullSize = entity.size;
|
||||
} else if (entity instanceof GramJs.Document) {
|
||||
mimeType = entity.mimeType;
|
||||
fullSize = entity.size.toJSNumber();
|
||||
fullSize = toJSNumber(entity.size);
|
||||
}
|
||||
|
||||
// Prevent HTML-in-video attacks
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import { RPCError } from '../../../lib/gramjs/errors';
|
||||
import { generateRandomBigInt } from '../../../lib/gramjs/Helpers';
|
||||
|
||||
import type {
|
||||
ForwardMessagesParams,
|
||||
@ -98,7 +98,6 @@ import {
|
||||
buildPeer,
|
||||
buildSendMessageAction,
|
||||
DEFAULT_PRIMITIVES,
|
||||
generateRandomBigInt,
|
||||
getEntityTypeById,
|
||||
} from '../gramjsBuilders';
|
||||
import {
|
||||
@ -1888,7 +1887,7 @@ export async function forwardApiMessages(params: ForwardMessagesParams) {
|
||||
|
||||
const priceInStars = messagePriceInStars ? messagePriceInStars * messageIds.length : undefined;
|
||||
|
||||
const randomIds = messageIds.map(generateRandomBigInt);
|
||||
const randomIds = messageIds.map(() => generateRandomBigInt());
|
||||
try {
|
||||
const update = await invokeRequest(new GramJs.messages.ForwardMessages({
|
||||
fromPeer: buildInputPeer(fromChat.id, fromChat.accessHash),
|
||||
@ -2498,7 +2497,7 @@ export async function sendQuickReply({
|
||||
if (!messages || messages instanceof GramJs.messages.MessagesNotModified) return;
|
||||
|
||||
const ids = messages.messages.map((m) => m.id);
|
||||
const randomIds = ids.map(generateRandomBigInt);
|
||||
const randomIds = ids.map(() => generateRandomBigInt());
|
||||
|
||||
const result = await invokeRequest(new GramJs.messages.SendQuickReplyMessages({
|
||||
peer: buildInputPeer(chat.id, chat.accessHash),
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import { RPCError } from '../../../lib/gramjs/errors';
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import type bigInt from 'big-integer';
|
||||
import BigInt from 'big-integer';
|
||||
import { AuthKey } from '../../../lib/gramjs/crypto/AuthKey';
|
||||
import { Logger } from '../../../lib/gramjs/extensions';
|
||||
import {
|
||||
@ -20,13 +18,13 @@ class PhoneCallState {
|
||||
|
||||
private seq = 0;
|
||||
|
||||
private gA?: bigInt.BigInteger;
|
||||
private gA?: bigint;
|
||||
|
||||
private gB: any;
|
||||
private gB?: bigint;
|
||||
|
||||
private p?: bigInt.BigInteger;
|
||||
private p?: bigint;
|
||||
|
||||
private random?: bigInt.BigInteger;
|
||||
private random?: bigint;
|
||||
|
||||
private waitForState: Promise<void>;
|
||||
|
||||
@ -55,8 +53,8 @@ class PhoneCallState {
|
||||
}
|
||||
|
||||
acceptCall({ p, g, random }: DhConfig) {
|
||||
const pLast = readBigIntFromBuffer(p, false);
|
||||
const randomLast = readBigIntFromBuffer(random, false);
|
||||
const pLast = readBigIntFromBuffer(Buffer.from(p), false);
|
||||
const randomLast = readBigIntFromBuffer(Buffer.from(random), false);
|
||||
|
||||
const gB = modExp(BigInt(g), randomLast, pLast);
|
||||
this.gB = gB;
|
||||
@ -77,7 +75,7 @@ class PhoneCallState {
|
||||
this.gA = readBigIntFromBuffer(Buffer.from(gAOrB), false);
|
||||
}
|
||||
const authKey = modExp(
|
||||
!this.isOutgoing ? this.gA : this.gB,
|
||||
(!this.isOutgoing ? this.gA : this.gB)!,
|
||||
this.random,
|
||||
this.p,
|
||||
);
|
||||
@ -125,14 +123,14 @@ class PhoneCallState {
|
||||
|
||||
// https://github.com/TelegramV/App/blob/ead52320975362139cabad18cf8346f98c349a22/src/js/MTProto/Calls/Internal.js#L72
|
||||
function computeEmojiIndex(bytes: Uint8Array) {
|
||||
return ((BigInt(bytes[0]).and(0x7F)).shiftLeft(56))
|
||||
.or((BigInt(bytes[1]).shiftLeft(48)))
|
||||
.or((BigInt(bytes[2]).shiftLeft(40)))
|
||||
.or((BigInt(bytes[3]).shiftLeft(32)))
|
||||
.or((BigInt(bytes[4]).shiftLeft(24)))
|
||||
.or((BigInt(bytes[5]).shiftLeft(16)))
|
||||
.or((BigInt(bytes[6]).shiftLeft(8)))
|
||||
.or((BigInt(bytes[7])));
|
||||
return ((BigInt(bytes[0]) & 0x7Fn) << 56n)
|
||||
| ((BigInt(bytes[1]) << 48n))
|
||||
| ((BigInt(bytes[2]) << 40n))
|
||||
| ((BigInt(bytes[3]) << 32n))
|
||||
| ((BigInt(bytes[4]) << 24n))
|
||||
| ((BigInt(bytes[5]) << 16n))
|
||||
| ((BigInt(bytes[6]) << 8n))
|
||||
| ((BigInt(bytes[7])));
|
||||
}
|
||||
|
||||
async function generateEmojiFingerprint(
|
||||
@ -144,7 +142,7 @@ async function generateEmojiFingerprint(
|
||||
const kPartSize = 8;
|
||||
for (let partOffset = 0; partOffset !== hash.byteLength; partOffset += kPartSize) {
|
||||
const value = computeEmojiIndex(hash.subarray(partOffset, partOffset + kPartSize));
|
||||
const index = value.modPow(1, emojiCount).toJSNumber();
|
||||
const index = Number(value % BigInt(emojiCount));
|
||||
const offset = emojiOffsets[index];
|
||||
const size = emojiOffsets[index + 1] - offset;
|
||||
result.push(String.fromCharCode(...emojiData.subarray(offset, offset + size)));
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import { RPCError } from '../../../lib/gramjs/errors';
|
||||
|
||||
@ -23,6 +22,7 @@ import {
|
||||
UNMUTE_TIMESTAMP,
|
||||
} from '../../../config';
|
||||
import { buildCollectionByKey } from '../../../util/iteratees';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { BLOCKED_LIST_LIMIT } from '../../../limits';
|
||||
import { buildAppConfig } from '../apiBuilders/appConfig';
|
||||
import { buildApiPhoto, buildPrivacyRules } from '../apiBuilders/common';
|
||||
@ -686,7 +686,7 @@ export async function fetchGlobalPrivacySettings() {
|
||||
shouldArchiveAndMuteNewNonContact: Boolean(result.archiveAndMuteNewNoncontactPeers),
|
||||
shouldHideReadMarks: Boolean(result.hideReadMarks),
|
||||
shouldNewNonContactPeersRequirePremium: Boolean(result.newNoncontactPeersRequirePremium),
|
||||
nonContactPeersPaidStars: Number(result.noncontactPeersPaidStars),
|
||||
nonContactPeersPaidStars: toJSNumber(result.noncontactPeersPaidStars),
|
||||
shouldDisplayGiftsButton: Boolean(result.displayGiftsButton),
|
||||
disallowedGifts: result.disallowedGifts && buildApiDisallowedGiftsSettings(result.disallowedGifts),
|
||||
};
|
||||
@ -726,7 +726,7 @@ export async function updateGlobalPrivacySettings({
|
||||
shouldArchiveAndMuteNewNonContact: Boolean(result.archiveAndMuteNewNoncontactPeers),
|
||||
shouldHideReadMarks: Boolean(result.hideReadMarks),
|
||||
shouldNewNonContactPeersRequirePremium: Boolean(result.newNoncontactPeersRequirePremium),
|
||||
nonContactPeersPaidStars: Number(result.noncontactPeersPaidStars),
|
||||
nonContactPeersPaidStars: toJSNumber(result.noncontactPeersPaidStars),
|
||||
shouldDisplayGiftsButton,
|
||||
disallowedGifts,
|
||||
};
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import bigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type { GiftProfileFilterOptions, ResaleGiftsFilterOptions } from '../../../types';
|
||||
@ -39,7 +38,7 @@ import { getPassword } from './twoFaSettings';
|
||||
|
||||
export async function fetchCheckCanSendGift({ giftId }: { giftId: string }) {
|
||||
const result = await invokeRequest(new GramJs.payments.CheckCanSendGift({
|
||||
giftId: bigInt(giftId),
|
||||
giftId: BigInt(giftId),
|
||||
}));
|
||||
|
||||
if (!result) {
|
||||
@ -112,10 +111,10 @@ export async function fetchResaleGifts({
|
||||
];
|
||||
|
||||
const params: GetResaleStarGifts = {
|
||||
giftId: bigInt(giftId),
|
||||
giftId: BigInt(giftId),
|
||||
offset,
|
||||
limit,
|
||||
attributesHash: attributesHash ? bigInt(attributesHash) : DEFAULT_PRIMITIVES.BIGINT,
|
||||
attributesHash: attributesHash ? BigInt(attributesHash) : DEFAULT_PRIMITIVES.BIGINT,
|
||||
attributes: buildInputResaleGiftsAttributes(attributes),
|
||||
...(filter && {
|
||||
sortByPrice: filter.sortType === 'byPrice' || undefined,
|
||||
@ -200,7 +199,7 @@ export function convertStarGift({
|
||||
}));
|
||||
}
|
||||
|
||||
export async function getStarsGiftOptions({
|
||||
export async function fetchStarsGiftOptions({
|
||||
chat,
|
||||
}: {
|
||||
chat?: ApiChat;
|
||||
@ -397,7 +396,7 @@ export async function fetchStarGiftUpgradePreview({
|
||||
giftId: string;
|
||||
}) {
|
||||
const result = await invokeRequest(new GramJs.payments.GetStarGiftUpgradePreview({
|
||||
giftId: bigInt(giftId),
|
||||
giftId: BigInt(giftId),
|
||||
}));
|
||||
|
||||
if (!result) {
|
||||
@ -527,7 +526,7 @@ export async function fetchStarGiftCollections({
|
||||
}) {
|
||||
const result = await invokeRequest(new GramJs.payments.GetStarGiftCollections({
|
||||
peer: buildInputPeer(peer.id, peer.accessHash),
|
||||
hash: hash ? bigInt(hash) : DEFAULT_PRIMITIVES.BIGINT,
|
||||
hash: hash ? BigInt(hash) : DEFAULT_PRIMITIVES.BIGINT,
|
||||
}));
|
||||
|
||||
if (!result || result instanceof GramJs.payments.StarGiftCollectionsNotModified) {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type {
|
||||
@ -109,8 +108,14 @@ export async function fetchFeaturedStickers({ hash }: { hash?: string }) {
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchFeaturedEmojiStickers() {
|
||||
const result = await invokeRequest(new GramJs.messages.GetFeaturedEmojiStickers({ hash: BigInt(0) }));
|
||||
export async function fetchFeaturedEmojiStickers({
|
||||
hash,
|
||||
}: {
|
||||
hash?: string;
|
||||
}) {
|
||||
const result = await invokeRequest(new GramJs.messages.GetFeaturedEmojiStickers({
|
||||
hash: hash ? BigInt(hash) : DEFAULT_PRIMITIVES.BIGINT,
|
||||
}));
|
||||
|
||||
if (!result || result instanceof GramJs.messages.FeaturedStickersNotModified) {
|
||||
return undefined;
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import BigInt from 'big-integer';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type { ApiEmojiStatusType, ApiPeer, ApiUser,
|
||||
} from '../../types';
|
||||
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
||||
import { buildApiPhoto } from '../apiBuilders/common';
|
||||
import { buildApiPeerId } from '../apiBuilders/peers';
|
||||
@ -88,7 +88,7 @@ export async function fetchFullUser({
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchCommonChats(user: ApiUser, maxId?: string) {
|
||||
export async function fetchCommonChats({ user, maxId }: { user: ApiUser; maxId?: string }) {
|
||||
const result = await invokeRequest(new GramJs.messages.GetCommonChats({
|
||||
userId: buildInputUser(user.id, user.accessHash),
|
||||
maxId: maxId
|
||||
@ -112,12 +112,13 @@ export async function fetchPaidMessagesStarsAmount(user: ApiUser) {
|
||||
id: [buildInputUser(user.id, user.accessHash)],
|
||||
}));
|
||||
|
||||
if (!result) {
|
||||
if (!result?.[0]) {
|
||||
return undefined;
|
||||
}
|
||||
const requirement = result[0];
|
||||
|
||||
if (result[0] instanceof GramJs.RequirementToContactPaidMessages) {
|
||||
return result[0].starsAmount?.toJSNumber();
|
||||
if (requirement instanceof GramJs.RequirementToContactPaidMessages) {
|
||||
return toJSNumber(requirement.starsAmount);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@ -149,7 +150,7 @@ export async function fetchTopUsers() {
|
||||
}
|
||||
|
||||
export async function fetchContactList() {
|
||||
const result = await invokeRequest(new GramJs.contacts.GetContacts({ hash: BigInt('0') }));
|
||||
const result = await invokeRequest(new GramJs.contacts.GetContacts({ hash: DEFAULT_PRIMITIVES.BIGINT }));
|
||||
if (!result || result instanceof GramJs.contacts.ContactsNotModified) {
|
||||
return undefined;
|
||||
}
|
||||
@ -224,7 +225,7 @@ export function updateContact({
|
||||
firstName,
|
||||
lastName,
|
||||
phone: phoneNumber,
|
||||
...(shouldSharePhoneNumber && { addPhonePrivacyException: shouldSharePhoneNumber }),
|
||||
addPhonePrivacyException: shouldSharePhoneNumber || undefined,
|
||||
}), {
|
||||
shouldReturnTrue: true,
|
||||
});
|
||||
@ -273,7 +274,7 @@ export async function fetchPaidMessagesRevenue({ user }: {
|
||||
userId: buildInputUser(user.id, user.accessHash),
|
||||
}));
|
||||
if (!result) return undefined;
|
||||
return result.starsAmount.toJSNumber();
|
||||
return toJSNumber(result.starsAmount);
|
||||
}
|
||||
|
||||
export async function fetchProfilePhotos({
|
||||
@ -294,7 +295,7 @@ export async function fetchProfilePhotos({
|
||||
userId: buildInputUser(id, accessHash),
|
||||
limit,
|
||||
offset,
|
||||
maxId: BigInt('0'),
|
||||
maxId: DEFAULT_PRIMITIVES.BIGINT,
|
||||
}));
|
||||
|
||||
if (!result) {
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
import type { BigInteger } from 'big-integer';
|
||||
|
||||
export class LocalUpdatePts {
|
||||
constructor(public pts: number, public ptsCount: number) {}
|
||||
}
|
||||
|
||||
export class LocalUpdateChannelPts {
|
||||
constructor(public channelId: BigInteger, public pts: number, public ptsCount: number) {}
|
||||
constructor(public channelId: bigint, public pts: number, public ptsCount: number) {}
|
||||
}
|
||||
|
||||
export type UpdatePts = LocalUpdatePts | LocalUpdateChannelPts;
|
||||
|
||||
export function buildLocalUpdatePts(pts: number, ptsCount: number, channelId?: BigInteger) {
|
||||
export function buildLocalUpdatePts(pts: number, ptsCount: number, channelId?: bigint) {
|
||||
return channelId ? new LocalUpdateChannelPts(channelId, pts, ptsCount) : new LocalUpdatePts(pts, ptsCount);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { ApiChat } from './chats';
|
||||
import type { ApiTypePrepaidGiveaway } from './payments';
|
||||
import type { ApiTypeCurrencyAmount } from './stars';
|
||||
|
||||
export interface ApiChannelStatistics {
|
||||
type: 'channel';
|
||||
@ -153,8 +154,8 @@ export interface StatisticsStoryInteractionCounter {
|
||||
}
|
||||
|
||||
export interface ChannelMonetizationBalances {
|
||||
currentBalance: number;
|
||||
availableBalance: number;
|
||||
overallRevenue: number;
|
||||
currentBalance: ApiTypeCurrencyAmount;
|
||||
availableBalance: ApiTypeCurrencyAmount;
|
||||
overallRevenue: ApiTypeCurrencyAmount;
|
||||
isWithdrawalEnabled?: boolean;
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
} from '../../../util/browser/windowEnvironment';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { formatMediaDuration } from '../../../util/dates/dateFormat';
|
||||
import { getServerTime } from '../../../util/serverTime';
|
||||
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
|
||||
@ -215,7 +216,7 @@ const PhoneCall: FC<StateProps> = ({
|
||||
setTimeout(stopFlipping, 250);
|
||||
}, [startFlipping, stopFlipping]);
|
||||
|
||||
const timeElapsed = phoneCall?.startDate && (Number(new Date()) / 1000 - phoneCall.startDate);
|
||||
const timeElapsed = phoneCall?.startDate && (getServerTime() - phoneCall.startDate);
|
||||
|
||||
useEffect(() => {
|
||||
if (phoneCall?.state === 'discarded') {
|
||||
|
||||
@ -7,6 +7,7 @@ import type { ApiChannelMonetizationStatistics } from '../../../api/types';
|
||||
|
||||
import { selectChat, selectChatFullInfo, selectTabState } from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { convertTonFromNanos } from '../../../util/formatCurrency';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
import { isGraph } from './helpers/isGraph';
|
||||
|
||||
@ -144,9 +145,10 @@ const MonetizationStatistics = ({
|
||||
}, [isReady, statistics, oldLang, chatId, dcId, forceUpdate]);
|
||||
|
||||
function renderAvailableReward() {
|
||||
const [integerTonPart, decimalTonPart] = availableBalance ? availableBalance.toFixed(4).split('.') : [0];
|
||||
const tonAmount = availableBalance ? convertTonFromNanos(availableBalance.amount) : 0;
|
||||
const [integerTonPart, decimalTonPart] = tonAmount.toFixed(4).split('.');
|
||||
const [integerUsdPart, decimalUsdPart] = availableBalance
|
||||
&& statistics?.usdRate ? (availableBalance * statistics.usdRate).toFixed(2).split('.') : [0];
|
||||
&& statistics?.usdRate ? (tonAmount * statistics.usdRate).toFixed(2).split('.') : [0];
|
||||
|
||||
return (
|
||||
<div className={styles.availableReward}>
|
||||
|
||||
@ -9,6 +9,7 @@ import type {
|
||||
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { formatFullDate } from '../../../util/dates/dateFormat';
|
||||
import { convertTonFromNanos } from '../../../util/formatCurrency';
|
||||
import { formatInteger, formatIntegerCompact } from '../../../util/textFormat';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
@ -206,9 +207,21 @@ const StatisticsOverview: FC<OwnProps> = ({
|
||||
{isToncoin ? (
|
||||
<tr>
|
||||
<td className={styles.tableCell}>
|
||||
{renderBalanceCell(balances?.availableBalance || 0, usdRate || 0, 'lng_channel_earn_available')}
|
||||
{renderBalanceCell(balances?.currentBalance || 0, usdRate || 0, 'lng_channel_earn_reward')}
|
||||
{renderBalanceCell(balances?.overallRevenue || 0, usdRate || 0, 'lng_channel_earn_total')}
|
||||
{renderBalanceCell(
|
||||
balances?.availableBalance ? convertTonFromNanos(balances.availableBalance.amount) : 0,
|
||||
usdRate || 0,
|
||||
'lng_channel_earn_available',
|
||||
)}
|
||||
{renderBalanceCell(
|
||||
balances?.currentBalance ? convertTonFromNanos(balances.currentBalance.amount) : 0,
|
||||
usdRate || 0,
|
||||
'lng_channel_earn_reward',
|
||||
)}
|
||||
{renderBalanceCell(
|
||||
balances?.overallRevenue ? convertTonFromNanos(balances.overallRevenue.amount) : 0,
|
||||
usdRate || 0,
|
||||
'lng_channel_earn_total',
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
) : schema.map((row) => (
|
||||
|
||||
@ -338,13 +338,13 @@ export const REPLIES_USER_ID = '1271266957'; // TODO For Test connection ID must
|
||||
export const VERIFICATION_CODES_USER_ID = '489000';
|
||||
export const ANONYMOUS_USER_ID = '2666000';
|
||||
export const RESTRICTED_EMOJI_SET_ID = '7173162320003080';
|
||||
export const CHANNEL_ID_BASE = 10 ** 12;
|
||||
export const CHANNEL_ID_BASE = 10n ** 12n;
|
||||
export const DEFAULT_GIF_SEARCH_BOT_USERNAME = 'gif';
|
||||
export const ALL_FOLDER_ID = 0;
|
||||
export const ARCHIVED_FOLDER_ID = 1;
|
||||
export const SAVED_FOLDER_ID = -1;
|
||||
export const FOLDER_TITLE_MAX_LENGTH = 12;
|
||||
export const DELETED_COMMENTS_CHANNEL_ID = '-1000000000777';
|
||||
export const DELETED_COMMENTS_CHANNEL_ID = (-CHANNEL_ID_BASE - 777n).toString();
|
||||
export const MAX_MEDIA_FILES_FOR_ALBUM = 10;
|
||||
export const MAX_ACTIVE_PINNED_CHATS = 5;
|
||||
export const SCHEDULED_WHEN_ONLINE = 0x7FFFFFFE;
|
||||
|
||||
@ -608,7 +608,12 @@ addActionHandler('openStarsGiftModal', async (global, actions, payload): Promise
|
||||
return;
|
||||
}
|
||||
|
||||
const starsGiftOptions = await callApi('getStarsGiftOptions', {});
|
||||
const chat = forUserId ? selectChat(global, forUserId) : undefined;
|
||||
if (forUserId && !chat) return;
|
||||
|
||||
const starsGiftOptions = await callApi('fetchStarsGiftOptions', {
|
||||
chat,
|
||||
});
|
||||
|
||||
global = getGlobal();
|
||||
global = updateTabState(global, {
|
||||
|
||||
@ -787,7 +787,7 @@ addActionHandler('clearCustomEmojiForEmoji', (global): ActionReturnType => {
|
||||
});
|
||||
|
||||
addActionHandler('loadFeaturedEmojiStickers', async (global): Promise<void> => {
|
||||
const featuredStickers = await callApi('fetchFeaturedEmojiStickers');
|
||||
const featuredStickers = await callApi('fetchFeaturedEmojiStickers', {});
|
||||
if (!featuredStickers) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -174,7 +174,10 @@ addActionHandler('loadCommonChats', async (global, actions, payload): Promise<vo
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await callApi('fetchCommonChats', user, commonChats?.maxId);
|
||||
const result = await callApi('fetchCommonChats', {
|
||||
user,
|
||||
maxId: commonChats?.maxId,
|
||||
});
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ import {
|
||||
VIDEO_STICKER_MIME_TYPE,
|
||||
} from '../../config';
|
||||
import { areDeepEqual } from '../../util/areDeepEqual';
|
||||
import { getCleanPeerId, isUserId } from '../../util/entities/ids';
|
||||
import { getRawPeerId, isUserId } from '../../util/entities/ids';
|
||||
import { areSortedArraysIntersecting, unique } from '../../util/iteratees';
|
||||
import { isLocalMessageId } from '../../util/keys/messageKey';
|
||||
import { getServerTime } from '../../util/serverTime';
|
||||
@ -385,7 +385,7 @@ export function isUploadingFileSticker(attachment: ApiAttachment) {
|
||||
export function getMessageLink(peer: ApiPeer, topicId?: ThreadId, messageId?: number) {
|
||||
const chatUsername = getMainUsername(peer);
|
||||
|
||||
const normalizedId = getCleanPeerId(peer.id);
|
||||
const normalizedId = getRawPeerId(peer.id).toString();
|
||||
|
||||
const chatPart = chatUsername || `c/${normalizedId}`;
|
||||
const topicPart = topicId && topicId !== MAIN_THREAD_ID ? `/${topicId}` : '';
|
||||
|
||||
@ -1,65 +1,92 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import { createHash, randomBytes } from './crypto/crypto';
|
||||
|
||||
export function readBigIntFromBuffer(buffer: Buffer | number[], little = true, signed = false): BigInt.BigInteger {
|
||||
let randBuffer = Buffer.from(buffer);
|
||||
const bytesNumber = randBuffer.length;
|
||||
if (little) {
|
||||
randBuffer = randBuffer.reverse();
|
||||
}
|
||||
let bigInt = BigInt(randBuffer.toString('hex'), 16);
|
||||
if (signed && Math.floor(bigInt.toString(2).length / 8) >= bytesNumber) {
|
||||
bigInt = bigInt.subtract(BigInt(2)
|
||||
.pow(BigInt(bytesNumber * 8)));
|
||||
}
|
||||
return bigInt;
|
||||
}
|
||||
export function readBigIntFromBuffer(buffer: Buffer, little = true, signed = false): bigint {
|
||||
const len = buffer.length;
|
||||
if (len === 0) return 0n;
|
||||
|
||||
export function toSignedLittleBuffer(big: BigInt.BigInteger, number = 8) {
|
||||
const bigNumber = BigInt(big);
|
||||
const byteArray: number[] = [];
|
||||
for (let i = 0; i < number; i++) {
|
||||
byteArray[i] = bigNumber.shiftRight(8 * i)
|
||||
.and(255)
|
||||
.toJSNumber();
|
||||
}
|
||||
|
||||
return Buffer.from(byteArray);
|
||||
}
|
||||
|
||||
export function readBufferFromBigInt(bigInt: BigInt.BigInteger, bytesNumber: number, little = true, signed = false) {
|
||||
const bitLength = bigInt.bitLength().toJSNumber();
|
||||
|
||||
const bytes = Math.ceil(bitLength / 8);
|
||||
if (bytesNumber < bytes) {
|
||||
throw new Error('OverflowError: int too big to convert');
|
||||
}
|
||||
if (!signed && bigInt.lesser(BigInt(0))) {
|
||||
throw new Error('Cannot convert to unsigned');
|
||||
}
|
||||
let below = false;
|
||||
if (bigInt.lesser(BigInt(0))) {
|
||||
below = true;
|
||||
bigInt = bigInt.abs();
|
||||
}
|
||||
|
||||
const hex = bigInt.toString(16).padStart(bytesNumber * 2, '0');
|
||||
let buffer = Buffer.from(hex, 'hex');
|
||||
|
||||
if (signed && below) {
|
||||
buffer[buffer.length - 1] = 256 - buffer[buffer.length - 1];
|
||||
for (let i = 0; i < buffer.length - 1; i++) {
|
||||
buffer[i] = 255 - buffer[i];
|
||||
// Hot path for longs
|
||||
if (len === 8) {
|
||||
if (signed) {
|
||||
return little ? buffer.readBigInt64LE(0) : buffer.readBigInt64BE(0);
|
||||
} else {
|
||||
return little ? buffer.readBigUInt64LE(0) : buffer.readBigUInt64BE(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse unsigned value
|
||||
let x = 0n;
|
||||
if (little) {
|
||||
buffer = buffer.reverse();
|
||||
for (let i = len - 1; i >= 0; i--) x = (x << 8n) | BigInt(buffer[i]);
|
||||
} else {
|
||||
for (let i = 0; i < len; i++) x = (x << 8n) | BigInt(buffer[i]);
|
||||
}
|
||||
|
||||
// Apply two's-complement decode if signed and sign bit is set
|
||||
if (signed) {
|
||||
const signBit = 1n << BigInt(len * 8 - 1);
|
||||
if ((x & signBit) !== 0n) x -= 1n << BigInt(len * 8);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export function toSignedLittleBuffer(big: bigint, number = 8) {
|
||||
const buffer = Buffer.allocUnsafe(number);
|
||||
|
||||
// Use Buffer method for 8-byte buffers
|
||||
if (number === 8) {
|
||||
buffer.writeBigInt64LE(big);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// For other sizes, extract bytes manually
|
||||
for (let i = 0; i < number; i++) {
|
||||
buffer[i] = Number((big >> BigInt(8 * i)) & 0xFFn);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
export function readBufferFromBigInt(
|
||||
value: bigint,
|
||||
bytesNumber: number,
|
||||
little = true,
|
||||
signed = false,
|
||||
): Buffer {
|
||||
if (!Number.isInteger(bytesNumber) || bytesNumber <= 0) {
|
||||
throw new RangeError('bytesNumber must be a positive integer');
|
||||
}
|
||||
if (!signed && value < 0n) {
|
||||
throw new RangeError('Cannot convert negative to unsigned');
|
||||
}
|
||||
|
||||
const bits = 8n * BigInt(bytesNumber);
|
||||
const min = signed ? -(1n << (bits - 1n)) : 0n;
|
||||
const max = signed ? (1n << (bits - 1n)) - 1n : (1n << bits) - 1n;
|
||||
|
||||
if (value < min || value > max) {
|
||||
throw new RangeError(
|
||||
`Value ${value} does not fit in ${bytesNumber} ${signed ? 'signed' : 'unsigned'} bytes`,
|
||||
);
|
||||
}
|
||||
|
||||
// Two's complement encode if negative
|
||||
let v = signed && value < 0n ? (1n << bits) + value : value;
|
||||
|
||||
const buf = Buffer.allocUnsafe(bytesNumber);
|
||||
if (little) {
|
||||
for (let i = 0; i < bytesNumber; i++) {
|
||||
buf[i] = Number(v & 0xFFn);
|
||||
v >>= 8n;
|
||||
}
|
||||
} else {
|
||||
for (let i = bytesNumber - 1; i >= 0; i--) {
|
||||
buf[i] = Number(v & 0xFFn);
|
||||
v >>= 8n;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
export function generateRandomLong(signed = true) {
|
||||
return readBigIntFromBuffer(generateRandomBytes(8), true, signed);
|
||||
}
|
||||
@ -68,16 +95,24 @@ export function mod(n: number, m: number) {
|
||||
return ((n % m) + m) % m;
|
||||
}
|
||||
|
||||
export function bigIntMod(n: BigInt.BigInteger, m: BigInt.BigInteger) {
|
||||
return ((n.remainder(m)).add(m)).remainder(m);
|
||||
export function bigIntMod(n: bigint, m: bigint) {
|
||||
return ((n % m) + m) % m;
|
||||
}
|
||||
|
||||
export function generateRandomBytes(count: number) {
|
||||
return Buffer.from(randomBytes(count));
|
||||
}
|
||||
|
||||
export function generateRandomBigInt(bytes: number = 8) {
|
||||
return readBigIntFromBuffer(generateRandomBytes(bytes), true, true);
|
||||
}
|
||||
|
||||
export function generateRandomInt32() {
|
||||
return Number(readBigIntFromBuffer(generateRandomBytes(4), true, true));
|
||||
}
|
||||
|
||||
export async function generateKeyDataFromNonce(
|
||||
serverNonceBigInt: BigInt.BigInteger, newNonceBigInt: BigInt.BigInteger,
|
||||
serverNonceBigInt: bigint, newNonceBigInt: bigint,
|
||||
) {
|
||||
const serverNonce = toSignedLittleBuffer(serverNonceBigInt, 16);
|
||||
const newNonce = toSignedLittleBuffer(newNonceBigInt, 32);
|
||||
@ -116,36 +151,76 @@ export function sha256(data: Buffer): Promise<Buffer> {
|
||||
}
|
||||
|
||||
export function modExp(
|
||||
a: bigInt.BigInteger,
|
||||
b: bigInt.BigInteger,
|
||||
n: bigInt.BigInteger,
|
||||
a: bigint,
|
||||
b: bigint,
|
||||
n: bigint,
|
||||
) {
|
||||
a = a.remainder(n);
|
||||
let result = BigInt.one;
|
||||
a = a % n;
|
||||
let result = 1n;
|
||||
let x = a;
|
||||
while (b.greater(BigInt.zero)) {
|
||||
const leastSignificantBit = b.remainder(BigInt(2));
|
||||
b = b.divide(BigInt(2));
|
||||
if (leastSignificantBit.eq(BigInt.one)) {
|
||||
result = result.multiply(x);
|
||||
result = result.remainder(n);
|
||||
while (b > 0n) {
|
||||
const leastSignificantBit = b % 2n;
|
||||
b = b / 2n;
|
||||
if (leastSignificantBit === 1n) {
|
||||
result = result * x;
|
||||
result = result % n;
|
||||
}
|
||||
x = x.multiply(x);
|
||||
x = x.remainder(n);
|
||||
x = x * x;
|
||||
x = x % n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getByteArray(integer: BigInt.BigInteger, signed = false) {
|
||||
const bits = integer.toString(2).length;
|
||||
const byteLength = Math.floor((bits + 8 - 1) / 8);
|
||||
return readBufferFromBigInt(BigInt(integer), byteLength, false, signed);
|
||||
export function getByteArray(integer: bigint, signed = false): Buffer {
|
||||
if (!signed && integer < 0n) {
|
||||
throw new RangeError('Cannot convert negative to unsigned');
|
||||
}
|
||||
|
||||
let bytes: number;
|
||||
if (signed) {
|
||||
if (integer >= 0n) {
|
||||
const bits = bitLength(integer) + 1;
|
||||
bytes = Math.max(1, Math.ceil(bits / 8));
|
||||
} else {
|
||||
const bits = bitLength(-integer - 1n) + 1;
|
||||
bytes = Math.max(1, Math.ceil(bits / 8));
|
||||
}
|
||||
} else {
|
||||
const bits = bitLength(integer);
|
||||
bytes = Math.max(1, Math.ceil(bits / 8));
|
||||
}
|
||||
|
||||
return readBufferFromBigInt(integer, bytes, false, signed);
|
||||
}
|
||||
|
||||
export function getRandomInt(min: number, max: number) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
export function randomBits(k: number): bigint {
|
||||
if (k <= 0) return 0n;
|
||||
|
||||
const bytes = randomBytes(Math.ceil(k / 8));
|
||||
|
||||
let r = 0n;
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
r = (r << 8n) | BigInt(bytes[i]);
|
||||
}
|
||||
|
||||
return r & ((1n << BigInt(k)) - 1n);
|
||||
}
|
||||
|
||||
export function randBetweenBigInt(a: bigint, b: bigint): bigint {
|
||||
const low = a < b ? a : b;
|
||||
const high = a < b ? b : a;
|
||||
const range = high - low + 1n;
|
||||
|
||||
if (range <= 1n) return low;
|
||||
|
||||
const k = bitLength(range - 1n);
|
||||
const twoPowK = 1n << BigInt(k);
|
||||
const limit = (twoPowK / range) * range;
|
||||
|
||||
for (;;) {
|
||||
const r = randomBits(k);
|
||||
if (r < limit) return low + (r % range);
|
||||
}
|
||||
}
|
||||
|
||||
export function sleep(ms: number) {
|
||||
@ -188,3 +263,73 @@ export function crc32(buf: Buffer | string) {
|
||||
}
|
||||
return (crc ^ (-1)) >>> 0;
|
||||
}
|
||||
|
||||
const testersCoeff: number[] = [];
|
||||
const testersBigCoeff: bigint[] = [];
|
||||
const testers: bigint[] = [];
|
||||
let testersN = 0;
|
||||
|
||||
// https://stackoverflow.com/a/76616288
|
||||
export function bitLength(x: bigint) {
|
||||
let k = 0;
|
||||
while (true) {
|
||||
if (testersN === k) {
|
||||
testersCoeff.push(32 << testersN);
|
||||
testersBigCoeff.push(BigInt(testersCoeff[testersN]));
|
||||
testers.push(1n << testersBigCoeff[testersN]);
|
||||
testersN++;
|
||||
}
|
||||
if (x < testers[k]) break;
|
||||
k++;
|
||||
}
|
||||
|
||||
if (!k) return 32 - Math.clz32(Number(x));
|
||||
|
||||
// determine length by bisection
|
||||
k--;
|
||||
let i = testersCoeff[k];
|
||||
let a = x >> testersBigCoeff[k];
|
||||
while (k--) {
|
||||
const b = a >> testersBigCoeff[k];
|
||||
if (b) {
|
||||
i += testersCoeff[k];
|
||||
a = b;
|
||||
}
|
||||
}
|
||||
|
||||
return i + 32 - Math.clz32(Number(a));
|
||||
}
|
||||
|
||||
export const BigMath = {
|
||||
abs(x: bigint) {
|
||||
return x < 0n ? -x : x;
|
||||
},
|
||||
sign(x: bigint) {
|
||||
if (x === 0n) return 0n;
|
||||
return x < 0n ? -1n : 1n;
|
||||
},
|
||||
pow(base: bigint, exponent: bigint) {
|
||||
return base ** exponent;
|
||||
},
|
||||
min(value: bigint, ...values: bigint[]) {
|
||||
for (const v of values) {
|
||||
if (v < value) value = v;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
max(value: bigint, ...values: bigint[]) {
|
||||
for (const v of values) {
|
||||
if (v > value) value = v;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
};
|
||||
|
||||
export function jsonStringifyWithBigInt(obj: any) {
|
||||
return JSON.stringify(obj, (key, value) => {
|
||||
if (typeof value === 'bigint') {
|
||||
return value.toString();
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import { pbkdf2 } from './crypto/crypto';
|
||||
import Api from './tl/api';
|
||||
|
||||
import {
|
||||
bigIntMod,
|
||||
bitLength,
|
||||
generateRandomBytes,
|
||||
modExp,
|
||||
readBigIntFromBuffer,
|
||||
@ -14,59 +13,6 @@ import {
|
||||
|
||||
const SIZE_FOR_HASH = 256;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param prime{BigInteger}
|
||||
* @param g{BigInteger}
|
||||
*/
|
||||
|
||||
/*
|
||||
We don't support changing passwords yet
|
||||
function checkPrimeAndGoodCheck(prime, g) {
|
||||
console.error('Unsupported function `checkPrimeAndGoodCheck` call. Arguments:', prime, g)
|
||||
|
||||
const goodPrimeBitsCount = 2048
|
||||
if (prime < 0 || prime.bitLength() !== goodPrimeBitsCount) {
|
||||
throw new Error(`bad prime count ${prime.bitLength()},expected ${goodPrimeBitsCount}`)
|
||||
}
|
||||
// TODO this is kinda slow
|
||||
if (Factorizator.factorize(prime)[0] !== 1) {
|
||||
throw new Error('give "prime" is not prime')
|
||||
}
|
||||
if (g.eq(BigInt(2))) {
|
||||
if ((prime.remainder(BigInt(8))).neq(BigInt(7))) {
|
||||
throw new Error(`bad g ${g}, mod8 ${prime % 8}`)
|
||||
}
|
||||
} else if (g.eq(BigInt(3))) {
|
||||
if ((prime.remainder(BigInt(3))).neq(BigInt(2))) {
|
||||
throw new Error(`bad g ${g}, mod3 ${prime % 3}`)
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} else if (g.eq(BigInt(4))) {
|
||||
|
||||
} else if (g.eq(BigInt(5))) {
|
||||
if (!([ BigInt(1), BigInt(4) ].includes(prime.remainder(BigInt(5))))) {
|
||||
throw new Error(`bad g ${g}, mod8 ${prime % 5}`)
|
||||
}
|
||||
} else if (g.eq(BigInt(6))) {
|
||||
if (!([ BigInt(19), BigInt(23) ].includes(prime.remainder(BigInt(24))))) {
|
||||
throw new Error(`bad g ${g}, mod8 ${prime % 24}`)
|
||||
}
|
||||
} else if (g.eq(BigInt(7))) {
|
||||
if (!([ BigInt(3), BigInt(5), BigInt(6) ].includes(prime.remainder(BigInt(7))))) {
|
||||
throw new Error(`bad g ${g}, mod8 ${prime % 7}`)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`bad g ${g}`)
|
||||
}
|
||||
const primeSub1Div2 = (prime.subtract(BigInt(1))).divide(BigInt(2))
|
||||
if (Factorizator.factorize(primeSub1Div2)[0] !== 1) {
|
||||
throw new Error('(prime - 1) // 2 is not prime')
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
function checkPrimeAndGood(primeBytes: Buffer, g: number) {
|
||||
const goodPrime = Buffer.from([
|
||||
0xC7, 0x1C, 0xAE, 0xB9, 0xC6, 0xB1, 0xC9, 0x04, 0x8E, 0x6C, 0x52, 0x2F, 0x70, 0xF1, 0x3F, 0x73,
|
||||
@ -95,30 +41,29 @@ function checkPrimeAndGood(primeBytes: Buffer, g: number) {
|
||||
// checkPrimeAndGoodCheck(readBigIntFromBuffer(primeBytes, false), g)
|
||||
}
|
||||
|
||||
function isGoodLarge(number: BigInt.BigInteger, p: BigInt.BigInteger): boolean {
|
||||
return (number.greater(BigInt(0)) && (p.subtract(number)
|
||||
.greater(BigInt(0))));
|
||||
function isGoodLarge(number: bigint, p: bigint): boolean {
|
||||
return number > 0n && number < p;
|
||||
}
|
||||
|
||||
function numBytesForHash(number: Buffer): Buffer {
|
||||
return Buffer.concat([Buffer.alloc(SIZE_FOR_HASH - number.length), number]);
|
||||
}
|
||||
|
||||
function bigNumForHash(g: BigInt.BigInteger) {
|
||||
function bigNumForHash(g: bigint) {
|
||||
return readBufferFromBigInt(g, SIZE_FOR_HASH, false);
|
||||
}
|
||||
|
||||
function isGoodModExpFirst(modexp: BigInt.BigInteger, prime: BigInt.BigInteger): boolean {
|
||||
const diff = prime.subtract(modexp);
|
||||
function isGoodModExpFirst(modexp: bigint, prime: bigint): boolean {
|
||||
const diff = prime - modexp;
|
||||
|
||||
const minDiffBitsCount = 2048 - 64;
|
||||
const maxModExpSize = 256;
|
||||
|
||||
return !(
|
||||
diff.lesser(BigInt(0))
|
||||
|| diff.bitLength().toJSNumber() < minDiffBitsCount
|
||||
|| modexp.bitLength().toJSNumber() < minDiffBitsCount
|
||||
|| Math.floor((modexp.bitLength().toJSNumber() + 7) / 8) > maxModExpSize
|
||||
diff < 0n
|
||||
|| bitLength(diff) < minDiffBitsCount
|
||||
|| bitLength(modexp) < minDiffBitsCount
|
||||
|| Math.floor((bitLength(modexp) + 7) / 8) > maxModExpSize
|
||||
);
|
||||
}
|
||||
|
||||
@ -189,7 +134,7 @@ export async function computeCheck(request: Api.account.Password, password: stri
|
||||
try {
|
||||
checkPrimeAndGood(algo.p, g);
|
||||
} catch (e) {
|
||||
throw new Error('bad /g in password');
|
||||
throw new Error('bad p/g in password');
|
||||
}
|
||||
if (!isGoodLarge(B, p)) {
|
||||
throw new Error('bad b in check');
|
||||
@ -200,7 +145,7 @@ export async function computeCheck(request: Api.account.Password, password: stri
|
||||
const bForHash = numBytesForHash(srpB);
|
||||
const gX = modExp(BigInt(g), x, p);
|
||||
const k = readBigIntFromBuffer(await sha256(Buffer.concat([pForHash, gForHash])), false);
|
||||
const kgX = bigIntMod(k.multiply(gX), p);
|
||||
const kgX = bigIntMod(k * gX, p);
|
||||
const generateAndCheckRandom = async () => {
|
||||
const randomSize = 256;
|
||||
|
||||
@ -211,20 +156,20 @@ export async function computeCheck(request: Api.account.Password, password: stri
|
||||
if (isGoodModExpFirst(A, p)) {
|
||||
const aForHash = bigNumForHash(A);
|
||||
const u = readBigIntFromBuffer(await sha256(Buffer.concat([aForHash, bForHash])), false);
|
||||
if (u.greater(BigInt(0))) {
|
||||
if (u > 0n) {
|
||||
return { a, aForHash, u };
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const { a, aForHash, u } = await generateAndCheckRandom();
|
||||
const gB = bigIntMod(B.subtract(kgX), p);
|
||||
const gB = bigIntMod(B - kgX, p);
|
||||
if (!isGoodModExpFirst(gB, p)) {
|
||||
throw new Error('bad gB');
|
||||
}
|
||||
|
||||
const ux = u.multiply(x);
|
||||
const aUx = a.add(ux);
|
||||
const ux = u * x;
|
||||
const aUx = a + ux;
|
||||
const S = modExp(gB, aUx, p);
|
||||
const [K, pSha, gSha, salt1Sha, salt2Sha] = await Promise.all([
|
||||
sha256(bigNumForHash(S)),
|
||||
@ -244,8 +189,7 @@ export async function computeCheck(request: Api.account.Password, password: stri
|
||||
|
||||
return new Api.InputCheckPasswordSRP({
|
||||
srpId,
|
||||
A: Buffer.from(aForHash),
|
||||
A: aForHash,
|
||||
M1,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { DownloadFileWithDcParams } from './downloadFile';
|
||||
import type { MockTypes } from './mockUtils/MockTypes';
|
||||
import type { SizeType } from './TelegramClient';
|
||||
|
||||
import { GENERAL_TOPIC_ID } from '../../../config';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import { Logger } from '../extensions';
|
||||
import { UpdateConnectionState } from '../network';
|
||||
import Api from '../tl/api';
|
||||
@ -195,7 +194,7 @@ class TelegramClient {
|
||||
about: 'lol',
|
||||
settings: new Api.PeerSettings({}),
|
||||
notifySettings: new Api.PeerNotifySettings({}),
|
||||
id: BigInt(1),
|
||||
id: 1n,
|
||||
commonChatsCount: 0,
|
||||
}),
|
||||
chats: [],
|
||||
@ -381,7 +380,7 @@ class TelegramClient {
|
||||
thumbSize: size ? size.type : '',
|
||||
}),
|
||||
{
|
||||
fileSize: size ? size.size : doc.size.toJSNumber(),
|
||||
fileSize: size ? size.size : toJSNumber(doc.size),
|
||||
progressCallback: args.progressCallback,
|
||||
start: args.start,
|
||||
end: args.end,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import bigInt from 'big-integer';
|
||||
import os from 'os';
|
||||
|
||||
import type LocalUpdatePremiumFloodWait from '../../../api/gramjs/updates/UpdatePremiumFloodWait';
|
||||
@ -16,6 +15,7 @@ import type { DownloadFileParams, DownloadFileWithDcParams, DownloadMediaParams
|
||||
import type { UploadFileParams } from './uploadFile';
|
||||
|
||||
import Deferred from '../../../util/Deferred';
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
import {
|
||||
FloodTestPhoneWaitError,
|
||||
FloodWaitError,
|
||||
@ -44,7 +44,7 @@ import { authFlow, checkAuthorization } from './auth';
|
||||
import { downloadFile } from './downloadFile';
|
||||
import { uploadFile } from './uploadFile';
|
||||
|
||||
import { getRandomInt, sleep } from '../Helpers';
|
||||
import { generateRandomBigInt, sleep } from '../Helpers';
|
||||
import RequestState from '../network/RequestState';
|
||||
import Session from '../sessions/Abstract';
|
||||
import MemorySession from '../sessions/Memory';
|
||||
@ -411,7 +411,7 @@ class TelegramClient {
|
||||
return undefined;
|
||||
}
|
||||
return sender.send(new Api.PingDelayDisconnect({
|
||||
pingId: bigInt(getRandomInt(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)),
|
||||
pingId: generateRandomBigInt(),
|
||||
disconnectDelay: PING_DISCONNECT_DELAY,
|
||||
}));
|
||||
};
|
||||
@ -877,7 +877,7 @@ class TelegramClient {
|
||||
thumbSize: '',
|
||||
}),
|
||||
{
|
||||
fileSize: doc.size.toJSNumber(),
|
||||
fileSize: toJSNumber(doc.size),
|
||||
dcId: doc.dcId,
|
||||
}) as Promise<Buffer | undefined>; // Sticker thumb cannot be larger than 2GB, right?
|
||||
});
|
||||
@ -995,7 +995,7 @@ class TelegramClient {
|
||||
thumbSize: size && 'type' in size ? size.type : '',
|
||||
}),
|
||||
{
|
||||
fileSize: size && 'size' in size ? size.size : doc.size.toJSNumber(),
|
||||
fileSize: size && 'size' in size ? size.size : toJSNumber(doc.size),
|
||||
progressCallback: args.progressCallback,
|
||||
start: args.start,
|
||||
end: args.end,
|
||||
@ -1055,7 +1055,7 @@ class TelegramClient {
|
||||
}
|
||||
|
||||
async downloadStaticMap(
|
||||
accessHash: bigInt.BigInteger,
|
||||
accessHash: bigint,
|
||||
long: number,
|
||||
lat: number,
|
||||
w: number,
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import bigInt from 'big-integer';
|
||||
|
||||
import type TelegramClient from './TelegramClient';
|
||||
import type { Update } from './TelegramClient';
|
||||
|
||||
import { tryParseBigInt } from '../../../util/numbers';
|
||||
import { getServerTime } from '../../../util/serverTime';
|
||||
import { DEFAULT_PRIMITIVES } from '../../../api/gramjs/gramjsBuilders';
|
||||
import { RPCError } from '../errors';
|
||||
@ -234,6 +233,7 @@ async function signInUserWithQrCode(
|
||||
let isScanningComplete = false;
|
||||
|
||||
const { apiId, apiHash } = apiCredentials;
|
||||
const exceptIds = authParams.accountIds?.map((id) => tryParseBigInt(id)).filter(Boolean) || [];
|
||||
|
||||
const inputPromise = (async () => {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
@ -245,7 +245,7 @@ async function signInUserWithQrCode(
|
||||
const result = await client.invoke(new Api.auth.ExportLoginToken({
|
||||
apiId,
|
||||
apiHash,
|
||||
exceptIds: authParams.accountIds?.map((id) => bigInt(id)) || [],
|
||||
exceptIds,
|
||||
}));
|
||||
if (!(result instanceof Api.auth.LoginToken)) {
|
||||
throw new Error('Unexpected');
|
||||
@ -286,7 +286,7 @@ async function signInUserWithQrCode(
|
||||
const result2 = await client.invoke(new Api.auth.ExportLoginToken({
|
||||
apiId,
|
||||
apiHash,
|
||||
exceptIds: authParams.accountIds?.map((id) => bigInt(id)) || [],
|
||||
exceptIds,
|
||||
}));
|
||||
|
||||
if (result2 instanceof Api.auth.LoginTokenSuccess && result2.authorization instanceof Api.auth.Authorization) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type TelegramClient from './TelegramClient';
|
||||
import type { SizeType } from './TelegramClient';
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import type bigInt from 'big-integer';
|
||||
|
||||
import type { GramJsAppConfig } from '../../../../api/gramjs/apiBuilders/appConfig';
|
||||
import type { ApiAvailableReaction } from '../../../../api/types';
|
||||
import type Api from '../../tl/api';
|
||||
@ -62,7 +60,7 @@ export type MockMessageReactions = {
|
||||
export type MockDocument = Partial<Api.Document> & {
|
||||
id: number;
|
||||
mimeType: string;
|
||||
size: bigInt.BigInteger;
|
||||
size: bigint;
|
||||
url: string;
|
||||
bytes: Buffer;
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
import { CHANNEL_ID_BASE } from '../../../../config';
|
||||
import Api from '../../tl/api';
|
||||
import createMockedChatAdminRights from './createMockedChatAdminRights';
|
||||
import createMockedChatBannedRights from './createMockedChatBannedRights';
|
||||
@ -14,7 +13,7 @@ export default function createMockedChannel(id: string, mockData: MockTypes): Ap
|
||||
if (!channel) throw Error('No such channel ' + id);
|
||||
|
||||
const {
|
||||
accessHash = BigInt(1),
|
||||
accessHash = 1n,
|
||||
title = 'Channel',
|
||||
date = MOCK_STARTING_DATE,
|
||||
bannedRights = createMockedChatBannedRights(id, mockData),
|
||||
@ -24,7 +23,7 @@ export default function createMockedChannel(id: string, mockData: MockTypes): Ap
|
||||
|
||||
return new Api.Channel({
|
||||
...rest,
|
||||
id: BigInt(Number(id) + 1000000000),
|
||||
id: -BigInt(id) - CHANNEL_ID_BASE,
|
||||
accessHash,
|
||||
title,
|
||||
bannedRights,
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
import Api from '../../tl/api';
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
import Api from '../../tl/api';
|
||||
@ -12,7 +10,7 @@ export default function createMockedDocument(documentId: number, mockData: MockT
|
||||
if (!document) throw Error('No such document ' + documentId);
|
||||
|
||||
const {
|
||||
accessHash = BigInt(1),
|
||||
accessHash = 1n,
|
||||
fileReference = Buffer.from([0]),
|
||||
date = MOCK_STARTING_DATE,
|
||||
dcId = 2,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
import { toJSNumber } from '../../../../util/numbers';
|
||||
import Api from '../../tl/api';
|
||||
|
||||
import { MOCK_STARTING_DATE } from './MockTypes';
|
||||
@ -12,7 +11,7 @@ export default function createMockedPhoto(documentId: number, mockData: MockType
|
||||
if (!document) throw Error('No such document ' + documentId);
|
||||
|
||||
const {
|
||||
accessHash = BigInt(1),
|
||||
accessHash = 1n,
|
||||
fileReference = Buffer.from([0]),
|
||||
date = MOCK_STARTING_DATE,
|
||||
dcId = 2,
|
||||
@ -32,13 +31,13 @@ export default function createMockedPhoto(documentId: number, mockData: MockType
|
||||
type: 'm',
|
||||
w: 100,
|
||||
h: 100,
|
||||
size: size.toJSNumber(),
|
||||
size: toJSNumber(size),
|
||||
}),
|
||||
new Api.PhotoSize({
|
||||
type: 'x',
|
||||
w: 100,
|
||||
h: 100,
|
||||
size: size.toJSNumber(),
|
||||
size: toJSNumber(size),
|
||||
}),
|
||||
],
|
||||
// thumbs?: Api.TypePhotoSize[];
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
import { CHANNEL_ID_BASE } from '../../../../config';
|
||||
import Api from '../../tl/api';
|
||||
|
||||
export default function createMockedReplies(chatId: string, id: number, mockData: MockTypes) {
|
||||
@ -19,7 +18,7 @@ export default function createMockedReplies(chatId: string, id: number, mockData
|
||||
comments: true,
|
||||
replies: replies.replies,
|
||||
repliesPts: 1,
|
||||
channelId: BigInt(1000000000 + 2),
|
||||
channelId: -2n - CHANNEL_ID_BASE,
|
||||
// recentRepliers?: Api.TypePeer[];
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
import { CHANNEL_ID_BASE } from '../../../../config';
|
||||
import Api from '../../tl/api';
|
||||
|
||||
export default function createMockedTypeInputPeer(id: string, mockData: MockTypes): Api.TypeInputPeer {
|
||||
@ -9,7 +8,7 @@ export default function createMockedTypeInputPeer(id: string, mockData: MockType
|
||||
if (user) {
|
||||
return new Api.InputPeerUser({
|
||||
userId: BigInt(id),
|
||||
accessHash: BigInt(1),
|
||||
accessHash: 1n,
|
||||
});
|
||||
}
|
||||
|
||||
@ -23,8 +22,8 @@ export default function createMockedTypeInputPeer(id: string, mockData: MockType
|
||||
const channel = mockData.channels.find((c) => c.id === id);
|
||||
if (channel) {
|
||||
return new Api.InputPeerChannel({
|
||||
channelId: BigInt(Number(id) + 1000000000),
|
||||
accessHash: BigInt(1),
|
||||
channelId: -BigInt(id) - CHANNEL_ID_BASE,
|
||||
accessHash: 1n,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
import { CHANNEL_ID_BASE } from '../../../../config';
|
||||
import Api from '../../tl/api';
|
||||
|
||||
export default function createMockedTypePeer(id: string, mockData: MockTypes): Api.TypePeer {
|
||||
@ -22,7 +21,7 @@ export default function createMockedTypePeer(id: string, mockData: MockTypes): A
|
||||
const channel = mockData.channels.find((c) => c.id === id);
|
||||
if (channel) {
|
||||
return new Api.PeerChannel({
|
||||
channelId: BigInt(Number(id) + 1000000000),
|
||||
channelId: -BigInt(id) - CHANNEL_ID_BASE,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
import Api from '../../tl/api';
|
||||
@ -12,7 +10,7 @@ export default function createMockedUser(id: string, mockData: MockTypes): Api.U
|
||||
const {
|
||||
firstName = 'John',
|
||||
lastName = 'Doe',
|
||||
accessHash = BigInt(1),
|
||||
accessHash = 1n,
|
||||
...rest
|
||||
} = user;
|
||||
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import { toJSNumber } from '../../../../util/numbers';
|
||||
import Api from '../../tl/api';
|
||||
|
||||
export default function getDocumentIdFromLocation(location: Api.TypeInputFileLocation): number {
|
||||
if (location instanceof Api.InputDocumentFileLocation) {
|
||||
return location.id.toJSNumber();
|
||||
return toJSNumber(location.id);
|
||||
}
|
||||
|
||||
if (location instanceof Api.InputPhotoFileLocation) {
|
||||
return location.id.toJSNumber();
|
||||
return toJSNumber(location.id);
|
||||
}
|
||||
|
||||
throw Error('Unsupported input file location type ' + location.className);
|
||||
throw new Error(`Unsupported input file location type ${location.className}`);
|
||||
}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { CHANNEL_ID_BASE } from '../../../../config';
|
||||
import Api from '../../tl/api';
|
||||
|
||||
export default function getIdFromInputPeer(peer: Api.TypeInputPeer | Api.TypeInputChannel) {
|
||||
if (peer instanceof Api.InputPeerChannel || peer instanceof Api.InputChannel) {
|
||||
return (Number(peer.channelId.toString()) - 1000000000).toString();
|
||||
return (-peer.channelId - CHANNEL_ID_BASE).toString();
|
||||
}
|
||||
|
||||
if (peer instanceof Api.InputPeerUser) {
|
||||
@ -10,7 +11,7 @@ export default function getIdFromInputPeer(peer: Api.TypeInputPeer | Api.TypeInp
|
||||
}
|
||||
|
||||
if (peer instanceof Api.InputPeerChat) {
|
||||
return peer.chatId.toString();
|
||||
return (-peer.chatId).toString();
|
||||
}
|
||||
|
||||
throw Error(`Unknown peer type${peer.className}`);
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import type BigInt from 'big-integer';
|
||||
|
||||
import { BinaryReader } from '../extensions';
|
||||
|
||||
import {
|
||||
@ -15,9 +13,9 @@ export class AuthKey {
|
||||
|
||||
_hash?: Buffer;
|
||||
|
||||
private auxHash?: BigInt.BigInteger;
|
||||
private auxHash?: bigint;
|
||||
|
||||
keyId?: BigInt.BigInteger;
|
||||
keyId?: bigint;
|
||||
|
||||
constructor(value?: Buffer, hash?: Buffer) {
|
||||
if (!hash || !value) {
|
||||
@ -55,7 +53,7 @@ export class AuthKey {
|
||||
}
|
||||
|
||||
async waitForKey() {
|
||||
while (!this.keyId) {
|
||||
while (this.keyId === undefined) {
|
||||
await sleep(20);
|
||||
}
|
||||
}
|
||||
@ -70,13 +68,13 @@ export class AuthKey {
|
||||
* Calculates the new nonce hash based on the current class fields' values
|
||||
* @param newNonce
|
||||
* @param number
|
||||
* @returns {BigInt.BigInteger}
|
||||
* @returns {bigint}
|
||||
*/
|
||||
async calcNewNonceHash(
|
||||
newNonce: BigInt.BigInteger,
|
||||
newNonce: bigint,
|
||||
number: number,
|
||||
): Promise<BigInt.BigInteger> {
|
||||
if (!this.auxHash) {
|
||||
): Promise<bigint> {
|
||||
if (this.auxHash === undefined) {
|
||||
throw new Error('Auth key not set');
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,16 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import { modExp } from '../Helpers';
|
||||
import { BigMath, modExp, randBetweenBigInt } from '../Helpers';
|
||||
|
||||
export class Factorizator {
|
||||
/**
|
||||
* Calculates the greatest common divisor
|
||||
* @param a {BigInteger}
|
||||
* @param b {BigInteger}
|
||||
* @returns {BigInteger}
|
||||
* @param a {bigint}
|
||||
* @param b {bigint}
|
||||
* @returns {bigint}
|
||||
*/
|
||||
static gcd(a: BigInt.BigInteger, b: BigInt.BigInteger) {
|
||||
while (b.neq(BigInt.zero)) {
|
||||
static gcd(a: bigint, b: bigint) {
|
||||
while (b !== 0n) {
|
||||
const temp = b;
|
||||
b = a.remainder(b);
|
||||
b = a % b;
|
||||
a = temp;
|
||||
}
|
||||
return a;
|
||||
@ -20,57 +18,57 @@ export class Factorizator {
|
||||
|
||||
/**
|
||||
* Factorizes the given number and returns both the divisor and the number divided by the divisor
|
||||
* @param pq {BigInteger}
|
||||
* @param pq {bigint}
|
||||
* @returns {{p: *, q: *}}
|
||||
*/
|
||||
static factorize(pq: BigInt.BigInteger) {
|
||||
if (pq.remainder(2).equals(BigInt.zero)) {
|
||||
return { p: BigInt(2), q: pq.divide(BigInt(2)) };
|
||||
static factorize(pq: bigint) {
|
||||
if (pq % 2n === 0n) {
|
||||
return { p: 2n, q: pq / 2n };
|
||||
}
|
||||
let y = BigInt.randBetween(BigInt(1), pq.minus(1));
|
||||
const c = BigInt.randBetween(BigInt(1), pq.minus(1));
|
||||
const m = BigInt.randBetween(BigInt(1), pq.minus(1));
|
||||
let y = randBetweenBigInt(1n, pq - 1n);
|
||||
const c = randBetweenBigInt(1n, pq - 1n);
|
||||
const m = randBetweenBigInt(1n, pq - 1n);
|
||||
|
||||
let g = BigInt.one;
|
||||
let r = BigInt.one;
|
||||
let q = BigInt.one;
|
||||
let x = BigInt.zero;
|
||||
let ys = BigInt.zero;
|
||||
let k;
|
||||
let g = 1n;
|
||||
let r = 1n;
|
||||
let q = 1n;
|
||||
let x = 0n;
|
||||
let ys = 0n;
|
||||
let k: bigint;
|
||||
|
||||
while (g.eq(BigInt.one)) {
|
||||
while (g === 1n) {
|
||||
x = y;
|
||||
for (let i = 0; BigInt(i).lesser(r); i++) {
|
||||
y = modExp(y, BigInt(2), pq).add(c).remainder(pq);
|
||||
for (let i = 0n; i < r; i++) {
|
||||
y = (modExp(y, 2n, pq) + c) % pq;
|
||||
}
|
||||
k = BigInt.zero;
|
||||
k = 0n;
|
||||
|
||||
while (k.lesser(r) && g.eq(BigInt.one)) {
|
||||
while (k < r && g === 1n) {
|
||||
ys = y;
|
||||
const condition = BigInt.min(m, r.minus(k));
|
||||
for (let i = 0; BigInt(i).lesser(condition); i++) {
|
||||
y = modExp(y, BigInt(2), pq).add(c).remainder(pq);
|
||||
q = q.multiply(x.minus(y).abs()).remainder(pq);
|
||||
const condition = BigMath.min(m, r - k);
|
||||
for (let i = 0n; i < condition; i++) {
|
||||
y = (modExp(y, 2n, pq) + c) % pq;
|
||||
q = (q * BigMath.abs(x - y)) % pq;
|
||||
}
|
||||
g = Factorizator.gcd(q, pq);
|
||||
k = k.add(m);
|
||||
k = k + m;
|
||||
}
|
||||
|
||||
r = r.multiply(2);
|
||||
r = r * 2n;
|
||||
}
|
||||
|
||||
if (g.eq(pq)) {
|
||||
if (g === pq) {
|
||||
while (true) {
|
||||
ys = modExp(ys, BigInt(2), pq).add(c).remainder(pq);
|
||||
g = Factorizator.gcd(x.minus(ys).abs(), pq);
|
||||
ys = (modExp(ys, 2n, pq) + c) % pq;
|
||||
g = Factorizator.gcd(BigMath.abs(x - ys), pq);
|
||||
|
||||
if (g.greater(1)) {
|
||||
if (g > 1n) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const p = g;
|
||||
q = pq.divide(g);
|
||||
q = pq / g;
|
||||
return p < q ? { p, q } : { p: q, q: p };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import bigInt from 'big-integer';
|
||||
|
||||
import {
|
||||
generateRandomBytes,
|
||||
modExp,
|
||||
@ -10,8 +8,8 @@ import {
|
||||
|
||||
export const SERVER_KEYS = [
|
||||
{
|
||||
fingerprint: bigInt('-3414540481677951611'),
|
||||
n: bigInt(
|
||||
fingerprint: BigInt('-3414540481677951611'),
|
||||
n: BigInt(
|
||||
'2937959817066933702298617714945612856538843112005886376816255642404751219133084745514657634448776440866'
|
||||
+ '1701890505066208632169112269581063774293102577308490531282748465986139880977280302242772832972539403531'
|
||||
+ '3160108704012876427630091361567343395380424193887227773571344877461690935390938502512438971889287359033'
|
||||
@ -22,8 +20,8 @@ export const SERVER_KEYS = [
|
||||
e: 65537,
|
||||
},
|
||||
{
|
||||
fingerprint: bigInt('-5595554452916591101'),
|
||||
n: bigInt(
|
||||
fingerprint: BigInt('-5595554452916591101'),
|
||||
n: BigInt(
|
||||
'2534288944884041556497168959071347320689884775908477905258202659454602246385394058588521595116849196570'
|
||||
+ '8222649399180603818074200620463776135424884632162512403163793083921641631564740959529419359595852941166'
|
||||
+ '8489405859523376133330223960965841179548922160312292373029437018775884567383353986024616752250817918203'
|
||||
@ -34,9 +32,9 @@ export const SERVER_KEYS = [
|
||||
e: 65537,
|
||||
},
|
||||
].reduce((acc, { fingerprint, ...keyInfo }) => {
|
||||
acc.set(fingerprint.toString(), keyInfo);
|
||||
acc.set(fingerprint, keyInfo);
|
||||
return acc;
|
||||
}, new Map<string, { n: bigInt.BigInteger; e: number }>());
|
||||
}, new Map<bigint, { n: bigint; e: number }>());
|
||||
|
||||
/**
|
||||
* Encrypts the given data known the fingerprint to be used
|
||||
@ -46,8 +44,8 @@ export const SERVER_KEYS = [
|
||||
* @param data the data to be encrypted.
|
||||
* @returns {Buffer|*|undefined} the cipher text, or undefined if no key matching this fingerprint is found.
|
||||
*/
|
||||
export async function encrypt(fingerprint: bigInt.BigInteger, data: Buffer) {
|
||||
const key = SERVER_KEYS.get(fingerprint.toString());
|
||||
export async function encrypt(fingerprint: bigint, data: Buffer) {
|
||||
const key = SERVER_KEYS.get(fingerprint);
|
||||
if (!key) {
|
||||
return undefined;
|
||||
}
|
||||
@ -60,7 +58,7 @@ export async function encrypt(fingerprint: bigInt.BigInteger, data: Buffer) {
|
||||
// rsa module rsa.encrypt adds 11 bits for padding which we don't want
|
||||
// rsa module uses rsa.transform.bytes2int(to_encrypt), easier way:
|
||||
const payload = readBigIntFromBuffer(toEncrypt, false);
|
||||
const encrypted = modExp(payload, bigInt(key.e), key.n);
|
||||
const encrypted = modExp(payload, BigInt(key.e), key.n);
|
||||
// rsa module uses transform.int2bytes(encrypted, keylength), easier:
|
||||
return readBufferFromBigInt(encrypted, 256, false);
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ export default class BinaryReader {
|
||||
/**
|
||||
* Reads a long integer (8 bytes or 64 bits) value.
|
||||
* @param signed
|
||||
* @returns {BigInteger}
|
||||
* @returns {bigint}
|
||||
*/
|
||||
readLong(signed = true) {
|
||||
return this.readLargeInt(64, signed);
|
||||
@ -66,7 +66,7 @@ export default class BinaryReader {
|
||||
|
||||
/**
|
||||
* Reads a real floating point (8 bytes) value.
|
||||
* @returns {BigInteger}
|
||||
* @returns {number}
|
||||
*/
|
||||
readDouble() {
|
||||
// was this a bug ? it should have been <d
|
||||
|
||||
@ -1,23 +1,21 @@
|
||||
import type BigInt from 'big-integer';
|
||||
|
||||
import type RequestState from '../network/RequestState';
|
||||
|
||||
export default class PendingState {
|
||||
_pending: Map<string, RequestState>;
|
||||
_pending: Map<bigint, RequestState>;
|
||||
|
||||
constructor() {
|
||||
this._pending = new Map();
|
||||
}
|
||||
|
||||
set(msgId: BigInt.BigInteger, state: RequestState) {
|
||||
this._pending.set(msgId.toString(), state);
|
||||
set(msgId: bigint, state: RequestState) {
|
||||
this._pending.set(msgId, state);
|
||||
}
|
||||
|
||||
get(msgId: BigInt.BigInteger) {
|
||||
return this._pending.get(msgId.toString());
|
||||
get(msgId: bigint) {
|
||||
return this._pending.get(msgId);
|
||||
}
|
||||
|
||||
getAndDelete(msgId: BigInt.BigInteger) {
|
||||
getAndDelete(msgId: bigint) {
|
||||
const state = this.get(msgId);
|
||||
this.delete(msgId);
|
||||
return state;
|
||||
@ -27,8 +25,8 @@ export default class PendingState {
|
||||
return Array.from(this._pending.values());
|
||||
}
|
||||
|
||||
delete(msgId: BigInt.BigInteger) {
|
||||
this._pending.delete(msgId.toString());
|
||||
delete(msgId: bigint) {
|
||||
return this._pending.delete(msgId);
|
||||
}
|
||||
|
||||
clear() {
|
||||
|
||||
247
src/lib/gramjs/helpers.test.ts
Normal file
247
src/lib/gramjs/helpers.test.ts
Normal file
@ -0,0 +1,247 @@
|
||||
import {
|
||||
readBigIntFromBuffer,
|
||||
readBufferFromBigInt,
|
||||
toSignedLittleBuffer,
|
||||
} from './Helpers';
|
||||
|
||||
describe('readBigIntFromBuffer', () => {
|
||||
describe('little endian unsigned', () => {
|
||||
it('should read 8-byte buffer using native method', () => {
|
||||
const buffer = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
|
||||
const result = readBigIntFromBuffer(buffer, true, false);
|
||||
expect(result).toBe(0x0807060504030201n);
|
||||
});
|
||||
|
||||
it('should read 4-byte buffer', () => {
|
||||
const buffer = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]);
|
||||
const result = readBigIntFromBuffer(buffer, true, false);
|
||||
expect(result).toBe(0xFFFFFFFFn);
|
||||
});
|
||||
|
||||
it('should read 2-byte buffer', () => {
|
||||
const buffer = Buffer.from([0x34, 0x12]);
|
||||
const result = readBigIntFromBuffer(buffer, true, false);
|
||||
expect(result).toBe(0x1234n);
|
||||
});
|
||||
});
|
||||
|
||||
describe('big endian unsigned', () => {
|
||||
it('should read 8-byte buffer using native method', () => {
|
||||
const buffer = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
|
||||
const result = readBigIntFromBuffer(buffer, false, false);
|
||||
expect(result).toBe(0x0102030405060708n);
|
||||
});
|
||||
|
||||
it('should read 4-byte buffer', () => {
|
||||
const buffer = Buffer.from([0x12, 0x34, 0x56, 0x78]);
|
||||
const result = readBigIntFromBuffer(buffer, false, false);
|
||||
expect(result).toBe(0x12345678n);
|
||||
});
|
||||
});
|
||||
|
||||
describe('signed values', () => {
|
||||
it('should read positive signed 8-byte value', () => {
|
||||
const buffer = Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
const result = readBigIntFromBuffer(buffer, true, true);
|
||||
expect(result).toBe(1n);
|
||||
});
|
||||
|
||||
it('should read negative signed 8-byte value', () => {
|
||||
const buffer = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
|
||||
const result = readBigIntFromBuffer(buffer, true, true);
|
||||
expect(result).toBe(-1n);
|
||||
});
|
||||
|
||||
it('should read negative signed 4-byte value', () => {
|
||||
const buffer = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]);
|
||||
const result = readBigIntFromBuffer(buffer, true, true);
|
||||
expect(result).toBe(-1n);
|
||||
});
|
||||
|
||||
it('should read max signed 8-byte value', () => {
|
||||
const buffer = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F]);
|
||||
const result = readBigIntFromBuffer(buffer, true, true);
|
||||
expect(result).toBe(0x7FFFFFFFFFFFFFFFn);
|
||||
});
|
||||
|
||||
it('should read min signed 8-byte value', () => {
|
||||
const buffer = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]);
|
||||
const result = readBigIntFromBuffer(buffer, true, true);
|
||||
expect(result).toBe(-0x8000000000000000n);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toSignedLittleBuffer', () => {
|
||||
describe('8-byte buffers (native method)', () => {
|
||||
it('should convert positive value', () => {
|
||||
const buffer = toSignedLittleBuffer(0x0102030405060708n, 8);
|
||||
expect(buffer).toEqual(Buffer.from([0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]));
|
||||
});
|
||||
|
||||
it('should convert negative value', () => {
|
||||
const buffer = toSignedLittleBuffer(-1n, 8);
|
||||
expect(buffer).toEqual(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
|
||||
});
|
||||
|
||||
it('should convert zero', () => {
|
||||
const buffer = toSignedLittleBuffer(0n, 8);
|
||||
expect(buffer).toEqual(Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
|
||||
});
|
||||
|
||||
it('should convert max signed 64-bit value', () => {
|
||||
const buffer = toSignedLittleBuffer(0x7FFFFFFFFFFFFFFFn, 8);
|
||||
expect(buffer).toEqual(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F]));
|
||||
});
|
||||
|
||||
it('should convert min signed 64-bit value', () => {
|
||||
const buffer = toSignedLittleBuffer(-0x8000000000000000n, 8);
|
||||
expect(buffer).toEqual(Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('non-8-byte buffers', () => {
|
||||
it('should convert 4-byte value', () => {
|
||||
const buffer = toSignedLittleBuffer(0x12345678n, 4);
|
||||
expect(buffer).toEqual(Buffer.from([0x78, 0x56, 0x34, 0x12]));
|
||||
});
|
||||
|
||||
it('should convert 2-byte value', () => {
|
||||
const buffer = toSignedLittleBuffer(0x1234n, 2);
|
||||
expect(buffer).toEqual(Buffer.from([0x34, 0x12]));
|
||||
});
|
||||
|
||||
it('should convert 16-byte value', () => {
|
||||
const buffer = toSignedLittleBuffer(0x0102030405060708090A0B0C0D0E0F10n, 16);
|
||||
expect(buffer).toEqual(Buffer.from([
|
||||
0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09,
|
||||
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
|
||||
]));
|
||||
});
|
||||
|
||||
it('should handle negative values for non-8-byte buffers', () => {
|
||||
const buffer = toSignedLittleBuffer(-1n, 4);
|
||||
expect(buffer).toEqual(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('readBufferFromBigInt', () => {
|
||||
describe('8-byte buffers (native methods)', () => {
|
||||
it('should write unsigned little endian', () => {
|
||||
const buffer = readBufferFromBigInt(0x0102030405060708n, 8, true, false);
|
||||
expect(buffer).toEqual(Buffer.from([0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]));
|
||||
});
|
||||
|
||||
it('should write unsigned big endian', () => {
|
||||
const buffer = readBufferFromBigInt(0x0102030405060708n, 8, false, false);
|
||||
expect(buffer).toEqual(Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]));
|
||||
});
|
||||
|
||||
it('should write signed positive little endian', () => {
|
||||
const buffer = readBufferFromBigInt(1234567890n, 8, true, true);
|
||||
const read = readBigIntFromBuffer(buffer, true, true);
|
||||
expect(read).toBe(1234567890n);
|
||||
});
|
||||
|
||||
it('should write signed negative little endian', () => {
|
||||
const buffer = readBufferFromBigInt(-1n, 8, true, true);
|
||||
expect(buffer).toEqual(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
|
||||
});
|
||||
|
||||
it('should write signed negative big endian', () => {
|
||||
const buffer = readBufferFromBigInt(-1n, 8, false, true);
|
||||
expect(buffer).toEqual(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('non-8-byte buffers', () => {
|
||||
it('should write 4-byte unsigned little endian', () => {
|
||||
const buffer = readBufferFromBigInt(0x12345678n, 4, true, false);
|
||||
expect(buffer).toEqual(Buffer.from([0x78, 0x56, 0x34, 0x12]));
|
||||
});
|
||||
|
||||
it('should write 4-byte unsigned big endian', () => {
|
||||
const buffer = readBufferFromBigInt(0x12345678n, 4, false, false);
|
||||
expect(buffer).toEqual(Buffer.from([0x12, 0x34, 0x56, 0x78]));
|
||||
});
|
||||
|
||||
it('should write 2-byte value', () => {
|
||||
const buffer = readBufferFromBigInt(0x1234n, 2, true, false);
|
||||
expect(buffer).toEqual(Buffer.from([0x34, 0x12]));
|
||||
});
|
||||
|
||||
it('should write 16-byte value', () => {
|
||||
const buffer = readBufferFromBigInt(0x0102030405060708090A0B0C0D0E0F10n, 16, false, false);
|
||||
expect(buffer).toEqual(Buffer.from([
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
]));
|
||||
});
|
||||
|
||||
it('should write signed negative 4-byte value', () => {
|
||||
const buffer = readBufferFromBigInt(-1n, 4, true, true);
|
||||
expect(buffer).toEqual(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]));
|
||||
});
|
||||
|
||||
it('should write signed negative 4-byte value big endian', () => {
|
||||
const buffer = readBufferFromBigInt(-1n, 4, false, true);
|
||||
expect(buffer).toEqual(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]));
|
||||
});
|
||||
|
||||
it('should pad with zeros for smaller values', () => {
|
||||
const buffer = readBufferFromBigInt(0xFFn, 4, true, false);
|
||||
expect(buffer).toEqual(Buffer.from([0xFF, 0x00, 0x00, 0x00]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('error handling', () => {
|
||||
it('should throw when converting negative to unsigned', () => {
|
||||
expect(() => readBufferFromBigInt(-1n, 8, true, false))
|
||||
.toThrow('Cannot convert negative to unsigned');
|
||||
});
|
||||
|
||||
it('should throw when value is too large for buffer', () => {
|
||||
const largeValue = 0x1FFFFFFFFFFFFFFFFn; // Too large for 8 bytes
|
||||
expect(() => readBufferFromBigInt(largeValue, 8, true, false))
|
||||
.toThrow('Value 36893488147419103231 does not fit in 8 unsigned bytes');
|
||||
});
|
||||
});
|
||||
|
||||
describe('round-trip consistency', () => {
|
||||
it('should maintain value through read/write cycle (unsigned)', () => {
|
||||
const original = 0x123456789ABCDEFn;
|
||||
const buffer = readBufferFromBigInt(original, 8, true, false);
|
||||
const result = readBigIntFromBuffer(buffer, true, false);
|
||||
expect(result).toBe(original);
|
||||
});
|
||||
|
||||
it('should maintain value through read/write cycle (signed positive)', () => {
|
||||
const original = 0x123456789ABCDEFn;
|
||||
const buffer = readBufferFromBigInt(original, 8, true, true);
|
||||
const result = readBigIntFromBuffer(buffer, true, true);
|
||||
expect(result).toBe(original);
|
||||
});
|
||||
|
||||
it('should maintain value through read/write cycle (signed negative)', () => {
|
||||
const original = -0x123456789ABCDEFn;
|
||||
const buffer = readBufferFromBigInt(original, 8, true, true);
|
||||
const result = readBigIntFromBuffer(buffer, true, true);
|
||||
expect(result).toBe(original);
|
||||
});
|
||||
|
||||
it('should maintain value through read/write cycle (big endian)', () => {
|
||||
const original = 0x123456789ABCDEFn;
|
||||
const buffer = readBufferFromBigInt(original, 8, false, false);
|
||||
const result = readBigIntFromBuffer(buffer, false, false);
|
||||
expect(result).toBe(original);
|
||||
});
|
||||
|
||||
it('should maintain value for 4-byte buffers', () => {
|
||||
const original = 0x12345678n;
|
||||
const buffer = readBufferFromBigInt(original, 4, true, false);
|
||||
const result = readBigIntFromBuffer(buffer, true, false);
|
||||
expect(result).toBe(original);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -5,8 +5,6 @@
|
||||
* @returns {Promise<{authKey: *, timeOffset: *}>}
|
||||
*/
|
||||
|
||||
import bigInt from 'big-integer';
|
||||
|
||||
import type MTProtoPlainSender from './MTProtoPlainSender';
|
||||
|
||||
import { IGE } from '../crypto/IGE';
|
||||
@ -43,7 +41,7 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
if (!(resPQ instanceof Api.ResPQ)) {
|
||||
throw new SecurityError(`Step 1 answer was ${resPQ}`);
|
||||
}
|
||||
if (resPQ.nonce.neq(nonce)) {
|
||||
if (resPQ.nonce !== nonce) {
|
||||
throw new SecurityError('Step 1 invalid nonce from server');
|
||||
}
|
||||
const pq = readBigIntFromBuffer(resPQ.pq, false, true);
|
||||
@ -70,7 +68,7 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
let targetFingerprint;
|
||||
let targetKey;
|
||||
for (const fingerprint of resPQ.serverPublicKeyFingerprints) {
|
||||
targetKey = SERVER_KEYS.get(fingerprint.toString());
|
||||
targetKey = SERVER_KEYS.get(fingerprint);
|
||||
if (targetKey !== undefined) {
|
||||
targetFingerprint = fingerprint;
|
||||
break;
|
||||
@ -98,11 +96,11 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
|
||||
const keyAesEncrypted = Buffer.concat([tempKeyXor, aesEncrypted]);
|
||||
const keyAesEncryptedInt = readBigIntFromBuffer(keyAesEncrypted, false, false);
|
||||
if (keyAesEncryptedInt.greaterOrEquals(targetKey.n)) {
|
||||
if (keyAesEncryptedInt >= targetKey.n) {
|
||||
log.debug('Aes key greater than RSA. retrying');
|
||||
continue;
|
||||
}
|
||||
const encryptedDataBuffer = modExp(keyAesEncryptedInt, bigInt(targetKey.e), targetKey.n);
|
||||
const encryptedDataBuffer = modExp(keyAesEncryptedInt, BigInt(targetKey.e), targetKey.n);
|
||||
encryptedData = readBufferFromBigInt(encryptedDataBuffer, 256, false, false);
|
||||
|
||||
break;
|
||||
@ -133,11 +131,11 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
) {
|
||||
throw new Error(`Step 2.1 answer was ${serverDhParams}`);
|
||||
}
|
||||
if (serverDhParams.nonce.neq(resPQ.nonce)) {
|
||||
if (serverDhParams.nonce !== resPQ.nonce) {
|
||||
throw new SecurityError('Step 2 invalid nonce from server');
|
||||
}
|
||||
|
||||
if (serverDhParams.serverNonce.neq(resPQ.serverNonce)) {
|
||||
if (serverDhParams.serverNonce !== resPQ.serverNonce) {
|
||||
throw new SecurityError('Step 2 invalid server nonce from server');
|
||||
}
|
||||
|
||||
@ -146,7 +144,7 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
toSignedLittleBuffer(newNonce, 32).slice(4, 20),
|
||||
);
|
||||
const nnh = readBigIntFromBuffer(sh, true, true);
|
||||
if (serverDhParams.newNonceHash.neq(nnh)) {
|
||||
if (serverDhParams.newNonceHash !== nnh) {
|
||||
throw new SecurityError('Step 2 invalid DH fail nonce from server');
|
||||
}
|
||||
}
|
||||
@ -178,10 +176,10 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
throw new SecurityError('Step 3 Invalid hash answer');
|
||||
}
|
||||
|
||||
if (serverDhInner.nonce.neq(resPQ.nonce)) {
|
||||
if (serverDhInner.nonce !== resPQ.nonce) {
|
||||
throw new SecurityError('Step 3 Invalid nonce in encrypted answer');
|
||||
}
|
||||
if (serverDhInner.serverNonce.neq(resPQ.serverNonce)) {
|
||||
if (serverDhInner.serverNonce !== resPQ.serverNonce) {
|
||||
throw new SecurityError(
|
||||
'Step 3 Invalid server nonce in encrypted answer',
|
||||
);
|
||||
@ -207,26 +205,26 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
false,
|
||||
false,
|
||||
);
|
||||
const gb = modExp(bigInt(serverDhInner.g), b, dhPrime);
|
||||
const gb = modExp(BigInt(serverDhInner.g), b, dhPrime);
|
||||
const gab = modExp(ga, b, dhPrime);
|
||||
|
||||
if (ga.lesserOrEquals(1)) {
|
||||
if (ga <= 1n) {
|
||||
throw new SecurityError('Step 3 failed ga > 1 check');
|
||||
}
|
||||
|
||||
if (gb.lesserOrEquals(1)) {
|
||||
if (gb <= 1n) {
|
||||
throw new SecurityError('Step 3 failed gb > 1 check');
|
||||
}
|
||||
|
||||
if (ga.greater(dhPrime.minus(1))) {
|
||||
throw new SecurityError('Step 3 failed ga > dh_prime - 1 check');
|
||||
if (ga >= (dhPrime - 1n)) {
|
||||
throw new SecurityError('Step 3 failed ga < dh_prime - 1 check');
|
||||
}
|
||||
|
||||
const toCheckAgainst = bigInt(2).pow(2048 - 64);
|
||||
if (!(ga.greaterOrEquals(toCheckAgainst) && ga.lesserOrEquals(dhPrime.minus(toCheckAgainst)))) {
|
||||
const toCheckAgainst = 2n ** (2048n - 64n);
|
||||
if (!(ga > toCheckAgainst && ga < (dhPrime - toCheckAgainst))) {
|
||||
throw new SecurityError('Step 3 failed dh_prime - 2^{2048-64} < ga < 2^{2048-64} check');
|
||||
}
|
||||
if (!(gb.greaterOrEquals(toCheckAgainst) && gb.lesserOrEquals(dhPrime.minus(toCheckAgainst)))) {
|
||||
if (!(gb > toCheckAgainst && gb < (dhPrime - toCheckAgainst))) {
|
||||
throw new SecurityError('Step 3 failed dh_prime - 2^{2048-64} < gb < 2^{2048-64} check');
|
||||
}
|
||||
|
||||
@ -234,7 +232,7 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
const clientDhInner = new Api.ClientDHInnerData({
|
||||
nonce: resPQ.nonce,
|
||||
serverNonce: resPQ.serverNonce,
|
||||
retryId: bigInt.zero, // TODO Actual retry ID
|
||||
retryId: 0n, // TODO Actual retry ID
|
||||
gB: getByteArray(gb, false),
|
||||
}).getBytes();
|
||||
|
||||
@ -265,10 +263,10 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
throw new Error(`Step 3.1 answer was ${dhGen}`);
|
||||
}
|
||||
const { name } = dhGen.constructor;
|
||||
if (dhGen.nonce.neq(resPQ.nonce)) {
|
||||
if (dhGen.nonce !== resPQ.nonce) {
|
||||
throw new SecurityError(`Step 3 invalid ${name} nonce from server`);
|
||||
}
|
||||
if (dhGen.serverNonce.neq(resPQ.serverNonce)) {
|
||||
if (dhGen.serverNonce !== resPQ.serverNonce) {
|
||||
throw new SecurityError(
|
||||
`Step 3 invalid ${name} server nonce from server`,
|
||||
);
|
||||
@ -279,10 +277,10 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) {
|
||||
const nonceNumber = 1 + nonceTypesString.indexOf(dhGen.className);
|
||||
|
||||
const newNonceHash = await authKey.calcNewNonceHash(newNonce, nonceNumber);
|
||||
// @ts-ignore
|
||||
const dhHash = dhGen[`newNonceHash${nonceNumber}`];
|
||||
// @ts-expect-error
|
||||
const dhHash = dhGen[`newNonceHash${nonceNumber}`] as bigint;
|
||||
|
||||
if (dhHash.neq(newNonceHash)) {
|
||||
if (dhHash !== newNonceHash) {
|
||||
throw new SecurityError('Step 3 invalid new nonce hash');
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
* This module contains the class used to communicate with Telegram's servers
|
||||
* in plain text, when no authorization key has been created yet.
|
||||
*/
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { Logger } from '../extensions';
|
||||
import type { Api } from '../tl';
|
||||
@ -53,11 +52,11 @@ export default class MTProtoPlainSender {
|
||||
}
|
||||
const reader = new BinaryReader(body);
|
||||
const authKeyId = reader.readLong();
|
||||
if (authKeyId.neq(BigInt(0))) {
|
||||
if (authKeyId !== 0n) {
|
||||
throw new Error('Bad authKeyId');
|
||||
}
|
||||
msgId = reader.readLong();
|
||||
if (msgId.eq(BigInt(0))) {
|
||||
if (msgId === 0n) {
|
||||
throw new Error('Bad msgId');
|
||||
}
|
||||
/** ^ We should make sure that the read ``msg_id`` is greater
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import type BigInt from 'big-integer';
|
||||
|
||||
import type { TLMessage } from '../tl/core';
|
||||
|
||||
import { RPCError, RPCMessageToError } from '../errors';
|
||||
@ -18,7 +16,7 @@ import {
|
||||
BadMessageError, InvalidBufferError, SecurityError, TypeNotFoundError,
|
||||
} from '../errors/Common';
|
||||
import PendingState from '../extensions/PendingState';
|
||||
import { sleep } from '../Helpers';
|
||||
import { jsonStringifyWithBigInt, sleep } from '../Helpers';
|
||||
import MessageContainer from '../tl/core/MessageContainer';
|
||||
import { doAuthentication } from './Authenticator';
|
||||
import MtProtoPlainSender from './MTProtoPlainSender';
|
||||
@ -823,16 +821,16 @@ export default class MTProtoSender {
|
||||
* @returns {*[]}
|
||||
* @private
|
||||
*/
|
||||
_popStates(msgId: BigInt.BigInteger) {
|
||||
_popStates(msgId: bigint) {
|
||||
const state = this._pendingState.getAndDelete(msgId);
|
||||
if (state) {
|
||||
return [state];
|
||||
}
|
||||
|
||||
const toPop: BigInt.BigInteger[] = [];
|
||||
const toPop: bigint[] = [];
|
||||
|
||||
for (const pendingState of this._pendingState.values()) {
|
||||
if (pendingState.containerId?.equals(msgId)) {
|
||||
if (pendingState.containerId === msgId) {
|
||||
toPop.push(pendingState.msgId!);
|
||||
}
|
||||
}
|
||||
@ -1005,7 +1003,7 @@ export default class MTProtoSender {
|
||||
_handleBadNotification(message: TLMessage) {
|
||||
const badMsg = message.obj;
|
||||
const states = this._popStates(badMsg.badMsgId);
|
||||
this._log.debug(`Handling bad msg ${JSON.stringify(badMsg)}`);
|
||||
this._log.debug(`Handling bad msg ${jsonStringifyWithBigInt(badMsg)}`);
|
||||
if ([16, 17].includes(badMsg.errorCode)) {
|
||||
// Sent msg_id too low or too high (respectively).
|
||||
// Use the current msg_id to determine the right time offset.
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { AuthKey } from '../crypto/AuthKey';
|
||||
|
||||
import { CTR } from '../crypto/CTR';
|
||||
@ -27,9 +25,9 @@ export default class MTProtoState {
|
||||
|
||||
timeOffset: number;
|
||||
|
||||
salt: bigInt.BigInteger;
|
||||
salt: bigint;
|
||||
|
||||
private id: bigInt.BigInteger;
|
||||
private id: bigint;
|
||||
|
||||
_sequence: number;
|
||||
|
||||
@ -37,7 +35,7 @@ export default class MTProtoState {
|
||||
|
||||
_isOutgoing: boolean;
|
||||
|
||||
private _lastMsgId: bigInt.BigInteger;
|
||||
private _lastMsgId: bigint;
|
||||
|
||||
private msgIds: string[];
|
||||
|
||||
@ -74,11 +72,11 @@ export default class MTProtoState {
|
||||
this._isCall = isCall;
|
||||
this._isOutgoing = isOutgoing;
|
||||
this.timeOffset = 0;
|
||||
this.salt = BigInt.zero;
|
||||
this.salt = 0n;
|
||||
|
||||
this.id = BigInt.zero;
|
||||
this.id = 0n;
|
||||
this._sequence = 0;
|
||||
this._lastMsgId = BigInt.zero;
|
||||
this._lastMsgId = 0n;
|
||||
this.msgIds = [];
|
||||
this.reset();
|
||||
}
|
||||
@ -90,7 +88,7 @@ export default class MTProtoState {
|
||||
// Session IDs can be random on every connection
|
||||
this.id = generateRandomLong(true);
|
||||
this._sequence = 0;
|
||||
this._lastMsgId = BigInt(0);
|
||||
this._lastMsgId = 0n;
|
||||
this.msgIds = [];
|
||||
}
|
||||
|
||||
@ -142,11 +140,13 @@ export default class MTProtoState {
|
||||
* @param contentRelated
|
||||
* @param afterId
|
||||
*/
|
||||
async writeDataAsMessage(buffer: BinaryWriter, data: Buffer, contentRelated: boolean, afterId?: BigInt.BigInteger) {
|
||||
async writeDataAsMessage(
|
||||
buffer: BinaryWriter, data: Buffer, contentRelated: boolean, afterId?: bigint,
|
||||
): Promise<bigint> {
|
||||
const msgId = this._getNewMsgId();
|
||||
const seqNo = this._getSeqNo(contentRelated);
|
||||
let body;
|
||||
if (!afterId) {
|
||||
if (afterId === undefined) {
|
||||
body = await GZIPPacked.gzipIfSmaller(contentRelated, data);
|
||||
} else {
|
||||
// Invoke query expects a query with a getBytes func
|
||||
@ -185,7 +185,7 @@ export default class MTProtoState {
|
||||
throw new Error('Auth key unset');
|
||||
}
|
||||
|
||||
if (!this.salt || !this.id || !authKey || !this.authKey.keyId) {
|
||||
if (this.salt === undefined || this.authKey.keyId === undefined) {
|
||||
throw new Error('Unset params');
|
||||
}
|
||||
|
||||
@ -255,7 +255,7 @@ export default class MTProtoState {
|
||||
if (!this._isCall) {
|
||||
const keyId = readBigIntFromBuffer(body.slice(0, 8));
|
||||
|
||||
if (!this.authKey.keyId || keyId.neq(this.authKey.keyId)) {
|
||||
if (keyId !== this.authKey.keyId) {
|
||||
throw new SecurityError('Server replied with an invalid auth key');
|
||||
}
|
||||
}
|
||||
@ -304,7 +304,7 @@ export default class MTProtoState {
|
||||
} else {
|
||||
reader.readLong(); // removeSalt
|
||||
const serverId = reader.readLong();
|
||||
if (!serverId.eq(this.id)) {
|
||||
if (serverId !== this.id) {
|
||||
throw new SecurityError('Server replied with a wrong session ID');
|
||||
}
|
||||
|
||||
@ -358,11 +358,9 @@ export default class MTProtoState {
|
||||
_getNewMsgId() {
|
||||
const now = Date.now() / 1000 + this.timeOffset;
|
||||
const nanoseconds = Math.floor((now - Math.floor(now)) * 1e9);
|
||||
let newMsgId = (BigInt(Math.floor(now))
|
||||
.shiftLeft(BigInt(32))).or(BigInt(nanoseconds)
|
||||
.shiftLeft(BigInt(2)));
|
||||
if (this._lastMsgId.greaterOrEquals(newMsgId)) {
|
||||
newMsgId = this._lastMsgId.add(BigInt(4));
|
||||
let newMsgId = (BigInt(Math.floor(now)) << 32n) | (BigInt(nanoseconds) << 2n);
|
||||
if (this._lastMsgId >= newMsgId) {
|
||||
newMsgId = this._lastMsgId + 4n;
|
||||
}
|
||||
this._lastMsgId = newMsgId;
|
||||
return newMsgId;
|
||||
@ -371,28 +369,28 @@ export default class MTProtoState {
|
||||
/**
|
||||
* Returns the understood time by the message id (server time + local offset)
|
||||
*/
|
||||
getMsgIdTimeLocal(msgId: BigInt.BigInteger) {
|
||||
if (this._lastMsgId.eq(0)) {
|
||||
getMsgIdTimeLocal(msgId: bigint) {
|
||||
if (this._lastMsgId === 0n) {
|
||||
// this means it's the first message sent/received so don't check yet
|
||||
return false;
|
||||
return undefined;
|
||||
}
|
||||
return msgId.shiftRight(BigInt(32)).toJSNumber() - this.timeOffset;
|
||||
return Number(msgId >> 32n) - this.timeOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the time offset to the correct
|
||||
* one given a known valid message ID.
|
||||
* @param correctMsgId {BigInteger}
|
||||
* @param correctMsgId {bigint}
|
||||
*/
|
||||
updateTimeOffset(correctMsgId: BigInt.BigInteger) {
|
||||
updateTimeOffset(correctMsgId: bigint) {
|
||||
const bad = this._getNewMsgId();
|
||||
const old = this.timeOffset;
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const correct = correctMsgId.shiftRight(BigInt(32)).toJSNumber();
|
||||
const correct = Number(correctMsgId >> 32n);
|
||||
this.timeOffset = correct - now;
|
||||
|
||||
if (this.timeOffset !== old) {
|
||||
this._lastMsgId = BigInt(0);
|
||||
this._lastMsgId = 0n;
|
||||
this._log.debug(
|
||||
// eslint-disable-next-line @stylistic/max-len
|
||||
`Updated time offset (old offset ${old}, bad ${bad.toString()}, good ${correctMsgId.toString()}, new ${this.timeOffset})`,
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import type BigInt from 'big-integer';
|
||||
|
||||
import type { Api } from '../tl';
|
||||
|
||||
import Deferred from '../../../util/Deferred';
|
||||
@ -8,9 +6,9 @@ export type CallableRequest = Api.AnyRequest | Api.MsgsAck | Api.MsgsStateInfo |
|
||||
type RequestResponse<T> = T extends { __response: infer R } ? R : void;
|
||||
|
||||
export default class RequestState<T extends CallableRequest = CallableRequest> {
|
||||
public containerId?: BigInt.BigInteger;
|
||||
public containerId?: bigint;
|
||||
|
||||
public msgId?: BigInt.BigInteger;
|
||||
public msgId?: bigint;
|
||||
|
||||
public request: any;
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import BigInt from 'big-integer';
|
||||
|
||||
import type { PromisedWebSockets } from '../../extensions';
|
||||
|
||||
import { readBufferFromBigInt } from '../../Helpers';
|
||||
|
||||
@ -3,7 +3,7 @@ export abstract class MTProtoRequest {
|
||||
|
||||
private sequence: number;
|
||||
|
||||
private msgId: number;
|
||||
private msgId: bigint;
|
||||
|
||||
private readonly dirty: boolean;
|
||||
|
||||
@ -19,7 +19,7 @@ export abstract class MTProtoRequest {
|
||||
|
||||
constructor() {
|
||||
this.sent = false;
|
||||
this.msgId = 0; // long
|
||||
this.msgId = 0n; // long
|
||||
this.sequence = 0;
|
||||
|
||||
this.dirty = false;
|
||||
|
||||
8
src/lib/gramjs/tl/api.d.ts
vendored
8
src/lib/gramjs/tl/api.d.ts
vendored
@ -1,8 +1,6 @@
|
||||
|
||||
// This file is autogenerated. All changes will be overwritten.
|
||||
|
||||
import { BigInteger } from 'big-integer';
|
||||
|
||||
export default Api;
|
||||
|
||||
namespace Api {
|
||||
@ -21,9 +19,9 @@ namespace Api {
|
||||
type Bool = boolean;
|
||||
type int = number;
|
||||
type double = number;
|
||||
type int128 = BigInteger;
|
||||
type int256 = BigInteger;
|
||||
type long = BigInteger;
|
||||
type int128 = bigint;
|
||||
type int256 = bigint;
|
||||
type long = bigint;
|
||||
type bytes = Buffer;
|
||||
|
||||
class VirtualClass<Args extends AnyLiteral> {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import type BigInt from 'big-integer';
|
||||
|
||||
import type { BinaryReader } from '../../extensions';
|
||||
|
||||
@ -13,7 +12,7 @@ export default class RPCResult {
|
||||
|
||||
private CONSTRUCTOR_ID: number;
|
||||
|
||||
private reqMsgId: BigInt.BigInteger;
|
||||
private reqMsgId: bigint;
|
||||
|
||||
private body?: Buffer;
|
||||
|
||||
@ -22,7 +21,7 @@ export default class RPCResult {
|
||||
private classType: string;
|
||||
|
||||
constructor(
|
||||
reqMsgId: BigInt.BigInteger,
|
||||
reqMsgId: bigint,
|
||||
body?: Buffer,
|
||||
error?: Api.RpcError,
|
||||
) {
|
||||
|
||||
@ -1,17 +1,15 @@
|
||||
import type BigInt from 'big-integer';
|
||||
|
||||
export default class TLMessage {
|
||||
static SIZE_OVERHEAD = 12;
|
||||
|
||||
static classType = 'constructor';
|
||||
|
||||
msgId: BigInt.BigInteger;
|
||||
msgId: bigint;
|
||||
|
||||
private seqNo: number;
|
||||
|
||||
obj: any;
|
||||
|
||||
constructor(msgId: bigInt.BigInteger, seqNo: number, obj: any) {
|
||||
constructor(msgId: bigint, seqNo: number, obj: any) {
|
||||
this.msgId = msgId;
|
||||
this.seqNo = seqNo;
|
||||
this.obj = obj;
|
||||
|
||||
@ -158,8 +158,6 @@ ${indent}}`.trim();
|
||||
return `
|
||||
// This file is autogenerated. All changes will be overwritten.
|
||||
|
||||
import { BigInteger } from 'big-integer';
|
||||
|
||||
export default Api;
|
||||
|
||||
namespace Api {
|
||||
@ -178,9 +176,9 @@ namespace Api {
|
||||
type Bool = boolean;
|
||||
type int = number;
|
||||
type double = number;
|
||||
type int128 = BigInteger;
|
||||
type int256 = BigInteger;
|
||||
type long = BigInteger;
|
||||
type int128 = bigint;
|
||||
type int256 = bigint;
|
||||
type long = bigint;
|
||||
type bytes = Buffer;
|
||||
|
||||
class VirtualClass<Args extends AnyLiteral> {
|
||||
|
||||
@ -8,7 +8,7 @@ export type FullEntity =
|
||||
| Api.ChannelFull;
|
||||
|
||||
export type EntityLike =
|
||||
| bigInt.BigInteger
|
||||
| bigint
|
||||
| string
|
||||
| Api.TypePeer
|
||||
| Api.TypeInputPeer
|
||||
|
||||
@ -1,26 +1,33 @@
|
||||
import { CHANNEL_ID_BASE } from '../../config';
|
||||
import { toJSNumber } from '../numbers';
|
||||
|
||||
export function isUserId(entityId: string) {
|
||||
return !entityId.startsWith('-');
|
||||
}
|
||||
|
||||
export function isChannelId(entityId: string) {
|
||||
const n = Number(entityId);
|
||||
const n = BigInt(entityId);
|
||||
return n < -CHANNEL_ID_BASE;
|
||||
}
|
||||
|
||||
export function toChannelId(mtpId: string) {
|
||||
const n = Number(mtpId);
|
||||
const n = BigInt(mtpId);
|
||||
return String(-CHANNEL_ID_BASE - n);
|
||||
}
|
||||
|
||||
export function getCleanPeerId(peerId: string) {
|
||||
return isChannelId(peerId)
|
||||
// Remove -1 and leading zeros
|
||||
? peerId.replace(/^-10+/, '')
|
||||
: peerId.replace('-', '');
|
||||
export function getRawPeerId(id: string) {
|
||||
const n = BigInt(id);
|
||||
if (isUserId(id)) {
|
||||
return n;
|
||||
}
|
||||
|
||||
if (isChannelId(id)) {
|
||||
return -n - CHANNEL_ID_BASE;
|
||||
}
|
||||
|
||||
return n * -1n;
|
||||
}
|
||||
|
||||
export function getPeerIdDividend(peerId: string) {
|
||||
return Math.abs(Number(getCleanPeerId(peerId)));
|
||||
return toJSNumber(getRawPeerId(peerId));
|
||||
}
|
||||
|
||||
27
src/util/numbers.ts
Normal file
27
src/util/numbers.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { DEBUG } from '../config';
|
||||
|
||||
export function toJSNumber(value: undefined): undefined;
|
||||
export function toJSNumber(value: bigint): number;
|
||||
export function toJSNumber(value?: bigint): number | undefined;
|
||||
export function toJSNumber(value?: bigint): number | undefined {
|
||||
if (value === undefined) return undefined;
|
||||
|
||||
if (DEBUG && (value < Number.MIN_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Unsafe BigInt conversion', value);
|
||||
}
|
||||
|
||||
return Number(value);
|
||||
}
|
||||
|
||||
export function tryParseBigInt(value: string): bigint | undefined {
|
||||
try {
|
||||
return BigInt(value);
|
||||
} catch (error) {
|
||||
if (DEBUG) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error parsing BigInt', value, error);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user