Show notification for FLOOD_PREMIUM_WAIT (#4471)

This commit is contained in:
Alexander Zinchuk 2024-04-19 13:38:32 +04:00
parent 0bda37c725
commit 8d942e62bb
13 changed files with 101 additions and 11 deletions

View File

@ -73,6 +73,10 @@ export interface GramJsAppConfig extends LimitsConfig {
// Boosts
group_transcribe_level_min?: number;
new_noncontact_peers_require_premium_without_ownpremium?: boolean;
// Upload premium notifications
upload_premium_speedup_notify_period?: number;
upload_premium_speedup_download?: number;
upload_premium_speedup_upload?: number;
}
function buildEmojiSounds(appConfig: GramJsAppConfig) {
@ -147,5 +151,8 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
storyChangelogUserId: appConfig.stories_changelog_user_id?.toString() ?? SERVICE_NOTIFICATIONS_USER_ID,
groupTranscribeLevelMin: appConfig.group_transcribe_level_min,
canLimitNewMessagesWithoutPremium: appConfig.new_noncontact_peers_require_premium_without_ownpremium,
bandwidthPremiumNotifyPeriod: appConfig.upload_premium_speedup_notify_period,
bandwidthPremiumUploadSpeedup: appConfig.upload_premium_speedup_upload,
bandwidthPremiumDownloadSpeedup: appConfig.upload_premium_speedup_download,
};
}

View File

@ -0,0 +1,3 @@
export default class LocalUpdatePremiumFloodWait {
constructor(public isUpload: boolean) {}
}

View File

