Gifts: Support channels (#5527)

This commit is contained in:
zubiden 2025-01-27 23:50:53 +01:00 committed by Alexander Zinchuk
parent c492bc677a
commit 10009ce9ba
45 changed files with 1075 additions and 663 deletions

View File

@ -1,29 +1,31 @@
import { Api as GramJs } from '../../../lib/gramjs';
import type {
ApiInputSavedStarGift,
ApiSavedStarGift,
ApiStarGift,
ApiStarGiftAttribute,
ApiUserStarGift,
} from '../../types';
import { numberToHexColor } from '../../../util/colors';
import { addDocumentToLocalDb } from '../helpers';
import { buildApiFormattedText } from './common';
import { buildApiPeerId } from './peers';
import { getApiChatIdFromMtpPeer } from './peers';
import { buildStickerFromDocument } from './symbols';
export function buildApiStarGift(starGift: GramJs.TypeStarGift): ApiStarGift {
if (starGift instanceof GramJs.StarGiftUnique) {
const {
id, num, ownerId, ownerName, title, attributes, availabilityIssued, availabilityTotal, slug,
id, num, ownerId, ownerName, title, attributes, availabilityIssued, availabilityTotal, slug, ownerAddress,
} = starGift;
return {
type: 'starGiftUnique',
id: id.toString(),
number: num,
ownerId: ownerId && buildApiPeerId(ownerId, 'user'),
ownerId: ownerId && getApiChatIdFromMtpPeer(ownerId),
ownerName,
ownerAddress,
attributes: attributes.map(buildApiStarGiftAttribute).filter(Boolean),
title,
totalCount: availabilityTotal,
@ -115,25 +117,30 @@ export function buildApiStarGiftAttribute(attribute: GramJs.TypeStarGiftAttribut
return {
type: 'originalDetails',
date,
recipientId: recipientId && buildApiPeerId(recipientId, 'user'),
recipientId: recipientId && getApiChatIdFromMtpPeer(recipientId),
message: message && buildApiFormattedText(message),
senderId: senderId && buildApiPeerId(senderId, 'user'),
senderId: senderId && getApiChatIdFromMtpPeer(senderId),
};
}
return undefined;
}
export function buildApiUserStarGift(userStarGift: GramJs.UserStarGift): ApiUserStarGift {
export function buildApiSavedStarGift(userStarGift: GramJs.SavedStarGift, peerId: string): ApiSavedStarGift {
const {
gift, date, convertStars, fromId, message, msgId, nameHidden, unsaved, upgradeStars, transferStars, canUpgrade,
savedId,
} = userStarGift;
const inputGift: ApiInputSavedStarGift | undefined = savedId && peerId
? { type: 'chat', chatId: peerId, savedId: savedId.toString() }
: msgId ? { type: 'user', messageId: msgId } : undefined;
return {
gift: buildApiStarGift(gift),
date,
starsToConvert: convertStars?.toJSNumber(),
fromId: fromId && buildApiPeerId(fromId, 'user'),
fromId: fromId && getApiChatIdFromMtpPeer(fromId),
message: message && buildApiFormattedText(message),
messageId: msgId,
isNameHidden: nameHidden,
@ -141,5 +148,7 @@ export function buildApiUserStarGift(userStarGift: GramJs.UserStarGift): ApiUser
canUpgrade,
alreadyPaidUpgradeStars: upgradeStars?.toJSNumber(),
transferStars: transferStars?.toJSNumber(),
inputGift,
savedId: savedId?.toString(),
};
}

View File

@ -11,6 +11,7 @@ import type {
ApiGroupCall,
ApiInputMessageReplyInfo,
ApiInputReplyInfo,
ApiInputSavedStarGift,
ApiKeyboardButton,
ApiMessage,
ApiMessageActionStarGift,
@ -193,7 +194,7 @@ export function buildApiMessageWithChatId(
: isSavedOutgoing;
const content = buildMessageContent(mtpMessage);
const action = mtpMessage.action
&& buildAction(mtpMessage.action, fromId, peerId, Boolean(mtpMessage.post), isOutgoing);
&& buildAction(mtpMessage.action, mtpMessage.id, fromId, peerId, Boolean(mtpMessage.post), isOutgoing);
if (action) {
content.action = action;
}
@ -369,16 +370,29 @@ export function buildApiFactCheck(factCheck: GramJs.FactCheck): ApiFactCheck {
};
}
function buildApiMessageActionStarGift(action: GramJs.MessageActionStarGift) : ApiMessageActionStarGift {
function buildApiMessageActionStarGift(
action: GramJs.MessageActionStarGift, messageId: number,
): ApiMessageActionStarGift {
const {
nameHidden, saved, converted, gift, message, convertStars, canUpgrade, upgraded, upgradeMsgId, upgradeStars,
peer, savedId, fromId,
} = action;
const inputSavedGift: ApiInputSavedStarGift = savedId && peer ? {
type: 'chat',
chatId: getApiChatIdFromMtpPeer(peer),
savedId: savedId.toString(),
} : {
type: 'user',
messageId,
};
return {
type: 'starGift',
isNameHidden: Boolean(nameHidden),
isSaved: Boolean(saved),
isConverted: converted,
fromId: fromId && getApiChatIdFromMtpPeer(fromId),
gift: buildApiStarGift(gift) as ApiStarGiftRegular,
message: message && buildApiFormattedText(message),
starsToConvert: convertStars?.toJSNumber(),
@ -386,16 +400,28 @@ function buildApiMessageActionStarGift(action: GramJs.MessageActionStarGift) : A
isUpgraded: upgraded,
upgradeMsgId,
alreadyPaidUpgradeStars: upgradeStars?.toJSNumber(),
peerId: peer && getApiChatIdFromMtpPeer(peer),
savedId: savedId?.toString(),
inputSavedGift,
};
}
function buildApiMessageActionStarGiftUnique(
action: GramJs.MessageActionStarGiftUnique,
action: GramJs.MessageActionStarGiftUnique, messageId: number,
): ApiMessageActionStarGiftUnique {
const {
gift, canExportAt, refunded, saved, transferStars, transferred, upgrade,
gift, canExportAt, refunded, saved, transferStars, transferred, upgrade, fromId, peer, savedId,
} = action;
const inputSavedGift: ApiInputSavedStarGift = savedId && peer ? {
type: 'chat',
chatId: getApiChatIdFromMtpPeer(peer),
savedId: savedId.toString(),
} : {
type: 'user',
messageId,
};
return {
type: 'starGiftUnique',
gift: buildApiStarGift(gift) as ApiStarGiftUnique,
@ -405,11 +431,16 @@ function buildApiMessageActionStarGiftUnique(
transferStars: transferStars?.toJSNumber(),
isTransferred: transferred,
isUpgrade: upgrade,
fromId: fromId && getApiChatIdFromMtpPeer(fromId),
peerId: peer && getApiChatIdFromMtpPeer(peer),
savedId: savedId?.toString(),
inputSavedGift,
};
}
function buildAction(
action: GramJs.TypeMessageAction,
messageId: number,
senderId: string | undefined,
targetPeerId: string | undefined,
isChannelPost: boolean,
@ -738,7 +769,7 @@ function buildAction(
transactionId = action.transactionId;
} else if (action instanceof GramJs.MessageActionStarGift && action.gift instanceof GramJs.StarGift) {
type = 'starGift';
starGift = buildApiMessageActionStarGift(action);
starGift = buildApiMessageActionStarGift(action, messageId);
if (isOutgoing) {
text = 'ActionGiftOutbound';
translationValues.push('%gift_payment_amount%');
@ -763,9 +794,11 @@ function buildAction(
translationValues.push('%action_origin_chat%');
}
starGift = buildApiMessageActionStarGiftUnique(action);
starGift = buildApiMessageActionStarGiftUnique(action, messageId);
if (targetPeerId) {
if (action.peer) {
targetChatId = getApiChatIdFromMtpPeer(action.peer);
} else if (targetPeerId) {
targetUserIds.push(targetPeerId);
targetChatId = targetPeerId;
}

View File

@ -52,10 +52,11 @@ export function buildApiPeerColor(peerColor: GramJs.TypePeerColor): ApiPeerColor
export function buildApiEmojiStatus(mtpEmojiStatus: GramJs.TypeEmojiStatus): ApiEmojiStatus | undefined {
if (mtpEmojiStatus instanceof GramJs.EmojiStatus) {
return { documentId: mtpEmojiStatus.documentId.toString() };
return { documentId: mtpEmojiStatus.documentId.toString(), until: mtpEmojiStatus.until };
}
if (mtpEmojiStatus instanceof GramJs.EmojiStatusUntil) {
// TODO: Support other parameters
if (mtpEmojiStatus instanceof GramJs.EmojiStatusCollectible) {
return { documentId: mtpEmojiStatus.documentId.toString(), until: mtpEmojiStatus.until };
}

View File

@ -23,6 +23,7 @@ import type {
ApiReactionWithPaid,
ApiReportReason,
ApiRequestInputInvoice,
ApiRequestInputSavedStarGift,
ApiSendMessageAction,
ApiSticker,
ApiStory,
@ -643,10 +644,10 @@ export function buildInputInvoice(invoice: ApiRequestInputInvoice) {
case 'stargift': {
const {
user, shouldHideName, giftId, message, shouldUpgrade,
peer, shouldHideName, giftId, message, shouldUpgrade,
} = invoice;
return new GramJs.InputInvoiceStarGift({
userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser,
peer: buildInputPeer(peer.id, peer.accessHash),
hideName: shouldHideName || undefined,
giftId: BigInt(giftId),
message: message && buildInputTextWithEntities(message),
@ -676,7 +677,7 @@ export function buildInputInvoice(invoice: ApiRequestInputInvoice) {
case 'stargiftUpgrade': {
return new GramJs.InputInvoiceStarGiftUpgrade({
msgId: invoice.messageId,
stargift: buildInputSavedStarGift(invoice.inputSavedGift),
keepOriginalDetails: invoice.shouldKeepOriginalDetails,
});
}
@ -732,15 +733,9 @@ export function buildInputEmojiStatus(emojiStatusId: string, expires?: number) {
return new GramJs.EmojiStatusEmpty();
}
if (expires) {
return new GramJs.EmojiStatusUntil({
documentId: BigInt(emojiStatusId),
until: expires,
});
}
return new GramJs.EmojiStatus({
documentId: BigInt(emojiStatusId),
until: expires,
});
}
@ -845,3 +840,16 @@ export function buildInputPrivacyRules(
return privacyRules;
}
export function buildInputSavedStarGift(inputGift: ApiRequestInputSavedStarGift) {
if (inputGift.type === 'user') {
return new GramJs.InputSavedStarGiftUser({
msgId: inputGift.messageId,
});
}
return new GramJs.InputSavedStarGiftChat({
peer: buildInputPeer(inputGift.chat.id, inputGift.chat.accessHash),
savedId: BigInt(inputGift.savedId),
});
}

View File

@ -608,6 +608,8 @@ async function getFullChannelInfo(
canViewRevenue: canViewMonetization,
paidReactionsAvailable,
hasScheduled,
stargiftsCount,
stargiftsAvailable,
} = result.fullChat;
if (chatPhoto) {
@ -700,6 +702,8 @@ async function getFullChannelInfo(
botVerification: botVerification && buildApiBotVerification(botVerification),
isPaidReactionAvailable: paidReactionsAvailable,
hasScheduledMessages: hasScheduled,
starGiftCount: stargiftsCount,
areStarGiftsAvailable: Boolean(stargiftsAvailable),
},
chats,
userStatusesById: statusesById,

View File

@ -6,16 +6,16 @@ import type {
ApiInputStorePaymentPurpose,
ApiPeer,
ApiRequestInputInvoice,
ApiRequestInputSavedStarGift,
ApiStarGiftRegular,
ApiThemeParameters,
ApiUser,
} from '../../types';
import { DEBUG } from '../../../config';
import {
buildApiSavedStarGift,
buildApiStarGift,
buildApiStarGiftAttribute,
buildApiUserStarGift,
} from '../apiBuilders/gifts';
import {
buildApiBoost,
@ -37,7 +37,12 @@ import {
} from '../apiBuilders/payments';
import { buildApiPeerId } from '../apiBuilders/peers';
import {
buildInputInvoice, buildInputPeer, buildInputStorePaymentPurpose, buildInputThemeParams, buildShippingInfo,
buildInputInvoice,
buildInputPeer,
buildInputSavedStarGift,
buildInputStorePaymentPurpose,
buildInputThemeParams,
buildShippingInfo,
} from '../gramjsBuilders';
import {
deserializeBytes,
@ -440,17 +445,17 @@ export async function fetchStarGifts() {
return result.gifts.map(buildApiStarGift).filter((gift): gift is ApiStarGiftRegular => gift.type === 'starGift');
}
export async function fetchUserStarGifts({
user,
export async function fetchSavedStarGifts({
peer,
offset = '',
limit,
}: {
user: ApiUser;
peer: ApiPeer;
offset?: string;
limit?: number;
}) {
const result = await invokeRequest(new GramJs.payments.GetUserStarGifts({
userId: buildInputPeer(user.id, user.accessHash),
const result = await invokeRequest(new GramJs.payments.GetSavedStarGifts({
peer: buildInputPeer(peer.id, peer.accessHash),
offset,
limit,
}));
@ -459,7 +464,7 @@ export async function fetchUserStarGifts({
return undefined;
}
const gifts = result.gifts.map(buildApiUserStarGift);
const gifts = result.gifts.map((g) => buildApiSavedStarGift(g, peer.id));
return {
gifts,
@ -468,25 +473,25 @@ export async function fetchUserStarGifts({
}
export function saveStarGift({
messageId,
inputGift,
shouldUnsave,
}: {
messageId: number;
inputGift: ApiRequestInputSavedStarGift;
shouldUnsave?: boolean;
}) {
return invokeRequest(new GramJs.payments.SaveStarGift({
msgId: messageId,
stargift: buildInputSavedStarGift(inputGift),
unsave: shouldUnsave || undefined,
}));
}
export function convertStarGift({
messageId,
inputSavedGift,
}: {
messageId: number;
inputSavedGift: ApiRequestInputSavedStarGift;
}) {
return invokeRequest(new GramJs.payments.ConvertStarGift({
msgId: messageId,
stargift: buildInputSavedStarGift(inputSavedGift),
}));
}
@ -671,14 +676,14 @@ export async function fetchStarGiftUpgradePreview({
}
export function upgradeGift({
messageId,
inputSavedGift,
shouldKeepOriginalDetails,
}: {
messageId: number;
inputSavedGift: ApiRequestInputSavedStarGift;
shouldKeepOriginalDetails?: true;
}) {
return invokeRequest(new GramJs.payments.UpgradeStarGift({
msgId: messageId,
stargift: buildInputSavedStarGift(inputSavedGift),
keepOriginalDetails: shouldKeepOriginalDetails,
}), {
shouldReturnTrue: true,

View File

@ -141,6 +141,8 @@ export interface ApiChatFullInfo {
hasPinnedStories?: boolean;
isPaidReactionAvailable?: boolean;
hasScheduledMessages?: boolean;
starGiftCount?: number;
areStarGiftsAvailable?: boolean;
boostsApplied?: number;
boostsToUnrestrict?: number;

View File

@ -1,18 +1,16 @@
import type { ThreadId, WebPageMediaSize } from '../../types';
import type { ApiWebDocument } from './bots';
import type { ApiGroupCall, PhoneCallAction } from './calls';
import type { ApiChat, ApiPeerColor } from './chats';
import type { ApiPeerColor } from './chats';
import type {
ApiInputStorePaymentPurpose,
ApiInputSavedStarGift,
ApiLabeledPrice,
ApiPremiumGiftCodeOption,
ApiStarGiftRegular,
ApiStarGiftUnique,
} from './payments';
import type {
ApiMessageStoryData, ApiStory, ApiWebPageStickerData, ApiWebPageStoryData,
} from './stories';
import type { ApiUser } from './users';
export interface ApiDimensions {
width: number;
@ -207,149 +205,6 @@ export interface ApiPoll {
};
}
/* Used for Invoice UI */
export type ApiInputInvoiceMessage = {
type: 'message';
chatId: string;
messageId: number;
isExtendedMedia?: boolean;
};
export type ApiInputInvoiceSlug = {
type: 'slug';
slug: string;
};
export type ApiInputInvoiceGiveaway = {
type: 'giveaway';
chatId: string;
additionalChannelIds?: string[];
isOnlyForNewSubscribers?: boolean;
areWinnersVisible?: boolean;
prizeDescription?: string;
countries?: string[];
untilDate: number;
currency: string;
amount: number;
option: ApiPremiumGiftCodeOption;
};
export type ApiInputInvoiceGiftCode = {
type: 'giftcode';
userIds: string[];
boostChannelId?: string;
currency: string;
amount: number;
option: ApiPremiumGiftCodeOption;
message?: ApiFormattedText;
};
export type ApiInputInvoiceStars = {
type: 'stars';
stars: number;
currency: string;
amount: number;
};
export type ApiInputInvoiceStarsGift = {
type: 'starsgift';
userId: string;
stars: number;
currency: string;
amount: number;
};
export type ApiInputInvoiceStarGift = {
type: 'stargift';
shouldHideName?: boolean;
userId: string;
giftId: string;
message?: ApiFormattedText;
shouldUpgrade?: true;
};
export type ApiInputInvoiceStarsGiveaway = {
type: 'starsgiveaway';
chatId: string;
additionalChannelIds?: string[];
isOnlyForNewSubscribers?: boolean;
areWinnersVisible?: boolean;
prizeDescription?: string;
countries?: string[];
untilDate: number;
currency: string;
amount: number;
stars: number;
users: number;
};
export type ApiInputInvoiceChatInviteSubscription = {
type: 'chatInviteSubscription';
hash: string;
};
export type ApiInputInvoiceStarGiftUpgrade = {
type: 'stargiftUpgrade';
messageId: number;
shouldKeepOriginalDetails?: true;
};
export type ApiInputInvoice = ApiInputInvoiceMessage | ApiInputInvoiceSlug | ApiInputInvoiceGiveaway
| ApiInputInvoiceGiftCode | ApiInputInvoiceStars | ApiInputInvoiceStarsGift | ApiInputInvoiceStarGiftUpgrade
| ApiInputInvoiceStarsGiveaway | ApiInputInvoiceStarGift | ApiInputInvoiceChatInviteSubscription;
/* Used for Invoice request */
export type ApiRequestInputInvoiceMessage = {
type: 'message';
chat: ApiChat;
messageId: number;
};
export type ApiRequestInputInvoiceSlug = {
type: 'slug';
slug: string;
};
export type ApiRequestInputInvoiceGiveaway = {
type: 'giveaway';
purpose: ApiInputStorePaymentPurpose;
option: ApiPremiumGiftCodeOption;
};
export type ApiRequestInputInvoiceStars = {
type: 'stars';
purpose: ApiInputStorePaymentPurpose;
};
export type ApiRequestInputInvoiceStarsGiveaway = {
type: 'starsgiveaway';
purpose: ApiInputStorePaymentPurpose;
};
export type ApiRequestInputInvoiceStarGift = {
type: 'stargift';
shouldHideName?: boolean;
user: ApiUser;
giftId: string;
message?: ApiFormattedText;
shouldUpgrade?: true;
};
export type ApiRequestInputInvoiceChatInviteSubscription = {
type: 'chatInviteSubscription';
hash: string;
};
export type ApiRequestInputInvoiceStarGiftUpgrade = {
type: 'stargiftUpgrade';
messageId: number;
shouldKeepOriginalDetails?: true;
};
export type ApiRequestInputInvoice = ApiRequestInputInvoiceMessage | ApiRequestInputInvoiceSlug
| ApiRequestInputInvoiceGiveaway | ApiRequestInputInvoiceStars | ApiRequestInputInvoiceStarsGiveaway
| ApiRequestInputInvoiceChatInviteSubscription | ApiRequestInputInvoiceStarGift | ApiRequestInputInvoiceStarGiftUpgrade;
export interface ApiInvoice {
prices: ApiLabeledPrice[];
totalAmount: number;
@ -485,6 +340,10 @@ export interface ApiMessageActionStarGift {
isUpgraded?: true;
upgradeMsgId?: number;
alreadyPaidUpgradeStars?: number;
fromId?: string;
peerId?: string;
savedId?: string;
inputSavedGift?: ApiInputSavedStarGift;
}
export interface ApiMessageActionStarGiftUnique {
@ -496,6 +355,10 @@ export interface ApiMessageActionStarGiftUnique {
gift: ApiStarGiftUnique;
canExportAt?: number;
transferStars?: number;
fromId?: string;
peerId?: string;
savedId?: string;
inputSavedGift?: ApiInputSavedStarGift;
}
export interface ApiAction {

View File

@ -1,6 +1,6 @@
import type { PREMIUM_FEATURE_SECTIONS } from '../../config';
import type { ApiWebDocument } from './bots';
import type { ApiChat } from './chats';
import type { ApiChat, ApiPeer } from './chats';
import type {
ApiDocument,
ApiFormattedText,
@ -213,6 +213,7 @@ export interface ApiStarGiftUnique {
number: number;
ownerId?: string;
ownerName?: string;
ownerAddress?: string;
issuedCount: number;
totalCount: number;
attributes: ApiStarGiftAttribute[];
@ -256,12 +257,14 @@ export interface ApiStarGiftAttributeOriginalDetails {
export type ApiStarGiftAttribute = ApiStarGiftAttributeModel | ApiStarGiftAttributePattern
| ApiStarGiftAttributeBackdrop | ApiStarGiftAttributeOriginalDetails;
export interface ApiUserStarGift {
export interface ApiSavedStarGift {
isNameHidden?: boolean;
isUnsaved?: boolean;
fromId?: string;
date: number;
gift: ApiStarGift;
inputGift?: ApiInputSavedStarGift;
savedId?: string;
message?: ApiFormattedText;
messageId?: number;
starsToConvert?: number;
@ -272,6 +275,27 @@ export interface ApiUserStarGift {
upgradeMsgId?: number; // Local field, used for Action Message
}
export interface ApiInputSavedStarGiftUser {
type: 'user';
messageId: number;
}
export interface ApiInputSavedStarGiftChat {
type: 'chat';
chatId: string;
savedId: string;
}
export type ApiInputSavedStarGift = ApiInputSavedStarGiftUser | ApiInputSavedStarGiftChat;
export type ApiRequestInputSavedStarGiftUser = ApiInputSavedStarGiftUser;
export type ApiRequestInputSavedStarGiftChat = {
type: 'chat';
chat: ApiChat;
savedId: string;
};
export type ApiRequestInputSavedStarGift = ApiRequestInputSavedStarGiftUser | ApiRequestInputSavedStarGiftChat;
export interface ApiPremiumGiftCodeOption {
users: number;
months: number;
@ -476,3 +500,146 @@ export interface ApiStarGiveawayOption {
}
export type ApiPaymentStatus = 'paid' | 'failed' | 'pending' | 'cancelled';
/* Used for Invoice UI */
export type ApiInputInvoiceMessage = {
type: 'message';
chatId: string;
messageId: number;
isExtendedMedia?: boolean;
};
export type ApiInputInvoiceSlug = {
type: 'slug';
slug: string;
};
export type ApiInputInvoiceGiveaway = {
type: 'giveaway';
chatId: string;
additionalChannelIds?: string[];
isOnlyForNewSubscribers?: boolean;
areWinnersVisible?: boolean;
prizeDescription?: string;
countries?: string[];
untilDate: number;
currency: string;
amount: number;
option: ApiPremiumGiftCodeOption;
};
export type ApiInputInvoiceGiftCode = {
type: 'giftcode';
userIds: string[];
boostChannelId?: string;
currency: string;
amount: number;
option: ApiPremiumGiftCodeOption;
message?: ApiFormattedText;
};
export type ApiInputInvoiceStars = {
type: 'stars';
stars: number;
currency: string;
amount: number;
};
export type ApiInputInvoiceStarsGift = {
type: 'starsgift';
userId: string;
stars: number;
currency: string;
amount: number;
};
export type ApiInputInvoiceStarGift = {
type: 'stargift';
shouldHideName?: boolean;
peerId: string;
giftId: string;
message?: ApiFormattedText;
shouldUpgrade?: true;
};
export type ApiInputInvoiceStarsGiveaway = {
type: 'starsgiveaway';
chatId: string;
additionalChannelIds?: string[];
isOnlyForNewSubscribers?: boolean;
areWinnersVisible?: boolean;
prizeDescription?: string;
countries?: string[];
untilDate: number;
currency: string;
amount: number;
stars: number;
users: number;
};
export type ApiInputInvoiceChatInviteSubscription = {
type: 'chatInviteSubscription';
hash: string;
};
export type ApiInputInvoiceStarGiftUpgrade = {
type: 'stargiftUpgrade';
inputSavedGift: ApiInputSavedStarGift;
shouldKeepOriginalDetails?: true;
};
export type ApiInputInvoice = ApiInputInvoiceMessage | ApiInputInvoiceSlug | ApiInputInvoiceGiveaway
| ApiInputInvoiceGiftCode | ApiInputInvoiceStars | ApiInputInvoiceStarsGift | ApiInputInvoiceStarGiftUpgrade
| ApiInputInvoiceStarsGiveaway | ApiInputInvoiceStarGift | ApiInputInvoiceChatInviteSubscription;
/* Used for Invoice request */
export type ApiRequestInputInvoiceMessage = {
type: 'message';
chat: ApiChat;
messageId: number;
};
export type ApiRequestInputInvoiceSlug = {
type: 'slug';
slug: string;
};
export type ApiRequestInputInvoiceGiveaway = {
type: 'giveaway';
purpose: ApiInputStorePaymentPurpose;
option: ApiPremiumGiftCodeOption;
};
export type ApiRequestInputInvoiceStars = {
type: 'stars';
purpose: ApiInputStorePaymentPurpose;
};
export type ApiRequestInputInvoiceStarsGiveaway = {
type: 'starsgiveaway';
purpose: ApiInputStorePaymentPurpose;
};
export type ApiRequestInputInvoiceStarGift = {
type: 'stargift';
shouldHideName?: boolean;
peer: ApiPeer;
giftId: string;
message?: ApiFormattedText;
shouldUpgrade?: true;
};
export type ApiRequestInputInvoiceChatInviteSubscription = {
type: 'chatInviteSubscription';
hash: string;
};
export type ApiRequestInputInvoiceStarGiftUpgrade = {
type: 'stargiftUpgrade';
inputSavedGift: ApiRequestInputSavedStarGift;
shouldKeepOriginalDetails?: true;
};
export type ApiRequestInputInvoice = ApiRequestInputInvoiceMessage | ApiRequestInputInvoiceSlug
| ApiRequestInputInvoiceGiveaway | ApiRequestInputInvoiceStars | ApiRequestInputInvoiceStarsGiveaway
| ApiRequestInputInvoiceChatInviteSubscription | ApiRequestInputInvoiceStarGift | ApiRequestInputInvoiceStarGiftUpgrade;

View File

@ -4,7 +4,7 @@ import type { ApiBusinessIntro, ApiBusinessLocation, ApiBusinessWorkHours } from
import type { ApiPeerColor } from './chats';
import type { ApiDocument, ApiPhoto } from './messages';
import type { ApiBotVerification } from './misc';
import type { ApiUserStarGift } from './payments';
import type { ApiSavedStarGift } from './payments';
export interface ApiUser {
id: string;
@ -89,8 +89,8 @@ export interface ApiUserCommonChats {
isFullyLoaded: boolean;
}
export interface ApiUserGifts {
gifts: ApiUserStarGift[];
export interface ApiSavedGifts {
gifts: ApiSavedStarGift[];
nextOffset?: string;
}

View File

@ -244,6 +244,7 @@
"SavedMessagesInfo" = "Forward here to save";
"BlockedListNotFound" = "No users found.";
"TextCopied" = "Text copied to clipboard.";
"WalletAddressCopied" = "Wallet address copied to clipboard.";
"Copy" = "Copy";
"ChatListDeleteAndLeaveGroupConfirmation" = "Are you sure you want to leave and delete {chat}?";
"ChannelLeaveAlertWithName" = "Are you sure you want to leave **{chat}**?";
@ -1361,6 +1362,7 @@
"StarsGiftHeaderSelf" = "Buy a Gift";
"StarGiftDescription" = "Give {user} gifts that can be kept on the profile or converted to Stars.";
"StarGiftDescriptionSelf" = "Buy yourself a gift to add to your profile or reserve for later.\n\nLimited-edition gifts upgraded to collectibles can be gifted to others.";
"StarGiftDescriptionChannel" = "Select gift to show appreciation to **{peer}**.";
"GiftLimited" = "limited";
"GiftDiscount" = "-{percent}%";
"GiftSoldCount" = "{count} sold";
@ -1368,23 +1370,24 @@
"GiftSoldOut" = "sold out";
"GiftMessagePlaceholder" = "Enter Message (Optional)";
"GiftHideMyName" = "Hide My Name";
"GiftHideNameDescription" = "Hide my name and message from visitors to {profile}'s profile. {receiver} will still see your name and message.";
"GiftHideNameDescription" = "You can hide your name and message from visitors to {receiver}'s profile. {receiver} will still see your name and message.";
"GiftHideNameDescriptionChannel" = "You can hide your name and message from all visitors of this channel except its admins.";
"GiftSend" = "Send a Gift for {amount}";
"GiftInfoSent" = "Sent Gift";
"GiftInfoReceived" = "Received Gift";
"GiftInfoTitle" = "Gift";
"GiftInfoDescription_one" = "You can keep this gift in your Profile or convert it to **{amount}** Star.";
"GiftInfoDescription_other" = "You can keep this gift in your Profile or convert it to **{amount}** Stars.";
"GiftInfoDescriptionOut_one" = "{user} can keep this gift in profile or convert it to **{amount}** Star.";
"GiftInfoDescriptionOut_other" = "{user} can keep this gift in profile or convert it to **{amount}** Stars.";
"GiftInfoPeerDescriptionOut_one" = "{peer} can keep this gift in profile or convert it to **{amount}** Star.";
"GiftInfoPeerDescriptionOut_other" = "{peer} can keep this gift in profile or convert it to **{amount}** Stars.";
"GiftInfoDescriptionUpgrade_one" = "You can keep this gift, upgrade it, or sell it for **{amount}** Star.";
"GiftInfoDescriptionUpgrade_other" = "You can keep this gift, upgrade it, or sell it for **{amount}** Stars.";
"GiftInfoDescriptionConverted_one" = "You converted this gift to **{amount}** Star.";
"GiftInfoDescriptionConverted_other" = "You converted this gift to **{amount}** Stars.";
"GiftInfoDescriptionOutConverted_one" = "{user} converted this gift to **{amount}** Star.";
"GiftInfoDescriptionOutConverted_other" = "{user} converted this gift to **{amount}** Stars.";
"GiftInfoPeerDescriptionOutConverted_one" = "{peer} converted this gift to **{amount}** Star.";
"GiftInfoPeerDescriptionOutConverted_other" = "{peer} converted this gift to **{amount}** Stars.";
"GiftInfoDescriptionFreeUpgrade" = "Upgrade this gift for free to turn it to a unique collectible.";
"GiftInfoDescriptionFreeUpgradeOut" = "{user} can turn this gift to a unique collectible";
"GiftInfoPeerDescriptionFreeUpgradeOut" = "{peer} can turn this gift to a unique collectible";
"GiftInfoDescriptionUpgraded" = "This gift was turned into a unique collectible.";
"GiftInfoFrom" = "From";
"GiftInfoDate" = "Date";
@ -1392,14 +1395,16 @@
"GiftInfoConvert_one" = "Convert to {amount} Star";
"GiftInfoConvert_other" = "Convert to {amount} Stars";
"GiftInfoConvertTitle" = "Convert Gift to Stars";
"GiftInfoConvertDescription1" = "Do you want to convert this gift from **{user}** to **{amount}**?";
"GiftInfoPeerConvertDescription" = "Do you want to convert this gift from **{peer}** to **{amount}**?";
"GiftInfoConvertDescription2" = "This action cannot be undone. This will permanently destroy the gift.";
"GiftInfoConvertDescriptionPeriod_one" = "Conversion is available for the next **{count} days**.";
"GiftInfoConvertDescriptionPeriod_other" = "Conversion is available for the next **{count} days**.";
"GiftInfoSaved" = "This gift is visible on your profile. {link}";
"GiftInfoHidden" = "This gift is hidden. Only you can see it. {link}";
"GiftInfoChannelSaved" = "This gift is visible in your channel's Gifts. {link}";
"GiftInfoChannelHidden" = "This gift is hidden from visitors of your channel. {link}";
"GiftInfoSavedHide" = "Hide >";
"GiftInfoSavedShow" = "Show >";
"GiftInfoHidden" = "This gift is hidden. Only you can see it. {link}";
"GiftInfoAvailability" = "Availability";
"GiftInfoAvailabilityValue_one" = "{count} of {total} left";
"GiftInfoAvailabilityValue_other" = "{count} of {total} left";
@ -1415,10 +1420,10 @@
"GiftAttributeModel" = "Model";
"GiftAttributeBackdrop" = "Backdrop";
"GiftAttributeSymbol" = "Symbol";
"GiftInfoOriginalInfo" = "Gifted to {user} on {date}.";
"GiftInfoOriginalInfoSender" = "Gifted by {sender} to {user} on {date}.";
"GiftInfoOriginalInfoText" = "Gifted to {user} on {date} with comment \"{text}\".";
"GiftInfoOriginalInfoTextSender" = "Gifted by {sender} to {user} on {date} with comment \"{text}\".";
"GiftInfoPeerOriginalInfo" = "Gifted to {peer} on {date}.";
"GiftInfoPeerOriginalInfoSender" = "Gifted by {sender} to {peer} on {date}.";
"GiftInfoPeerOriginalInfoText" = "Gifted to {peer} on {date} with comment \"{text}\".";
"GiftInfoPeerOriginalInfoTextSender" = "Gifted by {sender} to {peer} on {date} with comment \"{text}\".";
"GiftInfoStatus" = "Status";
"GiftInfoStatusNonUnique" = "Non-Unique";
"GiftInfoViewUpgraded" = "View Upgraded Gift";
@ -1431,7 +1436,7 @@
"GiftUpgradeTradeableTitle" = "Tradable";
"GiftUpgradeTradeableDescription" = "Sell or auction your gift on third-party NFT marketplaces.";
"GiftUpgradeTitle" = "Make unique";
"GiftUpgradeText" = "Let {peer} turn your gift into a unique collectible.";
"GiftPeerUpgradeText" = "Let {peer} turn your gift into a unique collectible.";
"GiftUpgradeTextOwn" = "Turn your gift into a unique collectible that you can transfer or auction.";
"GiftUpgradeKeepDetails" = "Keep sender's name and comment";
"GiftUpgradeButton" = "Upgrade {amount}";
@ -1440,6 +1445,7 @@
"GiftMakeUnique" = "Make unique for {stars}";
"GiftMakeUniqueAcc" = "Make unique";
"GiftMakeUniqueDescription" = "Enable this to let {user} turn your gift into a unique collectible. {link}";
"GiftMakeUniqueDescriptionChannel" = "Enable this to let admins of {peer} to turn your gift into a unique collectible. {link}";
"GiftMakeUniqueLink" = "Learn More >";
"StarsAmount" = "⭐️{amount}";
"StarsAmountText_one" = "{amount} Star";
@ -1457,14 +1463,15 @@
"MiniAppsMoreTabs_other" = "{botName} & {count} Others";
"PrizeCredits2_one" = "Your prize is {count} Star.";
"PrizeCredits2_other" = "Your prize is {count} Stars.";
"ActionStarGiftTitle" = "{user} sent you a Gift for {count} Stars";
"ActionStarGiftPeerTitle" = "{peer} sent you a Gift for {count} Stars";
"ActionStarGiftOutTitle" = "You have sent a gift for {count} Stars";
"ActionStarGiftOutDescription2_one" = "{user} can display this gift on their profile or convert it to {count} Star.";
"ActionStarGiftOutDescription2_other" = "{user} can display this gift on their profile or convert it to {count} Stars.";
"ActionStarGiftPeerOutDescription_one" = "{peer} can display this gift on their profile or convert it to {count} Star.";
"ActionStarGiftPeerOutDescription_other" = "{peer} can display this gift on their profile or convert it to {count} Stars.";
"ActionStarGiftDescription2_one" = "Add this gift to your profile or convert it to {count} Star.";
"ActionStarGiftDescription2_other" = "Add this gift to your profile or convert it to {count} Stars.";
"ActionStarGiftDisplaying" = "You kept this gift on your profile.";
"ActionStarGiftOutDescriptionUpgrade" = "{user} can turn this gift to a unique collectible.";
"ActionStarGiftChannelDisplaying" = "This gift is displayed to visitors of your channel.";
"ActionStarGiftPeerOutDescriptionUpgrade" = "{peer} can turn this gift to a unique collectible.";
"ActionStarGiftDescriptionUpgrade" = "Tap “Unpack” to turn this gift to a unique collectible.";
"ActionStarGiftUpgraded" = "This gift was upgraded.";
"ActionStarGiftUnpack" = "Unpack";

View File

@ -1,9 +1,9 @@
import React, { memo, useMemo, useRef } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { ApiUser, ApiUserStarGift } from '../../../api/types';
import type { ApiPeer, ApiSavedStarGift } from '../../../api/types';
import { selectUser } from '../../../global/selectors';
import { selectPeer } from '../../../global/selectors';
import { CUSTOM_PEER_HIDDEN } from '../../../util/objects/customPeer';
import { formatIntegerCompact } from '../../../util/textFormat';
import { getGiftAttributes, getStickerFromGift, getTotalGiftAvailability } from '../helpers/gifts';
@ -19,22 +19,22 @@ import Icon from '../icons/Icon';
import RadialPatternBackground from '../profile/RadialPatternBackground';
import GiftRibbon from './GiftRibbon';
import styles from './UserGift.module.scss';
import styles from './SavedGift.module.scss';
type OwnProps = {
userId: string;
gift: ApiUserStarGift;
peerId: string;
gift: ApiSavedStarGift;
observeIntersection?: ObserveFn;
};
type StateProps = {
fromPeer?: ApiUser;
fromPeer?: ApiPeer;
};
const GIFT_STICKER_SIZE = 90;
const UserGift = ({
userId,
const SavedGift = ({
peerId,
gift,
fromPeer,
observeIntersection,
@ -50,7 +50,7 @@ const UserGift = ({
const handleClick = useLastCallback(() => {
openGiftInfoModal({
userId,
peerId,
gift,
});
});
@ -92,7 +92,7 @@ const UserGift = ({
return (
<div ref={ref} className={styles.root} onClick={handleClick}>
{radialPatternBackdrop}
<Avatar className={styles.avatar} peer={avatarPeer} size="micro" />
{!radialPatternBackdrop && <Avatar className={styles.avatar} peer={avatarPeer} size="micro" />}
<AnimatedIconFromSticker
sticker={sticker}
noLoop
@ -117,10 +117,10 @@ const UserGift = ({
export default memo(withGlobal<OwnProps>(
(global, { gift }): StateProps => {
const fromPeer = gift.fromId ? selectUser(global, gift.fromId) : undefined;
const fromPeer = gift.fromId ? selectPeer(global, gift.fromId) : undefined;
return {
fromPeer,
};
},
)(UserGift));
)(SavedGift));

View File

@ -11,7 +11,9 @@ import type { ObserveFn } from '../../hooks/useIntersectionObserver';
import type { FocusDirection, MessageListType, ThreadId } from '../../types';
import type { OnIntersectPinnedMessage } from './hooks/usePinnedMessage';
import { getChatTitle, getMessageHtmlId, isJoinedChannelMessage } from '../../global/helpers';
import {
getChatTitle, getMessageHtmlId, getPeerTitle, isJoinedChannelMessage,
} from '../../global/helpers';
import { getMessageReplyInfo } from '../../global/helpers/replies';
import {
selectCanPlayAnimatedEmojis,
@ -21,6 +23,7 @@ import {
selectGiftStickerForStars,
selectIsCurrentUserPremium,
selectIsMessageFocused,
selectPeer,
selectTabState,
selectTheme,
selectTopicFromMessage,
@ -86,6 +89,7 @@ type StateProps = {
starsGiftSticker?: ApiSticker;
canPlayAnimatedEmojis?: boolean;
patternColor?: string;
currentUserId?: string;
isCurrentUserPremium?: boolean;
};
@ -119,6 +123,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
observeIntersectionForLoading,
observeIntersectionForPlaying,
onIntersectPinnedMessage,
currentUserId,
isCurrentUserPremium,
}) => {
const {
@ -407,16 +412,24 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
}
function renderStarGiftUserCaption() {
const targetUser = targetUsers && targetUsers[0];
const starGift = message.content.action?.starGift;
if (!targetUser || !senderUser || !starGift) return undefined;
if (!starGift) return undefined;
const { fromId, peerId } = starGift;
if (message.isOutgoing || (starGift.type === 'starGiftUnique' && starGift.isUpgrade)) {
const fromPeer = fromId ? selectPeer(getGlobal(), fromId) : undefined;
const targetPeer = peerId
? selectPeer(getGlobal(), peerId)
: starGift.type === 'starGiftUnique' && !message.isOutgoing
? targetChat : undefined;
if (targetPeer && targetPeer.id !== currentUserId) {
return (
<div className="action-message-user-caption">
<span> {lang('GiftTo')} </span>
<Avatar className="action-message-user-avatar" size="micro" peer={targetChat} />
<span> {targetUser.firstName} </span>
{starGift.type === 'starGift' && (
<Avatar className="action-message-user-avatar" size="micro" peer={targetPeer} />
)}
<span> {getPeerTitle(lang, targetPeer)} </span>
</div>
);
}
@ -424,15 +437,17 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
return (
<div className="action-message-user-caption">
<span> {lang('GiftFrom')} </span>
<Avatar className="action-message-user-avatar" size="micro" peer={senderUser} />
<span> {senderUser.firstName} </span>
{starGift.type === 'starGift' && (
<Avatar className="action-message-user-avatar" size="micro" peer={fromPeer || senderUser} />
)}
<span> {getPeerTitle(lang, fromPeer || senderUser!)} </span>
</div>
);
}
function renderStarGiftUserDescription() {
const starGift = message.content.action?.starGift as ApiMessageActionStarGift;
const targetUser = targetUsers && targetUsers[0]?.firstName;
const targetChatTitle = targetChat && getPeerTitle(lang, targetChat);
const starGiftMessage = starGift?.message;
if (!starGift) return undefined;
@ -442,7 +457,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
const amountToConvert = starGift?.starsToConvert;
if (starGift.isSaved) {
return lang('ActionStarGiftDisplaying');
return lang(starGift.savedId ? 'ActionStarGiftChannelDisplaying' : 'ActionStarGiftDisplaying');
}
if (starGift.isUpgraded) {
@ -451,24 +466,24 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
if (message.isOutgoing) {
if (amountToConvert) {
return lang('ActionStarGiftOutDescription2', {
user: targetUser || 'User',
return lang('ActionStarGiftPeerOutDescription', {
peer: targetChatTitle || 'Someone',
count: amountToConvert,
}, { withNodes: true, pluralValue: amountToConvert });
}
if (starGift.canUpgrade) {
return lang('ActionStarGiftOutDescriptionUpgrade', {
user: targetUser || 'User',
return lang('ActionStarGiftPeerOutDescriptionUpgrade', {
peer: targetChatTitle || 'Someone',
});
}
}
if (starGift.isConverted) {
return message.isOutgoing
? lang('GiftInfoDescriptionOutConverted', {
? lang('GiftInfoPeerDescriptionOutConverted', {
amount: formatInteger(amountToConvert!),
user: targetUser || 'User',
peer: targetChatTitle || 'Chat',
}, {
pluralValue: amountToConvert!,
withNodes: true,
@ -768,6 +783,7 @@ export default memo(withGlobal<OwnProps>(
noFocusHighlight,
}),
isCurrentUserPremium: selectIsCurrentUserPremium(global),
currentUserId: global.currentUserId,
};
},
)(ActionMessage));

View File

@ -4,13 +4,14 @@ import React, {
} from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { ApiMessage, ApiUser } from '../../../api/types';
import type { ApiMessage, ApiPeer } from '../../../api/types';
import type { ThemeKey } from '../../../types';
import type { GiftOption } from './GiftModal';
import { STARS_CURRENCY_CODE } from '../../../config';
import { getUserFullName } from '../../../global/helpers';
import { selectTabState, selectTheme, selectUser } from '../../../global/selectors';
import { getPeerTitle } from '../../../global/helpers';
import { isApiPeerUser } from '../../../global/helpers/peers';
import { selectPeer, selectTabState, selectTheme } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import buildStyle from '../../../util/buildStyle';
import { formatCurrency } from '../../../util/formatCurrency';
@ -32,7 +33,7 @@ import styles from './GiftComposer.module.scss';
export type OwnProps = {
gift: GiftOption;
userId: string;
peerId: string;
};
export type StateProps = {
@ -42,7 +43,7 @@ export type StateProps = {
patternColor?: string;
customBackground?: string;
backgroundColor?: string;
user?: ApiUser;
peer?: ApiPeer;
currentUserId?: string;
isPaymentFormLoading?: boolean;
};
@ -51,8 +52,8 @@ const LIMIT_DISPLAY_THRESHOLD = 50;
function GiftComposer({
gift,
userId,
user,
peerId,
peer,
captionLimit,
theme,
isBackgroundBlurred,
@ -73,6 +74,7 @@ function GiftComposer({
const customBackgroundValue = useCustomBackground(theme, customBackground);
const isStarGift = 'id' in gift;
const isPeerUser = peer && isApiPeerUser(peer);
const localMessage = useMemo(() => {
if (!isStarGift) {
@ -84,7 +86,7 @@ function GiftComposer({
date: Math.floor(Date.now() / 1000),
content: {
action: {
targetUserIds: [userId],
targetChatId: peerId,
mediaType: 'action',
text: 'ActionGiftInbound',
type: 'giftPremium',
@ -108,7 +110,7 @@ function GiftComposer({
date: Math.floor(Date.now() / 1000),
content: {
action: {
targetUserIds: [userId],
targetChatId: peerId,
mediaType: 'action',
text: 'ActionGiftInbound',
type: 'starGift',
@ -122,14 +124,17 @@ function GiftComposer({
isNameHidden: shouldHideName,
starsToConvert: gift.starsToConvert,
canUpgrade: shouldPayForUpgrade || undefined,
alreadyPaidUpgradeStars: shouldPayForUpgrade ? gift.upgradeStars : undefined,
isSaved: false,
gift,
peerId,
fromId: currentUserId,
},
translationValues: ['%action_origin%', '%gift_payment_amount%'],
},
},
} satisfies ApiMessage;
}, [currentUserId, gift, giftMessage, isStarGift, shouldHideName, shouldPayForUpgrade, userId]);
}, [currentUserId, gift, giftMessage, isStarGift, shouldHideName, shouldPayForUpgrade, peerId]);
const handleGiftMessageChange = useLastCallback((e: ChangeEvent<HTMLTextAreaElement>) => {
setGiftMessage(e.target.value);
@ -147,14 +152,14 @@ function GiftComposer({
if (!isStarGift) return;
openGiftUpgradeModal({
giftId: gift.id,
peerId: userId,
peerId,
});
});
const handleMainButtonClick = useLastCallback(() => {
if (isStarGift) {
sendStarGift({
userId,
peerId,
shouldHideName,
gift,
message: giftMessage ? { text: giftMessage } : undefined,
@ -165,7 +170,7 @@ function GiftComposer({
openInvoice({
type: 'giftcode',
userIds: [userId],
userIds: [peerId],
currency: gift.currency,
amount: gift.amount,
option: gift,
@ -176,7 +181,7 @@ function GiftComposer({
function renderOptionsSection() {
const symbolsLeft = captionLimit ? captionLimit - giftMessage.length : undefined;
const userFullName = getUserFullName(user)!;
const title = getPeerTitle(lang, peer!)!;
return (
<div className={styles.optionsSection}>
<TextArea
@ -204,12 +209,19 @@ function GiftComposer({
)}
{isStarGift && (
<div className={styles.description}>
{lang('GiftMakeUniqueDescription', {
user: userFullName,
link: <Link isPrimary onClick={handleOpenUpgradePreview}>{lang('GiftMakeUniqueLink')}</Link>,
}, {
withNodes: true,
})}
{isPeerUser
? lang('GiftMakeUniqueDescription', {
user: title,
link: <Link isPrimary onClick={handleOpenUpgradePreview}>{lang('GiftMakeUniqueLink')}</Link>,
}, {
withNodes: true,
})
: lang('GiftMakeUniqueDescriptionChannel', {
peer: title,
link: <Link isPrimary onClick={handleOpenUpgradePreview}>{lang('GiftMakeUniqueLink')}</Link>,
}, {
withNodes: true,
})}
</div>
)}
@ -225,7 +237,7 @@ function GiftComposer({
)}
{isStarGift && (
<div className={styles.description}>
{lang('GiftHideNameDescription', { profile: userFullName, receiver: userFullName })}
{isPeerUser ? lang('GiftHideNameDescription', { receiver: title }) : lang('GiftHideNameDescriptionChannel')}
</div>
)}
</div>
@ -298,7 +310,7 @@ function GiftComposer({
}
export default memo(withGlobal<OwnProps>(
(global, { userId }): StateProps => {
(global, { peerId }): StateProps => {
const theme = selectTheme(global);
const {
isBlurred: isBackgroundBlurred,
@ -306,12 +318,12 @@ export default memo(withGlobal<OwnProps>(
background: customBackground,
backgroundColor,
} = global.settings.themes[theme] || {};
const user = selectUser(global, userId);
const peer = selectPeer(global, peerId);
const tabState = selectTabState(global);
return {
user,
peer,
theme,
isBackgroundBlurred,
patternColor,

View File

@ -5,16 +5,17 @@ import React, {
import { getActions, withGlobal } from '../../../global';
import type {
ApiPeer,
ApiPremiumGiftCodeOption,
ApiStarGiftRegular,
ApiStarsAmount,
ApiUser,
} from '../../../api/types';
import type { TabState } from '../../../global/types';
import type { StarGiftCategory } from '../../../types';
import { getUserFullName } from '../../../global/helpers';
import { selectUser } from '../../../global/selectors';
import { getPeerTitle, getUserFullName } from '../../../global/helpers';
import { isApiPeerChat, isApiPeerUser } from '../../../global/helpers/peers';
import { selectPeer } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
@ -49,7 +50,7 @@ type StateProps = {
starGiftsById?: Record<string, ApiStarGiftRegular>;
starGiftIdsByCategory?: Record<StarGiftCategory, string[]>;
starBalance?: ApiStarsAmount;
user?: ApiUser;
peer?: ApiPeer;
isSelf?: boolean;
};
@ -61,7 +62,7 @@ const PremiumGiftModal: FC<OwnProps & StateProps> = ({
starGiftsById,
starGiftIdsByCategory,
starBalance,
user,
peer,
isSelf,
}) => {
const {
@ -80,6 +81,9 @@ const PremiumGiftModal: FC<OwnProps & StateProps> = ({
const isOpen = Boolean(modal);
const renderingModal = useCurrentOrPrev(modal);
const user = peer && isApiPeerUser(peer) ? peer : undefined;
const chat = peer && isApiPeerChat(peer) ? peer : undefined;
const [selectedGift, setSelectedGift] = useState<GiftOption | undefined>();
const [isHeaderHidden, setIsHeaderHidden] = useState(true);
const [isHeaderForStarGifts, setIsHeaderForStarGifts] = useState(false);
@ -156,14 +160,19 @@ const PremiumGiftModal: FC<OwnProps & StateProps> = ({
),
}, { withNodes: true });
const starGiftDescription = isSelf
? lang('StarGiftDescriptionSelf', undefined, {
const starGiftDescription = chat
? lang('StarGiftDescriptionChannel', { peer: getPeerTitle(lang, chat) }, {
withNodes: true,
renderTextFilters: ['br'],
withMarkdown: true,
})
: lang('StarGiftDescription', {
user: getUserFullName(user)!,
}, { withNodes: true, withMarkdown: true });
: isSelf
? lang('StarGiftDescriptionSelf', undefined, {
withNodes: true,
renderTextFilters: ['br'],
})
: lang('StarGiftDescription', {
user: getUserFullName(user)!,
}, { withNodes: true, withMarkdown: true });
function renderGiftPremiumHeader() {
return (
@ -254,13 +263,13 @@ const PremiumGiftModal: FC<OwnProps & StateProps> = ({
<div className={styles.avatars}>
<Avatar
size={AVATAR_SIZE}
peer={user}
peer={peer}
/>
<img className={styles.logoBackground} src={StarsBackground} alt="" draggable={false} />
</div>
{!isSelf && renderGiftPremiumHeader()}
{!isSelf && renderGiftPremiumDescription()}
{!isSelf && renderPremiumGifts()}
{!isSelf && !chat && renderGiftPremiumHeader()}
{!isSelf && !chat && renderGiftPremiumDescription()}
{!isSelf && !chat && renderPremiumGifts()}
{renderStarGiftsHeader()}
{renderStarGiftsDescription()}
@ -321,8 +330,8 @@ const PremiumGiftModal: FC<OwnProps & StateProps> = ({
activeKey={selectedGift ? 1 : 0}
>
{!selectedGift && renderMainScreen()}
{selectedGift && renderingModal?.forUserId && (
<GiftSendingOptions gift={selectedGift} userId={renderingModal.forUserId} />
{selectedGift && renderingModal?.forPeerId && (
<GiftSendingOptions gift={selectedGift} peerId={renderingModal.forPeerId} />
)}
</Transition>
</Modal>
@ -336,22 +345,22 @@ export default memo(withGlobal<OwnProps>((global, { modal }): StateProps => {
currentUserId,
} = global;
const user = modal?.forUserId ? selectUser(global, modal.forUserId) : undefined;
const isSelf = Boolean(currentUserId && modal?.forUserId === currentUserId);
const peer = modal?.forPeerId ? selectPeer(global, modal.forPeerId) : undefined;
const isSelf = Boolean(currentUserId && modal?.forPeerId === currentUserId);
return {
boostPerSentGift: global.appConfig?.boostsPerSentGift,
starGiftsById: starGifts?.byId,
starGiftIdsByCategory: starGifts?.idsByCategory,
starBalance: stars?.balance,
user,
peer,
isSelf,
};
})(PremiumGiftModal));
function getCategoryKey(category: StarGiftCategory) {
if (category === 'all') return -2;
if (category === 'stock') return -1;
if (category === 'limited') return 0;
if (category === 'limited') return -1;
if (category === 'stock') return 0;
return category;
}

View File

@ -78,8 +78,8 @@ const StarGiftCategoryList = ({
return (
<div ref={ref} className={buildClassName(styles.list, 'no-scrollbar')}>
{renderCategoryItem('all')}
{renderCategoryItem('stock')}
{renderCategoryItem('limited')}
{renderCategoryItem('stock')}
{starCategories?.map(renderCategoryItem)}
</div>
);

View File

@ -52,6 +52,7 @@
gap: 0.25rem;
}
/* stylelint-disable-next-line plugin/stylelint-group-selectors */
.uniqueGift {
margin-bottom: 0;
}
@ -59,3 +60,17 @@
.starAmountIcon {
margin-inline-start: 0 !important;
}
.ownerAddress {
font-family: var(--font-family-monospace);
font-size: 0.875rem;
cursor: pointer;
overflow: hidden;
}
.copyIcon {
margin-inline-start: 0.25rem;
color: var(--color-primary);
pointer-events: none;
}

View File

@ -3,13 +3,15 @@ import React, { memo, useMemo } from '../../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../../global';
import type {
ApiUser,
ApiPeer,
} from '../../../../api/types';
import type { TabState } from '../../../../global/types';
import { getUserFullName } from '../../../../global/helpers';
import { selectUser } from '../../../../global/selectors';
import { getHasAdminRight, getPeerTitle } from '../../../../global/helpers';
import { isApiPeerChat } from '../../../../global/helpers/peers';
import { selectPeer } from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import { copyTextToClipboard } from '../../../../util/clipboard';
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
import { formatStarsAsIcon, formatStarsAsText } from '../../../../util/localization/format';
import { CUSTOM_PEER_HIDDEN } from '../../../../util/objects/customPeer';
@ -27,6 +29,7 @@ import useOldLang from '../../../../hooks/useOldLang';
import AnimatedIconFromSticker from '../../../common/AnimatedIconFromSticker';
import Avatar from '../../../common/Avatar';
import BadgeButton from '../../../common/BadgeButton';
import Icon from '../../../common/icons/Icon';
import Button from '../../../ui/Button';
import ConfirmDialog from '../../../ui/ConfirmDialog';
import Link from '../../../ui/Link';
@ -40,16 +43,22 @@ export type OwnProps = {
};
type StateProps = {
userFrom?: ApiUser;
targetUser?: ApiUser;
fromPeer?: ApiPeer;
targetPeer?: ApiPeer;
currentUserId?: string;
starGiftMaxConvertPeriod?: number;
hasAdminRights?: boolean;
};
const STICKER_SIZE = 120;
const GiftInfoModal = ({
modal, userFrom, targetUser, currentUserId, starGiftMaxConvertPeriod,
modal,
fromPeer,
targetPeer,
currentUserId,
starGiftMaxConvertPeriod,
hasAdminRights,
}: OwnProps & StateProps) => {
const {
closeGiftInfoModal,
@ -58,6 +67,7 @@ const GiftInfoModal = ({
openChatWithInfo,
focusMessage,
openGiftUpgradeModal,
showNotification,
} = getActions();
const [isConvertConfirmOpen, openConvertConfirm, closeConvertConfirm] = useFlag();
@ -67,48 +77,55 @@ const GiftInfoModal = ({
const isOpen = Boolean(modal);
const renderingModal = useCurrentOrPrev(modal);
const renderingFromPeer = useCurrentOrPrev(fromPeer);
const renderingTargetPeer = useCurrentOrPrev(targetPeer);
const isTargetChat = renderingTargetPeer && isApiPeerChat(renderingTargetPeer);
const { gift: typeGift } = renderingModal || {};
const isUserGift = typeGift && 'gift' in typeGift;
const userGift = isUserGift ? typeGift : undefined;
const isSender = userGift?.fromId === currentUserId;
const canConvertDifference = (userGift && starGiftMaxConvertPeriod && (
userGift.date + starGiftMaxConvertPeriod - getServerTime()
const isSavedGift = typeGift && 'gift' in typeGift;
const savedGift = isSavedGift ? typeGift : undefined;
const isSender = savedGift?.fromId === currentUserId;
const canConvertDifference = (savedGift && starGiftMaxConvertPeriod && (
savedGift.date + starGiftMaxConvertPeriod - getServerTime()
)) || 0;
const conversionLeft = Math.ceil(canConvertDifference / 60 / 60 / 24);
const gift = isUserGift ? typeGift.gift : typeGift;
const gift = isSavedGift ? typeGift.gift : typeGift;
const giftSticker = gift && getStickerFromGift(gift);
const canFocusUpgrade = Boolean(userGift?.upgradeMsgId);
const canUpdate = Boolean(userGift?.messageId) && targetUser?.id === currentUserId && !canFocusUpgrade;
const canFocusUpgrade = Boolean(savedGift?.upgradeMsgId);
const canUpdate = !canFocusUpgrade && savedGift?.inputGift && (
isTargetChat ? hasAdminRights : renderingTargetPeer?.id === currentUserId
);
const handleClose = useLastCallback(() => {
closeGiftInfoModal();
});
const handleFocusUpgraded = useLastCallback(() => {
if (!userGift?.upgradeMsgId || !targetUser) return;
const { upgradeMsgId } = userGift;
focusMessage({ chatId: targetUser.id, messageId: upgradeMsgId! });
if (!savedGift?.upgradeMsgId || !renderingTargetPeer) return;
const { upgradeMsgId } = savedGift;
focusMessage({ chatId: renderingTargetPeer.id, messageId: upgradeMsgId! });
handleClose();
});
const handleTriggerVisibility = useLastCallback(() => {
const { messageId, isUnsaved } = userGift!;
changeGiftVisibility({ messageId: messageId!, shouldUnsave: !isUnsaved });
const { inputGift, isUnsaved } = savedGift!;
changeGiftVisibility({ gift: inputGift!, shouldUnsave: !isUnsaved });
handleClose();
});
const handleConvertToStars = useLastCallback(() => {
const { messageId } = userGift!;
convertGiftToStars({ messageId: messageId! });
const { inputGift } = savedGift!;
convertGiftToStars({ gift: inputGift! });
closeConvertConfirm();
handleClose();
});
const handleOpenUpgradeModal = useLastCallback(() => {
if (!userGift) return;
openGiftUpgradeModal({ giftId: userGift.gift.id, gift: userGift });
if (!savedGift) return;
openGiftUpgradeModal({ giftId: savedGift.gift.id, gift: savedGift });
});
const giftAttributes = useMemo(() => {
@ -124,7 +141,7 @@ const GiftInfoModal = ({
);
}
if (canUpdate && userGift?.alreadyPaidUpgradeStars && !userGift.upgradeMsgId) {
if (canUpdate && savedGift?.alreadyPaidUpgradeStars && !savedGift.upgradeMsgId) {
return (
<Button size="smaller" isShiny onClick={handleOpenUpgradeModal}>
{lang('GiftInfoUpgradeForFree')}
@ -146,17 +163,19 @@ const GiftInfoModal = ({
const {
fromId, isNameHidden, starsToConvert, isUnsaved, isConverted,
} = userGift || {};
} = savedGift || {};
const isVisibleForMe = isNameHidden && targetUser;
const isVisibleForMe = isNameHidden && renderingTargetPeer;
const description = (() => {
if (!userGift) return lang('GiftInfoSoldOutDescription');
if (userGift.upgradeMsgId) return lang('GiftInfoDescriptionUpgraded');
if (userGift.canUpgrade && userGift.alreadyPaidUpgradeStars) {
if (!savedGift) return lang('GiftInfoSoldOutDescription');
if (isTargetChat) return undefined;
if (savedGift.upgradeMsgId) return lang('GiftInfoDescriptionUpgraded');
if (savedGift.canUpgrade && savedGift.alreadyPaidUpgradeStars) {
return canUpdate
? lang('GiftInfoDescriptionFreeUpgrade')
: lang('GiftInfoDescriptionFreeUpgradeOut', { user: getUserFullName(targetUser)! });
: lang('GiftInfoPeerDescriptionFreeUpgradeOut', { peer: getPeerTitle(lang, renderingTargetPeer!)! });
}
if (!canUpdate && !isSender) return undefined;
if (isConverted && starsToConvert) {
@ -168,9 +187,9 @@ const GiftInfoModal = ({
withNodes: true,
withMarkdown: true,
})
: lang('GiftInfoDescriptionOutConverted', {
: lang('GiftInfoPeerDescriptionOutConverted', {
amount: formatInteger(starsToConvert!),
user: getUserFullName(targetUser)!,
peer: getPeerTitle(lang, renderingTargetPeer!)!,
}, {
pluralValue: starsToConvert,
withNodes: true,
@ -178,7 +197,7 @@ const GiftInfoModal = ({
});
}
if (userGift.canUpgrade && canUpdate) {
if (savedGift.canUpgrade && canUpdate) {
return lang('GiftInfoDescriptionUpgrade', {
amount: formatInteger(starsToConvert!),
}, {
@ -196,9 +215,9 @@ const GiftInfoModal = ({
withMarkdown: true,
pluralValue: starsToConvert || 0,
})
: lang('GiftInfoDescriptionOut', {
: lang('GiftInfoPeerDescriptionOut', {
amount: starsToConvert,
user: getUserFullName(targetUser)!,
peer: getPeerTitle(lang, renderingTargetPeer!)!,
}, {
withNodes: true,
withMarkdown: true,
@ -208,7 +227,7 @@ const GiftInfoModal = ({
function getTitle() {
if (gift?.type === 'starGiftUnique') return gift.title;
if (!userGift) return lang('GiftInfoSoldOutTitle');
if (!savedGift) return lang('GiftInfoSoldOutTitle');
return canUpdate ? lang('GiftInfoReceived') : lang('GiftInfoTitle');
}
@ -238,7 +257,7 @@ const GiftInfoModal = ({
{getTitle()}
</h1>
{description && (
<p className={buildClassName(styles.description, !userGift && gift?.type === 'starGift' && styles.soldOut)}>
<p className={buildClassName(styles.description, !savedGift && gift?.type === 'starGift' && styles.soldOut)}>
{description}
</p>
)}
@ -259,10 +278,10 @@ const GiftInfoModal = ({
]);
}
if (userGift?.date) {
if (savedGift?.date) {
tableData.push([
lang('GiftInfoDate'),
formatDateTimeToString(userGift.date * 1000, lang.code, true),
formatDateTimeToString(savedGift.date * 1000, lang.code, true),
]);
}
@ -280,7 +299,7 @@ const GiftInfoModal = ({
]);
}
const starsValue = gift.stars + (userGift?.alreadyPaidUpgradeStars || 0);
const starsValue = gift.stars + (savedGift?.alreadyPaidUpgradeStars || 0);
tableData.push([
lang('GiftInfoValue'),
@ -306,7 +325,7 @@ const GiftInfoModal = ({
]);
}
if (gift.upgradeStars && !userGift?.upgradeMsgId) {
if (gift.upgradeStars && !savedGift?.upgradeMsgId) {
tableData.push([
lang('GiftInfoStatus'),
<div className={styles.giftValue}>
@ -316,23 +335,43 @@ const GiftInfoModal = ({
]);
}
if (userGift?.message) {
if (savedGift?.message) {
tableData.push([
undefined,
renderTextWithEntities(userGift.message),
renderTextWithEntities(savedGift.message),
]);
}
}
if (gift.type === 'starGiftUnique') {
const { ownerName, ownerAddress, ownerId } = gift;
const {
model, backdrop, pattern, originalDetails,
} = giftAttributes || {};
const ownerName = gift.ownerName;
tableData.push([
lang('GiftInfoOwner'),
gift.ownerId ? { chatId: gift.ownerId } : ownerName || '',
]);
if (ownerAddress) {
tableData.push([
lang('GiftInfoOwner'),
<span
className={styles.ownerAddress}
onClick={() => {
copyTextToClipboard(ownerAddress);
showNotification({
message: { key: 'WalletAddressCopied' },
icon: 'copy',
});
}}
>
{ownerAddress}
<Icon className={styles.copyIcon} name="copy" />
</span>,
]);
} else {
tableData.push([
lang('GiftInfoOwner'),
ownerId ? { chatId: ownerId } : ownerName || '',
]);
}
if (model) {
tableData.push([
@ -373,34 +412,34 @@ const GiftInfoModal = ({
const {
date, recipientId, message, senderId,
} = originalDetails;
const global = getGlobal(); // User names does not need to be reactive
const global = getGlobal(); // Peer titles do not need to be reactive
const openChat = (id: string) => {
openChatWithInfo({ id });
closeGiftInfoModal();
};
const recipient = selectUser(global, recipientId)!;
const sender = senderId ? selectUser(global, senderId) : undefined;
const recipient = selectPeer(global, recipientId)!;
const sender = senderId ? selectPeer(global, senderId) : undefined;
const formattedDate = formatDateTimeToString(date * 1000, lang.code, true);
const recipientLink = (
// eslint-disable-next-line react/jsx-no-bind
<Link onClick={() => openChat(recipientId)} isPrimary>
{getUserFullName(recipient)}
{getPeerTitle(lang, recipient)}
</Link>
);
let text: TeactNode | undefined;
if (!sender || senderId === recipientId) {
text = message ? lang('GiftInfoOriginalInfoText', {
user: recipientLink,
text = message ? lang('GiftInfoPeerOriginalInfoText', {
peer: recipientLink,
text: renderTextWithEntities(message),
date: formattedDate,
}, {
withNodes: true,
}) : lang('GiftInfoOriginalInfo', {
user: recipientLink,
}) : lang('GiftInfoPeerOriginalInfo', {
peer: recipientLink,
date: formattedDate,
}, {
withNodes: true,
@ -409,18 +448,18 @@ const GiftInfoModal = ({
const senderLink = (
// eslint-disable-next-line react/jsx-no-bind
<Link onClick={() => openChat(sender.id)} isPrimary>
{getUserFullName(sender)}
{getPeerTitle(lang, sender)}
</Link>
);
text = message ? lang('GiftInfoOriginalInfoTextSender', {
user: recipientLink,
text = message ? lang('GiftInfoPeerOriginalInfoTextSender', {
peer: recipientLink,
sender: senderLink,
text: renderTextWithEntities(message),
date: formattedDate,
}, {
withNodes: true,
}) : lang('GiftInfoOriginalInfoSender', {
user: recipientLink,
}) : lang('GiftInfoPeerOriginalInfoSender', {
peer: recipientLink,
date: formattedDate,
sender: senderLink,
}, {
@ -440,8 +479,12 @@ const GiftInfoModal = ({
{canUpdate && (
<div className={styles.footerDescription}>
<div>
{lang(isUnsaved ? 'GiftInfoHidden' : 'GiftInfoSaved', {
link: <Link isPrimary onClick={handleTriggerVisibility}>{lang('GiftInfoSavedHide')}</Link>,
{lang(`GiftInfo${isTargetChat ? 'Channel' : ''}${isUnsaved ? 'Hidden' : 'Saved'}`, {
link: (
<Link isPrimary onClick={handleTriggerVisibility}>
{lang(`GiftInfoSaved${isUnsaved ? 'Show' : 'Hide'}`)}
</Link>
),
}, {
withNodes: true,
})}
@ -463,8 +506,8 @@ const GiftInfoModal = ({
footer,
};
}, [
typeGift, userGift, targetUser, giftSticker, lang, canUpdate, canConvertDifference, isSender, oldLang, gift,
giftAttributes, renderFooterButton,
typeGift, savedGift, renderingTargetPeer, giftSticker, lang, canUpdate, canConvertDifference, isSender, oldLang,
gift, giftAttributes, renderFooterButton, isTargetChat,
]);
return (
@ -478,7 +521,7 @@ const GiftInfoModal = ({
className={styles.modal}
onClose={handleClose}
/>
{userGift && (
{savedGift && (
<ConfirmDialog
isOpen={isConvertConfirmOpen}
onClose={closeConvertConfirm}
@ -486,9 +529,9 @@ const GiftInfoModal = ({
title={lang('GiftInfoConvertTitle')}
>
<div>
{lang('GiftInfoConvertDescription1', {
amount: formatStarsAsText(lang, userGift.starsToConvert!),
user: getUserFullName(userFrom)!,
{lang('GiftInfoPeerConvertDescription', {
amount: formatStarsAsText(lang, savedGift.starsToConvert!),
peer: getPeerTitle(lang, renderingFromPeer!)!,
}, {
withNodes: true,
withMarkdown: true,
@ -515,17 +558,20 @@ const GiftInfoModal = ({
export default memo(withGlobal<OwnProps>(
(global, { modal }): StateProps => {
const typeGift = modal?.gift;
const isUserGift = typeGift && 'gift' in typeGift;
const isSavedGift = typeGift && 'gift' in typeGift;
const fromId = isUserGift && typeGift.fromId;
const userFrom = fromId ? selectUser(global, fromId) : undefined;
const targetUser = modal?.userId ? selectUser(global, modal.userId) : undefined;
const fromId = isSavedGift && typeGift.fromId;
const fromPeer = fromId ? selectPeer(global, fromId) : undefined;
const targetPeer = modal?.peerId ? selectPeer(global, modal.peerId) : undefined;
const chat = targetPeer && isApiPeerChat(targetPeer) ? targetPeer : undefined;
const hasAdminRights = chat && getHasAdminRight(chat, 'postMessages');
return {
userFrom,
targetUser,
fromPeer,
targetPeer,
currentUserId: global.currentUserId,
starGiftMaxConvertPeriod: global.appConfig?.starGiftMaxConvertPeriod,
hasAdminRights,
};
},
)(GiftInfoModal));

View File

@ -63,9 +63,10 @@ const GiftUpgradeModal = ({ modal, recipient }: OwnProps & StateProps) => {
const handleUpgrade = useLastCallback(() => {
const gift = renderingModal?.gift;
if (!gift?.messageId) return;
if (!gift?.inputGift) return;
upgradeGift({
messageId: gift.messageId,
gift: gift.inputGift,
shouldKeepOriginalDetails,
upgradeStars: !gift.alreadyPaidUpgradeStars ? (gift.gift as ApiStarGiftRegular).upgradeStars : undefined,
});
@ -114,7 +115,7 @@ const GiftUpgradeModal = ({ modal, recipient }: OwnProps & StateProps) => {
] satisfies TableAboutData;
const subtitle = renderingRecipient
? lang('GiftUpgradeText', { peer: getPeerTitle(lang, renderingRecipient) })
? lang('GiftPeerUpgradeText', { peer: getPeerTitle(lang, renderingRecipient) })
: lang('GiftUpgradeTextOwn');
const header = (

View File

@ -7,7 +7,7 @@ import type { ApiStarTopupOption } from '../../../api/types';
import type { GlobalState, TabState } from '../../../global/types';
import type { RegularLangKey } from '../../../types/language';
import { getChatTitle, getUserFullName } from '../../../global/helpers';
import { getChatTitle, getPeerTitle, getUserFullName } from '../../../global/helpers';
import { selectChat, selectIsPremiumPurchaseBlocked, selectUser } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import renderText from '../../common/helpers/renderText';
@ -99,9 +99,9 @@ const StarsBalanceModal = ({
}
if (originGift) {
const user = selectUser(global, originGift.userId);
if (!user) return undefined;
return oldLang('StarsNeededTextGift', getUserFullName(user));
const peer = selectUser(global, originGift.peerId);
if (!peer) return undefined;
return oldLang('StarsNeededTextGift', getPeerTitle(lang, peer));
}
if (topup?.purpose === SUBSCRIPTION_PURPOSE) {
@ -109,7 +109,7 @@ const StarsBalanceModal = ({
}
return undefined;
}, [originReaction, originStarsPayment, originGift, topup?.purpose, oldLang]);
}, [originReaction, originStarsPayment, originGift, topup?.purpose, lang, oldLang]);
const shouldShowItems = Boolean(history?.all?.transactions.length && !shouldOpenOnBuy);
const shouldSuggestGifting = !shouldOpenOnBuy;

View File

@ -10,9 +10,9 @@ import type {
ApiChat,
ApiChatMember,
ApiMessage,
ApiSavedStarGift,
ApiTypeStory,
ApiUser,
ApiUserStarGift,
ApiUserStatus,
} from '../../api/types';
import type { TabState } from '../../global/types';
@ -81,7 +81,7 @@ import useTransitionFixes from './hooks/useTransitionFixes';
import Audio from '../common/Audio';
import Document from '../common/Document';
import UserGift from '../common/gift/UserGift';
import SavedGift from '../common/gift/SavedGift';
import GroupChatInfo from '../common/GroupChatInfo';
import Icon from '../common/icons/Icon';
import Media from '../common/Media';
@ -125,7 +125,7 @@ type StateProps = {
hasMembersTab?: boolean;
hasPreviewMediaTab?: boolean;
hasGiftsTab?: boolean;
gifts?: ApiUserStarGift[];
gifts?: ApiSavedStarGift[];
areMembersHidden?: boolean;
canAddMembers?: boolean;
canDeleteMembers?: boolean;
@ -234,7 +234,7 @@ const Profile: FC<OwnProps & StateProps> = ({
loadChannelRecommendations,
loadBotRecommendations,
loadPreviewMedias,
loadUserGifts,
loadPeerSavedGifts,
} = getActions();
// eslint-disable-next-line no-null/no-null
@ -364,7 +364,7 @@ const Profile: FC<OwnProps & StateProps> = ({
loadStoriesArchive({ peerId: currentUserId!, offsetId });
}, [currentUserId]);
const handleLoadGifts = useCallback(() => {
loadUserGifts({ userId: chatId });
loadPeerSavedGifts({ peerId: chatId });
}, [chatId]);
const [resultType, viewportIds, getMore, noProfileInfo] = useProfileViewportIds({
@ -774,8 +774,8 @@ const Profile: FC<OwnProps & StateProps> = ({
</div>
) : resultType === 'gifts' ? (
(gifts?.map((gift) => (
<UserGift
userId={chatId}
<SavedGift
peerId={chatId}
key={`${gift.date}-${gift.fromId}-${gift.gift.id}`}
gift={gift}
observeIntersection={observeIntersectionForMedia}
@ -908,8 +908,8 @@ export default memo(withGlobal<OwnProps>(
const storyByIds = peerStories?.byId;
const archiveStoryIds = peerStories?.archiveIds;
const hasGiftsTab = Boolean(userFullInfo?.starGiftCount) && !isSavedDialog;
const userGifts = global.users.giftsById[chatId];
const hasGiftsTab = Boolean(peerFullInfo?.starGiftCount) && !isSavedDialog;
const peerGifts = global.peers.giftsById[chatId];
return {
theme: selectTheme(global),
@ -934,7 +934,7 @@ export default memo(withGlobal<OwnProps>(
chatsById,
storyIds,
hasGiftsTab,
gifts: userGifts?.gifts,
gifts: peerGifts?.gifts,
pinnedStoryIds,
archiveStoryIds,
storyByIds,

View File

@ -17,6 +17,7 @@ import { callApi } from '../../../api/gramjs';
import { isChatChannel, isChatSuperGroup } from '../../helpers';
import {
getRequestInputInvoice,
getRequestInputSavedStarGift,
} from '../../helpers/payments';
import {
addActionHandler, getActions, getGlobal, setGlobal,
@ -123,12 +124,12 @@ addActionHandler('openInvoice', async (global, actions, payload): Promise<void>
addActionHandler('sendStarGift', (global, actions, payload): ActionReturnType => {
const {
gift, userId, message, shouldHideName, shouldUpgrade, tabId = getCurrentTabId(),
gift, peerId, message, shouldHideName, shouldUpgrade, tabId = getCurrentTabId(),
} = payload;
const inputInvoice: ApiInputInvoiceStarGift = {
type: 'stargift',
userId,
peerId,
giftId: gift.id,
message,
shouldHideName,
@ -520,7 +521,7 @@ addActionHandler('openGiftModal', async (global, actions, payload): Promise<void
global = getGlobal();
global = updateTabState(global, {
giftModal: {
forUserId,
forPeerId: forUserId,
gifts,
},
}, tabId);
@ -956,9 +957,14 @@ addActionHandler('launchPrepaidStarsGiveaway', async (global, actions, payload):
addActionHandler('upgradeGift', (global, actions, payload): ActionReturnType => {
const {
messageId, shouldKeepOriginalDetails, upgradeStars, tabId = getCurrentTabId(),
gift, shouldKeepOriginalDetails, upgradeStars, tabId = getCurrentTabId(),
} = payload;
const requestSavedGift = getRequestInputSavedStarGift(global, gift);
if (!requestSavedGift) {
return;
}
global = updateTabState(global, {
isWaitingForStarGiftUpgrade: true,
}, tabId);
@ -971,7 +977,7 @@ addActionHandler('upgradeGift', (global, actions, payload): ActionReturnType =>
if (!upgradeStars) {
callApi('upgradeGift', {
messageId,
inputSavedGift: requestSavedGift,
shouldKeepOriginalDetails: shouldKeepOriginalDetails || undefined,
});
@ -980,7 +986,7 @@ addActionHandler('upgradeGift', (global, actions, payload): ActionReturnType =>
const invoice: ApiInputInvoiceStarGiftUpgrade = {
type: 'stargiftUpgrade',
messageId,
inputSavedGift: gift,
shouldKeepOriginalDetails: shouldKeepOriginalDetails || undefined,
};

View File

@ -1,21 +1,21 @@
import type { ApiUserStarGift } from '../../../api/types';
import type { ApiSavedStarGift } from '../../../api/types';
import type { StarGiftCategory } from '../../../types';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { buildCollectionByKey } from '../../../util/iteratees';
import { callApi } from '../../../api/gramjs';
import { areInputSavedGiftsEqual, getRequestInputSavedStarGift } from '../../helpers/payments';
import { addActionHandler, getGlobal, setGlobal } from '../../index';
import {
appendStarsSubscriptions,
appendStarsTransactions,
replaceUserGifts,
replacePeerSavedGifts,
updateStarsBalance,
updateStarsSubscriptionLoading,
} from '../../reducers';
import { updateTabState } from '../../reducers/tabs';
import {
selectPeer,
selectUser,
} from '../../selectors';
addActionHandler('loadStarStatus', async (global): Promise<void> => {
@ -133,19 +133,19 @@ addActionHandler('loadStarGifts', async (global): Promise<void> => {
setGlobal(global);
});
addActionHandler('loadUserGifts', async (global, actions, payload): Promise<void> => {
const { userId, shouldRefresh } = payload;
addActionHandler('loadPeerSavedGifts', async (global, actions, payload): Promise<void> => {
const { peerId, shouldRefresh } = payload;
const user = selectUser(global, userId);
if (!user) return;
const peer = selectPeer(global, peerId);
if (!peer) return;
const currentGifts = global.users.giftsById[userId];
const currentGifts = global.peers.giftsById[peerId];
const localNextOffset = currentGifts?.nextOffset;
if (!shouldRefresh && currentGifts && !localNextOffset) return; // Already loaded all
const result = await callApi('fetchUserStarGifts', {
user,
const result = await callApi('fetchSavedStarGifts', {
peer,
offset: !shouldRefresh ? localNextOffset : '',
});
@ -157,7 +157,7 @@ addActionHandler('loadUserGifts', async (global, actions, payload): Promise<void
const newGifts = currentGifts && !shouldRefresh ? currentGifts.gifts.concat(result.gifts) : result.gifts;
global = replaceUserGifts(global, userId, newGifts, result.nextOffset);
global = replacePeerSavedGifts(global, peerId, newGifts, result.nextOffset);
setGlobal(global);
});
@ -216,53 +216,59 @@ addActionHandler('fulfillStarsSubscription', async (global, actions, payload): P
});
addActionHandler('changeGiftVisibility', async (global, actions, payload): Promise<void> => {
const { messageId, shouldUnsave } = payload;
const { gift, shouldUnsave } = payload;
const currentUserId = global.currentUserId!;
const peerId = gift.type === 'user' ? global.currentUserId! : gift.chatId;
const oldGifts = global.users.giftsById[currentUserId];
const requestInputGift = getRequestInputSavedStarGift(global, gift);
if (!requestInputGift) return;
const oldGifts = global.peers.giftsById[peerId];
if (oldGifts?.gifts?.length) {
const newGifts = oldGifts.gifts.map((gift) => {
if (gift.messageId === messageId) {
const newGifts = oldGifts.gifts.map((g) => {
if (g.inputGift && areInputSavedGiftsEqual(g.inputGift, gift)) {
return {
...gift,
...g,
isUnsaved: shouldUnsave,
} satisfies ApiUserStarGift;
} satisfies ApiSavedStarGift;
}
return gift;
return g;
});
global = replaceUserGifts(global, currentUserId, newGifts, oldGifts.nextOffset);
global = replacePeerSavedGifts(global, peerId, newGifts, oldGifts.nextOffset);
setGlobal(global);
}
const result = await callApi('saveStarGift', {
messageId,
inputGift: requestInputGift,
shouldUnsave,
});
global = getGlobal();
if (!result) {
global = replaceUserGifts(global, currentUserId, oldGifts.gifts, oldGifts.nextOffset);
global = replacePeerSavedGifts(global, peerId, oldGifts.gifts, oldGifts.nextOffset);
setGlobal(global);
return;
}
// Reload gift list to avoid issues with pagination
actions.loadUserGifts({ userId: currentUserId, shouldRefresh: true });
actions.loadPeerSavedGifts({ peerId, shouldRefresh: true });
});
addActionHandler('convertGiftToStars', async (global, actions, payload): Promise<void> => {
const { messageId, tabId = getCurrentTabId() } = payload;
const { gift, tabId = getCurrentTabId() } = payload;
const requestInputGift = getRequestInputSavedStarGift(global, gift);
if (!requestInputGift) return;
const result = await callApi('convertStarGift', {
messageId,
inputSavedGift: requestInputGift,
});
if (!result) {
return;
}
actions.loadUserGifts({ userId: global.currentUserId!, shouldRefresh: true });
actions.loadPeerSavedGifts({ peerId: global.currentUserId!, shouldRefresh: true });
actions.openStarsBalanceModal({ tabId });
});

View File

@ -1,6 +1,7 @@
import type { ActionReturnType } from '../../types';
import { PaymentStep } from '../../../types';
import { SERVICE_NOTIFICATIONS_USER_ID } from '../../../config';
import { applyLangPackDifference, requestLangPackDifference } from '../../../util/localization';
import { addActionHandler, setGlobal } from '../../index';
import {
@ -211,9 +212,9 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
case 'newMessage': {
const actionStarGift = update.message.content?.action?.starGift;
if (actionStarGift?.type !== 'starGiftUnique' || !update.message.isOutgoing) {
return undefined;
}
if (!update.message.isOutgoing && update.message.chatId !== SERVICE_NOTIFICATIONS_USER_ID) return undefined;
if (actionStarGift?.type !== 'starGiftUnique') return undefined;
Object.values(global.byTabId).forEach(({ id: tabId }) => {
const tabState = selectTabState(global, tabId);
if (tabState.isWaitingForStarGiftUpgrade) {

View File

@ -76,7 +76,7 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
}
const giftModalState = selectTabState(global, tabId).giftModal;
if (giftModalState && inputInvoice.userIds[0] === giftModalState.forUserId) {
if (giftModalState && inputInvoice.userIds[0] === giftModalState.forPeerId) {
global = updateTabState(global, {
giftModal: {
...giftModalState,

View File

@ -1,4 +1,4 @@
import type { ApiMessageActionStarGift, ApiUserStarGift } from '../../../api/types';
import type { ApiMessageActionStarGift, ApiSavedStarGift } from '../../../api/types';
import type { ActionReturnType } from '../../types';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
@ -266,9 +266,10 @@ addActionHandler('openGiftInfoModalFromMessage', (global, actions, payload): Act
upgradeMsgId: starGift.upgradeMsgId,
canUpgrade: starGift.canUpgrade,
alreadyPaidUpgradeStars: starGift.alreadyPaidUpgradeStars,
} satisfies ApiUserStarGift;
inputGift: starGift.inputSavedGift,
} satisfies ApiSavedStarGift;
actions.openGiftInfoModal({ userId: giftReceiverId, gift, tabId });
actions.openGiftInfoModal({ peerId: giftReceiverId, gift, tabId });
});
addActionHandler('openGiftInfoModal', (global, actions, payload): ActionReturnType => {
@ -276,11 +277,11 @@ addActionHandler('openGiftInfoModal', (global, actions, payload): ActionReturnTy
gift, tabId = getCurrentTabId(),
} = payload;
const userId = 'userId' in payload ? payload.userId : undefined;
const peerId = 'peerId' in payload ? payload.peerId : undefined;
return updateTabState(global, {
giftInfoModal: {
userId,
peerId,
gift,
},
}, tabId);

View File

@ -4,10 +4,7 @@ import { addCallback, removeCallback } from '../lib/teact/teactn';
import type {
ApiAvailableReaction,
ApiBotPreviewMedia,
ApiMessage,
ApiUserCommonChats,
ApiUserGifts,
} from '../api/types';
import type { MessageList, ThreadId } from '../types';
import type { ActionReturnType, GlobalState } from './types';
@ -276,6 +273,10 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
if (!cached.settings.botVerificationShownPeerIds) {
cached.settings.botVerificationShownPeerIds = initialState.settings.botVerificationShownPeerIds;
}
if (!cached.peers) {
cached.peers = initialState.peers;
}
}
function updateCache(force?: boolean) {
@ -386,15 +387,7 @@ function reduceCustomEmojis<T extends GlobalState>(global: T): GlobalState['cust
};
}
function reduceUsers<T extends GlobalState>(global: T): {
commonChatsById: Record<string, ApiUserCommonChats>;
giftsById: Record<string, ApiUserGifts>;
botAppPermissionsById: any;
statusesById: any;
fullInfoById: any;
byId: any;
previewMediaByBotId: Record<string, ApiBotPreviewMedia[]>;
} {
function reduceUsers<T extends GlobalState>(global: T): GlobalState['users'] {
const {
users: {
byId, statusesById, fullInfoById, botAppPermissionsById,

View File

@ -34,7 +34,7 @@ import { getGlobal } from '../index';
import {
getChatTitle, getCleanPeerId, isPeerUser, isUserId,
} from './chats';
import { getMainUsername, getUserFullName } from './users';
import { getMainUsername, getUserFirstOrLastName, getUserFullName } from './users';
const RE_LINK = new RegExp(RE_LINK_TEMPLATE, 'i');
@ -210,6 +210,16 @@ export function isAnonymousOwnMessage(message: ApiMessage) {
}
export function getPeerTitle(lang: OldLangFn | LangFn, peer: ApiPeer | CustomPeer) {
if (!peer) return undefined;
if ('isCustomPeer' in peer) {
// TODO: Remove any after full migration to new lang
return peer.titleKey ? lang(peer.titleKey as any) : peer.title;
}
return isPeerUser(peer) ? getUserFirstOrLastName(peer) : getChatTitle(lang, peer);
}
export function getPeerFullTitle(lang: OldLangFn | LangFn, peer: ApiPeer | CustomPeer) {
if (!peer) return undefined;
if ('isCustomPeer' in peer) {
// TODO: Remove any after full migration to new lang
return peer.titleKey ? lang(peer.titleKey as any) : peer.title;

View File

@ -1,7 +1,9 @@
import type {
ApiInputInvoice,
ApiInputSavedStarGift,
ApiMessage,
ApiRequestInputInvoice,
ApiRequestInputSavedStarGift,
ApiStarsAmount,
ApiStarsTransaction,
ApiStarsTransactionPeer,
@ -11,7 +13,8 @@ import type { CustomPeer } from '../../types';
import type { LangFn } from '../../util/localization';
import type { GlobalState } from '../types';
import { selectChat, selectUser } from '../selectors';
import arePropsShallowEqual from '../../util/arePropsShallowEqual';
import { selectChat, selectPeer, selectUser } from '../selectors';
export function getRequestInputInvoice<T extends GlobalState>(
global: T, inputInvoice: ApiInputInvoice,
@ -20,15 +23,15 @@ export function getRequestInputInvoice<T extends GlobalState>(
if (inputInvoice.type === 'stargift') {
const {
userId, shouldHideName, giftId, message, shouldUpgrade,
peerId, shouldHideName, giftId, message, shouldUpgrade,
} = inputInvoice;
const user = selectUser(global, userId);
const peer = selectPeer(global, peerId);
if (!user) return undefined;
if (!peer) return undefined;
return {
type: 'stargift',
user,
peer,
shouldHideName,
giftId,
message,
@ -174,10 +177,13 @@ export function getRequestInputInvoice<T extends GlobalState>(
}
if (inputInvoice.type === 'stargiftUpgrade') {
const { messageId, shouldKeepOriginalDetails } = inputInvoice;
const { inputSavedGift, shouldKeepOriginalDetails } = inputInvoice;
const savedGift = getRequestInputSavedStarGift(global, inputSavedGift);
if (!savedGift) return undefined;
return {
type: 'stargiftUpgrade',
messageId,
inputSavedGift: savedGift,
shouldKeepOriginalDetails,
};
}
@ -185,6 +191,25 @@ export function getRequestInputInvoice<T extends GlobalState>(
return undefined;
}
export function getRequestInputSavedStarGift<T extends GlobalState>(
global: T, inputGift: ApiInputSavedStarGift,
): ApiRequestInputSavedStarGift | undefined {
if (inputGift.type === 'user') return inputGift;
if (inputGift.type === 'chat') {
const chat = selectChat(global, inputGift.chatId);
if (!chat) return undefined;
return {
type: 'chat',
chat,
savedId: inputGift.savedId,
};
}
return undefined;
}
export function buildStarsTransactionCustomPeer(
peer: Exclude<ApiStarsTransactionPeer, ApiStarsTransactionPeerPeer>,
): CustomPeer {
@ -315,3 +340,7 @@ export function getPrizeStarsTransactionFromGiveaway(message: ApiMessage): ApiSt
giveawayPostId: message.id,
};
}
export function areInputSavedGiftsEqual(one: ApiInputSavedStarGift, two: ApiInputSavedStarGift) {
return arePropsShallowEqual(one, two);
}

View File

@ -102,10 +102,14 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
fullInfoById: {},
previewMediaByBotId: {},
commonChatsById: {},
giftsById: {},
botAppPermissionsById: {},
},
peers: {
giftsById: {},
profilePhotosById: {},
},
chats: {
listIds: {},
isFullyLoaded: {},
@ -310,7 +314,6 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
isHidden: false,
},
profilePhotosById: {},
monetizationInfo: {},
};

View File

@ -62,15 +62,21 @@ export function replacePeerPhotos<T extends GlobalState>(
if (!value) {
return {
...global,
profilePhotosById: omit(global.profilePhotosById, [peerId]),
peers: {
...global.peers,
profilePhotosById: omit(global.peers.profilePhotosById, [peerId]),
},
};
}
return {
...global,
profilePhotosById: {
...global.profilePhotosById,
[peerId]: value,
peers: {
...global.peers,
profilePhotosById: {
...global.peers.profilePhotosById,
[peerId]: value,
},
},
};
}

View File

@ -1,9 +1,9 @@
import type {
ApiMissingInvitedUser,
ApiSavedStarGift,
ApiUser,
ApiUserCommonChats,
ApiUserFullInfo,
ApiUserStarGift,
ApiUserStatus,
} from '../../api/types';
import type { BotAppPermissions } from '../../types';
@ -324,19 +324,19 @@ export function updateBotAppPermissions<T extends GlobalState>(
};
}
export function replaceUserGifts<T extends GlobalState>(
export function replacePeerSavedGifts<T extends GlobalState>(
global: T,
userId: string,
gifts: ApiUserStarGift[],
peerId: string,
gifts: ApiSavedStarGift[],
nextOffset?: string,
): T {
global = {
...global,
users: {
...global.users,
peers: {
...global.peers,
giftsById: {
...global.users.giftsById,
[userId]: {
...global.peers.giftsById,
[peerId]: {
gifts,
nextOffset,
},

View File

@ -1,13 +1,25 @@
import type { ApiPeer } from '../../api/types';
import type { GlobalState } from '../types';
import { selectChat } from './chats';
import { selectUser } from './users';
import { SERVICE_NOTIFICATIONS_USER_ID } from '../../config';
import { selectChat, selectChatFullInfo } from './chats';
import { selectBot, selectIsPremiumPurchaseBlocked, selectUser } from './users';
export function selectPeer<T extends GlobalState>(global: T, peerId: string): ApiPeer | undefined {
return selectUser(global, peerId) || selectChat(global, peerId);
}
export function selectPeerPhotos<T extends GlobalState>(global: T, peerId: string) {
return global.profilePhotosById[peerId];
return global.peers.profilePhotosById[peerId];
}
export function selectCanGift<T extends GlobalState>(global: T, peerId: string) {
const bot = selectBot(global, peerId);
const user = selectUser(global, peerId);
const chat = selectChat(global, peerId);
const areStarGiftsAvailable = chat ? selectChatFullInfo(global, peerId)?.areStarGiftsAvailable : user;
return Boolean(!selectIsPremiumPurchaseBlocked(global) && !bot && peerId !== SERVICE_NOTIFICATIONS_USER_ID
&& areStarGiftsAvailable);
}

View File

@ -5,7 +5,6 @@ import type {
import type { BotAppPermissions } from '../../types';
import type { GlobalState } from '../types';
import { SERVICE_NOTIFICATIONS_USER_ID } from '../../config';
import { isUserBot } from '../helpers';
export function selectUser<T extends GlobalState>(global: T, userId: string): ApiUser | undefined {
@ -62,14 +61,6 @@ export function selectBot<T extends GlobalState>(global: T, userId: string): Api
return user;
}
export function selectCanGift<T extends GlobalState>(global: T, userId: string) {
const bot = selectBot(global, userId);
const user = selectUser(global, userId);
return !selectIsPremiumPurchaseBlocked(global) && user && !bot
&& !user.isSelf && userId !== SERVICE_NOTIFICATIONS_USER_ID;
}
export function selectBotAppPermissions<T extends GlobalState>(
global: T, userId: string,
): BotAppPermissions | undefined {

View File

@ -17,6 +17,7 @@ import type {
ApiInputInvoice,
ApiInputInvoiceStarGift,
ApiInputMessageReplyInfo,
ApiInputSavedStarGift,
ApiKeyboardButton,
ApiLimitTypeWithModal,
ApiMessage,
@ -32,6 +33,7 @@ import type {
ApiReaction,
ApiReactionWithPaid,
ApiReportReason,
ApiSavedStarGift,
ApiSendMessageAction,
ApiSessionData,
ApiStarGift,
@ -44,7 +46,6 @@ import type {
ApiTypePrepaidGiveaway,
ApiUpdate,
ApiUser,
ApiUserStarGift,
ApiVideo,
BotsPrivacyType,
PrivacyVisibility,
@ -2305,8 +2306,8 @@ export interface ActionPayloads {
messageId: number;
} & WithTabId;
openGiftInfoModal: ({
userId: string;
gift: ApiUserStarGift;
peerId: string;
gift: ApiSavedStarGift;
} | {
gift: ApiStarGift;
}) & WithTabId;
@ -2314,24 +2315,24 @@ export interface ActionPayloads {
openGiftUpgradeModal: {
giftId: string;
peerId?: string;
gift?: ApiUserStarGift;
gift?: ApiSavedStarGift;
} & WithTabId;
closeGiftUpgradeModal: WithTabId | undefined;
upgradeGift: {
messageId: number;
gift: ApiInputSavedStarGift;
shouldKeepOriginalDetails?: boolean;
upgradeStars?: number;
} & WithTabId;
loadUserGifts: {
userId: string;
loadPeerSavedGifts: {
peerId: string;
shouldRefresh?: boolean;
};
changeGiftVisibility: {
messageId: number;
gift: ApiInputSavedStarGift;
shouldUnsave?: boolean;
};
convertGiftToStars: {
messageId: number;
gift: ApiInputSavedStarGift;
} & WithTabId;
openStarsGiftModal: ({

View File

@ -24,6 +24,7 @@ import type {
ApiQuickReply,
ApiReaction,
ApiReactionKey,
ApiSavedGifts,
ApiSavedReactionTag,
ApiSession,
ApiSponsoredMessage,
@ -40,7 +41,6 @@ import type {
ApiUser,
ApiUserCommonChats,
ApiUserFullInfo,
ApiUserGifts,
ApiUserStatus,
ApiVideo,
ApiWallpaper,
@ -176,10 +176,13 @@ export type GlobalState = {
fullInfoById: Record<string, ApiUserFullInfo>;
previewMediaByBotId: Record<string, ApiBotPreviewMedia[]>;
commonChatsById: Record<string, ApiUserCommonChats>;
giftsById: Record<string, ApiUserGifts>;
botAppPermissionsById: Record<string, BotAppPermissions>;
};
profilePhotosById: Record<string, ApiPeerPhotos>;
peers: {
profilePhotosById: Record<string, ApiPeerPhotos>;
giftsById: Record<string, ApiSavedGifts>;
};
chats: {
// TODO Replace with `Partial<Record>` to properly handle missing keys

View File

@ -32,6 +32,7 @@ import type {
ApiPremiumSection,
ApiReactionWithPaid,
ApiReceiptRegular,
ApiSavedStarGift,
ApiStarGift,
ApiStarGiftAttribute,
ApiStarGiveawayOption,
@ -42,7 +43,6 @@ import type {
ApiTypePrepaidGiveaway,
ApiTypeStoryView,
ApiUser,
ApiUserStarGift,
ApiVideo,
ApiWebPage,
} from '../../api/types';
@ -603,8 +603,8 @@ export type TabState = {
giftModal?: {
isCompleted?: boolean;
forUserId: string;
gifts: ApiPremiumGiftCodeOption[];
forPeerId: string;
gifts?: ApiPremiumGiftCodeOption[];
};
limitReachedModal?: {
@ -710,14 +710,14 @@ export type TabState = {
};
giftInfoModal?: {
userId?: string;
gift: ApiUserStarGift | ApiStarGift;
peerId?: string;
gift: ApiSavedStarGift | ApiStarGift;
};
giftUpgradeModal?: {
sampleAttributes: ApiStarGiftAttribute[];
recipientId?: string;
gift?: ApiUserStarGift;
gift?: ApiSavedStarGift;
};
suggestedStatusModal?: {

View File

@ -12,5 +12,5 @@ for (const tl of Object.values(Api)) {
}
}
export const LAYER = 197;
export const LAYER = 198;
export { tlobjects };

File diff suppressed because one or more lines are too long

View File

@ -24,11 +24,11 @@ inputMediaUploadedPhoto#1e287d04 flags:# spoiler:flags.2?true file:InputFile sti
inputMediaPhoto#b3ba0635 flags:# spoiler:flags.1?true id:InputPhoto ttl_seconds:flags.0?int = InputMedia;
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia;
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true spoiler:flags.5?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaDocument#33473058 flags:# spoiler:flags.2?true id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
inputMediaUploadedDocument#37c9330 flags:# nosound_video:flags.3?true force_file:flags.4?true spoiler:flags.5?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> video_cover:flags.6?InputPhoto video_timestamp:flags.7?int ttl_seconds:flags.1?int = InputMedia;
inputMediaDocument#a8763ab5 flags:# spoiler:flags.2?true id:InputDocument video_cover:flags.3?InputPhoto video_timestamp:flags.4?int ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia;
inputMediaPhotoExternal#e5bbfe1a flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaDocumentExternal#fb52dc99 flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaDocumentExternal#779600f9 flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int video_cover:flags.2?InputPhoto video_timestamp:flags.3?int = InputMedia;
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
inputMediaInvoice#405fef0d flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:flags.3?string provider_data:DataJSON start_param:flags.1?string extended_media:flags.2?InputMedia = InputMedia;
inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
@ -83,7 +83,7 @@ chatForbidden#6592a1a7 id:long title:string = Chat;
channel#e00998b7 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
channelFull#9ff3b858 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification = ChatFull;
channelFull#52d6806b flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
chatParticipantAdmin#a0933f5b user_id:long inviter_id:long date:int = ChatParticipant;
@ -99,7 +99,7 @@ messageMediaPhoto#695150d7 flags:# spoiler:flags.3?true photo:flags.0?Photo ttl_
messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
messageMediaContact#70322949 phone_number:string first_name:string last_name:string vcard:string user_id:long = MessageMedia;
messageMediaUnsupported#9f84f49e = MessageMedia;
messageMediaDocument#dd570bd5 flags:# nopremium:flags.3?true spoiler:flags.4?true video:flags.6?true round:flags.7?true voice:flags.8?true document:flags.0?Document alt_documents:flags.5?Vector<Document> ttl_seconds:flags.2?int = MessageMedia;
messageMediaDocument#52d8ccd9 flags:# nopremium:flags.3?true spoiler:flags.4?true video:flags.6?true round:flags.7?true voice:flags.8?true document:flags.0?Document alt_documents:flags.5?Vector<Document> video_cover:flags.9?Photo video_timestamp:flags.10?int ttl_seconds:flags.2?int = MessageMedia;
messageMediaWebPage#ddf10c3b flags:# force_large_media:flags.0?true force_small_media:flags.1?true manual:flags.3?true safe:flags.4?true webpage:WebPage = MessageMedia;
messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
messageMediaGame#fdb19008 game:Game = MessageMedia;
@ -157,8 +157,8 @@ messageActionRequestedPeerSentMe#93b31848 button_id:int peers:Vector<RequestedPe
messageActionPaymentRefunded#41b3e202 flags:# peer:Peer currency:string total_amount:long payload:flags.0?bytes charge:PaymentCharge = MessageAction;
messageActionGiftStars#45d5b021 flags:# currency:string amount:long stars:long crypto_currency:flags.0?string crypto_amount:flags.0?long transaction_id:flags.1?string = MessageAction;
messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction;
messageActionStarGift#d8f4f0a7 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long = MessageAction;
messageActionStarGiftUnique#26077b99 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long = MessageAction;
messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction;
messageActionStarGiftUnique#acdfcb81 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long = MessageAction;
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
photoEmpty#2331b22d id:long = Photo;
@ -1124,9 +1124,9 @@ inputInvoiceSlug#c326caef slug:string = InputInvoice;
inputInvoicePremiumGiftCode#98986c0d purpose:InputStorePaymentPurpose option:PremiumGiftCodeOption = InputInvoice;
inputInvoiceStars#65f00ce3 purpose:InputStorePaymentPurpose = InputInvoice;
inputInvoiceChatInviteSubscription#34e793f1 hash:string = InputInvoice;
inputInvoiceStarGift#25d8c1d8 flags:# hide_name:flags.0?true include_upgrade:flags.2?true user_id:InputUser gift_id:long message:flags.1?TextWithEntities = InputInvoice;
inputInvoiceStarGiftUpgrade#5ebe7262 flags:# keep_original_details:flags.0?true msg_id:int = InputInvoice;
inputInvoiceStarGiftTransfer#ae3ba9ed msg_id:int to_id:InputUser = InputInvoice;
inputInvoiceStarGift#e8625e92 flags:# hide_name:flags.0?true include_upgrade:flags.2?true peer:InputPeer gift_id:long message:flags.1?TextWithEntities = InputInvoice;
inputInvoiceStarGiftUpgrade#4d818d5d flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = InputInvoice;
inputInvoiceStarGiftTransfer#4a5f5bd9 stargift:InputSavedStarGift to_id:InputPeer = InputInvoice;
payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
messages.transcribedAudio#cfb9d957 flags:# pending:flags.0?true transcription_id:long text:string trial_remains_num:flags.1?int trial_remains_until_date:flags.1?int = messages.TranscribedAudio;
help.premiumPromo#5334759c status_text:string status_entities:Vector<MessageEntity> video_sections:Vector<string> videos:Vector<Document> period_options:Vector<PremiumSubscriptionOption> users:Vector<User> = help.PremiumPromo;
@ -1140,8 +1140,9 @@ inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?tru
premiumGiftOption#74c34319 flags:# months:int currency:string amount:long bot_url:string store_product:flags.0?string = PremiumGiftOption;
paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod;
emojiStatusEmpty#2de11aae = EmojiStatus;
emojiStatus#929b619d document_id:long = EmojiStatus;
emojiStatusUntil#fa30a8c7 document_id:long until:int = EmojiStatus;
emojiStatus#e7ff068a flags:# document_id:long until:flags.0?int = EmojiStatus;
emojiStatusCollectible#7184603b flags:# collectible_id:long document_id:long title:string slug:string pattern_document_id:long center_color:int edge_color:int pattern_color:int text_color:int until:flags.0?int = EmojiStatus;
inputEmojiStatusCollectible#7141dbf flags:# collectible_id:long until:flags.0?int = EmojiStatus;
account.emojiStatusesNotModified#d08ce645 = account.EmojiStatuses;
account.emojiStatuses#90c467d1 hash:long statuses:Vector<EmojiStatus> = account.EmojiStatuses;
reactionEmpty#79f5d419 = Reaction;
@ -1366,11 +1367,9 @@ messageReactor#4ba3a95a flags:# top:flags.0?true my:flags.1?true anonymous:flags
starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true stars:long yearly_boosts:int store_product:flags.2?string currency:string amount:long winners:Vector<StarsGiveawayWinnersOption> = StarsGiveawayOption;
starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption;
starGift#2cc73c8 flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long = StarGift;
starGiftUnique#3482f322 flags:# id:long title:string slug:string num:int owner_id:flags.0?long owner_name:flags.1?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int = StarGift;
starGiftUnique#f2fe7e4a flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int = StarGift;
payments.starGiftsNotModified#a388a368 = payments.StarGifts;
payments.starGifts#901689ea hash:int gifts:Vector<StarGift> = payments.StarGifts;
userStarGift#325835e1 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true from_id:flags.1?long date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long = UserStarGift;
payments.userStarGifts#6b65b517 flags:# count:int gifts:Vector<UserStarGift> next_offset:flags.0?string users:Vector<User> = payments.UserStarGifts;
messageReportOption#7903e3d9 text:string option:bytes = MessageReportOption;
reportResultChooseOption#f0e4e0b6 title:string options:Vector<MessageReportOption> = ReportResult;
reportResultAddComment#6f09ac31 flags:# optional:flags.0?true option:bytes = ReportResult;
@ -1390,12 +1389,17 @@ botVerification#f93cd45c bot_id:long icon:long description:string = BotVerificat
starGiftAttributeModel#39d99013 name:string document:Document rarity_permille:int = StarGiftAttribute;
starGiftAttributePattern#13acff19 name:string document:Document rarity_permille:int = StarGiftAttribute;
starGiftAttributeBackdrop#94271762 name:string center_color:int edge_color:int pattern_color:int text_color:int rarity_permille:int = StarGiftAttribute;
starGiftAttributeOriginalDetails#c02c4f4b flags:# sender_id:flags.0?long recipient_id:long date:int message:flags.1?TextWithEntities = StarGiftAttribute;
starGiftAttributeOriginalDetails#e0bff26c flags:# sender_id:flags.0?Peer recipient_id:Peer date:int message:flags.1?TextWithEntities = StarGiftAttribute;
payments.starGiftUpgradePreview#167bd90b sample_attributes:Vector<StarGiftAttribute> = payments.StarGiftUpgradePreview;
users.users#62d706b8 users:Vector<User> = users.Users;
users.usersSlice#315a4974 count:int users:Vector<User> = users.Users;
payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector<User> = payments.UniqueStarGift;
messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector<User> = messages.WebPagePreview;
savedStarGift#6056dba5 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long = SavedStarGift;
payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector<SavedStarGift> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.SavedStarGifts;
inputSavedStarGiftUser#69279795 msg_id:int = InputSavedStarGift;
inputSavedStarGiftChat#f101aa7f peer:InputPeer saved_id:long = InputSavedStarGift;
payments.starGiftWithdrawalUrl#84aa3a9c url:string = payments.StarGiftWithdrawalUrl;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
initConnection#c1cd5ea9 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy params:flags.1?JSONValue query:!X = X;
@ -1483,7 +1487,7 @@ messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
messages.sendMessage#983f9745 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long = Updates;
messages.sendMedia#7852834e flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long = Updates;
messages.forwardMessages#d5039208 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;
messages.forwardMessages#6d74da08 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int = Updates;
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
messages.report#fc78af9b peer:InputPeer id:Vector<int> option:bytes message:string = ReportResult;
@ -1682,13 +1686,13 @@ channels.getChannelRecommendations#25a71742 flags:# channel:flags.0?InputChannel
channels.searchPosts#d19f987b hashtag:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
bots.setBotInfo#10cf3123 flags:# bot:flags.2?InputUser lang_code:string name:flags.3?string about:flags.0?string description:flags.1?string = Bool;
bots.canSendMessage#1359f4e6 bot:InputUser = Bool;
bots.getBotRecommendations#a1b70815 bot:InputUser = users.Users;
bots.allowSendMessage#f132e3ef bot:InputUser = Updates;
bots.invokeWebViewCustomMethod#87fc5e7 bot:InputUser custom_method:string params:DataJSON = DataJSON;
bots.getPopularAppBots#c2510192 offset:string limit:int = bots.PopularAppBots;
bots.getPreviewMedias#a2a5594d bot:InputUser = Vector<BotPreviewMedia>;
bots.toggleUserEmojiStatusPermission#6de6392 bot:InputUser enabled:Bool = Bool;
bots.checkDownloadFileParams#50077589 bot:InputUser file_name:string url:string = Bool;
bots.getBotRecommendations#a1b70815 bot:InputUser = users.Users;
payments.getPaymentForm#37148dbb flags:# invoice:InputInvoice theme_params:flags.0?DataJSON = payments.PaymentForm;
payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt;
payments.validateRequestedInfo#b6c8f12b flags:# save:flags.0?true invoice:InputInvoice info:PaymentRequestedInfo = payments.ValidatedRequestedInfo;
@ -1711,14 +1715,13 @@ payments.changeStarsSubscription#c7770878 flags:# peer:InputPeer subscription_id
payments.fulfillStarsSubscription#cc5bebb3 peer:InputPeer subscription_id:string = Bool;
payments.getStarsGiveawayOptions#bd1efd3e = Vector<StarsGiveawayOption>;
payments.getStarGifts#c4563590 hash:int = payments.StarGifts;
payments.getUserStarGifts#5e72c7e1 user_id:InputUser offset:string limit:int = payments.UserStarGifts;
payments.saveStarGift#92fd2aae flags:# unsave:flags.0?true msg_id:int = Bool;
payments.convertStarGift#72770c83 msg_id:int = Bool;
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
payments.saveStarGift#2a2a697c flags:# unsave:flags.0?true stargift:InputSavedStarGift = Bool;
payments.convertStarGift#74bf076b stargift:InputSavedStarGift = Bool;
payments.getStarGiftUpgradePreview#9c9abcb1 gift_id:long = payments.StarGiftUpgradePreview;
payments.upgradeStarGift#cf4f0781 flags:# keep_original_details:flags.0?true msg_id:int = Updates;
payments.transferStarGift#333fb526 msg_id:int to_id:InputUser = Updates;
payments.upgradeStarGift#aed6e4f5 flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = Updates;
payments.transferStarGift#7f18176a stargift:InputSavedStarGift to_id:InputPeer = Updates;
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
payments.getSavedStarGifts#23830de9 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer offset:string limit:int = payments.SavedStarGifts;
phone.requestCall#a6c4600c flags:# video:flags.0?true user_id:InputUser conference_call:flags.1?InputGroupCall random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;

View File

@ -303,7 +303,7 @@
"payments.refundStarsCharge",
"payments.getStarsGiftOptions",
"payments.getStarGifts",
"payments.getUserStarGifts",
"payments.getSavedStarGifts",
"payments.saveStarGift",
"payments.convertStarGift",
"payments.getStarGiftUpgradePreview",

View File

@ -33,11 +33,11 @@ inputMediaUploadedPhoto#1e287d04 flags:# spoiler:flags.2?true file:InputFile sti
inputMediaPhoto#b3ba0635 flags:# spoiler:flags.1?true id:InputPhoto ttl_seconds:flags.0?int = InputMedia;
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia;
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true spoiler:flags.5?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaDocument#33473058 flags:# spoiler:flags.2?true id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
inputMediaUploadedDocument#37c9330 flags:# nosound_video:flags.3?true force_file:flags.4?true spoiler:flags.5?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> video_cover:flags.6?InputPhoto video_timestamp:flags.7?int ttl_seconds:flags.1?int = InputMedia;
inputMediaDocument#a8763ab5 flags:# spoiler:flags.2?true id:InputDocument video_cover:flags.3?InputPhoto video_timestamp:flags.4?int ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia;
inputMediaPhotoExternal#e5bbfe1a flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaDocumentExternal#fb52dc99 flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaDocumentExternal#779600f9 flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int video_cover:flags.2?InputPhoto video_timestamp:flags.3?int = InputMedia;
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
inputMediaInvoice#405fef0d flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:flags.3?string provider_data:DataJSON start_param:flags.1?string extended_media:flags.2?InputMedia = InputMedia;
inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
@ -103,7 +103,7 @@ channel#e00998b7 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
channelFull#9ff3b858 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification = ChatFull;
channelFull#52d6806b flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@ -124,7 +124,7 @@ messageMediaPhoto#695150d7 flags:# spoiler:flags.3?true photo:flags.0?Photo ttl_
messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
messageMediaContact#70322949 phone_number:string first_name:string last_name:string vcard:string user_id:long = MessageMedia;
messageMediaUnsupported#9f84f49e = MessageMedia;
messageMediaDocument#dd570bd5 flags:# nopremium:flags.3?true spoiler:flags.4?true video:flags.6?true round:flags.7?true voice:flags.8?true document:flags.0?Document alt_documents:flags.5?Vector<Document> ttl_seconds:flags.2?int = MessageMedia;
messageMediaDocument#52d8ccd9 flags:# nopremium:flags.3?true spoiler:flags.4?true video:flags.6?true round:flags.7?true voice:flags.8?true document:flags.0?Document alt_documents:flags.5?Vector<Document> video_cover:flags.9?Photo video_timestamp:flags.10?int ttl_seconds:flags.2?int = MessageMedia;
messageMediaWebPage#ddf10c3b flags:# force_large_media:flags.0?true force_small_media:flags.1?true manual:flags.3?true safe:flags.4?true webpage:WebPage = MessageMedia;
messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
messageMediaGame#fdb19008 game:Game = MessageMedia;
@ -183,8 +183,8 @@ messageActionRequestedPeerSentMe#93b31848 button_id:int peers:Vector<RequestedPe
messageActionPaymentRefunded#41b3e202 flags:# peer:Peer currency:string total_amount:long payload:flags.0?bytes charge:PaymentCharge = MessageAction;
messageActionGiftStars#45d5b021 flags:# currency:string amount:long stars:long crypto_currency:flags.0?string crypto_amount:flags.0?long transaction_id:flags.1?string = MessageAction;
messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction;
messageActionStarGift#d8f4f0a7 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long = MessageAction;
messageActionStarGiftUnique#26077b99 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long = MessageAction;
messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction;
messageActionStarGiftUnique#acdfcb81 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long = MessageAction;
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
@ -1475,9 +1475,9 @@ inputInvoiceSlug#c326caef slug:string = InputInvoice;
inputInvoicePremiumGiftCode#98986c0d purpose:InputStorePaymentPurpose option:PremiumGiftCodeOption = InputInvoice;
inputInvoiceStars#65f00ce3 purpose:InputStorePaymentPurpose = InputInvoice;
inputInvoiceChatInviteSubscription#34e793f1 hash:string = InputInvoice;
inputInvoiceStarGift#25d8c1d8 flags:# hide_name:flags.0?true include_upgrade:flags.2?true user_id:InputUser gift_id:long message:flags.1?TextWithEntities = InputInvoice;
inputInvoiceStarGiftUpgrade#5ebe7262 flags:# keep_original_details:flags.0?true msg_id:int = InputInvoice;
inputInvoiceStarGiftTransfer#ae3ba9ed msg_id:int to_id:InputUser = InputInvoice;
inputInvoiceStarGift#e8625e92 flags:# hide_name:flags.0?true include_upgrade:flags.2?true peer:InputPeer gift_id:long message:flags.1?TextWithEntities = InputInvoice;
inputInvoiceStarGiftUpgrade#4d818d5d flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = InputInvoice;
inputInvoiceStarGiftTransfer#4a5f5bd9 stargift:InputSavedStarGift to_id:InputPeer = InputInvoice;
payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
@ -1498,8 +1498,9 @@ premiumGiftOption#74c34319 flags:# months:int currency:string amount:long bot_ur
paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod;
emojiStatusEmpty#2de11aae = EmojiStatus;
emojiStatus#929b619d document_id:long = EmojiStatus;
emojiStatusUntil#fa30a8c7 document_id:long until:int = EmojiStatus;
emojiStatus#e7ff068a flags:# document_id:long until:flags.0?int = EmojiStatus;
emojiStatusCollectible#7184603b flags:# collectible_id:long document_id:long title:string slug:string pattern_document_id:long center_color:int edge_color:int pattern_color:int text_color:int until:flags.0?int = EmojiStatus;
inputEmojiStatusCollectible#7141dbf flags:# collectible_id:long until:flags.0?int = EmojiStatus;
account.emojiStatusesNotModified#d08ce645 = account.EmojiStatuses;
account.emojiStatuses#90c467d1 hash:long statuses:Vector<EmojiStatus> = account.EmojiStatuses;
@ -1876,15 +1877,11 @@ starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true
starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption;
starGift#2cc73c8 flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long = StarGift;
starGiftUnique#3482f322 flags:# id:long title:string slug:string num:int owner_id:flags.0?long owner_name:flags.1?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int = StarGift;
starGiftUnique#f2fe7e4a flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int = StarGift;
payments.starGiftsNotModified#a388a368 = payments.StarGifts;
payments.starGifts#901689ea hash:int gifts:Vector<StarGift> = payments.StarGifts;
userStarGift#325835e1 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true from_id:flags.1?long date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long = UserStarGift;
payments.userStarGifts#6b65b517 flags:# count:int gifts:Vector<UserStarGift> next_offset:flags.0?string users:Vector<User> = payments.UserStarGifts;
messageReportOption#7903e3d9 text:string option:bytes = MessageReportOption;
reportResultChooseOption#f0e4e0b6 title:string options:Vector<MessageReportOption> = ReportResult;
@ -1917,7 +1914,7 @@ botVerification#f93cd45c bot_id:long icon:long description:string = BotVerificat
starGiftAttributeModel#39d99013 name:string document:Document rarity_permille:int = StarGiftAttribute;
starGiftAttributePattern#13acff19 name:string document:Document rarity_permille:int = StarGiftAttribute;
starGiftAttributeBackdrop#94271762 name:string center_color:int edge_color:int pattern_color:int text_color:int rarity_permille:int = StarGiftAttribute;
starGiftAttributeOriginalDetails#c02c4f4b flags:# sender_id:flags.0?long recipient_id:long date:int message:flags.1?TextWithEntities = StarGiftAttribute;
starGiftAttributeOriginalDetails#e0bff26c flags:# sender_id:flags.0?Peer recipient_id:Peer date:int message:flags.1?TextWithEntities = StarGiftAttribute;
payments.starGiftUpgradePreview#167bd90b sample_attributes:Vector<StarGiftAttribute> = payments.StarGiftUpgradePreview;
@ -1928,6 +1925,15 @@ payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector<User> = payments.Uni
messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector<User> = messages.WebPagePreview;
savedStarGift#6056dba5 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long = SavedStarGift;
payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector<SavedStarGift> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.SavedStarGifts;
inputSavedStarGiftUser#69279795 msg_id:int = InputSavedStarGift;
inputSavedStarGiftChat#f101aa7f peer:InputPeer saved_id:long = InputSavedStarGift;
payments.starGiftWithdrawalUrl#84aa3a9c url:string = payments.StarGiftWithdrawalUrl;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -2077,6 +2083,7 @@ account.updatePersonalChannel#d94305e0 channel:InputChannel = Bool;
account.toggleSponsoredMessages#b9d9a38d enabled:Bool = Bool;
account.getReactionsNotifySettings#6dd654c = ReactionsNotifySettings;
account.setReactionsNotifySettings#316ce548 settings:ReactionsNotifySettings = ReactionsNotifySettings;
account.getCollectibleEmojiStatuses#2e7b4543 hash:long = account.EmojiStatuses;
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
@ -2121,7 +2128,7 @@ messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
messages.sendMessage#983f9745 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long = Updates;
messages.sendMedia#7852834e flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long = Updates;
messages.forwardMessages#d5039208 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;
messages.forwardMessages#6d74da08 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int = Updates;
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
messages.report#fc78af9b peer:InputPeer id:Vector<int> option:bytes message:string = ReportResult;
@ -2505,10 +2512,8 @@ payments.changeStarsSubscription#c7770878 flags:# peer:InputPeer subscription_id
payments.fulfillStarsSubscription#cc5bebb3 peer:InputPeer subscription_id:string = Bool;
payments.getStarsGiveawayOptions#bd1efd3e = Vector<StarsGiveawayOption>;
payments.getStarGifts#c4563590 hash:int = payments.StarGifts;
payments.getUserStarGifts#5e72c7e1 user_id:InputUser offset:string limit:int = payments.UserStarGifts;
payments.saveStarGift#92fd2aae flags:# unsave:flags.0?true msg_id:int = Bool;
payments.convertStarGift#72770c83 msg_id:int = Bool;
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
payments.saveStarGift#2a2a697c flags:# unsave:flags.0?true stargift:InputSavedStarGift = Bool;
payments.convertStarGift#74bf076b stargift:InputSavedStarGift = Bool;
payments.botCancelStarsSubscription#6dfa0622 flags:# restore:flags.0?true user_id:InputUser charge_id:string = Bool;
payments.getConnectedStarRefBots#5869a553 flags:# peer:InputPeer offset_date:flags.2?int offset_link:flags.2?string limit:int = payments.ConnectedStarRefBots;
payments.getConnectedStarRefBot#b7d998f0 peer:InputPeer bot:InputUser = payments.ConnectedStarRefBots;
@ -2516,10 +2521,13 @@ payments.getSuggestedStarRefBots#d6b48f7 flags:# order_by_revenue:flags.0?true o
payments.connectStarRefBot#7ed5348a peer:InputPeer bot:InputUser = payments.ConnectedStarRefBots;
payments.editConnectedStarRefBot#e4fca4a3 flags:# revoked:flags.0?true peer:InputPeer link:string = payments.ConnectedStarRefBots;
payments.getStarGiftUpgradePreview#9c9abcb1 gift_id:long = payments.StarGiftUpgradePreview;
payments.upgradeStarGift#cf4f0781 flags:# keep_original_details:flags.0?true msg_id:int = Updates;
payments.transferStarGift#333fb526 msg_id:int to_id:InputUser = Updates;
payments.getUserStarGift#b502e4a5 msg_id:Vector<int> = payments.UserStarGifts;
payments.upgradeStarGift#aed6e4f5 flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = Updates;
payments.transferStarGift#7f18176a stargift:InputSavedStarGift to_id:InputPeer = Updates;
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
payments.getSavedStarGifts#23830de9 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer offset:string limit:int = payments.SavedStarGifts;
payments.getSavedStarGift#b455a106 stargift:Vector<InputSavedStarGift> = payments.SavedStarGifts;
payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password:InputCheckPasswordSRP = payments.StarGiftWithdrawalUrl;
payments.toggleChatStarGiftNotifications#60eaefa1 flags:# enabled:flags.0?true peer:InputPeer = Bool;
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
@ -2638,4 +2646,4 @@ smsjobs.getStatus#10a698e8 = smsjobs.Status;
smsjobs.getSmsJob#778d902f job_id:string = SmsJob;
smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool;
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;

View File

@ -561,7 +561,7 @@ export type StarsSubscriptions = {
export type ConfettiStyle = 'poppers' | 'top-down';
export type StarGiftInfo = {
userId: string;
peerId: string;
gift: ApiStarGiftRegular;
shouldHideName?: boolean;
message?: ApiFormattedText;

View File

@ -218,6 +218,7 @@ export interface LangPair {
'SavedMessagesInfo': undefined;
'BlockedListNotFound': undefined;
'TextCopied': undefined;
'WalletAddressCopied': undefined;
'Copy': undefined;
'DeleteAndStop': undefined;
'DeleteForAll': undefined;
@ -1161,6 +1162,7 @@ export interface LangPair {
'GiftSoldOut': undefined;
'GiftMessagePlaceholder': undefined;
'GiftHideMyName': undefined;
'GiftHideNameDescriptionChannel': undefined;
'GiftInfoSent': undefined;
'GiftInfoReceived': undefined;
'GiftInfoTitle': undefined;
@ -1208,6 +1210,7 @@ export interface LangPair {
'StarsReactionLinkText': undefined;
'StarsReactionLink': undefined;
'ActionStarGiftDisplaying': undefined;
'ActionStarGiftChannelDisplaying': undefined;
'ActionStarGiftDescriptionUpgrade': undefined;
'ActionStarGiftUpgraded': undefined;
'ActionStarGiftUnpack': undefined;
@ -1622,6 +1625,9 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'StarGiftDescription': {
'user': V;
};
'StarGiftDescriptionChannel': {
'peer': V;
};
'GiftDiscount': {
'percent': V;
};
@ -1632,17 +1638,16 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'count': V;
};
'GiftHideNameDescription': {
'profile': V;
'receiver': V;
};
'GiftSend': {
'amount': V;
};
'GiftInfoDescriptionFreeUpgradeOut': {
'user': V;
'GiftInfoPeerDescriptionFreeUpgradeOut': {
'peer': V;
};
'GiftInfoConvertDescription1': {
'user': V;
'GiftInfoPeerConvertDescription': {
'peer': V;
'amount': V;
};
'GiftInfoSaved': {
@ -1651,6 +1656,12 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'GiftInfoHidden': {
'link': V;
};
'GiftInfoChannelSaved': {
'link': V;
};
'GiftInfoChannelHidden': {
'link': V;
};
'GiftInfoIssued': {
'issued': V;
'total': V;
@ -1658,27 +1669,27 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'GiftInfoCollectible': {
'number': V;
};
'GiftInfoOriginalInfo': {
'user': V;
'GiftInfoPeerOriginalInfo': {
'peer': V;
'date': V;
};
'GiftInfoOriginalInfoSender': {
'GiftInfoPeerOriginalInfoSender': {
'sender': V;
'user': V;
'peer': V;
'date': V;
};
'GiftInfoOriginalInfoText': {
'user': V;
'GiftInfoPeerOriginalInfoText': {
'peer': V;
'date': V;
'text': V;
};
'GiftInfoOriginalInfoTextSender': {
'GiftInfoPeerOriginalInfoTextSender': {
'sender': V;
'user': V;
'peer': V;
'date': V;
'text': V;
};
'GiftUpgradeText': {
'GiftPeerUpgradeText': {
'peer': V;
};
'GiftUpgradeButton': {
@ -1691,6 +1702,10 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'user': V;
'link': V;
};
'GiftMakeUniqueDescriptionChannel': {
'peer': V;
'link': V;
};
'StarsAmount': {
'amount': V;
};
@ -1703,15 +1718,15 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'StarsReactionTerms': {
'link': V;
};
'ActionStarGiftTitle': {
'user': V;
'ActionStarGiftPeerTitle': {
'peer': V;
'count': V;
};
'ActionStarGiftOutTitle': {
'count': V;
};
'ActionStarGiftOutDescriptionUpgrade': {
'user': V;
'ActionStarGiftPeerOutDescriptionUpgrade': {
'peer': V;
};
'StarsSubscribeInfo': {
'link': V;
@ -1918,8 +1933,8 @@ export interface LangPairPluralWithVariables<V extends unknown = LangVariable> {
'GiftInfoDescription': {
'amount': V;
};
'GiftInfoDescriptionOut': {
'user': V;
'GiftInfoPeerDescriptionOut': {
'peer': V;
'amount': V;
};
'GiftInfoDescriptionUpgrade': {
@ -1928,8 +1943,8 @@ export interface LangPairPluralWithVariables<V extends unknown = LangVariable> {
'GiftInfoDescriptionConverted': {
'amount': V;
};
'GiftInfoDescriptionOutConverted': {
'user': V;
'GiftInfoPeerDescriptionOutConverted': {
'peer': V;
'amount': V;
};
'GiftInfoConvert': {
@ -1952,8 +1967,8 @@ export interface LangPairPluralWithVariables<V extends unknown = LangVariable> {
'PrizeCredits2': {
'count': V;
};
'ActionStarGiftOutDescription2': {
'user': V;
'ActionStarGiftPeerOutDescription': {
'peer': V;
'count': V;
};
'ActionStarGiftDescription2': {