Layer: Support layer 225

This commit is contained in:
Alexander Zinchuk 2026-06-01 01:14:57 +02:00
parent 3b63674727
commit b78f86e681
31 changed files with 727 additions and 168 deletions

View File

@ -132,7 +132,11 @@ export interface GramJsAppConfig extends LimitsConfig {
whitelisted_bots?: string[];
settings_display_passkeys?: boolean;
passkeys_account_passkeys_max?: number;
ai_compose_styles?: [string, string, string][];
aicompose_tone_examples_num?: number;
aicompose_tone_title_length_max?: number;
aicompose_tone_prompt_length_max?: number;
aicompose_tone_saved_limit_default?: number;
aicompose_tone_saved_limit_premium?: number;
}
function buildEmojiSounds(appConfig: GramJsAppConfig) {
@ -164,11 +168,6 @@ function buildDiceEmojiesSuccess(appConfig: GramJsAppConfig) {
}, {} as ApiAppConfig['diceEmojiesSuccess']) : {};
}
function buildAiComposeStyles(appConfig: GramJsAppConfig) {
const { ai_compose_styles } = appConfig;
return ai_compose_styles?.map(([tone, documentId, title]) => ({ tone, documentId, title }));
}
function getLimit(appConfig: GramJsAppConfig, key: Limit, fallbackKey: ApiLimitType) {
const defaultLimit = appConfig[`${key}_default`] || DEFAULT_LIMITS[fallbackKey][0];
const premiumLimit = appConfig[`${key}_premium`] || DEFAULT_LIMITS[fallbackKey][1];
@ -282,7 +281,11 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
passkeysMaxCount: appConfig.passkeys_account_passkeys_max,
diceEmojies: appConfig.emojies_send_dice,
diceEmojiesSuccess: buildDiceEmojiesSuccess(appConfig),
aiComposeStyles: buildAiComposeStyles(appConfig),
aiComposeToneExamplesNum: appConfig.aicompose_tone_examples_num,
aiComposeToneTitleLengthMax: appConfig.aicompose_tone_title_length_max,
aiComposeTonePromptLengthMax: appConfig.aicompose_tone_prompt_length_max,
aiComposeToneSavedLimitDefault: appConfig.aicompose_tone_saved_limit_default,
aiComposeToneSavedLimitPremium: appConfig.aicompose_tone_saved_limit_premium,
};
return {

View File

@ -3,6 +3,9 @@ import type { Entity } from '../../../lib/gramjs/types';
import { strippedPhotoToJpg } from '../../../lib/gramjs/Utils';
import type {
ApiAiComposeTone,
ApiAiComposeToneDefault,
ApiAiComposeToneExample,
ApiComposedMessageWithAI,
ApiFormattedText,
ApiMessageEntity,
@ -334,6 +337,41 @@ export function buildApiMessageEntity(entity: GramJs.TypeMessageEntity): ApiMess
};
}
export function buildApiAiComposeToneExample(
example: GramJs.AiComposeToneExample,
): ApiAiComposeToneExample {
return {
from: buildApiFormattedText(example.from),
to: buildApiFormattedText(example.to),
};
}
export function buildApiAiComposeTone(
tone: GramJs.TypeAiComposeTone,
): ApiAiComposeTone | ApiAiComposeToneDefault {
if (tone instanceof GramJs.AiComposeToneDefault) {
return {
tone: tone.tone,
emojiId: tone.emojiId.toString(),
title: tone.title,
};
}
return {
id: tone.id.toString(),
accessHash: tone.accessHash.toString(),
slug: tone.slug,
title: tone.title,
isCreator: tone.creator || undefined,
emojiId: tone.emojiId?.toString(),
prompt: tone.prompt,
installsCount: tone.installsCount,
authorId: tone.authorId?.toString(),
exampleEnglish: tone.exampleEnglish
? buildApiAiComposeToneExample(tone.exampleEnglish) : undefined,
};
}
export function buildApiComposedMessageWithAI(
result: GramJs.messages.ComposedMessageWithAI,
): ApiComposedMessageWithAI {

View File

@ -12,6 +12,7 @@ import type {
ApiEmojiStatusType,
ApiFormattedText,
ApiGroupCall,
ApiInputAiComposeTone,
ApiInputPrivacyRules,
ApiInputReplyInfo,
ApiInputStorePaymentPurpose,
@ -983,6 +984,17 @@ export function buildInputEmojiStatus(emojiStatus: ApiEmojiStatusType) {
});
}
export function buildInputAiComposeTone(tone: ApiInputAiComposeTone): GramJs.TypeInputAiComposeTone {
switch (tone.type) {
case 'default':
return new GramJs.InputAiComposeToneDefault({ tone: tone.tone });
case 'id':
return new GramJs.InputAiComposeToneID({ id: BigInt(tone.id), accessHash: BigInt(tone.accessHash) });
case 'slug':
return new GramJs.InputAiComposeToneSlug({ slug: tone.slug });
}
}
export function buildInputTextWithEntities(formatted: ApiFormattedText) {
return new GramJs.TextWithEntities({
text: formatted.text,

View File

@ -15,6 +15,7 @@ import type {
ApiError,
ApiFormattedText,
ApiGlobalMessageSearchType,
ApiInputAiComposeTone,
ApiInputReplyInfo,
ApiInputSuggestedPostInfo,
ApiMessage,
@ -63,7 +64,7 @@ import {
buildApiSponsoredMessageReportResult,
buildThreadReadState,
} from '../apiBuilders/chats';
import { buildApiComposedMessageWithAI, buildApiFormattedText } from '../apiBuilders/common';
import { buildApiAiComposeTone, buildApiComposedMessageWithAI, buildApiFormattedText } from '../apiBuilders/common';
import { buildApiTopicWithState } from '../apiBuilders/forums';
import {
buildMessageMediaContent, buildMessagePollFromMedia, buildMessageTextContent,
@ -87,6 +88,7 @@ import {
import { getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
import { buildApiUser, buildApiUserStatuses } from '../apiBuilders/users';
import {
buildInputAiComposeTone,
buildInputChannel,
buildInputDocument,
buildInputMediaDocument,
@ -2800,13 +2802,13 @@ export async function composeMessageWithAI({
shouldProofread,
isEmojify,
translateToLang,
changeTone,
tone,
}: {
text: ApiFormattedText;
shouldProofread?: boolean;
isEmojify?: boolean;
translateToLang?: string;
changeTone?: string;
tone?: ApiInputAiComposeTone;
}): Promise<{ result?: ApiComposedMessageWithAI; error?: 'floodPremium' | 'aiError' | 'generic' }> {
try {
const result = await invokeRequest(new GramJs.messages.ComposeMessageWithAI({
@ -2814,7 +2816,7 @@ export async function composeMessageWithAI({
proofread: shouldProofread || undefined,
emojify: isEmojify || undefined,
translateToLang,
changeTone,
tone: tone ? buildInputAiComposeTone(tone) : undefined,
}), { shouldThrow: true });
if (!result) return { error: 'generic' };
@ -2832,3 +2834,22 @@ export async function composeMessageWithAI({
return { error: 'generic' };
}
}
export async function fetchAiComposeTones({
hash,
}: {
hash?: string;
}) {
const result = await invokeRequest(new GramJs.aicompose.GetTones({
hash: hash ? BigInt(hash) : DEFAULT_PRIMITIVES.BIGINT,
}));
if (!result || result instanceof GramJs.aicompose.TonesNotModified) {
return undefined;
}
return {
tones: result.tones.map(buildApiAiComposeTone),
hash: result.hash.toString(),
};
}

View File

@ -1049,6 +1049,8 @@ export function updater(update: Update) {
});
} else if (update instanceof GramJs.UpdateConfig) {
sendApiUpdate({ '@type': 'updateConfig' });
} else if (update instanceof GramJs.UpdateAiComposeTones) {
sendApiUpdate({ '@type': 'updateAiComposeTones' });
} else if (update instanceof GramJs.UpdatePinnedForumTopic) {
sendApiUpdate({
'@type': 'updatePinnedTopic',

View File

@ -649,6 +649,44 @@ export interface ApiFormattedTextWithEmojiOnlyCount extends ApiFormattedText {
emojiOnlyCount?: number;
}
export type ApiInputAiComposeTone = {
type: 'default';
tone: string;
} | {
type: 'id';
id: string;
accessHash: string;
} | {
type: 'slug';
slug: string;
};
export interface ApiAiComposeToneExample {
from: ApiFormattedText;
to: ApiFormattedText;
}
export interface ApiAiComposeTone {
id: string;
accessHash: string;
slug: string;
title: string;
isCreator?: true;
emojiId?: string;
prompt?: string;
installsCount?: number;
authorId?: string;
exampleEnglish?: ApiAiComposeToneExample;
}
export interface ApiAiComposeToneDefault {
tone: string;
emojiId: string;
title: string;
}
export type ApiAiComposeToneType = ApiAiComposeTone | ApiAiComposeToneDefault;
export interface ApiComposedMessageWithAI {
resultText: ApiFormattedText;
diffText?: ApiFormattedText;

View File

@ -243,12 +243,6 @@ export interface ApiCountryCode extends ApiCountry {
patterns?: string[];
}
export interface ApiAiComposeStyle {
tone: string;
documentId: string;
title: string;
}
export interface ApiAppConfig {
hash: number;
emojiSounds: Record<string, string>;
@ -340,7 +334,11 @@ export interface ApiAppConfig {
value: number;
frameStart: number;
}>;
aiComposeStyles?: ApiAiComposeStyle[];
aiComposeToneExamplesNum?: number;
aiComposeToneTitleLengthMax?: number;
aiComposeTonePromptLengthMax?: number;
aiComposeToneSavedLimitDefault?: number;
aiComposeToneSavedLimitPremium?: number;
}
export interface ApiConfig {

View File

@ -533,6 +533,10 @@ export type ApiUpdateConfig = {
'@type': 'updateConfig';
};
export type ApiUpdateAiComposeTones = {
'@type': 'updateAiComposeTones';
};
export type ApiUpdateResetContacts = {
'@type': 'updateResetContactList';
};
@ -964,6 +968,7 @@ export type ApiUpdate = (
| ApiDeleteQuickReply | ApiUpdateDeleteQuickReplyMessages | ApiUpdateDeleteProfilePhoto | ApiUpdateNewProfilePhoto
| ApiUpdateEntities | ApiUpdatePaidReactionPrivacy | ApiUpdateLangPackTooLong | ApiUpdateLangPack
| ApiUpdateNotSupportedInFrozenAccountError
| ApiUpdateAiComposeTones
);
export type OnApiUpdate = (update: ApiUpdate) => void;

View File

@ -2883,13 +2883,6 @@
"AiMessageEditorDailyLimitReached" = "Daily limit reached. To increase limits, get {link}.";
"AiMessageEditorDailyLimitReachedPremium" = "Daily limit reached.";
"AiMessageEditorGenericError" = "Please try again later.";
"AiMessageEditorStyleFormal" = "Formal";
"AiMessageEditorStyleShort" = "Short";
"AiMessageEditorStyleTribal" = "Tribal";
"AiMessageEditorStyleCorp" = "Corp";
"AiMessageEditorStyleBiblical" = "Biblical";
"AiMessageEditorStyleViking" = "Viking";
"AiMessageEditorStyleZen" = "Zen";
"AiMessageEditorResult" = "Result";
"AiMessageEditorOriginal" = "Original";
"AiMessageEditorApply" = "Apply";

View File

@ -253,6 +253,7 @@ const Main = ({
loadPeerColors,
loadSavedReactionTags,
loadTimezones,
loadAiComposeTones,
loadQuickReplies,
loadStarStatus,
loadAvailableEffects,
@ -348,6 +349,7 @@ const Main = ({
loadRestrictedEmojiStickers();
loadQuickReplies();
loadTimezones();
loadAiComposeTones();
loadActiveGiftAuctions();
}
}, [isMasterTab, isSynced, isAppConfigLoaded, isAccountFrozen]);

View File

@ -92,7 +92,7 @@
}
.emojifyCheckboxControl {
column-gap: 0.5rem;
--control-gap: 0.5rem;
}
.emojifyCheckboxLabel {

View File

@ -156,13 +156,16 @@ const AiMessageEditorModal = ({
case 'translate':
composeWithAiMessageEditor({
translateToLang: translateTab?.selectedLanguage,
changeTone: translateTab?.selectedTone,
tone: translateTab?.selectedTone,
isEmojify: translateTab?.shouldEmojify,
});
break;
case 'style':
if (styleTab?.selectedTone) {
composeWithAiMessageEditor({ changeTone: styleTab.selectedTone, isEmojify: styleTab?.shouldEmojify });
composeWithAiMessageEditor({
tone: styleTab.selectedTone,
isEmojify: styleTab?.shouldEmojify,
});
}
break;
case 'fix':

View File

@ -1,14 +1,15 @@
import { memo, useMemo } from '../../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../../global';
import type { ApiAiComposeStyle, ApiComposedMessageWithAI, ApiFormattedText } from '../../../../api/types';
import type {
ApiAiComposeToneType, ApiComposedMessageWithAI, ApiFormattedText, ApiInputAiComposeTone,
} from '../../../../api/types';
import type { TabWithProperties } from '../../../ui/TabList';
import { ApiMessageEntityTypes } from '../../../../api/types';
import EMOJI_REGEX from '../../../../lib/twemojiRegex';
import { compareAiTones, getInputTone } from '../../../../util/aiComposeTones';
import buildClassName from '../../../../util/buildClassName';
import { MEMO_EMPTY_ARRAY } from '../../../../util/memo';
import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities';
import { getStyleTitle } from './helpers';
import useLang from '../../../../hooks/useLang';
import useLastCallback from '../../../../hooks/useLastCallback';
@ -24,7 +25,7 @@ import styles from './AiTextStyleEditor.module.scss';
type OwnProps = {
text?: ApiFormattedText;
selectedTone?: string;
selectedTone?: ApiInputAiComposeTone;
shouldEmojify?: boolean;
isLoading?: boolean;
result?: ApiComposedMessageWithAI;
@ -33,7 +34,7 @@ type OwnProps = {
};
type StateProps = {
aiComposeStyles: ApiAiComposeStyle[];
tones: ApiAiComposeToneType[];
};
const AiTextStyleEditor = ({
@ -44,7 +45,7 @@ const AiTextStyleEditor = ({
result,
error,
isPremium,
aiComposeStyles,
tones,
}: OwnProps & StateProps) => {
const {
setAiMessageEditorStyleOptions,
@ -57,27 +58,19 @@ const AiTextStyleEditor = ({
const hasRequest = Boolean(selectedTone) || shouldEmojify;
const shouldShowError = Boolean(error) && hasRequest;
const styleTabs = useMemo((): TabWithProperties[] => aiComposeStyles.map(({ documentId, title, tone }) => {
const emojiMatch = title.match(EMOJI_REGEX);
const localizedTitle = getStyleTitle(lang, tone, title);
const styleTabs = useMemo((): TabWithProperties[] => tones.map((entry) => ({
customEmojiDocumentId: entry.emojiId,
title: entry.title,
})), [tones]);
return {
emoticon: documentId ? {
type: ApiMessageEntityTypes.CustomEmoji,
offset: 0,
length: emojiMatch?.[0].length || 2,
documentId,
} : undefined,
title: localizedTitle,
};
}), [aiComposeStyles, lang]);
const activeStyleIndex = aiComposeStyles.findIndex(({ tone }) => tone === selectedTone);
const activeStyleIndex = tones.findIndex(
(entry) => compareAiTones(selectedTone, getInputTone(entry)),
);
const handleStyleSelect = useLastCallback((index: number) => {
const styleId = aiComposeStyles[index].tone;
setAiMessageEditorStyleOptions({ selectedTone: styleId });
composeWithAiMessageEditor({ changeTone: styleId, isEmojify: shouldEmojify });
const tone = getInputTone(tones[index]);
setAiMessageEditorStyleOptions({ selectedTone: tone });
composeWithAiMessageEditor({ tone, isEmojify: shouldEmojify });
});
const handleEmojifyChange = useLastCallback((newEmojify: boolean) => {
@ -85,7 +78,7 @@ const AiTextStyleEditor = ({
setAiMessageEditorStyleOptions({ shouldEmojify: newEmojify, clearResult: true });
} else {
setAiMessageEditorStyleOptions({ shouldEmojify: newEmojify });
composeWithAiMessageEditor({ changeTone: selectedTone, isEmojify: newEmojify });
composeWithAiMessageEditor({ tone: selectedTone, isEmojify: newEmojify });
}
});
@ -93,7 +86,7 @@ const AiTextStyleEditor = ({
const showResultLabel = hasRequest || isLoading;
const displayLabel = showResultLabel ? lang('AiMessageEditorResult') : lang('AiMessageEditorOriginal');
const transitionKey = (activeStyleIndex >= 0 ? activeStyleIndex : 0) + (shouldEmojify ? aiComposeStyles.length : 0);
const transitionKey = (activeStyleIndex >= 0 ? activeStyleIndex : 0) + (shouldEmojify ? tones.length : 0);
function renderPreviewText() {
if (shouldShowError) {
@ -158,7 +151,7 @@ const AiTextStyleEditor = ({
export default memo(withGlobal<OwnProps>(
(global): Complete<StateProps> => {
return {
aiComposeStyles: global.appConfig?.aiComposeStyles ?? [],
tones: global.aiComposeTones?.tones ?? MEMO_EMPTY_ARRAY,
};
},
)(AiTextStyleEditor));

View File

@ -1,11 +1,15 @@
import { memo, useMemo, useRef, useState } from '../../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../../global';
import type { ApiAiComposeStyle, ApiComposedMessageWithAI, ApiFormattedText } from '../../../../api/types';
import type {
ApiAiComposeToneType, ApiComposedMessageWithAI, ApiFormattedText, ApiInputAiComposeTone,
} from '../../../../api/types';
import type { IAnchorPosition } from '../../../../types';
import { SUPPORTED_TRANSLATION_LANGUAGES } from '../../../../config';
import { compareAiTones, getInputTone } from '../../../../util/aiComposeTones';
import buildClassName from '../../../../util/buildClassName';
import { MEMO_EMPTY_ARRAY } from '../../../../util/memo';
import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities';
import useFlag from '../../../../hooks/useFlag';
@ -24,12 +28,10 @@ import sharedStyles from './AiEditorShared.module.scss';
import modalStyles from './AiMessageEditorModal.module.scss';
import styles from './AiTextTranslateEditor.module.scss';
const EMPTY_AI_COMPOSE_STYLES: ApiAiComposeStyle[] = [];
type OwnProps = {
text?: ApiFormattedText;
selectedLanguage?: string;
selectedTone?: string;
selectedTone?: ApiInputAiComposeTone;
shouldEmojify?: boolean;
isLoading?: boolean;
result?: ApiComposedMessageWithAI;
@ -38,7 +40,7 @@ type OwnProps = {
};
type StateProps = {
aiComposeStyles: ApiAiComposeStyle[];
tones: ApiAiComposeToneType[];
};
const AiTextTranslateEditor = ({
@ -50,7 +52,7 @@ const AiTextTranslateEditor = ({
result,
error,
isPremium,
aiComposeStyles,
tones,
}: OwnProps & StateProps) => {
const {
setAiMessageEditorTranslateOptions,
@ -96,7 +98,7 @@ const AiTextTranslateEditor = ({
composeWithAiMessageEditor({
translateToLang: langCode,
isEmojify: shouldEmojify,
changeTone: selectedTone,
tone: selectedTone,
});
});
@ -106,7 +108,7 @@ const AiTextTranslateEditor = ({
composeWithAiMessageEditor({
translateToLang: selectedLanguage,
isEmojify: newEmojify,
changeTone: selectedTone,
tone: selectedTone,
});
}
});
@ -124,13 +126,13 @@ const AiTextTranslateEditor = ({
const getMenuElement = useLastCallback(() => document.querySelector('.language-menu .bubble'));
const getLayout = useLastCallback(() => ({ withPortal: true }));
const handleToneSelect = useLastCallback((tone?: string) => {
setAiMessageEditorTranslateOptions({ selectedTone: tone });
const handleToneSelect = useLastCallback((newTone?: ApiInputAiComposeTone) => {
setAiMessageEditorTranslateOptions({ selectedTone: newTone });
if (selectedLanguage) {
composeWithAiMessageEditor({
translateToLang: selectedLanguage,
isEmojify: shouldEmojify,
changeTone: tone,
tone: newTone,
});
}
});
@ -138,9 +140,11 @@ const AiTextTranslateEditor = ({
const displayResult = result?.resultText;
const languageIndex = SUPPORTED_TRANSLATION_LANGUAGES.indexOf(selectedLanguage || '');
const toneIndex = aiComposeStyles.findIndex(({ tone }) => tone === selectedTone);
const toneIndex = tones.findIndex(
(entry) => compareAiTones(selectedTone, getInputTone(entry)),
);
const totalLanguages = SUPPORTED_TRANSLATION_LANGUAGES.length;
const totalTones = aiComposeStyles.length;
const totalTones = tones.length;
const transitionKey = languageIndex
+ (toneIndex + 1) * totalLanguages
+ (shouldEmojify ? totalLanguages * (totalTones + 1) : 0);
@ -238,7 +242,7 @@ const AiTextTranslateEditor = ({
export default memo(withGlobal<OwnProps>(
(global): Complete<StateProps> => {
return {
aiComposeStyles: global.appConfig.aiComposeStyles || EMPTY_AI_COMPOSE_STYLES,
tones: global.aiComposeTones?.tones ?? MEMO_EMPTY_ARRAY,
};
},
)(AiTextTranslateEditor));

View File

@ -1,10 +0,0 @@
import type { LangFn } from '../../../../util/localization';
export function getStyleTitle(lang: LangFn, tone: string, fallbackTitle: string) {
if (!tone) return fallbackTitle;
const capitalizedTone = tone.charAt(0).toUpperCase() + tone.slice(1);
const key = `AiMessageEditorStyle${capitalizedTone}`;
// @ts-ignore - Dynamic lang key
const translated = lang(key);
return translated !== key ? translated : fallbackTitle;
}

View File

@ -1,44 +1,44 @@
import { memo } from '../../../lib/teact/teact';
import { withGlobal } from '../../../global';
import type { ApiAiComposeStyle } from '../../../api/types';
import type { ApiAiComposeToneType, ApiInputAiComposeTone } from '../../../api/types';
import { compareAiTones, getInputTone } from '../../../util/aiComposeTones';
import buildClassName from '../../../util/buildClassName';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback';
import CustomEmoji from '../../common/CustomEmoji';
import { getStyleTitle } from '../composer/AiMessageEditorModal/helpers';
import styles from './TranslationToneSelector.module.scss';
const EMOJI_SIZE = 20;
const EMPTY_AI_COMPOSE_STYLES: ApiAiComposeStyle[] = [];
type OwnProps = {
selectedTone?: string;
selectedTone?: ApiInputAiComposeTone;
style?: string;
onSelectTone: (tone?: string) => void;
onSelectTone: (tone?: ApiInputAiComposeTone) => void;
};
type StateProps = {
aiComposeStyles: ApiAiComposeStyle[];
tones: ApiAiComposeToneType[];
};
const TranslationToneSelector = ({
selectedTone,
style,
aiComposeStyles,
tones,
onSelectTone,
}: OwnProps & StateProps) => {
const lang = useLang();
const handleToneClick = useLastCallback((tone?: string) => {
const handleToneClick = useLastCallback((tone?: ApiInputAiComposeTone) => {
onSelectTone(tone);
});
if (!aiComposeStyles.length) return undefined;
if (!tones.length) return undefined;
return (
<div className={buildClassName(styles.root, 'TranslationToneSelector')} style={style}>
@ -50,22 +50,29 @@ const TranslationToneSelector = ({
<span className={styles.neutralEmoji}>🏳</span>
<span className={styles.title}>{lang('TranslationToneNeutral')}</span>
</div>
{aiComposeStyles.map(({ tone, documentId, title }) => (
<div
key={tone}
className={buildClassName(styles.item, selectedTone === tone && styles.selected)}
onClick={() => handleToneClick(tone)}
>
{documentId && (
<CustomEmoji
documentId={documentId}
size={EMOJI_SIZE}
shouldNotLoop
/>
)}
<span className={styles.title}>{getStyleTitle(lang, tone, title)}</span>
</div>
))}
{tones.map((entry) => {
const inputTone = getInputTone(entry);
return (
<div
key={'tone' in entry ? entry.tone : entry.id}
className={buildClassName(
styles.item,
compareAiTones(selectedTone, inputTone) && styles.selected,
)}
onClick={() => handleToneClick(inputTone)}
>
{entry.emojiId && (
<CustomEmoji
documentId={entry.emojiId}
size={EMOJI_SIZE}
shouldNotLoop
/>
)}
<span className={styles.title}>{entry.title}</span>
</div>
);
})}
</div>
</div>
);
@ -74,7 +81,7 @@ const TranslationToneSelector = ({
export default memo(withGlobal<OwnProps>(
(global): Complete<StateProps> => {
return {
aiComposeStyles: global.appConfig.aiComposeStyles || EMPTY_AI_COMPOSE_STYLES,
tones: global.aiComposeTones?.tones ?? MEMO_EMPTY_ARRAY,
};
},
)(TranslationToneSelector));

View File

@ -25,6 +25,7 @@ export type TabWithProperties = {
isBadgeActive?: boolean;
contextActions?: MenuItemContextAction[];
emoticon?: string | ApiMessageEntityCustomEmoji;
customEmojiDocumentId?: string;
noTitleAnimations?: boolean;
};

View File

@ -124,8 +124,9 @@ const TabList = ({
const hasContextActions = tabs.some((tab) => tab.contextActions?.length);
const renderTab = (tab: TabWithProperties, index: number) => {
const customEmojiId = tab.customEmojiDocumentId
|| (typeof tab.emoticon === 'object' ? tab.emoticon.documentId : undefined);
const stringEmoticon = typeof tab.emoticon === 'string' ? tab.emoticon : undefined;
const customEmoji = typeof tab.emoticon === 'object' ? tab.emoticon : undefined;
return (
<div
@ -140,9 +141,9 @@ const TabList = ({
onContextMenu={hasContextActions ? (e) => handleContextMenu(index, e) : undefined}
>
{stringEmoticon && <span className={styles.tabEmoji}>{stringEmoticon}</span>}
{customEmoji && (
{customEmojiId && (
<CustomEmoji
documentId={customEmoji.documentId}
documentId={customEmojiId}
className={styles.tabEmoji}
size={EMOJI_SIZE}
shouldNotLoop

View File

@ -1,20 +1,25 @@
import type { ApiInputAiComposeTone } from '../../../api/types';
import { compareAiTones, getToneCacheKey } from '../../../util/aiComposeTones';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { callApi } from '../../../api/gramjs';
import { addActionHandler, getGlobal, setGlobal } from '../../index';
import { updateTabState } from '../../reducers/tabs';
import { selectTabState } from '../../selectors';
function buildStyleCacheKey(tone: string | undefined, emojify: boolean | undefined) {
return `${tone || ''}_${emojify ? '1' : '0'}`;
function buildStyleCacheKey(tone?: ApiInputAiComposeTone, emojify?: boolean) {
return `${tone ? getToneCacheKey(tone) : ''}_${emojify ? '1' : '0'}`;
}
function buildTranslateCacheKey(lang: string | undefined, tone: string | undefined, emojify: boolean | undefined) {
return `${lang || ''}_${tone || ''}_${emojify ? '1' : '0'}`;
function buildTranslateCacheKey(
lang?: string, tone?: ApiInputAiComposeTone, emojify?: boolean,
) {
return `${lang || ''}_${tone ? getToneCacheKey(tone) : ''}_${emojify ? '1' : '0'}`;
}
addActionHandler('composeWithAiMessageEditor', async (global, actions, payload): Promise<void> => {
const {
shouldProofread, isEmojify, translateToLang, changeTone,
shouldProofread, isEmojify, translateToLang, tone,
tabId = getCurrentTabId(),
} = payload;
@ -29,11 +34,11 @@ addActionHandler('composeWithAiMessageEditor', async (global, actions, payload):
cachedResult = modal.fixTab?.cache;
} else if (translateToLang) {
tabKey = 'translateTab';
const cacheKey = buildTranslateCacheKey(translateToLang, changeTone, isEmojify);
const cacheKey = buildTranslateCacheKey(translateToLang, tone, isEmojify);
cachedResult = modal.translateTab?.cache?.[cacheKey];
} else {
tabKey = 'styleTab';
const cacheKey = buildStyleCacheKey(changeTone, isEmojify);
const cacheKey = buildStyleCacheKey(tone, isEmojify);
cachedResult = modal.styleTab?.cache?.[cacheKey];
}
@ -67,7 +72,7 @@ addActionHandler('composeWithAiMessageEditor', async (global, actions, payload):
shouldProofread,
isEmojify,
translateToLang,
changeTone,
tone,
});
global = getGlobal();
@ -92,11 +97,11 @@ addActionHandler('composeWithAiMessageEditor', async (global, actions, payload):
if (translateToLang) {
const { selectedLanguage, selectedTone, shouldEmojify } = modal.translateTab || {};
isOutdatedResult = selectedLanguage !== translateToLang
|| selectedTone !== changeTone
|| !compareAiTones(selectedTone, tone)
|| Boolean(shouldEmojify) !== Boolean(isEmojify);
} else if (!shouldProofread) {
const { selectedTone, shouldEmojify } = modal.styleTab || {};
isOutdatedResult = selectedTone !== changeTone
isOutdatedResult = !compareAiTones(selectedTone, tone)
|| Boolean(shouldEmojify) !== Boolean(isEmojify);
}
@ -105,10 +110,10 @@ addActionHandler('composeWithAiMessageEditor', async (global, actions, payload):
if (shouldProofread) {
updatedCache = result;
} else if (translateToLang) {
const cacheKey = buildTranslateCacheKey(translateToLang, changeTone, isEmojify);
const cacheKey = buildTranslateCacheKey(translateToLang, tone, isEmojify);
updatedCache = { ...currentTabState.cache, [cacheKey]: result };
} else {
const cacheKey = buildStyleCacheKey(changeTone, isEmojify);
const cacheKey = buildStyleCacheKey(tone, isEmojify);
updatedCache = { ...currentTabState.cache, [cacheKey]: result };
}
}
@ -142,3 +147,19 @@ addActionHandler('composeWithAiMessageEditor', async (global, actions, payload):
}, tabId);
setGlobal(global);
});
addActionHandler('loadAiComposeTones', async (global): Promise<void> => {
const hash = global.aiComposeTones?.hash;
const result = await callApi('fetchAiComposeTones', { hash });
if (!result) return;
global = getGlobal();
global = {
...global,
aiComposeTones: {
tones: result.tones,
hash: result.hash,
},
};
setGlobal(global);
});

View File

@ -82,6 +82,10 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
actions.loadConfig();
break;
case 'updateAiComposeTones':
actions.loadAiComposeTones();
break;
case 'updateNewAuthorization': {
// Load more info about this session
actions.loadAuthorizations();

View File

@ -17,6 +17,7 @@ import type {
ApiFormattedText,
ApiGeoPoint,
ApiGlobalMessageSearchType,
ApiInputAiComposeTone,
ApiInputInvoice,
ApiInputInvoiceStarGift,
ApiInputMessageReplyInfo,
@ -2598,6 +2599,7 @@ export interface ActionPayloads {
} & WithTabId;
loadPeerColors: undefined;
loadTimezones: undefined;
loadAiComposeTones: undefined;
openLeftColumnContent: {
contentKey?: LeftColumnContent;
} & WithTabId;
@ -2657,12 +2659,12 @@ export interface ActionPayloads {
} & WithTabId;
setAiMessageEditorTranslateOptions: {
selectedLanguage?: string;
selectedTone?: string;
selectedTone?: ApiInputAiComposeTone;
shouldEmojify?: boolean;
clearResult?: boolean;
} & WithTabId;
setAiMessageEditorStyleOptions: {
selectedTone?: string;
selectedTone?: ApiInputAiComposeTone;
shouldEmojify?: boolean;
clearResult?: boolean;
} & WithTabId;
@ -2670,7 +2672,7 @@ export interface ActionPayloads {
shouldProofread?: boolean;
isEmojify?: boolean;
translateToLang?: string;
changeTone?: string;
tone?: ApiInputAiComposeTone;
} & WithTabId;
applyAiMessageEditorResult: WithTabId | undefined;
sendAiMessageEditorResult: ({

View File

@ -1,4 +1,5 @@
import type {
ApiAiComposeToneType,
ApiAppConfig,
ApiAttachBot,
ApiAvailableEffect,
@ -92,6 +93,10 @@ export type GlobalState = {
byId: Record<string, ApiTimezone>;
hash: number;
};
aiComposeTones?: {
tones: ApiAiComposeToneType[];
hash: string;
};
isCacheApiSupported?: boolean;
connectionState?: ApiUpdateConnectionStateType;
currentUserId?: string;

View File

@ -17,6 +17,7 @@ import type {
ApiGeoPoint,
ApiGlobalMessageSearchType,
ApiGroupStatistics,
ApiInputAiComposeTone,
ApiInputInvoice,
ApiLimitTypeWithModal,
ApiMessage,
@ -679,12 +680,12 @@ export type TabState = {
isFromAttachment?: boolean;
translateTab?: AiEditorTabBase & {
selectedLanguage?: string;
selectedTone?: string;
selectedTone?: ApiInputAiComposeTone;
shouldEmojify?: boolean;
cache?: Record<string, ApiComposedMessageWithAI>;
};
styleTab?: AiEditorTabBase & {
selectedTone?: string;
selectedTone?: ApiInputAiComposeTone;
shouldEmojify?: boolean;
cache?: Record<string, ApiComposedMessageWithAI>;
};

View File

@ -12,6 +12,6 @@ for (const tl of Object.values(Api)) {
}
}
export const LAYER = 224;
export const LAYER = 225;
export { tlobjects };

File diff suppressed because one or more lines are too long

View File

@ -70,7 +70,7 @@ storage.fileMov#4b09ebbc = storage.FileType;
storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
userEmpty#d3bc4b7a id:long = User;
user#31774388 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true bot_forum_view:flags2.16?true bot_forum_can_manage_topics:flags2.17?true bot_can_manage_bots:flags2.18?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?RecentStory color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long send_paid_messages_stars:flags2.15?long = User;
user#31774388 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true bot_forum_view:flags2.16?true bot_forum_can_manage_topics:flags2.17?true bot_can_manage_bots:flags2.18?true bot_guestchat:flags2.19?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?RecentStory color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long send_paid_messages_stars:flags2.15?long = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true personal:flags.2?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
userStatusEmpty#9d05049 = UserStatus;
@ -94,7 +94,7 @@ chatParticipants#3cbc93f8 chat_id:long participants:Vector<ChatParticipant> vers
chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
message#3ae56482 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true flags2:# offline:flags2.1?true video_processing_pending:flags2.4?true paid_suggested_post_stars:flags2.8?true paid_suggested_post_ton:flags2.9?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int from_rank:flags2.12?string peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long via_business_bot_id:flags2.0?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int quick_reply_shortcut_id:flags.30?int effect:flags2.2?long factcheck:flags2.3?FactCheck report_delivery_until_date:flags2.5?int paid_message_stars:flags2.6?long suggested_post:flags2.7?SuggestedPost schedule_repeat_period:flags2.10?int summary_from_language:flags2.11?string = Message;
message#95ef6f2b flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true flags2:# offline:flags2.1?true video_processing_pending:flags2.4?true paid_suggested_post_stars:flags2.8?true paid_suggested_post_ton:flags2.9?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int from_rank:flags2.12?string peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long via_business_bot_id:flags2.0?long guestchat_via_from:flags2.19?Peer reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int quick_reply_shortcut_id:flags.30?int effect:flags2.2?long factcheck:flags2.3?FactCheck report_delivery_until_date:flags2.5?int paid_message_stars:flags2.6?long suggested_post:flags2.7?SuggestedPost schedule_repeat_period:flags2.10?int summary_from_language:flags2.11?string = Message;
messageService#7a800e0a flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true reactions_are_possible:flags.9?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer saved_peer_id:flags.28?Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction reactions:flags.20?MessageReactions ttl_period:flags.25?int = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
messageMediaPhoto#e216eb63 flags:# spoiler:flags.3?true live_photo:flags.4?true photo:flags.0?Photo ttl_seconds:flags.2?int video:flags.4?Document = MessageMedia;
@ -196,7 +196,7 @@ geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint;
auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode;
auth.sentCodePaymentRequired#e0955a3c store_product:string phone_code_hash:string support_email_address:string support_email_subject:string currency:string amount:long = auth.SentCode;
auth.sentCodePaymentRequired#f8827ebf store_product:string phone_code_hash:string support_email_address:string support_email_subject:string premium_days:int currency:string amount:long = auth.SentCode;
auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization;
auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization;
auth.exportedAuthorization#b434e2b8 id:long bytes:bytes = auth.ExportedAuthorization;
@ -412,6 +412,8 @@ updateEmojiGameInfo#fb9c547a info:messages.EmojiGameInfo = Update;
updateStarGiftCraftFail#ac072444 = Update;
updateChatParticipantRank#bd8367b9 chat_id:long user_id:long rank:string version:int = Update;
updateManagedBot#4880ed9a user_id:long bot_id:long qts:int = Update;
updateBotGuestChatQuery#cdd4093d flags:# query_id:long message:Message reference_messages:flags.0?Vector<Message> qts:int = Update;
updateAiComposeTones#8c0f91fb = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
@ -718,6 +720,7 @@ topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
topPeerCategoryForwardUsers#a8406ca9 = TopPeerCategory;
topPeerCategoryForwardChats#fbeec0f0 = TopPeerCategory;
topPeerCategoryBotsApp#fd9e7bec = TopPeerCategory;
topPeerCategoryBotsGuestChat#6c24f3dd = TopPeerCategory;
topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector<TopPeer> = TopPeerCategoryPeers;
contacts.topPeersNotModified#de266ef5 = contacts.TopPeers;
contacts.topPeers#70b772a8 categories:Vector<TopPeerCategoryPeers> chats:Vector<Chat> users:Vector<User> = contacts.TopPeers;
@ -997,13 +1000,13 @@ help.userInfoEmpty#f3ae2eed = help.UserInfo;
help.userInfo#1eb3758 message:string entities:Vector<MessageEntity> author:string date:int = help.UserInfo;
pollAnswer#4b7d786a flags:# text:TextWithEntities option:bytes media:flags.0?MessageMedia added_by:flags.1?Peer date:flags.1?int = PollAnswer;
inputPollAnswer#199fed96 flags:# text:TextWithEntities media:flags.0?InputMedia = PollAnswer;
poll#b8425be9 id:long flags:# closed:flags.0?true public_voters:flags.1?true multiple_choice:flags.2?true quiz:flags.3?true open_answers:flags.6?true revoting_disabled:flags.7?true shuffle_answers:flags.8?true hide_results_until_close:flags.9?true creator:flags.10?true question:TextWithEntities answers:Vector<PollAnswer> close_period:flags.4?int close_date:flags.5?int hash:long = Poll;
poll#966e2dbf id:long flags:# closed:flags.0?true public_voters:flags.1?true multiple_choice:flags.2?true quiz:flags.3?true open_answers:flags.6?true revoting_disabled:flags.7?true shuffle_answers:flags.8?true hide_results_until_close:flags.9?true creator:flags.10?true subscribers_only:flags.11?true question:TextWithEntities answers:Vector<PollAnswer> close_period:flags.4?int close_date:flags.5?int countries_iso2:flags.12?Vector<string> hash:long = Poll;
pollAnswerVoters#3645230a flags:# chosen:flags.0?true correct:flags.1?true option:bytes voters:flags.2?int recent_voters:flags.2?Vector<Peer> = PollAnswerVoters;
pollResults#ba7bb15e flags:# min:flags.0?true has_unread_votes:flags.6?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int recent_voters:flags.3?Vector<Peer> solution:flags.4?string solution_entities:flags.4?Vector<MessageEntity> solution_media:flags.5?MessageMedia = PollResults;
pollResults#ba7bb15e flags:# min:flags.0?true has_unread_votes:flags.6?true can_view_stats:flags.7?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int recent_voters:flags.3?Vector<Peer> solution:flags.4?string solution_entities:flags.4?Vector<MessageEntity> solution_media:flags.5?MessageMedia = PollResults;
chatOnlines#f041e250 onlines:int = ChatOnlines;
statsURL#47a971e0 url:string = StatsURL;
chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true anonymous:flags.10?true manage_call:flags.11?true other:flags.12?true manage_topics:flags.13?true post_stories:flags.14?true edit_stories:flags.15?true delete_stories:flags.16?true manage_direct_messages:flags.17?true manage_ranks:flags.18?true = ChatAdminRights;
chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true manage_topics:flags.18?true send_photos:flags.19?true send_videos:flags.20?true send_roundvideos:flags.21?true send_audios:flags.22?true send_voices:flags.23?true send_docs:flags.24?true send_plain:flags.25?true edit_rank:flags.26?true until_date:int = ChatBannedRights;
chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true manage_topics:flags.18?true send_photos:flags.19?true send_videos:flags.20?true send_roundvideos:flags.21?true send_audios:flags.22?true send_voices:flags.23?true send_docs:flags.24?true send_plain:flags.25?true edit_rank:flags.26?true send_reactions:flags.27?true until_date:int = ChatBannedRights;
inputWallPaper#e630b979 id:long access_hash:long = InputWallPaper;
inputWallPaperSlug#72091c80 slug:string = InputWallPaper;
inputWallPaperNoFile#967a462e id:long = InputWallPaper;
@ -1053,6 +1056,7 @@ webPageAttributeStickerSet#50cc03d3 flags:# emojis:flags.0?true text_color:flags
webPageAttributeUniqueStarGift#cf6f6db8 gift:StarGift = WebPageAttribute;
webPageAttributeStarGiftCollection#31cad303 icons:Vector<Document> = WebPageAttribute;
webPageAttributeStarGiftAuction#1c641c2 gift:StarGift end_date:int = WebPageAttribute;
webPageAttributeAiComposeTone#7781fe18 emoji_id:long = WebPageAttribute;
messages.votesList#4899484e flags:# count:int votes:Vector<MessagePeerVote> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.VotesList;
bankCardOpenUrl#f568028a url:string name:string = BankCardOpenUrl;
payments.bankCardData#3e24e573 title:string open_urls:Vector<BankCardOpenUrl> = payments.BankCardData;
@ -1203,7 +1207,7 @@ inputStorePaymentPremiumGiveaway#160544ca flags:# only_new_subscribers:flags.0?t
inputStorePaymentStarsTopup#f9a2a6cb flags:# stars:long currency:string amount:long spend_purpose_peer:flags.0?InputPeer = InputStorePaymentPurpose;
inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose;
inputStorePaymentAuthCode#9bb2636d flags:# restore:flags.0?true phone_number:string phone_code_hash:string currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentAuthCode#3fc18057 flags:# restore:flags.0?true phone_number:string phone_code_hash:string premium_days:int currency:string amount:long = InputStorePaymentPurpose;
paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod;
emojiStatusEmpty#2de11aae = EmojiStatus;
emojiStatus#e7ff068a flags:# document_id:long until:flags.0?int = EmojiStatus;
@ -1558,6 +1562,16 @@ inputMessageReadMetric#402b4495 msg_id:int view_id:long time_in_view_ms:int acti
bots.exportedBotToken#3c60b621 token:string = bots.ExportedBotToken;
bots.requestedButton#f13bbcd7 webapp_req_id:string = bots.RequestedButton;
messages.composedMessageWithAI#90d7adfa flags:# result_text:TextWithEntities diff_text:flags.0?TextWithEntities = messages.ComposedMessageWithAI;
stats.pollStats#2999beed votes_graph:StatsGraph = stats.PollStats;
inputAiComposeToneDefault#1fe9a9bf tone:string = InputAiComposeTone;
inputAiComposeToneID#773c080 id:long access_hash:long = InputAiComposeTone;
inputAiComposeToneSlug#1fa01357 slug:string = InputAiComposeTone;
aiComposeTone#cff63ea9 flags:# creator:flags.0?true id:long access_hash:long slug:string title:string emoji_id:flags.1?long prompt:flags.4?string installs_count:flags.2?int author_id:flags.3?long example_english:flags.5?AiComposeToneExample = AiComposeTone;
aiComposeToneDefault#9bad6414 tone:string emoji_id:long title:string = AiComposeTone;
aicompose.tonesNotModified#c1f46103 = aicompose.Tones;
aicompose.tones#6c9d0efe hash:long tones:Vector<AiComposeTone> users:Vector<User> = aicompose.Tones;
aiComposeToneExample#f1d628ec from:TextWithEntities to:TextWithEntities = AiComposeToneExample;
bots.accessSettings#dd1fbf93 flags:# restricted:flags.0?true add_users:flags.1?Vector<User> = bots.AccessSettings;
---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;
@ -1643,7 +1657,7 @@ contacts.unblock#b550d328 flags:# my_stories_from:flags.0?true id:InputPeer = Bo
contacts.getBlocked#9a868f80 flags:# my_stories_from:flags.0?true offset:int limit:int = contacts.Blocked;
contacts.search#11f812d8 q:string limit:int = contacts.Found;
contacts.resolveUsername#725afbbc flags:# username:string referer:flags.0?string = contacts.ResolvedPeer;
contacts.getTopPeers#973478b6 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true bots_app:flags.16?true offset:int limit:int hash:long = contacts.TopPeers;
contacts.getTopPeers#973478b6 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true bots_app:flags.16?true bots_guestchat:flags.17?true offset:int limit:int hash:long = contacts.TopPeers;
contacts.addContact#d9ba2e54 flags:# add_phone_privacy_exception:flags.0?true id:InputUser first_name:string last_name:string phone:string note:flags.1?TextWithEntities = Updates;
contacts.resolvePhone#8af94344 phone:string = contacts.ResolvedPeer;
contacts.editCloseFriends#ba6705f0 id:Vector<long> = Bool;
@ -1811,7 +1825,7 @@ messages.getFutureChatCreatorAfterLeave#3b7d0ea6 peer:InputPeer = User;
messages.editChatParticipantRank#a00f32b0 peer:InputPeer participant:InputPeer rank:string = Updates;
messages.declineUrlAuth#35436bbc url:string = Bool;
messages.checkUrlAuthMatchCode#c9a47b0b url:string match_code:string = Bool;
messages.composeMessageWithAI#fd426afe flags:# proofread:flags.0?true emojify:flags.3?true text:TextWithEntities translate_to_lang:flags.1?string change_tone:flags.2?string = messages.ComposedMessageWithAI;
messages.composeMessageWithAI#daecc589 flags:# proofread:flags.0?true emojify:flags.3?true text:TextWithEntities translate_to_lang:flags.1?string tone:flags.2?InputAiComposeTone = messages.ComposedMessageWithAI;
messages.addPollAnswer#19bc4b6d peer:InputPeer msg_id:int answer:PollAnswer = Updates;
messages.getUnreadPollVotes#43286cf2 flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readPollVotes#1720b4d8 flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
@ -1999,4 +2013,11 @@ premium.getBoostsList#60f67660 flags:# gifts:flags.0?true peer:InputPeer offset:
premium.getMyBoosts#be77b4a = premium.MyBoosts;
premium.applyBoost#6b7da746 flags:# slots:flags.0?Vector<int> peer:InputPeer = premium.MyBoosts;
premium.getBoostsStatus#42f1f61 peer:InputPeer = premium.BoostsStatus;
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;`;
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;
aicompose.createTone#4aa83913 flags:# display_author:flags.0?true emoji_id:long title:string prompt:string = AiComposeTone;
aicompose.updateTone#903bcf59 flags:# tone:InputAiComposeTone display_author:flags.0?Bool emoji_id:flags.1?long title:flags.2?string prompt:flags.3?string = AiComposeTone;
aicompose.saveTone#1782cbb1 tone:InputAiComposeTone unsave:Bool = Bool;
aicompose.deleteTone#dd39316a tone:InputAiComposeTone = Bool;
aicompose.getTone#b2e8ba03 tone:InputAiComposeTone = aicompose.Tones;
aicompose.getTones#abd59201 hash:long = aicompose.Tones;
aicompose.getToneExample#d1b4ab14 tone:InputAiComposeTone num:int = AiComposeToneExample;`;

View File

@ -446,5 +446,12 @@
"premium.applyBoost",
"premium.getMyBoosts",
"premium.getBoostsList",
"fragment.getCollectibleInfo"
"fragment.getCollectibleInfo",
"aicompose.createTone",
"aicompose.updateTone",
"aicompose.saveTone",
"aicompose.deleteTone",
"aicompose.getTone",
"aicompose.getTones",
"aicompose.getToneExample"
]

View File

@ -86,7 +86,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
userEmpty#d3bc4b7a id:long = User;
user#31774388 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true bot_forum_view:flags2.16?true bot_forum_can_manage_topics:flags2.17?true bot_can_manage_bots:flags2.18?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?RecentStory color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long send_paid_messages_stars:flags2.15?long = User;
user#31774388 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true bot_forum_view:flags2.16?true bot_forum_can_manage_topics:flags2.17?true bot_can_manage_bots:flags2.18?true bot_guestchat:flags2.19?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?RecentStory color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long send_paid_messages_stars:flags2.15?long = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true personal:flags.2?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
@ -118,7 +118,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
message#3ae56482 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true flags2:# offline:flags2.1?true video_processing_pending:flags2.4?true paid_suggested_post_stars:flags2.8?true paid_suggested_post_ton:flags2.9?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int from_rank:flags2.12?string peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long via_business_bot_id:flags2.0?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int quick_reply_shortcut_id:flags.30?int effect:flags2.2?long factcheck:flags2.3?FactCheck report_delivery_until_date:flags2.5?int paid_message_stars:flags2.6?long suggested_post:flags2.7?SuggestedPost schedule_repeat_period:flags2.10?int summary_from_language:flags2.11?string = Message;
message#95ef6f2b flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true flags2:# offline:flags2.1?true video_processing_pending:flags2.4?true paid_suggested_post_stars:flags2.8?true paid_suggested_post_ton:flags2.9?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int from_rank:flags2.12?string peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long via_business_bot_id:flags2.0?long guestchat_via_from:flags2.19?Peer reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int quick_reply_shortcut_id:flags.30?int effect:flags2.2?long factcheck:flags2.3?FactCheck report_delivery_until_date:flags2.5?int paid_message_stars:flags2.6?long suggested_post:flags2.7?SuggestedPost schedule_repeat_period:flags2.10?int summary_from_language:flags2.11?string = Message;
messageService#7a800e0a flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true reactions_are_possible:flags.9?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer saved_peer_id:flags.28?Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction reactions:flags.20?MessageReactions ttl_period:flags.25?int = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
@ -227,7 +227,7 @@ geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radiu
auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode;
auth.sentCodePaymentRequired#e0955a3c store_product:string phone_code_hash:string support_email_address:string support_email_subject:string currency:string amount:long = auth.SentCode;
auth.sentCodePaymentRequired#f8827ebf store_product:string phone_code_hash:string support_email_address:string support_email_subject:string premium_days:int currency:string amount:long = auth.SentCode;
auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization;
auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization;
@ -465,6 +465,8 @@ updateEmojiGameInfo#fb9c547a info:messages.EmojiGameInfo = Update;
updateStarGiftCraftFail#ac072444 = Update;
updateChatParticipantRank#bd8367b9 chat_id:long user_id:long rank:string version:int = Update;
updateManagedBot#4880ed9a user_id:long bot_id:long qts:int = Update;
updateBotGuestChatQuery#cdd4093d flags:# query_id:long message:Message reference_messages:flags.0?Vector<Message> qts:int = Update;
updateAiComposeTones#8c0f91fb = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -852,6 +854,7 @@ topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
topPeerCategoryForwardUsers#a8406ca9 = TopPeerCategory;
topPeerCategoryForwardChats#fbeec0f0 = TopPeerCategory;
topPeerCategoryBotsApp#fd9e7bec = TopPeerCategory;
topPeerCategoryBotsGuestChat#6c24f3dd = TopPeerCategory;
topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector<TopPeer> = TopPeerCategoryPeers;
@ -1232,11 +1235,11 @@ help.userInfo#1eb3758 message:string entities:Vector<MessageEntity> author:strin
pollAnswer#4b7d786a flags:# text:TextWithEntities option:bytes media:flags.0?MessageMedia added_by:flags.1?Peer date:flags.1?int = PollAnswer;
inputPollAnswer#199fed96 flags:# text:TextWithEntities media:flags.0?InputMedia = PollAnswer;
poll#b8425be9 id:long flags:# closed:flags.0?true public_voters:flags.1?true multiple_choice:flags.2?true quiz:flags.3?true open_answers:flags.6?true revoting_disabled:flags.7?true shuffle_answers:flags.8?true hide_results_until_close:flags.9?true creator:flags.10?true question:TextWithEntities answers:Vector<PollAnswer> close_period:flags.4?int close_date:flags.5?int hash:long = Poll;
poll#966e2dbf id:long flags:# closed:flags.0?true public_voters:flags.1?true multiple_choice:flags.2?true quiz:flags.3?true open_answers:flags.6?true revoting_disabled:flags.7?true shuffle_answers:flags.8?true hide_results_until_close:flags.9?true creator:flags.10?true subscribers_only:flags.11?true question:TextWithEntities answers:Vector<PollAnswer> close_period:flags.4?int close_date:flags.5?int countries_iso2:flags.12?Vector<string> hash:long = Poll;
pollAnswerVoters#3645230a flags:# chosen:flags.0?true correct:flags.1?true option:bytes voters:flags.2?int recent_voters:flags.2?Vector<Peer> = PollAnswerVoters;
pollResults#ba7bb15e flags:# min:flags.0?true has_unread_votes:flags.6?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int recent_voters:flags.3?Vector<Peer> solution:flags.4?string solution_entities:flags.4?Vector<MessageEntity> solution_media:flags.5?MessageMedia = PollResults;
pollResults#ba7bb15e flags:# min:flags.0?true has_unread_votes:flags.6?true can_view_stats:flags.7?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int recent_voters:flags.3?Vector<Peer> solution:flags.4?string solution_entities:flags.4?Vector<MessageEntity> solution_media:flags.5?MessageMedia = PollResults;
chatOnlines#f041e250 onlines:int = ChatOnlines;
@ -1244,7 +1247,7 @@ statsURL#47a971e0 url:string = StatsURL;
chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true anonymous:flags.10?true manage_call:flags.11?true other:flags.12?true manage_topics:flags.13?true post_stories:flags.14?true edit_stories:flags.15?true delete_stories:flags.16?true manage_direct_messages:flags.17?true manage_ranks:flags.18?true = ChatAdminRights;
chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true manage_topics:flags.18?true send_photos:flags.19?true send_videos:flags.20?true send_roundvideos:flags.21?true send_audios:flags.22?true send_voices:flags.23?true send_docs:flags.24?true send_plain:flags.25?true edit_rank:flags.26?true until_date:int = ChatBannedRights;
chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true manage_topics:flags.18?true send_photos:flags.19?true send_videos:flags.20?true send_roundvideos:flags.21?true send_audios:flags.22?true send_voices:flags.23?true send_docs:flags.24?true send_plain:flags.25?true edit_rank:flags.26?true send_reactions:flags.27?true until_date:int = ChatBannedRights;
inputWallPaper#e630b979 id:long access_hash:long = InputWallPaper;
inputWallPaperSlug#72091c80 slug:string = InputWallPaper;
@ -1322,6 +1325,7 @@ webPageAttributeStickerSet#50cc03d3 flags:# emojis:flags.0?true text_color:flags
webPageAttributeUniqueStarGift#cf6f6db8 gift:StarGift = WebPageAttribute;
webPageAttributeStarGiftCollection#31cad303 icons:Vector<Document> = WebPageAttribute;
webPageAttributeStarGiftAuction#1c641c2 gift:StarGift end_date:int = WebPageAttribute;
webPageAttributeAiComposeTone#7781fe18 emoji_id:long = WebPageAttribute;
messages.votesList#4899484e flags:# count:int votes:Vector<MessagePeerVote> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.VotesList;
@ -1560,7 +1564,7 @@ inputStorePaymentPremiumGiveaway#160544ca flags:# only_new_subscribers:flags.0?t
inputStorePaymentStarsTopup#f9a2a6cb flags:# stars:long currency:string amount:long spend_purpose_peer:flags.0?InputPeer = InputStorePaymentPurpose;
inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose;
inputStorePaymentAuthCode#9bb2636d flags:# restore:flags.0?true phone_number:string phone_code_hash:string currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentAuthCode#3fc18057 flags:# restore:flags.0?true phone_number:string phone_code_hash:string premium_days:int currency:string amount:long = InputStorePaymentPurpose;
paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod;
@ -2147,6 +2151,22 @@ bots.requestedButton#f13bbcd7 webapp_req_id:string = bots.RequestedButton;
messages.composedMessageWithAI#90d7adfa flags:# result_text:TextWithEntities diff_text:flags.0?TextWithEntities = messages.ComposedMessageWithAI;
stats.pollStats#2999beed votes_graph:StatsGraph = stats.PollStats;
inputAiComposeToneDefault#1fe9a9bf tone:string = InputAiComposeTone;
inputAiComposeToneID#773c080 id:long access_hash:long = InputAiComposeTone;
inputAiComposeToneSlug#1fa01357 slug:string = InputAiComposeTone;
aiComposeTone#cff63ea9 flags:# creator:flags.0?true id:long access_hash:long slug:string title:string emoji_id:flags.1?long prompt:flags.4?string installs_count:flags.2?int author_id:flags.3?long example_english:flags.5?AiComposeToneExample = AiComposeTone;
aiComposeToneDefault#9bad6414 tone:string emoji_id:long title:string = AiComposeTone;
aicompose.tonesNotModified#c1f46103 = aicompose.Tones;
aicompose.tones#6c9d0efe hash:long tones:Vector<AiComposeTone> users:Vector<User> = aicompose.Tones;
aiComposeToneExample#f1d628ec from:TextWithEntities to:TextWithEntities = AiComposeToneExample;
bots.accessSettings#dd1fbf93 flags:# restricted:flags.0?true add_users:flags.1?Vector<User> = bots.AccessSettings;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -2331,7 +2351,7 @@ contacts.unblock#b550d328 flags:# my_stories_from:flags.0?true id:InputPeer = Bo
contacts.getBlocked#9a868f80 flags:# my_stories_from:flags.0?true offset:int limit:int = contacts.Blocked;
contacts.search#11f812d8 q:string limit:int = contacts.Found;
contacts.resolveUsername#725afbbc flags:# username:string referer:flags.0?string = contacts.ResolvedPeer;
contacts.getTopPeers#973478b6 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true bots_app:flags.16?true offset:int limit:int hash:long = contacts.TopPeers;
contacts.getTopPeers#973478b6 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true bots_app:flags.16?true bots_guestchat:flags.17?true offset:int limit:int hash:long = contacts.TopPeers;
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
contacts.resetSaved#879537f1 = Bool;
contacts.getSaved#82f1e39f = Vector<SavedContact>;
@ -2593,13 +2613,17 @@ messages.getFutureChatCreatorAfterLeave#3b7d0ea6 peer:InputPeer = User;
messages.editChatParticipantRank#a00f32b0 peer:InputPeer participant:InputPeer rank:string = Updates;
messages.declineUrlAuth#35436bbc url:string = Bool;
messages.checkUrlAuthMatchCode#c9a47b0b url:string match_code:string = Bool;
messages.composeMessageWithAI#fd426afe flags:# proofread:flags.0?true emojify:flags.3?true text:TextWithEntities translate_to_lang:flags.1?string change_tone:flags.2?string = messages.ComposedMessageWithAI;
messages.composeMessageWithAI#daecc589 flags:# proofread:flags.0?true emojify:flags.3?true text:TextWithEntities translate_to_lang:flags.1?string tone:flags.2?InputAiComposeTone = messages.ComposedMessageWithAI;
messages.reportReadMetrics#4067c5e6 peer:InputPeer metrics:Vector<InputMessageReadMetric> = Bool;
messages.reportMusicListen#ddbcd819 id:InputDocument listened_duration:int = Bool;
messages.addPollAnswer#19bc4b6d peer:InputPeer msg_id:int answer:PollAnswer = Updates;
messages.deletePollAnswer#ac8505a5 peer:InputPeer msg_id:int option:bytes = Updates;
messages.getUnreadPollVotes#43286cf2 flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readPollVotes#1720b4d8 flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
messages.setBotGuestChatResult#b8f106e3 query_id:long result:InputBotInlineResult = InputBotInlineMessageID;
messages.deleteParticipantReactions#a0b80cf8 peer:InputPeer participant:InputPeer = Bool;
messages.deleteParticipantReaction#e3b7f82c peer:InputPeer msg_id:int participant:InputPeer = Updates;
messages.getPersonalChannelHistory#55fb0996 user_id:InputUser limit:int max_id:int min_id:int hash:long = messages.Messages;
updates.getState#edd4882a = updates.State;
updates.getDifference#19c2f763 flags:# pts:int pts_limit:flags.1?int pts_total_limit:flags.0?int date:int qts:int qts_limit:flags.2?int = updates.Difference;
@ -2740,6 +2764,8 @@ bots.createBot#e5b17f2b flags:# via_deeplink:flags.0?true name:string username:s
bots.exportBotToken#bd0d99eb bot:InputUser revoke:Bool = bots.ExportedBotToken;
bots.requestWebViewButton#31a2a35e user_id:InputUser button:KeyboardButton = bots.RequestedButton;
bots.getRequestedWebViewButton#bf25b7f3 bot:InputUser webapp_req_id:string = KeyboardButton;
bots.getAccessSettings#213853a3 bot:InputUser = bots.AccessSettings;
bots.editAccessSettings#31813cd8 flags:# restricted:flags.0?true bot:InputUser add_users:flags.1?Vector<InputUser> = Bool;
payments.getPaymentForm#37148dbb flags:# invoice:InputInvoice theme_params:flags.0?DataJSON = payments.PaymentForm;
payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt;
@ -2878,6 +2904,7 @@ stats.getMessagePublicForwards#5f150144 channel:InputChannel msg_id:int offset:s
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;
stats.getStoryStats#374fef40 flags:# dark:flags.0?true peer:InputPeer id:int = stats.StoryStats;
stats.getStoryPublicForwards#a6437ef6 peer:InputPeer id:int offset:string limit:int = stats.PublicForwards;
stats.getPollStats#c27dfa68 flags:# dark:flags.0?true peer:InputPeer msg_id:int = stats.PollStats;
chatlists.exportChatlistInvite#8472478e chatlist:InputChatlist title:string peers:Vector<InputPeer> = chatlists.ExportedChatlistInvite;
chatlists.deleteExportedInvite#719c5c5e chatlist:InputChatlist slug:string = Bool;
@ -2940,3 +2967,11 @@ 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;
aicompose.createTone#4aa83913 flags:# display_author:flags.0?true emoji_id:long title:string prompt:string = AiComposeTone;
aicompose.updateTone#903bcf59 flags:# tone:InputAiComposeTone display_author:flags.0?Bool emoji_id:flags.1?long title:flags.2?string prompt:flags.3?string = AiComposeTone;
aicompose.saveTone#1782cbb1 tone:InputAiComposeTone unsave:Bool = Bool;
aicompose.deleteTone#dd39316a tone:InputAiComposeTone = Bool;
aicompose.getTone#b2e8ba03 tone:InputAiComposeTone = aicompose.Tones;
aicompose.getTones#abd59201 hash:long = aicompose.Tones;
aicompose.getToneExample#d1b4ab14 tone:InputAiComposeTone num:int = AiComposeToneExample;

View File

@ -170,5 +170,4 @@ export const DEFAULT_APP_CONFIG: ApiAppConfig = {
passkeysMaxCount: 5,
diceEmojies: [],
diceEmojiesSuccess: {},
aiComposeStyles: [],
};

View File

@ -2102,13 +2102,6 @@ export interface LangPair {
'AiMessageEditorSelectStyle': undefined;
'AiMessageEditorDailyLimitReachedPremium': undefined;
'AiMessageEditorGenericError': undefined;
'AiMessageEditorStyleFormal': undefined;
'AiMessageEditorStyleShort': undefined;
'AiMessageEditorStyleTribal': undefined;
'AiMessageEditorStyleCorp': undefined;
'AiMessageEditorStyleBiblical': undefined;
'AiMessageEditorStyleViking': undefined;
'AiMessageEditorStyleZen': undefined;
'AiMessageEditorResult': undefined;
'AiMessageEditorOriginal': undefined;
'AiMessageEditorApply': undefined;

View File

@ -0,0 +1,31 @@
import type {
ApiAiComposeToneDefault, ApiAiComposeToneType, ApiInputAiComposeTone,
} from '../api/types';
function isDefaultTone(tone: ApiAiComposeToneType): tone is ApiAiComposeToneDefault {
return 'tone' in tone;
}
export function getInputTone(tone: ApiAiComposeToneType): ApiInputAiComposeTone {
if (isDefaultTone(tone)) {
return { type: 'default', tone: tone.tone };
}
return { type: 'id', id: tone.id, accessHash: tone.accessHash };
}
export function getToneCacheKey(tone: ApiInputAiComposeTone): string {
switch (tone.type) {
case 'default': return `d:${tone.tone}`;
case 'id': return `i:${tone.id}:${tone.accessHash}`;
case 'slug': return `s:${tone.slug}`;
}
}
export function compareAiTones(
a?: ApiInputAiComposeTone,
b?: ApiInputAiComposeTone,
): boolean {
if (!a && !b) return true;
if (!a || !b) return false;
return getToneCacheKey(a) === getToneCacheKey(b);
}