/* This file is part of Telegram Desktop, the official desktop version of Telegram messaging app, see https://telegram.org Telegram Desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the OpenSSL library. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once #include "core/version.h" #include "settings.h" constexpr str_const AppNameOld = "Telegram Win (Unofficial)"; constexpr str_const AppName = "Telegram Desktop"; constexpr str_const AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"; // used in updater.cpp and Setup.iss for Windows constexpr str_const AppFile = "Telegram"; enum { MTPShortBufferSize = 65535, // of ints, 256 kb MTPPacketSizeMax = 67108864, // 64 mb MTPIdsBufferSize = 400, // received msgIds and wereAcked msgIds count stored MTPCheckResendTimeout = 10000, // how much time passed from send till we resend request or check it's state, in ms MTPCheckResendWaiting = 1000, // how much time to wait for some more requests, when resending request or checking it's state, in ms MTPAckSendWaiting = 10000, // how much time to wait for some more requests, when sending msg acks MTPResendThreshold = 1, // how much ints should message contain for us not to resend, but to check it's state MTPContainerLives = 600, // container lives 10 minutes in haveSent map MTPMinReceiveDelay = 4000, // 4 seconds MTPMaxReceiveDelay = 64000, // 64 seconds MTPMinConnectDelay = 1000, // tcp connect should take less then 1 second MTPMaxConnectDelay = 8000, // tcp connect should take 8 seconds max MTPConnectionOldTimeout = 192000, // 192 seconds MTPTcpConnectionWaitTimeout = 2000, // 2 seconds waiting for tcp, until we accept http MTPIPv4ConnectionWaitTimeout = 1000, // 1 seconds waiting for ipv4, until we accept ipv6 MTPMillerRabinIterCount = 30, // 30 Miller-Rabin iterations for dh_prime primality check MTPUploadSessionsCount = 2, // max 2 upload sessions is created MTPDownloadSessionsCount = 2, // max 2 download sessions is created MTPKillFileSessionTimeout = 5000, // how much time without upload / download causes additional session kill MTPEnumDCTimeout = 8000, // 8 seconds timeout for help_getConfig to work (then move to other dc) MTPDebugBufferSize = 1024 * 1024, // 1 mb start size MaxUsersPerInvite = 100, // max users in one super group invite request MTPPingDelayDisconnect = 60, // 1 min MTPPingSendAfterAuto = 30, // send new ping starting from 30 seconds (add to existing container) MTPPingSendAfter = 45, // send new ping after 45 seconds without ping MTPChannelGetDifferenceLimit = 100, MaxSelectedItems = 100, MaxPhoneCodeLength = 4, // max length of country phone code MaxPhoneTailLength = 32, // rest of the phone number, without country code (seen 12 at least), need more for service numbers MaxScrollSpeed = 37, // 37px per 15ms while select-by-drag FingerAccuracyThreshold = 3, // touch flick ignore 3px MaxScrollAccelerated = 4000, // 4000px per second MaxScrollFlick = 2500, // 2500px per second LocalEncryptIterCount = 4000, // key derivation iteration count LocalEncryptNoPwdIterCount = 4, // key derivation iteration count without pwd (not secure anyway) LocalEncryptSaltSize = 32, // 256 bit LocalEncryptKeySize = 256, // 2048 bit AnimationTimerDelta = 7, ClipThreadsCount = 8, AverageGifSize = 320 * 240, WaitBeforeGifPause = 200, // wait 200ms for gif draw before pausing it InlineBotRequestDelay = 400, // wait 400ms before context bot realtime request RecentInlineBotsLimit = 10, AVBlockSize = 4096, // 4Kb for ffmpeg blocksize SaveRecentEmojisTimeout = 3000, // 3 secs SaveWindowPositionTimeout = 1000, // 1 sec AutoSearchTimeout = 900, // 0.9 secs SearchPerPage = 50, SearchManyPerPage = 100, LinksOverviewPerPage = 12, MediaOverviewStartPerPage = 5, MediaOverviewPreloadCount = 4, AudioSimultaneousLimit = 4, AudioCheckPositionTimeout = 100, // 100ms per check audio pos AudioCheckPositionDelta = 2400, // update position called each 2400 samples AudioFadeTimeout = 7, // 7ms AudioFadeDuration = 500, AudioVoiceMsgSkip = 400, // 200ms AudioVoiceMsgFade = 300, // 300ms AudioPreloadSamples = 2 * 48000, // preload next part if less than 5 seconds remains AudioVoiceMsgFrequency = 48000, // 48 kHz AudioVoiceMsgMaxLength = 100 * 60, // 100 minutes AudioVoiceMsgUpdateView = 100, // 100ms AudioVoiceMsgChannels = 2, // stereo AudioVoiceMsgBufferSize = 256 * 1024, // 256 Kb buffers (1.3 - 3.0 secs) AudioVoiceMsgInMemory = 2 * 1024 * 1024, // 2 Mb audio is hold in memory and auto loaded AudioPauseDeviceTimeout = 3000, // pause in 3 secs after playing is over WaveformSamplesCount = 100, StickerInMemory = 2 * 1024 * 1024, // 2 Mb stickers hold in memory, auto loaded and displayed inline StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker AnimationInMemory = 10 * 1024 * 1024, // 10 Mb gif and mp4 animations held in memory while playing MaxZoomLevel = 7, // x8 ZoomToScreenLevel = 1024, // just constant ShortcutsCountLimit = 256, // how many shortcuts can be in json file PreloadHeightsCount = 3, // when 3 screens to scroll left make a preload request EmojiPanPerRow = 7, EmojiPanRowsPerPage = 6, StickerPanPerRow = 5, StickerPanRowsPerPage = 4, StickersUpdateTimeout = 3600000, // update not more than once in an hour SearchPeopleLimit = 5, MinUsernameLength = 5, MaxUsernameLength = 32, UsernameCheckTimeout = 200, MaxChannelDescription = 255, MaxGroupChannelTitle = 255, MaxPhotoCaption = 200, MaxMessageSize = 4096, MaxHttpRedirects = 5, // when getting external data/images WriteMapTimeout = 1000, SaveDraftTimeout = 1000, // save draft after 1 secs of not changing text SaveDraftAnywayTimeout = 5000, // or save anyway each 5 secs SaveCloudDraftIdleTimeout = 14000, // save draft to the cloud after 14 more seconds SaveCloudDraftTimeout = 1000, // save draft to the cloud with 1 sec extra delay SaveDraftBeforeQuitTimeout = 1500, // give the app 1.5 secs to save drafts to cloud when quitting SetOnlineAfterActivity = 30, // user with hidden last seen stays online for such amount of seconds in the interface ServiceUserId = 777000, WebPageUserId = 701000, CacheBackgroundTimeout = 3000, // cache background scaled image after 3s BackgroundsInRow = 3, UpdateDelayConstPart = 8 * 3600, // 8 hour min time between update check requests UpdateDelayRandPart = 8 * 3600, // 8 hour max - min time between update check requests WrongPasscodeTimeout = 1500, SessionsShortPollTimeout = 60000, ChoosePeerByDragTimeout = 1000, // 1 second mouse not moved to choose dialog when dragging a file ReloadChannelMembersTimeout = 1000, // 1 second wait before reload members in channel after adding }; inline bool isNotificationsUser(uint64 id) { return (id == 333000) || (id == ServiceUserId); } inline bool isServiceUser(uint64 id) { return !(id % 1000);// (id == 333000) || (id == ServiceUserId); } #ifdef Q_OS_WIN inline const GUID &cGUID() { #ifndef OS_MAC_STORE static const GUID gGuid = { 0x87a94ab0, 0xe370, 0x4cde, { 0x98, 0xd3, 0xac, 0xc1, 0x10, 0xc5, 0x96, 0x7d } }; #else // OS_MAC_STORE static const GUID gGuid = { 0xe51fb841, 0x8c0b, 0x4ef9, { 0x9e, 0x9e, 0x5a, 0x0, 0x78, 0x56, 0x76, 0x27 } }; #endif // OS_MAC_STORE return gGuid; } #endif inline const char *cGUIDStr() { #ifndef OS_MAC_STORE static const char *gGuidStr = "{87A94AB0-E370-4cde-98D3-ACC110C5967D}"; #else // OS_MAC_STORE static const char *gGuidStr = "{E51FB841-8C0B-4EF9-9E9E-5A0078567627}"; #endif // OS_MAC_STORE return gGuidStr; } inline const char **cPublicRSAKeys(int &keysCount) { static const char *(keys[]) = {"\ -----BEGIN RSA PUBLIC KEY-----\n\ MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n\ lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS\n\ an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw\n\ Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+\n\ 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n\n\ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n\ -----END RSA PUBLIC KEY-----"}; keysCount = base::array_size(keys); return keys; } struct BuiltInDc { int id; const char *ip; int port; }; static const BuiltInDc _builtInDcs[] = { { 1, "149.154.175.50", 443 }, { 2, "149.154.167.51", 443 }, { 3, "149.154.175.100", 443 }, { 4, "149.154.167.91", 443 }, { 5, "149.154.171.5", 443 } }; static const BuiltInDc _builtInDcsIPv6[] = { { 1, "2001:b28:f23d:f001::a", 443 }, { 2, "2001:67c:4e8:f002::a", 443 }, { 3, "2001:b28:f23d:f003::a", 443 }, { 4, "2001:67c:4e8:f004::a", 443 }, { 5, "2001:b28:f23f:f005::a", 443 } }; static const BuiltInDc _builtInTestDcs[] = { { 1, "149.154.175.10", 443 }, { 2, "149.154.167.40", 443 }, { 3, "149.154.175.117", 443 } }; static const BuiltInDc _builtInTestDcsIPv6[] = { { 1, "2001:b28:f23d:f001::e", 443 }, { 2, "2001:67c:4e8:f002::e", 443 }, { 3, "2001:b28:f23d:f003::e", 443 } }; inline const BuiltInDc *builtInDcs() { return cTestMode() ? _builtInTestDcs : _builtInDcs; } inline int builtInDcsCount() { return (cTestMode() ? sizeof(_builtInTestDcs) : sizeof(_builtInDcs)) / sizeof(BuiltInDc); } inline const BuiltInDc *builtInDcsIPv6() { return cTestMode() ? _builtInTestDcsIPv6 : _builtInDcsIPv6; } inline int builtInDcsCountIPv6() { return (cTestMode() ? sizeof(_builtInTestDcsIPv6) : sizeof(_builtInDcsIPv6)) / sizeof(BuiltInDc); } static const char *UpdatesPublicKey = "\ -----BEGIN RSA PUBLIC KEY-----\n\ MIGJAoGBAMA4ViQrjkPZ9xj0lrer3r23JvxOnrtE8nI69XLGSr+sRERz9YnUptnU\n\ BZpkIfKaRcl6XzNJiN28cVwO1Ui5JSa814UAiDHzWUqCaXUiUEQ6NmNTneiGx2sQ\n\ +9PKKlb8mmr3BB9A45ZNwLT6G9AK3+qkZLHojeSA+m84/a6GP4svAgMBAAE=\n\ -----END RSA PUBLIC KEY-----\ "; static const char *UpdatesPublicAlphaKey = "\ -----BEGIN RSA PUBLIC KEY-----\n\ MIGJAoGBALWu9GGs0HED7KG7BM73CFZ6o0xufKBRQsdnq3lwA8nFQEvmdu+g/I1j\n\ 0LQ+0IQO7GW4jAgzF/4+soPDb6uHQeNFrlVx1JS9DZGhhjZ5rf65yg11nTCIHZCG\n\ w/CVnbwQOw0g5GBwwFV3r0uTTvy44xx8XXxk+Qknu4eBCsmrAFNnAgMBAAE=\n\ -----END RSA PUBLIC KEY-----\ "; #ifdef CUSTOM_API_ID #include "../../../TelegramPrivate/custom_api_id.h" // Custom API id and API hash #else static const int32 ApiId = 17349; static const char *ApiHash = "344583e45741c457fe1862106095a5eb"; #endif #if Q_BYTE_ORDER == Q_BIG_ENDIAN #error "Only little endian is supported!" #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN #ifndef BETA_VERSION_MACRO #error "Beta version macro is not defined." #endif #if (defined CUSTOM_API_ID) && (BETA_VERSION_MACRO > 0ULL) #include "../../../TelegramPrivate/beta_private.h" // private key for downloading closed betas #else static const char *BetaPrivateKey = ""; #endif inline const char *cApiDeviceModel() { #ifdef Q_OS_WIN return "PC"; #elif defined Q_OS_MAC return "Mac"; #elif defined Q_OS_LINUX return "PC"; #endif } inline const char *cApiSystemVersion() { #ifdef Q_OS_WIN return "Windows"; #elif defined Q_OS_MAC return "OS X"; #elif defined Q_OS_LINUX return "Linux"; #endif } inline QString cApiAppVersion() { return QString::number(AppVersion); } constexpr str_const AppLinksDomain = "t.me"; inline QString CreateInternalLink(const QString &query) { return str_const_toString(AppLinksDomain) + '/' + query; } inline QString CreateInternalLinkHttps(const QString &query) { return qsl("https://") + CreateInternalLink(query); } extern QString gKeyFile; inline const QString &cDataFile() { if (!gKeyFile.isEmpty()) return gKeyFile; static const QString res(qsl("data")); return res; } inline const QString &cTempDir() { static const QString res = cWorkingDir() + qsl("tdata/tdld/"); return res; } static const char *DefaultCountry = "US"; static const char *DefaultLanguage = "en"; enum { DialogsFirstLoad = 20, // first dialogs part size requested DialogsPerPage = 500, // next dialogs part size MessagesFirstLoad = 30, // first history part size requested MessagesPerPage = 50, // next history part size FileLoaderQueueStopTimeout = 5000, DownloadPartSize = 64 * 1024, // 64kb for photo DocumentDownloadPartSize = 128 * 1024, // 128kb for document UseBigFilesFrom = 10 * 1024 * 1024, // mtp big files methods used for files greater than 10mb MaxFileQueries = 16, // max 16 file parts downloaded at the same time MaxWebFileQueries = 8, // max 8 http[s] files downloaded at the same time UploadPartSize = 32 * 1024, // 32kb for photo DocumentMaxPartsCount = 3000, // no more than 3000 parts DocumentUploadPartSize0 = 32 * 1024, // 32kb for tiny document ( < 1mb ) DocumentUploadPartSize1 = 64 * 1024, // 64kb for little document ( <= 32mb ) DocumentUploadPartSize2 = 128 * 1024, // 128kb for small document ( <= 375mb ) DocumentUploadPartSize3 = 256 * 1024, // 256kb for medium document ( <= 750mb ) DocumentUploadPartSize4 = 512 * 1024, // 512kb for large document ( <= 1500mb ) MaxUploadFileParallelSize = MTPUploadSessionsCount * 512 * 1024, // max 512kb uploaded at the same time in each session UploadRequestInterval = 500, // one part each half second, if not uploaded faster MaxPhotosInMemory = 50, // try to clear some memory after 50 photos are created NoUpdatesTimeout = 60 * 1000, // if nothing is received in 1 min we ping NoUpdatesAfterSleepTimeout = 60 * 1000, // if nothing is received in 1 min when was a sleepmode we ping WaitForSkippedTimeout = 1000, // 1s wait for skipped seq or pts in updates WaitForChannelGetDifference = 1000, // 1s wait after show channel history before sending getChannelDifference MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory NotifySettingSaveTimeout = 1000, // wait 1 second before saving notify setting to server UpdateChunk = 100 * 1024, // 100kb parts when downloading the update IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle UpdateFullChannelTimeout = 5000, // not more than once in 5 seconds SendViewsTimeout = 1000, // send views each second ForwardOnAdd = 100, // how many messages from chat history server should forward to user, that was added to this chat }; inline const QRegularExpression &cWordSplit() { static QRegularExpression regexp(qsl("[\\@\\s\\-\\+\\(\\)\\[\\]\\{\\}\\<\\>\\,\\.\\:\\!\\_\\;\\\"\\'\\x0]")); return regexp; } inline const QRegularExpression &cRussianLetters() { static QRegularExpression regexp(QString::fromUtf8("[а-яА-ЯёЁ]")); return regexp; } inline const QStringList &cImgExtensions() { static QStringList result; if (result.isEmpty()) { result.reserve(4); result.push_back(qsl(".jpg")); result.push_back(qsl(".jpeg")); result.push_back(qsl(".png")); result.push_back(qsl(".gif")); } return result; } inline const QStringList &cExtensionsForCompress() { static QStringList result; if (result.isEmpty()) { result.push_back(qsl(".jpg")); result.push_back(qsl(".jpeg")); result.push_back(qsl(".png")); } return result; }