@ -77,11 +77,12 @@ import {
import localDb from '../localDb';
import { scheduleMutedChatUpdate, scheduleMutedTopicUpdate } from '../scheduleUnmute';
import LocalUpdatePremiumFloodWait from './UpdatePremiumFloodWait';
import { LocalUpdateChannelPts, LocalUpdatePts, type UpdatePts } from './UpdatePts';
export type Update = (
(GramJs.TypeUpdate | GramJs.TypeUpdates) & { _entities?: (GramJs.TypeUser | GramJs.TypeChat)[] }
) | typeof connection.UpdateConnectionState | UpdatePts;
) | typeof connection.UpdateConnectionState | UpdatePts | LocalUpdatePremiumFloodWait;
const DELETE_MISSING_CHANNEL_MESSAGE_DELAY = 1000;
@ -1193,6 +1194,11 @@ export function updater(update: Update) {
chatId: buildApiPeerId(update.channelId, 'channel'),
isEnabled: update.enabled ? true : undefined,
});
} else if (update instanceof LocalUpdatePremiumFloodWait) {
onUpdate({
'@type': 'updatePremiumFloodWait',
isUpload: update.isUpload,
});
} else if (update instanceof LocalUpdatePts || update instanceof LocalUpdateChannelPts) {
// Do nothing, handled on the manager side
} else if (DEBUG) {

View File

@ -204,6 +204,9 @@ export interface ApiAppConfig {
storyChangelogUserId: string;
groupTranscribeLevelMin?: number;
canLimitNewMessagesWithoutPremium?: boolean;
bandwidthPremiumNotifyPeriod?: number;
bandwidthPremiumUploadSpeedup?: number;
bandwidthPremiumDownloadSpeedup?: number;
}
export interface ApiConfig {

View File

@ -733,6 +733,11 @@ export type ApiUpdateSavedReactionTags = {
'@type': 'updateSavedReactionTags';
};
export type ApiUpdatePremiumFloodWait = {
'@type': 'updatePremiumFloodWait';
isUpload?: boolean;
};
export type ApiUpdate = (
ApiUpdateReady | ApiUpdateSession | ApiUpdateWebAuthTokenFailed | ApiUpdateRequestUserUpdate |
ApiUpdateAuthorizationState | ApiUpdateAuthorizationError | ApiUpdateConnectionState | ApiUpdateCurrentUser |
@ -763,7 +768,7 @@ export type ApiUpdate = (
ApiRequestReconnectApi | ApiRequestSync | ApiUpdateFetchingDifference | ApiUpdateChannelMessages |
ApiUpdateStealthMode | ApiUpdateAttachMenuBots | ApiUpdateNewAuthorization | ApiUpdateGroupInvitePrivacyForbidden |
ApiUpdateViewForumAsMessages | ApiUpdateSavedDialogPinned | ApiUpdatePinnedSavedDialogIds | ApiUpdateChatLastMessage |
ApiUpdateDeleteSavedHistory |
ApiUpdateDeleteSavedHistory | ApiUpdatePremiumFloodWait |
ApiUpdateQuickReplyMessage | ApiUpdateQuickReplies | ApiDeleteQuickReply | ApiUpdateDeleteQuickReplyMessages
);

View File

@ -155,6 +155,12 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
case 'updateAttachMenuBots':
actions.loadAttachBots({ hash: global.attachMenu.hash });
break;
case 'updatePremiumFloodWait': {
actions.processPremiumFloodWait({
isUpload: update.isUpload,
});
}
}
return undefined;

View File

@ -35,6 +35,7 @@ import {
import { getIsMobile, getIsTablet } from '../../../hooks/useAppLayout';
export const APP_VERSION_URL = 'version.txt';
const FLOOD_PREMIUM_WAIT_NOTIFICATION_DURATION = 6000;
const MAX_STORED_EMOJIS = 8 * 4; // Represents four rows of recent emojis
addActionHandler('toggleChatInfo', (global, actions, payload): ActionReturnType => {
@ -750,6 +751,43 @@ addActionHandler('setShouldCloseRightColumn', (global, actions, payload): Action
}, tabId);
});
addActionHandler('processPremiumFloodWait', (global, actions, payload): ActionReturnType => {
const { isUpload } = payload;
const {
bandwidthPremiumDownloadSpeedup,
bandwidthPremiumUploadSpeedup,
bandwidthPremiumNotifyPeriod,
} = global.appConfig || {};
const { lastPremiumBandwithNotificationDate: lastNotifiedAt } = global.settings;
if (!bandwidthPremiumDownloadSpeedup || !bandwidthPremiumUploadSpeedup || !bandwidthPremiumNotifyPeriod) {
return undefined;
}
if (lastNotifiedAt && Date.now() < lastNotifiedAt + bandwidthPremiumNotifyPeriod * 1000) return undefined;
const unblurredTabIds = Object.values(global.byTabId).filter((l) => !l.isBlurred).map((l) => l.id);
unblurredTabIds.forEach((tabId) => {
actions.showNotification({
title: langProvider.translate(isUpload ? 'UploadSpeedLimited' : 'DownloadSpeedLimited'),
message: langProvider.translate(
isUpload ? 'UploadSpeedLimitedMessage' : 'DownloadSpeedLimitedMessage',
isUpload ? bandwidthPremiumUploadSpeedup : bandwidthPremiumDownloadSpeedup,
),
duration: FLOOD_PREMIUM_WAIT_NOTIFICATION_DURATION,
tabId,
});
});
return {
...global,
settings: {
...global.settings,
lastPremiumBandwithNotificationDate: Date.now(),
},
};
});
let prevIsScreenLocked: boolean | undefined;
let prevBlurredTabsCount: number = 0;
let onlineTimeout: number | undefined;

View File

@ -1009,6 +1009,7 @@ export type GlobalState = {
themes: Partial<Record<ThemeKey, IThemeSettings>>;
privacy: Partial<Record<ApiPrivacyKey, ApiPrivacySettings>>;
notifyExceptions?: Record<number, NotifyException>;
lastPremiumBandwithNotificationDate?: number;
};
push?: {
@ -1852,6 +1853,9 @@ export interface ActionPayloads {
setGlobalSearchClosing: ({
isClosing?: boolean;
} & WithTabId) | undefined;
processPremiumFloodWait: {
isUpload?: boolean;
};
// Accounts
reportPeer: {

View File

@ -1,9 +1,9 @@
import type { Api } from '..';
import type { TmpPasswordResult, TwoFaParams, updateTwoFaSettings } from './2fa';
import type { BotAuthParams, UserAuthParams } from './auth';
import type { uploadFile, UploadFileParams } from './uploadFile';
import type { downloadFile, DownloadFileParams } from './downloadFile';
import type { TwoFaParams, updateTwoFaSettings, TmpPasswordResult } from './2fa';
import type { uploadFile, UploadFileParams } from './uploadFile';
import type { Api } from '..';
declare class TelegramClient {
constructor(...args: any);

View File

@ -634,6 +634,7 @@ class TelegramClient {
authKeyCallback: this._authKeyCallback.bind(this),
isMainSender: dcId === this.session.dcId,
isExported: true,
updateCallback: this._handleUpdate.bind(this),
getShouldDebugExportedSenders: this.getShouldDebugExportedSenders.bind(this),
onConnectionBreak: () => this._cleanupExportedSender(dcId, index),
});

View File

@ -7,6 +7,7 @@ import { Foreman } from '../../../util/foreman';
import errors from '../errors';
import Api from '../tl/api';
import LocalUpdatePremiumFloodWait from '../../../api/gramjs/updates/UpdatePremiumFloodWait';
import { sleep } from '../Helpers';
import { getDownloadPartSize } from '../Utils';
@ -185,6 +186,9 @@ async function downloadFile2(
progressCallback(progress);
}
// Limit updates to one per file
let isPremiumFloodWaitSent = false;
// Allocate memory
await fileView.init();
@ -292,6 +296,10 @@ async function downloadFile2(
await sleep(DISCONNECT_SLEEP);
continue;
} else if (err instanceof errors.FloodWaitError) {
if (err instanceof errors.FloodPremiumWaitError && !isPremiumFloodWaitSent) {
sender?._updateCallback(new LocalUpdatePremiumFloodWait(false));
isPremiumFloodWaitSent = true;
}
await sleep(err.seconds * 1000);
continue;
}

View File

@ -1,11 +1,12 @@
// eslint-disable-next-line import/no-named-default
import { default as Api } from '../tl/api';
import type TelegramClient from './TelegramClient';
import { Foreman } from '../../../util/foreman';
import errors from '../errors';
import Api from '../tl/api';
import LocalUpdatePremiumFloodWait from '../../../api/gramjs/updates/UpdatePremiumFloodWait';
import { generateRandomBytes, readBigIntFromBuffer, sleep } from '../Helpers';
import { getUploadPartSize } from '../Utils';
import errors from '../errors';
import { Foreman } from '../../../util/foreman';
interface OnProgress {
isCanceled?: boolean;
@ -64,6 +65,9 @@ export async function uploadFile(
onProgress(progress);
}
// Limit updates to one per file
let isPremiumFloodWaitSent = false;
const promises: Promise<any>[] = [];
for (let i = 0; i < partCount; i++) {
@ -130,6 +134,10 @@ export async function uploadFile(
await sleep(DISCONNECT_SLEEP);
continue;
} else if (err instanceof errors.FloodWaitError) {
if (err instanceof errors.FloodPremiumWaitError && !isPremiumFloodWaitSent) {
sender?._updateCallback(new LocalUpdatePremiumFloodWait(true));
isPremiumFloodWaitSent = true;
}
await sleep(err.seconds * 1000);
continue;
}

View File

@ -119,6 +119,7 @@ module.exports = {
FileMigrateError,
FloodTestPhoneWaitError,
FloodWaitError,
FloodPremiumWaitError,
PhoneMigrateError,
SlowModeWaitError,
UserMigrateError,