tweb/public/3.ecfbd0f9b839f0b7d92f.chun...

1 line
135 KiB
Plaintext

{"version":3,"sources":["webpack:///./src/helpers/assumeType.ts","webpack:///./src/lib/searchIndex.ts","webpack:///./src/helpers/dom/htmlToSpan.ts","webpack:///./src/helpers/cleanSearchText.ts","webpack:///./src/lib/mtproto/mtproto_config.ts","webpack:///./src/helpers/cleanUsername.ts","webpack:///./src/lib/appManagers/appUsersManager.ts","webpack:///./src/lib/appManagers/appPeersManager.ts","webpack:///./src/lib/appManagers/appChatsManager.ts","webpack:///./src/helpers/array.ts","webpack:///./src/lib/appManagers/apiUpdatesManager.ts"],"names":["assumeType","x","SearchIndex","options","minChars","fullTexts","Map","id","searchText","this","trim","delete","set","query","newFoundObjs","queryWords","split","queryWordsLength","length","forEach","fullText","what","found","foundChars","i","word","idx","indexOf","fullTextLength","push","sort","a","b","Set","map","o","htmlToSpan","html","span","document","createElement","innerHTML","badCharsRe","trimRe","clearBadCharsAndTrim","text","replace","latinizeString","ch","latinizeCh","LatinizeMap","undefined","cleanSearchText","latinize","hasTag","charAt","toLowerCase","processSearchText","includeTag","clearBadChars","ignoreCase","REPLIES_PEER_ID","SERVICE_PEER_ID","MUTE_UNTIL","cleanUsername","username","appUsersManager","storage","appStateManager","storages","users","updateUsersStatuses","timestampNow","user","updateUserStatus","clear","setInterval","rootScope","addEventListener","addMultipleEventsListeners","update","userId","user_id","status","expires","serverTimeManager","serverTimeOffset","was_online","dispatchEvent","setUserToStateIfNeeded","updateUserPhoto","forceUserOnline","photo","_","console","warn","updateUserName","saveApiUser","Object","assign","first_name","last_name","e","getSelf","contactsIndex","indexObject","getUserSearchText","getState","then","state","storagesResults","contactsList","Array","isArray","pushContact","contactsFillPromise","resolve","peerId","getFromCache","getUser","init","usernames","_userId","isPeerNeeded","findAndSplice","getTopPeersPromises","createSearchIndex","updatedContactsList","pushToState","cached","isFulfilled","promise","invokeApi","result","saveApiUsers","contacts","contact","onContactsModified","slice","Promise","resolvedPeer","appChatsManager","saveApiChats","chats","appPeersManager","getPeer","getPeerId","peer","add","requestPeer","phone","pFlags","self","format","filter","Boolean","join","includeSaved","sortBy","fillContacts","_contactsList","results","search","has","userId1","userId2","sortName1","sortName","sortName2","localeCompare","status1","getUserStatusForSort","p","myId","testSelfSearch","unshift","block","invokeApiSingle","getInputPeerById","value","apiUpdatesManager","processLocalUpdate","peer_id","getOutputPeer","blocked","index","apiUsers","override","oldUser","min","oldSearchUsername","searchUsername","initials","fullName","deleted","getAbbreviation","changedPhoto","changedTitle","photo_id","wasContact","newContact","onContactUpdated","formatPhoneNumber","formatted","access_hash","key","args","isBot","support","date","now","Date","d","getDate","getMonth","getHours","getMinutes","bot","isRegularUser","isContact","allowMin","phone_number","vcard","eventTimestamp","timestamp","updatesState","syncLoading","importContacts","phones","userIds","error","Error","type","inputContacts","j","client_id","toString","importedContactsResult","imported","importedContact","topPeersCache","cachedTime","peers","offset","limit","hash","topPeers","categories","topPeer","rating","contactsBlocked","count","peerIds","u","concat","c","invokeApiCacheable","q","cacheSeconds","my_results","curIsContact","offline","showPhone","getUserInput","add_phone_privacy_exception","updates","processUpdateMessage","DialogColorsFg","DialogColors","DialogColorsMap","hasRights","getUserPhoto","getChatPhoto","chat","getChat","migrated_to","deactivated","plainText","onlyFirstName","title","wrapEmojiText","chatId","isChannel","channel_id","chat_id","getUserString","getChatString","isUser","peerParams","substr","isMegagroup","isBroadcast","ignorePeerId","getChannelInputPeer","getChatInputPeer","pic","getDialogType","onChatUpdated","updateChannelParticipant","clearCache","params","channel","updateChatDefaultBannedRights","default_banned_rights","_chatId","apiChats","saveApiChat","oldChat","participants_count","rights","defaultRights","action","isThread","creator","kicked","left","megagroup","admin_rights","banned_rights","myFlags","post_messages","delete_messages","broadcast","until_date","bind","good","about","channelId","input","getChannelInput","usersInputs","fwdLimit","fwd_limit","deleteChatUser","leaveChannel","leaveChat","deleteChannel","deleteChat","find","bool","inputFile","inputChatPhoto","file","participant","getParticipantPeerId","actor_id","qts","prev_participant","new_participant","keys","kicked_by","editBanned","view_messages","messagesChats","enabled","migrateChat","accumulate","arr","initialValue","reduce","acc","findAndSpliceAll","array","verify","out","findIndex","splice","forEachReverse","callback","insertInDescendSortedArray","element","property","pos","sortProperty","prev","next","len","filterUnique","pendingPtsUpdates","pendingSeqUpdates","syncPending","channelStates","attached","log","Warn","Log","debug","updateMessage","processOpts","seq","seqStart","seq_start","forceGetDifference","processUpdate","isOut","fromId","from_id","toId","message","fwd_from","reply_to","entities","pts","pts_count","Proxy","target","saveUpdatesState","us","nextSeq","pendingUpdatesData","saveUpdate","popPendingSeqUpdate","seqAwaiting","ptsAwaiting","clearTimeout","timeout","curState","getChannelState","curPts","goodPts","goodIndex","getDifference","first","wasSyncing","pts_total_limit","differenceResult","other_updates","new_messages","apiMessage","nextState","intermediate_state","justAName","channelState","getChannelDifference","addChannelState","lastPtsUpdateTime","toPeerId","fwdHeader","reason","hasUser","post","hasChat","popPts","popSeq","window","setTimeout","popPendingPtsUpdate","_state","newVersion","noErrorBox","stateResult","setUpdatesProcessor","setProxy","fetch","res","ok","reject","suffix","parseMarkdown","inbox_date","media","catch"],"mappings":"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","file":"3.ecfbd0f9b839f0b7d92f.chunk.js","sourcesContent":["export default function assumeType<T>(x: unknown): asserts x is T {\r\n return; // ¯\\_(ツ)_/¯\r\n}\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n * \n * Originally from:\n * https://github.com/zhukov/webogram\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\n * https://github.com/zhukov/webogram/blob/master/LICENSE\n */\n\nimport { processSearchText, ProcessSearchTextOptions } from '../helpers/cleanSearchText';\n\nexport default class SearchIndex<SearchWhat> {\n private fullTexts: Map<SearchWhat, string> = new Map();\n\n // minChars can be 0 because it requires at least one word (one symbol) to be found\n constructor(private options?: ProcessSearchTextOptions, private minChars = 0) {\n }\n\n public indexObject(id: SearchWhat, searchText: string) {\n /* if(searchIndex.fullTexts.hasOwnProperty(id)) {\n return false;\n } */\n\n if(this.options && searchText.trim()) {\n searchText = processSearchText(searchText, this.options);\n }\n\n if(!searchText) {\n this.fullTexts.delete(id);\n return false;\n }\n\n this.fullTexts.set(id, searchText);\n \n /* const shortIndexes = searchIndex.shortIndexes;\n searchText.split(' ').forEach((searchWord) => {\n let len = Math.min(searchWord.length, 3),\n wordPart, i;\n for(i = 1; i <= len; i++) {\n wordPart = searchWord.substr(0, i);\n if(shortIndexes[wordPart] === undefined) {\n shortIndexes[wordPart] = [id];\n } else {\n shortIndexes[wordPart].push(id);\n }\n }\n }); */\n }\n\n public search(query: string) {\n const fullTexts = this.fullTexts;\n //const shortIndexes = searchIndex.shortIndexes;\n\n if(this.options) {\n query = processSearchText(query, this.options);\n }\n\n const newFoundObjs: Array<{fullText: string, fullTextLength: number, what: SearchWhat, foundChars: number}> = [];\n const queryWords = query.split(' ');\n const queryWordsLength = queryWords.length;\n fullTexts.forEach((fullText, what) => {\n let found = true;\n let foundChars = 0;\n for(let i = 0; i < queryWordsLength; ++i) { // * verify that all words are found\n const word = queryWords[i];\n const idx = fullText.indexOf(word);\n if(idx === -1 || (idx !== 0 && fullText[idx - 1] !== ' ')) { // * search only from word beginning\n found = false;\n break;\n }\n\n foundChars += word.length;\n }\n\n if(found) {\n foundChars += queryWordsLength - 1;\n const fullTextLength = fullText.length;\n if(this.minChars <= foundChars || fullTextLength <= foundChars) {\n newFoundObjs.push({fullText, fullTextLength, what, foundChars});\n }\n }\n });\n\n newFoundObjs.sort((a, b) => a.fullTextLength - b.fullTextLength || b.foundChars - a.foundChars);\n\n //newFoundObjs.sort((a, b) => a.fullText.localeCompare(b.fullText));\n const newFoundObjs2: Set<SearchWhat> = new Set(newFoundObjs.map(o => o.what));\n\n /* const queryWords = query.split(' ');\n let foundArr: number[];\n for(let i = 0; i < queryWords.length; i++) {\n const newFound = shortIndexes[queryWords[i].substr(0, 3)];\n if(!newFound) {\n foundArr = [];\n break;\n }\n \n if(foundArr === undefined || foundArr.length > newFound.length) {\n foundArr = newFound;\n }\n }\n\n for(let j = 0; j < foundArr.length; j++) {\n let found = true;\n let searchText = fullTexts[foundArr[j]];\n for(let i = 0; i < queryWords.length; i++) {\n if(searchText.indexOf(queryWords[i]) === -1) {\n found = false;\n break;\n }\n }\n\n if(found) {\n newFoundObjs[foundArr[j]] = true;\n }\n } */\n\n return newFoundObjs2;\n }\n}\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nexport default function htmlToSpan(html: string) {\r\n const span = document.createElement('span');\r\n span.innerHTML = html;\r\n return span;\r\n}\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n * \n * Originally from:\n * https://github.com/zhukov/webogram\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\n * https://github.com/zhukov/webogram/blob/master/LICENSE\n */\n\nimport Config from \"../lib/config\";\n\nconst badCharsRe = /[`~!@#$%^&*()\\-_=+\\[\\]\\\\|{}'\";:\\/?.>,<]+/g;\nconst trimRe = /^\\s+|\\s$/g;\n\nexport function clearBadCharsAndTrim(text: string) {\n return text.replace(badCharsRe, '').replace(trimRe, '');\n}\n\nexport function latinizeString(text: string) {\n return text.replace(/[^A-Za-z0-9]/g, (ch) => {\n const latinizeCh = Config.LatinizeMap[ch];\n return latinizeCh !== undefined ? latinizeCh : ch;\n });\n}\n\nexport default function cleanSearchText(text: string, latinize = true) {\n const hasTag = text.charAt(0) === '%';\n text = clearBadCharsAndTrim(text);\n if(latinize) text = latinizeString(text);\n \n text = text.toLowerCase();\n if(hasTag) text = '%' + text;\n\n return text;\n}\n\nexport type ProcessSearchTextOptions = Partial<{\n clearBadChars: boolean,\n latinize: boolean,\n ignoreCase: boolean,\n includeTag: boolean\n}>;\n\nexport function processSearchText(text: string, options: ProcessSearchTextOptions = {}) {\n const hasTag = options.includeTag && text.charAt(0) === '%';\n if(options.clearBadChars) text = clearBadCharsAndTrim(text);\n if(options.latinize) text = latinizeString(text);\n if(options.ignoreCase) text = text.toLowerCase();\n if(hasTag) text = '%' + text;\n return text;\n}\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\n/**\r\n * Legacy Webogram's format, don't change dcID to camelCase. date is timestamp\r\n */\r\nexport type UserAuth = {dcID: number | string, date: number, id: number};\r\n\r\nexport const REPLIES_PEER_ID = 1271266957;\r\nexport const SERVICE_PEER_ID = 777000;\r\nexport const MUTE_UNTIL = 0x7FFFFFFF;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nexport default function cleanUsername(username: string) {\r\n return username && username.toLowerCase() || '';\r\n}\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n * \n * Originally from:\n * https://github.com/zhukov/webogram\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\n * https://github.com/zhukov/webogram/blob/master/LICENSE\n */\n\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\nimport { filterUnique } from \"../../helpers/array\";\nimport { CancellablePromise, deferredPromise } from \"../../helpers/cancellablePromise\";\nimport cleanSearchText from \"../../helpers/cleanSearchText\";\nimport cleanUsername from \"../../helpers/cleanUsername\";\nimport { tsNow } from \"../../helpers/date\";\nimport { formatPhoneNumber } from \"../../helpers/formatPhoneNumber\";\nimport { safeReplaceObject, isObject } from \"../../helpers/object\";\nimport { Chat, InputContact, InputMedia, InputUser, User as MTUser, UserProfilePhoto, UserStatus } from \"../../layer\";\nimport I18n, { i18n, LangPackKey } from \"../langPack\";\n//import apiManager from '../mtproto/apiManager';\nimport apiManager from '../mtproto/mtprotoworker';\nimport { REPLIES_PEER_ID, SERVICE_PEER_ID } from \"../mtproto/mtproto_config\";\nimport serverTimeManager from \"../mtproto/serverTimeManager\";\nimport { RichTextProcessor } from \"../richtextprocessor\";\nimport rootScope from \"../rootScope\";\nimport SearchIndex from \"../searchIndex\";\nimport apiUpdatesManager from \"./apiUpdatesManager\";\nimport appChatsManager from \"./appChatsManager\";\nimport appPeersManager from \"./appPeersManager\";\nimport appStateManager from \"./appStateManager\";\n\nexport type User = MTUser.user;\nexport type TopPeerType = 'correspondents' | 'bots_inline';\nexport type MyTopPeer = {id: number, rating: number};\n\nexport class AppUsersManager {\n private storage = appStateManager.storages.users;\n \n private users: {[userId: number]: User};\n private usernames: {[username: string]: number};\n private contactsIndex: SearchIndex<number>;\n private contactsFillPromise: CancellablePromise<Set<number>>;\n private contactsList: Set<number>;\n private updatedContactsList: boolean;\n \n private getTopPeersPromises: {[type in TopPeerType]?: Promise<MyTopPeer[]>};\n\n constructor() {\n this.clear(true);\n\n setInterval(this.updateUsersStatuses, 60000);\n\n rootScope.addEventListener('state_synchronized', this.updateUsersStatuses);\n\n rootScope.addMultipleEventsListeners({\n updateUserStatus: (update) => {\n const userId = update.user_id;\n const user = this.users[userId];\n if(user) {\n user.status = update.status;\n if(user.status) {\n if('expires' in user.status) {\n user.status.expires -= serverTimeManager.serverTimeOffset;\n }\n\n if('was_online' in user.status) {\n user.status.was_online -= serverTimeManager.serverTimeOffset;\n }\n }\n\n //user.sortStatus = this.getUserStatusForSort(user.status);\n rootScope.dispatchEvent('user_update', userId);\n this.setUserToStateIfNeeded(user);\n } //////else console.warn('No user by id:', userId);\n },\n\n updateUserPhoto: (update) => {\n const userId = update.user_id;\n const user = this.users[userId];\n if(user) {\n this.forceUserOnline(userId);\n\n if(update.photo._ === 'userProfilePhotoEmpty') {\n delete user.photo;\n } else {\n user.photo = safeReplaceObject(user.photo, update.photo);\n }\n\n this.setUserToStateIfNeeded(user);\n\n rootScope.dispatchEvent('user_update', userId);\n rootScope.dispatchEvent('avatar_update', userId);\n } else console.warn('No user by id:', userId);\n },\n\n updateUserName: (update) => {\n const userId = update.user_id;\n const user = this.users[userId];\n if(user) {\n this.forceUserOnline(userId);\n \n this.saveApiUser(Object.assign({}, user, {\n first_name: update.first_name,\n last_name: update.last_name,\n username: update.username\n }), true);\n }\n }\n });\n\n /* case 'updateContactLink':\n this.onContactUpdated(update.user_id, update.my_link._ === 'contactLinkContact');\n break; */\n\n rootScope.addEventListener('language_change', (e) => {\n const userId = this.getSelf().id;\n this.contactsIndex.indexObject(userId, this.getUserSearchText(userId));\n });\n\n appStateManager.getState().then((state) => {\n const users = appStateManager.storagesResults.users;\n if(users.length) {\n for(let i = 0, length = users.length; i < length; ++i) {\n const user = users[i];\n if(user) {\n this.users[user.id] = user;\n }\n }\n }\n\n const contactsList = state.contactsList;\n if(contactsList && Array.isArray(contactsList)) {\n contactsList.forEach(userId => {\n this.pushContact(userId);\n });\n\n if(contactsList.length) {\n this.contactsFillPromise = deferredPromise();\n this.contactsFillPromise.resolve(this.contactsList);\n }\n }\n\n appStateManager.addEventListener('peerNeeded', (peerId: number) => {\n if(peerId < 0 || this.storage.getFromCache(peerId)) {\n return;\n }\n\n this.storage.set({\n [peerId]: this.getUser(peerId)\n });\n });\n\n appStateManager.addEventListener('peerUnneeded', (peerId: number) => {\n if(peerId < 0 || !this.storage.getFromCache(peerId)) {\n return;\n }\n\n this.storage.delete(peerId);\n });\n });\n }\n\n public clear(init = false) {\n if(!init) {\n const users = appStateManager.storagesResults.users;\n for(const _userId in this.users) {\n const userId = +_userId;\n if(!userId) continue;\n if(!appStateManager.isPeerNeeded(userId)) {\n const user = this.users[userId];\n if(user.username) {\n delete this.usernames[cleanUsername(user.username)];\n }\n\n users.findAndSplice((user) => user.id === userId);\n this.storage.delete(userId);\n delete this.users[userId];\n }\n }\n } else {\n this.users = {};\n this.usernames = {};\n }\n \n this.getTopPeersPromises = {};\n this.contactsIndex = this.createSearchIndex();\n this.contactsFillPromise = undefined;\n this.contactsList = new Set();\n this.updatedContactsList = false;\n }\n\n private onContactsModified() {\n const contactsList = [...this.contactsList];\n appStateManager.pushToState('contactsList', contactsList);\n }\n\n public fillContacts() {\n if(this.contactsFillPromise && this.updatedContactsList) {\n return {\n cached: this.contactsFillPromise.isFulfilled,\n promise: this.contactsFillPromise\n };\n }\n\n this.updatedContactsList = true;\n\n const promise = deferredPromise<Set<number>>();\n apiManager.invokeApi('contacts.getContacts').then((result) => {\n if(result._ === 'contacts.contacts') {\n this.contactsList.clear();\n \n this.saveApiUsers(result.users);\n\n result.contacts.forEach((contact) => {\n this.pushContact(contact.user_id);\n });\n\n this.onContactsModified();\n\n this.contactsFillPromise = promise;\n }\n\n promise.resolve(this.contactsList);\n }, () => {\n this.updatedContactsList = false;\n });\n\n return {\n cached: this.contactsFillPromise?.isFulfilled,\n promise: this.contactsFillPromise || (this.contactsFillPromise = promise)\n };\n }\n\n public resolveUsername(username: string): Promise<Chat | User> {\n if(username[0] === '@') {\n username = username.slice(1);\n }\n\n username = username.toLowerCase();\n if(this.usernames[username]) {\n return Promise.resolve(this.users[this.usernames[username]]);\n }\n\n return apiManager.invokeApi('contacts.resolveUsername', {username}).then(resolvedPeer => {\n this.saveApiUsers(resolvedPeer.users);\n appChatsManager.saveApiChats(resolvedPeer.chats);\n\n return appPeersManager.getPeer(appPeersManager.getPeerId(resolvedPeer.peer));\n });\n }\n\n public pushContact(userId: number) {\n this.contactsList.add(userId);\n this.contactsIndex.indexObject(userId, this.getUserSearchText(userId));\n appStateManager.requestPeer(userId, 'contacts');\n }\n\n public getUserSearchText(id: number) {\n const user = this.users[id];\n if(!user) {\n return '';\n }\n\n const arr: string[] = [\n user.first_name,\n user.last_name,\n user.phone,\n user.username,\n user.pFlags.self ? I18n.format('SavedMessages', true) : '',\n user.pFlags.self ? 'Saved Messages' : ''\n ];\n\n return arr.filter(Boolean).join(' ');\n }\n\n public getContacts(query?: string, includeSaved = false, sortBy: 'name' | 'online' | 'none' = 'name') {\n return this.fillContacts().promise.then(_contactsList => {\n let contactsList = [..._contactsList];\n if(query) {\n const results = this.contactsIndex.search(query);\n const filteredContactsList = [...contactsList].filter(id => results.has(id));\n\n contactsList = filteredContactsList;\n }\n\n if(sortBy === 'name') {\n contactsList.sort((userId1, userId2) => {\n const sortName1 = (this.users[userId1] || {}).sortName || '';\n const sortName2 = (this.users[userId2] || {}).sortName || '';\n return sortName1.localeCompare(sortName2);\n });\n } else if(sortBy === 'online') {\n contactsList.sort((userId1, userId2) => {\n const status1 = appUsersManager.getUserStatusForSort(appUsersManager.getUser(userId1).status);\n const status2 = appUsersManager.getUserStatusForSort(appUsersManager.getUser(userId2).status);\n return status2 - status1;\n });\n }\n\n contactsList.findAndSplice(p => p === rootScope.myId);\n if(includeSaved) {\n if(this.testSelfSearch(query)) {\n contactsList.unshift(rootScope.myId);\n }\n }\n\n return contactsList;\n });\n }\n\n public toggleBlock(peerId: number, block: boolean) {\n return apiManager.invokeApiSingle(block ? 'contacts.block' : 'contacts.unblock', {\n id: appPeersManager.getInputPeerById(peerId)\n }).then(value => {\n if(value) {\n apiUpdatesManager.processLocalUpdate({\n _: 'updatePeerBlocked',\n peer_id: appPeersManager.getOutputPeer(peerId),\n blocked: block\n });\n }\n\n return value;\n });\n }\n\n public testSelfSearch(query: string) {\n const user = this.getSelf();\n const index = this.createSearchIndex();\n index.indexObject(user.id, this.getUserSearchText(user.id));\n return index.search(query).has(user.id);\n }\n\n private createSearchIndex() {\n return new SearchIndex<number>({\n clearBadChars: true,\n ignoreCase: true,\n latinize: true,\n includeTag: true\n });\n }\n\n public saveApiUsers(apiUsers: MTUser[], override?: boolean) {\n apiUsers.forEach((user) => this.saveApiUser(user, override));\n }\n\n public saveApiUser(user: MTUser, override?: boolean) {\n if(user._ === 'userEmpty') return;\n\n const userId = user.id;\n const oldUser = this.users[userId];\n\n // ! commented block can affect performance !\n // if(oldUser && !override) {\n // console.log('saveApiUser same');\n // return;\n // }\n\n if(user.pFlags === undefined) {\n user.pFlags = {};\n }\n\n if(user.pFlags.min && oldUser !== undefined) {\n return;\n }\n\n // * exclude from state\n // defineNotNumerableProperties(user, ['initials', 'num', 'rFirstName', 'rFullName', 'rPhone', 'sortName', 'sortStatus']);\n\n if(!oldUser || oldUser.username !== user.username) {\n if(oldUser?.username) {\n const oldSearchUsername = cleanUsername(oldUser.username);\n delete this.usernames[oldSearchUsername];\n }\n\n if(user.username) {\n const searchUsername = cleanUsername(user.username);\n this.usernames[searchUsername] = userId;\n }\n }\n\n if(!oldUser \n || oldUser.initials === undefined \n || oldUser.sortName === undefined \n || oldUser.first_name !== user.first_name \n || oldUser.last_name !== user.last_name) {\n const fullName = user.first_name + (user.last_name ? ' ' + user.last_name : '');\n\n user.sortName = user.pFlags.deleted ? '' : cleanSearchText(fullName, false); \n user.initials = RichTextProcessor.getAbbreviation(fullName);\n } else {\n user.sortName = oldUser.sortName;\n user.initials = oldUser.initials;\n }\n\n if(user.status) {\n if((user.status as UserStatus.userStatusOnline).expires) {\n (user.status as UserStatus.userStatusOnline).expires -= serverTimeManager.serverTimeOffset;\n }\n\n if((user.status as UserStatus.userStatusOffline).was_online) {\n (user.status as UserStatus.userStatusOffline).was_online -= serverTimeManager.serverTimeOffset;\n }\n }\n\n //user.sortStatus = user.pFlags.bot ? -1 : this.getUserStatusForSort(user.status);\n\n let changedPhoto = false, changedTitle = false;\n if(oldUser === undefined) {\n this.users[userId] = user;\n } else {\n if(user.first_name !== oldUser.first_name \n || user.last_name !== oldUser.last_name \n || user.username !== oldUser.username) {\n changedTitle = true;\n }\n\n const oldPhotoId = (oldUser.photo as UserProfilePhoto.userProfilePhoto)?.photo_id;\n const newPhotoId = (user.photo as UserProfilePhoto.userProfilePhoto)?.photo_id;\n if(oldPhotoId !== newPhotoId) {\n changedPhoto = true;\n }\n\n /* if(user.pFlags.bot && user.bot_info_version !== oldUser.bot_info_version) {\n \n } */\n\n const wasContact = !!oldUser.pFlags.contact;\n const newContact = !!user.pFlags.contact;\n\n safeReplaceObject(oldUser, user);\n rootScope.dispatchEvent('user_update', userId);\n\n if(wasContact !== newContact) {\n this.onContactUpdated(userId, newContact, wasContact);\n }\n }\n\n if(changedPhoto) {\n rootScope.dispatchEvent('avatar_update', user.id);\n }\n\n if(changedTitle) {\n rootScope.dispatchEvent('peer_title_edit', user.id);\n }\n\n this.setUserToStateIfNeeded(user);\n }\n\n public setUserToStateIfNeeded(user: User) {\n if(appStateManager.isPeerNeeded(user.id)) {\n this.storage.set({\n [user.id]: user\n });\n }\n }\n\n public formatUserPhone(phone: string) {\n return '+' + formatPhoneNumber(phone).formatted;\n }\n\n public isUserOnlineVisible(id: number) {\n return this.getUserStatusForSort(id) > 3;\n }\n\n public getUserStatusForSort(status: User['status'] | number) {\n if(typeof(status) === 'number') {\n status = this.getUser(status).status;\n }\n\n if(status) {\n const expires = status._ === 'userStatusOnline' ? status.expires : (status._ === 'userStatusOffline' ? status.was_online : 0);\n if(expires) {\n return expires;\n }\n\n /* const timeNow = tsNow(true);\n switch(status._) {\n case 'userStatusRecently':\n return timeNow - 86400 * 3;\n case 'userStatusLastWeek':\n return timeNow - 86400 * 7;\n case 'userStatusLastMonth':\n return timeNow - 86400 * 30;\n } */\n switch(status._) {\n case 'userStatusRecently':\n return 3;\n case 'userStatusLastWeek':\n return 2;\n case 'userStatusLastMonth':\n return 1;\n }\n }\n\n return 0;\n }\n\n public getUser(id: any): User {\n if(isObject(id)) {\n return id;\n }\n\n return this.users[id] || {id: id, pFlags: {deleted: true}, access_hash: ''} as User;\n }\n\n public getSelf() {\n return this.getUser(rootScope.myId);\n }\n\n public getUserStatusString(userId: number): HTMLElement {\n let key: LangPackKey;\n let args: any[];\n\n switch(userId) {\n case REPLIES_PEER_ID:\n key = 'Peer.RepliesNotifications';\n break;\n case SERVICE_PEER_ID:\n key = 'Peer.ServiceNotifications';\n break;\n default: {\n if(this.isBot(userId)) {\n key = 'Bot';\n break;\n }\n\n const user = this.getUser(userId);\n if(!user) {\n key = '' as any;\n break;\n }\n\n if(user.pFlags.support) {\n key = 'SupportStatus';\n break;\n }\n\n switch(user.status?._) {\n case 'userStatusRecently': {\n key = 'Lately';\n break;\n }\n \n case 'userStatusLastWeek': {\n key = 'WithinAWeek';\n break;\n }\n \n case 'userStatusLastMonth': {\n key = 'WithinAMonth';\n break;\n }\n \n case 'userStatusOffline': {\n const date = user.status.was_online;\n const now = Date.now() / 1000;\n \n if((now - date) < 60) {\n key = 'Peer.Status.justNow';\n } else if((now - date) < 3600) {\n key = 'Peer.Status.minAgo';\n const c = (now - date) / 60 | 0;\n args = [c];\n } else if(now - date < 86400) {\n key = 'LastSeen.HoursAgo';\n const c = (now - date) / 3600 | 0;\n args = [c];\n } else {\n key = 'Peer.Status.LastSeenAt';\n const d = new Date(date * 1000);\n args = [('0' + d.getDate()).slice(-2) + '.' + ('0' + (d.getMonth() + 1)).slice(-2), \n ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2)];\n }\n \n break;\n }\n \n case 'userStatusOnline': {\n key = 'Online';\n break;\n }\n \n default: {\n key = 'ALongTimeAgo';\n break;\n }\n }\n\n break;\n }\n }\n \n return i18n(key, args);\n }\n\n public isBot(id: number) {\n return this.users[id] && this.users[id].pFlags.bot;\n }\n\n public isContact(id: number) {\n return this.contactsList.has(id) || (this.users[id] && this.users[id].pFlags.contact);\n }\n \n public isRegularUser(id: number) {\n const user = this.users[id];\n return user && !this.isBot(id) && !user.pFlags.deleted && !user.pFlags.support;\n }\n\n public isNonContactUser(id: number) {\n return this.isRegularUser(id) && !this.isContact(id) && id !== rootScope.myId;\n }\n\n public hasUser(id: number, allowMin?: boolean) {\n const user = this.users[id];\n return isObject(user) && (allowMin || !user.pFlags.min);\n }\n\n public canSendToUser(id: number) {\n const user = this.getUser(id);\n return !user.pFlags.deleted && user.id !== REPLIES_PEER_ID;\n }\n\n public getUserPhoto(id: number) {\n const user = this.getUser(id);\n\n return user && user.photo || {\n _: 'userProfilePhotoEmpty'\n };\n }\n\n public getUserString(id: number) {\n const user = this.getUser(id);\n return 'u' + id + (user.access_hash ? '_' + user.access_hash : '');\n }\n\n public getUserInput(id: number): InputUser {\n const user = this.getUser(id);\n if(user.pFlags && user.pFlags.self) {\n return {_: 'inputUserSelf'};\n }\n\n return {\n _: 'inputUser',\n user_id: id,\n access_hash: user.access_hash\n };\n }\n\n public getContactMediaInput(id: number): InputMedia.inputMediaContact {\n const user = this.getUser(id);\n\n return {\n _: 'inputMediaContact',\n first_name: user.first_name,\n last_name: user.last_name,\n phone_number: user.phone,\n vcard: '',\n user_id: id\n };\n }\n\n public updateUsersStatuses = () => {\n const timestampNow = tsNow(true);\n for(const i in this.users) {\n const user = this.users[i];\n this.updateUserStatus(user, timestampNow);\n }\n };\n\n public updateUserStatus(user: MTUser.user, timestampNow = tsNow(true)) {\n if(user.status &&\n user.status._ === 'userStatusOnline' &&\n user.status.expires < timestampNow) {\n\n user.status = {_: 'userStatusOffline', was_online: user.status.expires};\n rootScope.dispatchEvent('user_update', user.id);\n\n this.setUserToStateIfNeeded(user);\n }\n }\n\n public forceUserOnline(id: number, eventTimestamp?: number) {\n if(this.isBot(id)) {\n return;\n }\n\n const timestamp = tsNow(true);\n const onlineTimeFor = 60;\n if(eventTimestamp) {\n if((timestamp - eventTimestamp) >= onlineTimeFor) {\n return;\n }\n } else if(apiUpdatesManager.updatesState.syncLoading) {\n return;\n }\n\n const user = this.getUser(id);\n if(user &&\n user.status &&\n user.status._ !== 'userStatusOnline' &&\n user.status._ !== 'userStatusEmpty' &&\n !user.pFlags.support &&\n !user.pFlags.deleted) {\n\n user.status = {\n _: 'userStatusOnline',\n expires: timestamp + onlineTimeFor\n };\n \n //user.sortStatus = this.getUserStatusForSort(user.status);\n rootScope.dispatchEvent('user_update', id);\n\n this.setUserToStateIfNeeded(user);\n }\n }\n\n public importContact(first_name: string, last_name: string, phone: string) {\n return this.importContacts([{\n first_name,\n last_name,\n phones: [phone]\n }]).then(userIds => {\n if(!userIds.length) {\n const error = new Error();\n (error as any).type = 'NO_USER';\n throw error;\n }\n\n return userIds[0];\n });\n }\n\n public importContacts(contacts: {phones: string[], first_name: string, last_name: string}[]) {\n const inputContacts: InputContact[] = [];\n\n for(let i = 0; i < contacts.length; ++i) {\n for(let j = 0; j < contacts[i].phones.length; ++j) {\n inputContacts.push({\n _: 'inputPhoneContact',\n client_id: (i << 16 | j).toString(10),\n phone: contacts[i].phones[j],\n first_name: contacts[i].first_name,\n last_name: contacts[i].last_name\n });\n }\n }\n\n return apiManager.invokeApi('contacts.importContacts', {\n contacts: inputContacts\n }).then((importedContactsResult) => {\n this.saveApiUsers(importedContactsResult.users);\n\n const userIds = importedContactsResult.imported.map((importedContact) => {\n this.onContactUpdated(importedContact.user_id, true);\n return importedContact.user_id;\n });\n\n return userIds;\n });\n }\n\n public getTopPeers(type: TopPeerType) {\n if(this.getTopPeersPromises[type]) return this.getTopPeersPromises[type];\n\n return this.getTopPeersPromises[type] = appStateManager.getState().then((state) => {\n const cached = state.topPeersCache[type];\n if(cached && (cached.cachedTime + 86400e3) > Date.now() && cached.peers) {\n return cached.peers;\n }\n\n return apiManager.invokeApi('contacts.getTopPeers', {\n [type]: true,\n offset: 0,\n limit: 15,\n hash: 0\n }).then((result) => {\n let topPeers: MyTopPeer[] = [];\n if(result._ === 'contacts.topPeers') {\n //console.log(result);\n this.saveApiUsers(result.users);\n appChatsManager.saveApiChats(result.chats);\n\n if(result.categories.length) {\n topPeers = result.categories[0].peers.map((topPeer) => {\n const peerId = appPeersManager.getPeerId(topPeer.peer);\n appStateManager.requestPeer(peerId, 'topPeer');\n return {id: peerId, rating: topPeer.rating};\n });\n }\n }\n \n state.topPeersCache[type] = {\n peers: topPeers,\n cachedTime: Date.now()\n };\n appStateManager.pushToState('topPeersCache', state.topPeersCache);\n \n return topPeers;\n });\n });\n }\n\n public getBlocked(offset = 0, limit = 0) {\n return apiManager.invokeApiSingle('contacts.getBlocked', {offset, limit}).then(contactsBlocked => {\n this.saveApiUsers(contactsBlocked.users);\n appChatsManager.saveApiChats(contactsBlocked.chats);\n const count = contactsBlocked._ === 'contacts.blocked' ? contactsBlocked.users.length + contactsBlocked.chats.length : contactsBlocked.count;\n\n const peerIds = contactsBlocked.users.map(u => u.id).concat(contactsBlocked.chats.map(c => -c.id));\n\n return {count, peerIds};\n });\n }\n\n /* public searchContacts(query: string, limit = 20) {\n return Promise.all([\n this.getContacts(query),\n apiManager.invokeApi('contacts.search', {\n q: query,\n limit\n })\n ]).then(results => {\n const [myContacts, peers] = results;\n\n this.saveApiUsers(peers.users);\n appChatsManager.saveApiChats(peers.chats);\n\n // * contacts.search returns duplicates in my_results\n const myResults = new Set(myContacts.concat(peers.my_results.map(p => appPeersManager.getPeerID(p))));\n\n const out = {\n my_results: [...myResults].slice(0, limit),\n results: peers.results.map(p => appPeersManager.getPeerID(p))\n };\n\n return out;\n });\n } */\n public searchContacts(query: string, limit = 20) {\n return apiManager.invokeApiCacheable('contacts.search', {\n q: query,\n limit\n }, {cacheSeconds: 60}).then(peers => {\n this.saveApiUsers(peers.users);\n appChatsManager.saveApiChats(peers.chats);\n\n const out = {\n my_results: filterUnique(peers.my_results.map(p => appPeersManager.getPeerId(p))), // ! contacts.search returns duplicates in my_results\n results: peers.results.map(p => appPeersManager.getPeerId(p))\n };\n\n return out;\n });\n }\n\n private onContactUpdated(userId: number, isContact: boolean, curIsContact = this.isContact(userId)) {\n if(isContact !== curIsContact) {\n if(isContact) {\n this.pushContact(userId);\n } else {\n this.contactsList.delete(userId);\n }\n\n this.onContactsModified();\n\n rootScope.dispatchEvent('contacts_update', userId);\n }\n }\n\n public updateUsername(username: string) {\n return apiManager.invokeApi('account.updateUsername', {\n username\n }).then((user) => {\n this.saveApiUser(user);\n });\n }\n\n public setUserStatus(userId: number, offline: boolean) {\n if(this.isBot(userId)) {\n return;\n }\n\n const user = this.users[userId];\n if(user) {\n const status: any = offline ? {\n _: 'userStatusOffline',\n was_online: tsNow(true)\n } : {\n _: 'userStatusOnline',\n expires: tsNow(true) + 500\n };\n\n user.status = status;\n //user.sortStatus = this.getUserStatusForSort(user.status);\n rootScope.dispatchEvent('user_update', userId);\n }\n }\n\n public addContact(userId: number, first_name: string, last_name: string, phone: string, showPhone?: true) {\n /* if(!userId) {\n return this.importContacts([{\n first_name,\n last_name,\n phones: [phone]\n }]);\n } */\n\n return apiManager.invokeApi('contacts.addContact', {\n id: this.getUserInput(userId),\n first_name,\n last_name,\n phone,\n add_phone_privacy_exception: showPhone\n }).then((updates) => {\n apiUpdatesManager.processUpdateMessage(updates, {override: true});\n\n this.onContactUpdated(userId, true);\n });\n }\n\n public deleteContacts(userIds: number[]) {\n return apiManager.invokeApi('contacts.deleteContacts', {\n id: userIds.map(userId => this.getUserInput(userId))\n }).then((updates) => {\n apiUpdatesManager.processUpdateMessage(updates, {override: true});\n\n userIds.forEach(userId => {\n this.onContactUpdated(userId, false);\n });\n });\n }\n}\n\nconst appUsersManager = new AppUsersManager();\nMOUNT_CLASS_TO.appUsersManager = appUsersManager;\nexport default appUsersManager\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport type { ChatPhoto, DialogPeer, InputDialogPeer, InputNotifyPeer, InputPeer, Peer, Update, UserProfilePhoto } from \"../../layer\";\r\nimport type { LangPackKey } from \"../langPack\";\r\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\r\nimport { isObject } from \"../../helpers/object\";\r\nimport { RichTextProcessor } from \"../richtextprocessor\";\r\nimport rootScope from \"../rootScope\";\r\nimport appChatsManager from \"./appChatsManager\";\r\nimport appUsersManager from \"./appUsersManager\";\r\nimport I18n from '../langPack';\r\n\r\n// https://github.com/eelcohn/Telegram-API/wiki/Calculating-color-for-a-Telegram-user-on-IRC\r\n/*\r\n HTML-color IRC-color Description\r\n #c03d33 4 red\r\n #4fad2d 3 green\r\n #d09306 7 yellow\r\n #168acd 10 blue\r\n #8544d6 6 purple\r\n #cd4073 13 pink\r\n #2996ad 11 sea\r\n #ce671b 5 orange\r\n */\r\nconst DialogColorsFg = ['#fc5c51', '#0fb297', '#d09306', '#3d72ed', '#895dd5', '#cd4073', '#00c1a6', '#fa790f'];\r\nconst DialogColors = ['red', 'green', 'yellow', 'blue', 'violet', 'pink', 'cyan', 'orange'];\r\nconst DialogColorsMap = [0, 7, 4, 1, 6, 3, 5];\r\n\r\nexport type PeerType = 'channel' | 'chat' | 'megagroup' | 'group' | 'saved';\r\nexport class AppPeersManager {\r\n /* public savePeerInstance(peerId: number, instance: any) {\r\n if(peerId < 0) appChatsManager.saveApiChat(instance);\r\n else appUsersManager.saveApiUser(instance);\r\n } */\r\n\r\n public canPinMessage(peerId: number) {\r\n return peerId > 0 || appChatsManager.hasRights(-peerId, 'pin_messages');\r\n }\r\n\r\n public getPeerPhoto(peerId: number): UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto {\r\n const photo = peerId > 0\r\n ? appUsersManager.getUserPhoto(peerId)\r\n : appChatsManager.getChatPhoto(-peerId);\r\n\r\n return photo._ !== 'chatPhotoEmpty' && photo._ !== 'userProfilePhotoEmpty' ? photo : null;\r\n }\r\n\r\n public getPeerMigratedTo(peerId: number) {\r\n if(peerId >= 0) {\r\n return false;\r\n }\r\n\r\n let chat = appChatsManager.getChat(-peerId);\r\n if(chat && chat.migrated_to && chat.pFlags.deactivated) {\r\n return this.getPeerId(chat.migrated_to);\r\n }\r\n \r\n return false;\r\n }\r\n\r\n public getPeerTitle(peerId: number | any, plainText = false, onlyFirstName = false) {\r\n if(!peerId) {\r\n peerId = rootScope.myId;\r\n }\r\n \r\n let peer: any = {}; \r\n if(!isObject(peerId)) {\r\n peer = this.getPeer(peerId);\r\n } else peer = peerId;\r\n\r\n let title = '';\r\n if(peerId > 0) {\r\n if(peer.first_name) title += peer.first_name;\r\n if(peer.last_name && (!onlyFirstName || !title)) title += ' ' + peer.last_name;\r\n \r\n if(!title) title = peer.pFlags.deleted ? I18n.format('HiddenName', true) : peer.username;\r\n else title = title.trim();\r\n } else {\r\n title = peer.title;\r\n\r\n if(onlyFirstName) {\r\n title = title.split(' ')[0];\r\n }\r\n }\r\n \r\n return plainText ? title : RichTextProcessor.wrapEmojiText(title);\r\n }\r\n \r\n public getOutputPeer(peerId: number): Peer {\r\n if(peerId > 0) {\r\n return {_: 'peerUser', user_id: peerId};\r\n }\r\n\r\n let chatId = -peerId;\r\n if(appChatsManager.isChannel(chatId)) {\r\n return {_: 'peerChannel', channel_id: chatId};\r\n }\r\n\r\n return {_: 'peerChat', chat_id: chatId};\r\n }\r\n\r\n public getPeerString(peerId: number) {\r\n if(peerId > 0) {\r\n return appUsersManager.getUserString(peerId);\r\n }\r\n return appChatsManager.getChatString(-peerId);\r\n }\r\n\r\n public getPeerUsername(peerId: number): string {\r\n if(peerId > 0) {\r\n return appUsersManager.getUser(peerId).username || '';\r\n }\r\n return appChatsManager.getChat(-peerId).username || '';\r\n }\r\n\r\n public getPeer(peerId: number) {\r\n return peerId > 0\r\n ? appUsersManager.getUser(peerId)\r\n : appChatsManager.getChat(-peerId)\r\n }\r\n\r\n public getPeerId(peerId: Peer | InputPeer | number | string): number {\r\n if(typeof(peerId) === 'number') return peerId;\r\n else if(isObject(peerId)) return (peerId as Peer.peerUser).user_id || -((peerId as Peer.peerChannel).channel_id || (peerId as Peer.peerChat).chat_id);\r\n else if(!peerId) return 0;\r\n \r\n const isUser = (peerId as string).charAt(0) === 'u';\r\n const peerParams = (peerId as string).substr(1).split('_');\r\n\r\n return isUser ? +peerParams[0] : -peerParams[0] || 0;\r\n }\r\n\r\n public getDialogPeer(peerId: number): DialogPeer {\r\n return {\r\n _: 'dialogPeer',\r\n peer: this.getOutputPeer(peerId)\r\n };\r\n }\r\n\r\n public isChannel(peerId: number): boolean {\r\n return (peerId < 0) && appChatsManager.isChannel(-peerId);\r\n }\r\n\r\n public isMegagroup(peerId: number) {\r\n return (peerId < 0) && appChatsManager.isMegagroup(-peerId);\r\n }\r\n\r\n public isAnyGroup(peerId: number): boolean {\r\n return (peerId < 0) && !appChatsManager.isBroadcast(-peerId);\r\n }\r\n\r\n public isBroadcast(peerId: number): boolean {\r\n return this.isChannel(peerId) && !this.isMegagroup(peerId);\r\n }\r\n\r\n public isBot(peerId: number): boolean {\r\n return (peerId > 0) && appUsersManager.isBot(peerId);\r\n }\r\n\r\n /* public getInputPeer(peerString: string): InputPeer {\r\n var firstChar = peerString.charAt(0);\r\n var peerParams = peerString.substr(1).split('_');\r\n let id = +peerParams[0];\r\n\r\n if(firstChar === 'u') {\r\n //appUsersManager.saveUserAccess(id, peerParams[1]);\r\n\r\n return {\r\n _: 'inputPeerUser',\r\n user_id: id,\r\n access_hash: peerParams[1]\r\n };\r\n } else if(firstChar === 'c' || firstChar === 's') {\r\n //appChatsManager.saveChannelAccess(id, peerParams[1]);\r\n if(firstChar === 's') {\r\n appChatsManager.saveIsMegagroup(id);\r\n }\r\n\r\n return {\r\n _: 'inputPeerChannel',\r\n channel_id: id,\r\n access_hash: peerParams[1] || '0'\r\n };\r\n } else {\r\n return {\r\n _: 'inputPeerChat',\r\n chat_id: id\r\n };\r\n }\r\n } */\r\n\r\n public getInputNotifyPeerById(peerId: number, ignorePeerId: true): Exclude<InputNotifyPeer, InputNotifyPeer.inputNotifyPeer>;\r\n public getInputNotifyPeerById(peerId: number, ignorePeerId?: false): InputNotifyPeer.inputNotifyPeer;\r\n public getInputNotifyPeerById(peerId: number, ignorePeerId?: boolean): InputNotifyPeer {\r\n if(ignorePeerId) {\r\n if(peerId > 0) {\r\n return {_: 'inputNotifyUsers'};\r\n } else {\r\n if(appPeersManager.isBroadcast(peerId)) {\r\n return {_: 'inputNotifyBroadcasts'};\r\n } else {\r\n return {_: 'inputNotifyChats'};\r\n }\r\n }\r\n } else {\r\n return {\r\n _: 'inputNotifyPeer', \r\n peer: this.getInputPeerById(peerId)\r\n };\r\n }\r\n }\r\n\r\n public getInputPeerById(peerId: number): InputPeer {\r\n if(!peerId) {\r\n return {_: 'inputPeerEmpty'};\r\n }\r\n\r\n if(peerId < 0) {\r\n const chatId = -peerId;\r\n if(!appChatsManager.isChannel(chatId)) {\r\n return appChatsManager.getChatInputPeer(chatId);\r\n } else {\r\n return appChatsManager.getChannelInputPeer(chatId);\r\n }\r\n }\r\n\r\n return {\r\n _: 'inputPeerUser',\r\n user_id: peerId,\r\n access_hash: appUsersManager.getUser(peerId).access_hash\r\n };\r\n }\r\n\r\n public getInputDialogPeerById(peerId: number): InputDialogPeer {\r\n return {\r\n _: 'inputDialogPeer',\r\n peer: this.getInputPeerById(peerId)\r\n }\r\n }\r\n\r\n public getPeerColorById(peerId: number, pic = true) {\r\n if(!peerId) return '';\r\n\r\n const idx = DialogColorsMap[(peerId < 0 ? -peerId : peerId) % 7];\r\n const color = (pic ? DialogColors : DialogColorsFg)[idx];\r\n return color;\r\n }\r\n\r\n public getPeerSearchText(peerId: number) {\r\n let text;\r\n if(peerId > 0) {\r\n text = '%pu ' + appUsersManager.getUserSearchText(peerId);\r\n } else if(peerId < 0) {\r\n const chat = appChatsManager.getChat(-peerId);\r\n text = '%pg ' + (chat.title || '');\r\n }\r\n return text;\r\n }\r\n\r\n public getDialogType(peerId: number): PeerType {\r\n if(appPeersManager.isMegagroup(peerId)) {\r\n return 'megagroup';\r\n } else if(appPeersManager.isChannel(peerId)) {\r\n return 'channel';\r\n } else if(peerId < 0) {\r\n return 'group';\r\n } else {\r\n return peerId === rootScope.myId ? 'saved' : 'chat';\r\n }\r\n }\r\n\r\n public getDeleteButtonText(peerId: number): LangPackKey {\r\n switch(this.getDialogType(peerId)) {\r\n case 'channel':\r\n return appChatsManager.hasRights(-peerId, 'delete_chat') ? 'ChannelDelete' : 'ChatList.Context.LeaveChannel';\r\n\r\n case 'megagroup':\r\n case 'group':\r\n return appChatsManager.hasRights(-peerId, 'delete_chat') ? 'DeleteMega' : 'ChatList.Context.LeaveGroup';\r\n \r\n default:\r\n return 'ChatList.Context.DeleteChat';\r\n }\r\n }\r\n}\r\n\r\nconst appPeersManager = new AppPeersManager();\r\nMOUNT_CLASS_TO.appPeersManager = appPeersManager;\r\nexport default appPeersManager;\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n * \n * Originally from:\n * https://github.com/zhukov/webogram\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\n * https://github.com/zhukov/webogram/blob/master/LICENSE\n */\n\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\nimport { isObject, safeReplaceObject, copy, deepEqual } from \"../../helpers/object\";\nimport { ChannelParticipant, Chat, ChatAdminRights, ChatBannedRights, ChatParticipant, ChatPhoto, InputChannel, InputChatPhoto, InputFile, InputPeer, Update, Updates } from \"../../layer\";\nimport apiManagerProxy from \"../mtproto/mtprotoworker\";\nimport apiManager from '../mtproto/mtprotoworker';\nimport { RichTextProcessor } from \"../richtextprocessor\";\nimport rootScope from \"../rootScope\";\nimport apiUpdatesManager from \"./apiUpdatesManager\";\nimport appPeersManager from \"./appPeersManager\";\nimport appStateManager from \"./appStateManager\";\nimport appUsersManager from \"./appUsersManager\";\n\nexport type Channel = Chat.channel;\n\nexport type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags'] | 'change_type' | 'change_permissions' | 'delete_chat' | 'view_participants';\n\nexport class AppChatsManager {\n private storage = appStateManager.storages.chats;\n \n private chats: {[id: number]: Chat.channel | Chat.chat | any};\n //private usernames: any;\n //private channelAccess: any;\n //private megagroups: {[id: number]: true};\n\n constructor() {\n this.clear(true);\n\n rootScope.addMultipleEventsListeners({\n /* updateChannel: (update) => {\n const channelId = update.channel_id;\n //console.log('updateChannel:', update);\n rootScope.broadcast('channel_settings', {channelId});\n }, */\n\n updateChannelParticipant: (update) => {\n apiManagerProxy.clearCache('channels.getParticipants', (params) => {\n return (params.channel as InputChannel.inputChannel).channel_id === update.channel_id;\n });\n },\n\n updateChatDefaultBannedRights: (update) => {\n const chatId = -appPeersManager.getPeerId(update.peer);\n const chat: Chat.chat = this.chats[chatId];\n if(chat) {\n chat.default_banned_rights = update.default_banned_rights;\n rootScope.dispatchEvent('chat_update', chatId);\n }\n }\n });\n\n appStateManager.getState().then((state) => {\n const chats = appStateManager.storagesResults.chats;\n if(chats.length) {\n for(let i = 0, length = chats.length; i < length; ++i) {\n const chat = chats[i];\n if(chat) {\n this.chats[chat.id] = chat;\n }\n }\n }\n\n appStateManager.addEventListener('peerNeeded', (peerId: number) => {\n if(peerId > 0 || this.storage.getFromCache(-peerId)) {\n return;\n }\n\n this.storage.set({\n [-peerId]: this.getChat(-peerId)\n });\n });\n\n appStateManager.addEventListener('peerUnneeded', (peerId: number) => {\n if(peerId > 0 || !this.storage.getFromCache(-peerId)) {\n return;\n }\n\n this.storage.delete(-peerId);\n });\n });\n }\n\n public clear(init = false) {\n if(!init) {\n const chats = appStateManager.storagesResults.chats;\n for(const _chatId in this.chats) {\n const chatId = +_chatId;\n if(!chatId) continue;\n if(!appStateManager.isPeerNeeded(-chatId)) {\n /* const chat = this.chats[chatId];\n if(chat.username) {\n delete this.usernames[cleanUsername(chat.username)];\n } */\n \n chats.findAndSplice((chat) => chat.id === chatId);\n this.storage.delete(chatId);\n delete this.chats[chatId];\n }\n }\n } else {\n this.chats = {};\n }\n }\n\n public saveApiChats(apiChats: any[], override?: boolean) {\n apiChats.forEach(chat => this.saveApiChat(chat, override));\n }\n\n public saveApiChat(chat: Chat, override?: boolean) {\n if(chat._ === 'chatEmpty') return;\n /* if(chat._ !== 'chat' && chat._ !== 'channel') {\n return;\n } */\n \n // * exclude from state\n // defineNotNumerableProperties(chat, ['rTitle', 'initials']);\n\n const oldChat: Exclude<Chat, Chat.chatEmpty> = this.chats[chat.id];\n\n /* if(oldChat && !override) {\n return;\n } */\n\n if((chat as Chat.chat).pFlags === undefined) {\n (chat as Chat.chat).pFlags = {};\n }\n\n if((chat as Chat.channel).pFlags.min && oldChat !== undefined) {\n return;\n }\n\n chat.initials = RichTextProcessor.getAbbreviation(chat.title);\n\n if(chat._ === 'channel' &&\n chat.participants_count === undefined &&\n oldChat !== undefined &&\n (oldChat as Chat.channel).participants_count) {\n chat.participants_count = (oldChat as Chat.channel).participants_count;\n }\n\n /* if(chat.username) {\n let searchUsername = searchIndexManager.cleanUsername(chat.username);\n this.usernames[searchUsername] = chat.id;\n } */\n\n let changedPhoto = false, changedTitle = false;\n if(oldChat === undefined) {\n this.chats[chat.id] = chat;\n } else {\n const oldPhotoId = ((oldChat as Chat.chat).photo as ChatPhoto.chatPhoto)?.photo_id;\n const newPhotoId = ((chat as Chat.chat).photo as ChatPhoto.chatPhoto)?.photo_id;\n if(oldPhotoId !== newPhotoId) {\n changedPhoto = true;\n }\n\n if(oldChat.title !== chat.title) {\n changedTitle = true;\n }\n\n safeReplaceObject(oldChat, chat);\n rootScope.dispatchEvent('chat_update', chat.id);\n }\n\n if(changedPhoto) {\n rootScope.dispatchEvent('avatar_update', -chat.id);\n }\n\n if(changedTitle) {\n rootScope.dispatchEvent('peer_title_edit', -chat.id);\n }\n\n if(appStateManager.isPeerNeeded(-chat.id)) {\n this.storage.set({\n [chat.id]: chat\n });\n }\n }\n\n public getChat(id: number) {\n if(id < 0) id = -id;\n return this.chats[id] || {_: 'chatEmpty', id, deleted: true, access_hash: '', pFlags: {}/* this.channelAccess[id] */};\n }\n\n public combineParticipantBannedRights(id: number, rights: ChatBannedRights) {\n const chat: Chat.channel = this.getChat(id);\n\n if(chat.default_banned_rights) {\n rights = copy(rights);\n const defaultRights = chat.default_banned_rights.pFlags;\n for(let i in defaultRights) {\n // @ts-ignore\n rights.pFlags[i] = defaultRights[i];\n }\n }\n\n return rights;\n }\n\n // * creator can still send messages to left channel. so this function shows server rights. see canSendToPeer for local rights in messages manager.\n public hasRights(id: number, action: ChatRights, rights?: ChatAdminRights | ChatBannedRights, isThread?: boolean) {\n const chat: Chat = this.getChat(id);\n if(chat._ === 'chatEmpty') return false;\n\n if((chat as Chat.chat).pFlags.deactivated && action !== 'view_messages') {\n return false;\n }\n\n if((chat as Chat.chat).pFlags.creator && rights === undefined) {\n return true;\n }\n\n if(chat._ === 'chatForbidden' ||\n chat._ === 'channelForbidden' ||\n (chat as Chat.chat).pFlags.kicked ||\n (chat.pFlags.left && !(chat as Chat.channel).pFlags.megagroup)) {\n return false;\n }\n\n if(!rights) {\n rights = chat.admin_rights || (chat as Chat.channel).banned_rights || chat.default_banned_rights;\n\n if(!rights) {\n return false;\n }\n }\n\n let myFlags: Partial<{[flag in keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags']]: true}> = {};\n if(rights) {\n myFlags = rights.pFlags as any;\n }\n\n switch(action) {\n case 'embed_links':\n case 'send_games':\n case 'send_gifs':\n case 'send_inline':\n case 'send_media':\n case 'send_messages':\n case 'send_polls':\n case 'send_stickers': {\n if(!isThread && chat.pFlags.left) {\n return false;\n }\n\n if(rights._ === 'chatBannedRights' && myFlags[action]) {\n return false;\n }\n\n if(chat._ === 'channel') {\n if(!chat.pFlags.megagroup && !myFlags.post_messages) {\n return false;\n }\n }\n\n break;\n }\n\n // * revoke foreign messages\n case 'delete_messages': {\n return !!myFlags.delete_messages;\n }\n\n case 'pin_messages': {\n return rights._ === 'chatAdminRights' ? myFlags[action] || !!myFlags.post_messages : !myFlags[action];\n }\n\n case 'invite_users':\n case 'change_info': {\n return rights._ === 'chatAdminRights' ? myFlags[action] : !myFlags[action];\n }\n\n // * only creator can do that\n case 'change_type':\n case 'delete_chat': {\n return false;\n }\n\n case 'change_permissions': {\n return rights._ === 'chatAdminRights' && myFlags['ban_users'];\n }\n\n case 'view_participants': {\n return !!(chat._ === 'chat' || !chat.pFlags.broadcast || chat.pFlags.creator || chat.admin_rights);\n }\n }\n\n return true;\n }\n\n public editChatDefaultBannedRights(id: number, banned_rights: ChatBannedRights) {\n const chat: Chat.chat = this.getChat(id);\n if(chat.default_banned_rights) {\n if(chat.default_banned_rights.until_date === banned_rights.until_date && deepEqual(chat.default_banned_rights.pFlags, banned_rights.pFlags)) {\n return Promise.resolve();\n }\n }\n \n return apiManager.invokeApi('messages.editChatDefaultBannedRights', {\n peer: appPeersManager.getInputPeerById(-id),\n banned_rights\n }).then(this.onChatUpdated.bind(this, id));\n }\n\n /* public resolveUsername(username: string) {\n return this.usernames[username] || 0;\n } */\n\n /* public saveChannelAccess(id: number, accessHash: string) {\n this.channelAccess[id] = accessHash;\n } */\n\n /* public saveIsMegagroup(id: number) {\n this.megagroups[id] = true;\n } */\n\n public isChannel(id: number) {\n const chat = this.chats[id];\n return chat && (chat._ === 'channel' || chat._ === 'channelForbidden')/* || this.channelAccess[id] */;\n }\n\n public isMegagroup(id: number) {\n /* if(this.megagroups[id]) {\n return true;\n } */\n\n const chat = this.chats[id];\n return chat && chat._ === 'channel' && chat.pFlags.megagroup;\n }\n\n public isBroadcast(id: number) {\n return this.isChannel(id) && !this.isMegagroup(id);\n }\n\n public isInChat(id: number) {\n let good = true;\n const chat: Chat = this.getChat(id);\n if(chat._ === 'channelForbidden' \n || chat._ === 'chatForbidden' \n || chat._ === 'chatEmpty' \n || (chat as Chat.chat).pFlags.left \n || (chat as Chat.chat).pFlags.kicked \n || (chat as Chat.chat).pFlags.deactivated) {\n good = false;\n }\n\n return good;\n }\n\n public getChannelInput(id: number): InputChannel {\n const chat: Chat = this.getChat(id);\n if(chat._ === 'chatEmpty' || !(chat as Chat.channel).access_hash) {\n return {\n _: 'inputChannelEmpty'\n };\n } else {\n return {\n _: 'inputChannel',\n channel_id: id,\n access_hash: (chat as Chat.channel).access_hash/* || this.channelAccess[id] */ || '0'\n };\n }\n }\n\n public getChatInputPeer(id: number): InputPeer.inputPeerChat {\n return {\n _: 'inputPeerChat',\n chat_id: id\n };\n }\n\n public getChannelInputPeer(id: number): InputPeer.inputPeerChannel {\n return {\n _: 'inputPeerChannel',\n channel_id: id,\n access_hash: this.getChat(id).access_hash/* || this.channelAccess[id] */ || 0\n };\n }\n\n public hasChat(id: number, allowMin?: true) {\n const chat = this.chats[id]\n return isObject(chat) && (allowMin || !chat.pFlags.min);\n }\n\n public getChatPhoto(id: number) {\n const chat: Chat.chat = this.getChat(id);\n\n return chat && chat.photo || {\n _: 'chatPhotoEmpty'\n };\n }\n\n public getChatString(id: number) {\n const chat = this.getChat(id);\n if(this.isChannel(id)) {\n return (this.isMegagroup(id) ? 's' : 'c') + id + '_' + chat.access_hash;\n }\n return 'g' + id;\n }\n\n /* public wrapForFull(id: number, fullChat: any) {\n const chatFull = copy(fullChat);\n const chat = this.getChat(id);\n\n if(!chatFull.participants_count) {\n chatFull.participants_count = chat.participants_count;\n }\n\n if(chatFull.participants &&\n chatFull.participants._ === 'chatParticipants') {\n chatFull.participants.participants = this.wrapParticipants(id, chatFull.participants.participants);\n }\n\n if(chatFull.about) {\n chatFull.rAbout = RichTextProcessor.wrapRichText(chatFull.about, {noLinebreaks: true});\n }\n\n //chatFull.peerString = this.getChatString(id);\n chatFull.chat = chat;\n\n return chatFull;\n }\n\n public wrapParticipants(id: number, participants: any[]) {\n const chat = this.getChat(id);\n const myId = appUsersManager.getSelf().id;\n if(this.isChannel(id)) {\n const isAdmin = chat.pFlags.creator;\n participants.forEach((participant) => {\n participant.canLeave = myId === participant.user_id;\n participant.canKick = isAdmin && participant._ === 'channelParticipant';\n\n // just for order by last seen\n participant.user = appUsersManager.getUser(participant.user_id);\n });\n } else {\n const isAdmin = chat.pFlags.creator || chat.pFlags.admins_enabled && chat.pFlags.admin;\n participants.forEach((participant) => {\n participant.canLeave = myId === participant.user_id;\n participant.canKick = !participant.canLeave && (\n chat.pFlags.creator ||\n participant._ === 'chatParticipant' && (isAdmin || myId === participant.inviter_id)\n );\n\n // just for order by last seen\n participant.user = appUsersManager.getUser(participant.user_id);\n });\n }\n\n return participants;\n } */\n\n public createChannel(title: string, about: string): Promise<number> {\n return apiManager.invokeApi('channels.createChannel', {\n broadcast: true,\n title,\n about\n }).then((updates) => {\n apiUpdatesManager.processUpdateMessage(updates);\n\n const channelId = (updates as any).chats[0].id;\n rootScope.dispatchEvent('history_focus', {peerId: -channelId});\n\n return channelId;\n });\n }\n\n public inviteToChannel(id: number, userIds: number[]) {\n const input = this.getChannelInput(id);\n const usersInputs = userIds.map(u => appUsersManager.getUserInput(u));\n\n return apiManager.invokeApi('channels.inviteToChannel', {\n channel: input,\n users: usersInputs\n }).then(this.onChatUpdated.bind(this, id));\n }\n\n public createChat(title: string, userIds: number[]): Promise<number> {\n return apiManager.invokeApi('messages.createChat', {\n users: userIds.map(u => appUsersManager.getUserInput(u)),\n title\n }).then(updates => {\n apiUpdatesManager.processUpdateMessage(updates);\n\n const chatId = (updates as any as Updates.updates).chats[0].id;\n rootScope.dispatchEvent('history_focus', {peerId: -chatId});\n\n return chatId;\n });\n }\n\n private onChatUpdated = (chatId: number, updates?: any) => {\n //console.log('onChatUpdated', chatId, updates);\n\n apiUpdatesManager.processUpdateMessage(updates);\n if(updates?.updates?.length && this.isChannel(chatId)) {\n rootScope.dispatchEvent('invalidate_participants', chatId);\n }\n };\n\n public leaveChannel(id: number) {\n return apiManager.invokeApi('channels.leaveChannel', {\n channel: this.getChannelInput(id)\n }).then(this.onChatUpdated.bind(this, id));\n }\n\n public joinChannel(id: number) {\n return apiManager.invokeApi('channels.joinChannel', {\n channel: this.getChannelInput(id)\n }).then(this.onChatUpdated.bind(this, id));\n }\n\n public addChatUser(id: number, userId: number, fwdLimit = 100) {\n return apiManager.invokeApi('messages.addChatUser', {\n chat_id: id,\n user_id: appUsersManager.getUserInput(userId),\n fwd_limit: fwdLimit\n }).then(this.onChatUpdated.bind(this, id));\n }\n\n public deleteChatUser(id: number, userId: number) {\n return apiManager.invokeApi('messages.deleteChatUser', {\n chat_id: id,\n user_id: appUsersManager.getUserInput(userId)\n }).then(this.onChatUpdated.bind(this, id));\n }\n\n public leaveChat(id: number) {\n return this.deleteChatUser(id, appUsersManager.getSelf().id);\n }\n\n public leave(id: number) {\n return this.isChannel(id) ? this.leaveChannel(id) : this.leaveChat(id);\n }\n\n public delete(id: number) {\n return this.isChannel(id) ? this.deleteChannel(id) : this.deleteChat(id);\n }\n\n public deleteChannel(id: number) {\n return apiManager.invokeApi('channels.deleteChannel', {\n channel: this.getChannelInput(id)\n }).then(this.onChatUpdated.bind(this, id));\n }\n\n public deleteChat(id: number) {\n //return this.leaveChat(id).then(() => {\n return apiManager.invokeApi('messages.deleteChat', {\n chat_id: id\n });\n //});\n }\n\n public migrateChat(id: number): Promise<number> {\n const chat: Chat = this.getChat(id);\n if(chat._ === 'channel') return Promise.resolve(chat.id);\n return apiManager.invokeApi('messages.migrateChat', {\n chat_id: id\n }).then((updates) => {\n this.onChatUpdated(id, updates);\n const update: Update.updateChannel = (updates as Updates.updates).updates.find(u => u._ === 'updateChannel') as any;\n return update.channel_id;\n });\n }\n\n public updateUsername(id: number, username: string) {\n return apiManager.invokeApi('channels.updateUsername', {\n channel: this.getChannelInput(id),\n username\n }).then((bool) => {\n if(bool) {\n const chat: Chat.channel = this.getChat(id);\n chat.username = username;\n }\n\n return bool;\n });\n }\n\n public editPhoto(id: number, inputFile: InputFile) {\n const inputChatPhoto: InputChatPhoto = {\n _: 'inputChatUploadedPhoto',\n file: inputFile\n };\n\n let promise: any;\n if(this.isChannel(id)) {\n promise = apiManager.invokeApi('channels.editPhoto', {\n channel: this.getChannelInput(id),\n photo: inputChatPhoto\n });\n } else {\n promise = apiManager.invokeApi('messages.editChatPhoto', {\n chat_id: id,\n photo: inputChatPhoto\n });\n }\n\n return promise.then((updates: any) => {\n apiUpdatesManager.processUpdateMessage(updates);\n });\n }\n\n public editTitle(id: number, title: string) {\n let promise: any;\n\n if(this.isChannel(id)) {\n promise = apiManager.invokeApi('channels.editTitle', {\n channel: this.getChannelInput(id),\n title\n });\n } else {\n promise = apiManager.invokeApi('messages.editChatTitle', {\n chat_id: id,\n title\n });\n }\n\n return promise.then((updates: any) => {\n apiUpdatesManager.processUpdateMessage(updates);\n });\n }\n\n public editAbout(id: number, about: string) {\n return apiManager.invokeApi('messages.editChatAbout', {\n peer: appPeersManager.getInputPeerById(-id),\n about\n }).then(bool => {\n //apiUpdatesManager.processUpdateMessage(updates);\n rootScope.dispatchEvent('peer_bio_edit', -id);\n });\n }\n\n public getParticipantPeerId(participant: ChannelParticipant | ChatParticipant) {\n const peerId = (participant as ChannelParticipant.channelParticipantBanned).peer ? \n appPeersManager.getPeerId((participant as ChannelParticipant.channelParticipantBanned).peer) : \n (participant as ChatParticipant.chatParticipant).user_id;\n return peerId;\n }\n\n public editBanned(id: number, participant: number | ChannelParticipant, banned_rights: ChatBannedRights) {\n const peerId = typeof(participant) === 'number' ? participant : this.getParticipantPeerId(participant);\n return apiManager.invokeApi('channels.editBanned', {\n channel: this.getChannelInput(id),\n participant: appPeersManager.getInputPeerById(peerId),\n banned_rights\n }).then((updates) => {\n this.onChatUpdated(id, updates);\n\n if(typeof(participant) !== 'number') {\n const timestamp = Date.now() / 1000 | 0;\n apiUpdatesManager.processLocalUpdate({\n _: 'updateChannelParticipant',\n channel_id: id,\n date: timestamp,\n actor_id: undefined,\n qts: undefined,\n user_id: peerId,\n prev_participant: participant,\n new_participant: Object.keys(banned_rights.pFlags).length ? {\n _: 'channelParticipantBanned',\n date: timestamp,\n banned_rights,\n kicked_by: appUsersManager.getSelf().id,\n peer: appPeersManager.getOutputPeer(peerId),\n pFlags: {}\n } : undefined\n });\n }\n });\n }\n\n public clearChannelParticipantBannedRights(id: number, participant: number | ChannelParticipant) {\n return this.editBanned(id, participant, {\n _: 'chatBannedRights',\n until_date: 0,\n pFlags: {}\n });\n }\n \n public kickFromChannel(id: number, participant: number | ChannelParticipant) {\n return this.editBanned(id, participant, {\n _: 'chatBannedRights',\n until_date: 0,\n pFlags: {\n view_messages: true\n }\n });\n }\n\n public resolveChannel(id: number) {\n return apiManager.invokeApiSingle('channels.getChannels', {\n id: [{\n _: 'inputChannel',\n channel_id: id,\n access_hash: '0'\n }]\n }).then(messagesChats => {\n this.saveApiChats(messagesChats.chats);\n });\n }\n\n public togglePreHistoryHidden(id: number, enabled: boolean) {\n return this.migrateChat(id).then(channelId => {\n return apiManager.invokeApi('channels.togglePreHistoryHidden', {\n channel: this.getChannelInput(channelId),\n enabled\n });\n }).then(updates => {\n apiUpdatesManager.processUpdateMessage(updates);\n });\n }\n\n public toggleSignatures(id: number, enabled: boolean) {\n return apiManager.invokeApi('channels.toggleSignatures', {\n channel: this.getChannelInput(id),\n enabled\n }).then(updates => {\n apiUpdatesManager.processUpdateMessage(updates);\n });\n }\n}\n\nconst appChatsManager = new AppChatsManager();\nMOUNT_CLASS_TO.appChatsManager = appChatsManager;\nexport default appChatsManager;\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\n/* import { copy } from \"./object\";\r\n\r\nexport function listMergeSorted(list1: any[] = [], list2: any[] = []) {\r\n const result = copy(list1);\r\n\r\n const minId = list1.length ? list1[list1.length - 1] : 0xFFFFFFFF;\r\n for(let i = 0; i < list2.length; i++) {\r\n if(list2[i] < minId) {\r\n result.push(list2[i]);\r\n }\r\n }\r\n\r\n return result;\r\n} */\r\n\r\nexport const accumulate = (arr: number[], initialValue: number) => arr.reduce((acc, value) => acc + value, initialValue);\r\n\r\nexport function findAndSpliceAll<T>(array: Array<T>, verify: (value: T, index: number, arr: typeof array) => boolean) {\r\n const out: typeof array = [];\r\n let idx = -1;\r\n while((idx = array.findIndex(verify)) !== -1) {\r\n out.push(array.splice(idx, 1)[0]);\r\n }\r\n\r\n return out;\r\n}\r\n\r\nexport function forEachReverse<T>(array: Array<T>, callback: (value: T, index?: number, array?: Array<T>) => void) {\r\n for(let length = array.length, i = length - 1; i >= 0; --i) {\r\n callback(array[i], i, array);\r\n }\r\n};\r\n\r\nexport function insertInDescendSortedArray<T extends {[smth in K]?: number}, K extends keyof T>(array: Array<T>, element: T, property: K, pos?: number) {\r\n const sortProperty: number = element[property];\r\n\r\n if(pos === undefined) {\r\n pos = array.indexOf(element);\r\n if(pos !== -1) {\r\n const prev = array[pos - 1];\r\n const next = array[pos + 1];\r\n if((!prev || prev[property] >= sortProperty) && (!next || next[property] <= sortProperty)) {\r\n // console.warn('same pos', pos, sortProperty, prev, next);\r\n return pos;\r\n }\r\n \r\n array.splice(pos, 1);\r\n }\r\n }\r\n\r\n const len = array.length;\r\n if(!len || sortProperty <= array[len - 1][property]) {\r\n return array.push(element) - 1;\r\n } else if(sortProperty >= array[0][property]) {\r\n array.unshift(element);\r\n return 0;\r\n } else {\r\n for(let i = 0; i < len; i++) {\r\n if(sortProperty > array[i][property]) {\r\n array.splice(i, 0, element);\r\n return i;\r\n }\r\n }\r\n }\r\n\r\n console.error('wtf', array, element);\r\n return array.indexOf(element);\r\n}\r\n\r\nexport function filterUnique<T extends Array<any>>(arr: T): T {\r\n return [...new Set(arr)] as T;\r\n}\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n * \n * Originally from:\n * https://github.com/zhukov/webogram\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\n * https://github.com/zhukov/webogram/blob/master/LICENSE\n */\n\n//import apiManager from '../mtproto/apiManager';\nimport DEBUG, { MOUNT_CLASS_TO } from '../../config/debug';\nimport { Message, MessageEntity, MessageFwdHeader, Peer, Update, Updates } from '../../layer';\nimport { logger, LogTypes } from '../logger';\nimport apiManager from '../mtproto/mtprotoworker';\nimport rootScope from '../rootScope';\n//import networkerFactory from '../mtproto/networkerFactory';\nimport appUsersManager from \"./appUsersManager\";\nimport appChatsManager from \"./appChatsManager\";\nimport appPeersManager from \"./appPeersManager\";\nimport appStateManager from './appStateManager';\nimport serverTimeManager from '../mtproto/serverTimeManager';\nimport assumeType from '../../helpers/assumeType';\nimport noop from '../../helpers/noop';\nimport RichTextProcessor from '../richtextprocessor';\nimport App from '../../config/app';\n\ntype UpdatesState = {\n pendingPtsUpdates: (Update & {pts: number, pts_count: number})[],\n pendingSeqUpdates?: {[seq: number]: {seq: number, date: number, updates: any[]}},\n syncPending: {\n seqAwaiting?: number,\n ptsAwaiting?: true,\n timeout: number\n },\n syncLoading: Promise<void>,\n\n seq?: number,\n pts?: number,\n date?: number,\n lastPtsUpdateTime?: number\n};\n\nconst SYNC_DELAY = 6;\n\nexport class ApiUpdatesManager {\n public updatesState: UpdatesState = {\n pendingPtsUpdates: [],\n pendingSeqUpdates: {},\n syncPending: null,\n syncLoading: null\n };\n\n private channelStates: {[channelId: number]: UpdatesState} = {};\n private attached = false;\n\n private log = logger('UPDATES', LogTypes.Error | LogTypes.Warn | LogTypes.Log/* | LogTypes.Debug */);\n private debug = DEBUG;\n\n private setProxy() {\n const self = this;\n this.updatesState = new Proxy(this.updatesState, {\n set: function(target: ApiUpdatesManager['updatesState'], key: keyof ApiUpdatesManager['updatesState'], value: ApiUpdatesManager['updatesState'][typeof key]) {\n // @ts-ignore\n target[key] = value;\n self.saveUpdatesState();\n return true;\n }\n });\n }\n\n public saveUpdatesState() {\n const us = this.updatesState;\n appStateManager.pushToState('updates', {\n seq: us.seq,\n pts: us.pts,\n date: us.date\n });\n }\n\n private popPendingSeqUpdate() {\n const state = this.updatesState;\n const nextSeq = state.seq + 1;\n const pendingUpdatesData = state.pendingSeqUpdates[nextSeq];\n if(!pendingUpdatesData) {\n return false;\n }\n\n const updates = pendingUpdatesData.updates;\n for(let i = 0, length = updates.length; i < length; ++i) {\n this.saveUpdate(updates[i]);\n }\n\n state.seq = pendingUpdatesData.seq;\n if(pendingUpdatesData.date && state.date < pendingUpdatesData.date) {\n state.date = pendingUpdatesData.date;\n }\n delete state.pendingSeqUpdates[nextSeq];\n \n if(!this.popPendingSeqUpdate() &&\n state.syncPending &&\n state.syncPending.seqAwaiting &&\n state.seq >= state.syncPending.seqAwaiting) {\n if(!state.syncPending.ptsAwaiting) {\n clearTimeout(state.syncPending.timeout);\n state.syncPending = null;\n } else {\n delete state.syncPending.seqAwaiting;\n }\n }\n \n return true;\n }\n\n private popPendingPtsUpdate(channelId: number) {\n const curState = channelId ? this.getChannelState(channelId) : this.updatesState;\n if(!curState.pendingPtsUpdates.length) {\n return false;\n }\n\n curState.pendingPtsUpdates.sort((a, b) => {\n return a.pts - b.pts;\n });\n // this.log('pop update', channelId, curState.pendingPtsUpdates)\n \n let curPts = curState.pts;\n let goodPts = 0;\n let goodIndex = 0;\n for(let i = 0, length = curState.pendingPtsUpdates.length; i < length; ++i) {\n const update = curState.pendingPtsUpdates[i];\n curPts += update.pts_count;\n if(curPts >= update.pts) {\n goodPts = update.pts;\n goodIndex = i;\n }\n }\n \n if(!goodPts) {\n return false;\n }\n \n this.debug && this.log.debug('pop pending pts updates', goodPts, curState.pendingPtsUpdates.slice(0, goodIndex + 1));\n \n curState.pts = goodPts;\n for(let i = 0; i <= goodIndex; ++i) {\n const update = curState.pendingPtsUpdates[i];\n\n // @ts-ignore\n this.saveUpdate(update);\n }\n curState.pendingPtsUpdates.splice(0, goodIndex + 1);\n \n if(!curState.pendingPtsUpdates.length && curState.syncPending) {\n if(!curState.syncPending.seqAwaiting) {\n clearTimeout(curState.syncPending.timeout);\n curState.syncPending = null;\n } else {\n delete curState.syncPending.ptsAwaiting;\n }\n }\n \n return true;\n }\n\n public forceGetDifference() {\n if(!this.updatesState.syncLoading) {\n this.getDifference();\n }\n }\n\n public processLocalUpdate(update: Update) {\n this.processUpdateMessage({\n _: 'updateShort',\n update\n } as Updates);\n }\n\n public processUpdateMessage = (updateMessage: any, options: Partial<{\n override: boolean\n }> = {}) => {\n // return forceGetDifference()\n const processOpts = {\n date: updateMessage.date,\n seq: updateMessage.seq,\n seqStart: updateMessage.seq_start,\n //ignoreSyncLoading: options.ignoreSyncLoading\n };\n\n this.debug && this.log.debug('processUpdateMessage', updateMessage);\n \n switch(updateMessage._) {\n case 'updatesTooLong':\n case 'new_session_created':\n this.forceGetDifference();\n break;\n \n case 'updateShort':\n this.processUpdate(updateMessage.update, processOpts);\n break;\n \n case 'updateShortMessage':\n case 'updateShortChatMessage': {\n assumeType<Updates.updateShortChatMessage | Updates.updateShortMessage>(updateMessage);\n this.debug && this.log.debug('updateShortMessage | updateShortChatMessage', {...updateMessage});\n const isOut = updateMessage.pFlags.out;\n const fromId = (updateMessage as Updates.updateShortChatMessage).from_id || (isOut ? rootScope.myId : (updateMessage as Updates.updateShortMessage).user_id);\n const toId = (updateMessage as Updates.updateShortChatMessage).chat_id\n ? -(updateMessage as Updates.updateShortChatMessage).chat_id\n : ((updateMessage as Updates.updateShortMessage).user_id || rootScope.myId);\n \n this.processUpdate({\n _: 'updateNewMessage',\n message: {\n _: 'message',\n pFlags: updateMessage.pFlags,\n id: updateMessage.id,\n from_id: appPeersManager.getOutputPeer(fromId),\n peer_id: appPeersManager.getOutputPeer(toId),\n date: updateMessage.date,\n message: updateMessage.message,\n fwd_from: updateMessage.fwd_from,\n reply_to: updateMessage.reply_to,\n entities: updateMessage.entities\n },\n pts: updateMessage.pts,\n pts_count: updateMessage.pts_count\n }, processOpts);\n break;\n }\n \n case 'updatesCombined':\n case 'updates':\n appUsersManager.saveApiUsers(updateMessage.users, options.override);\n appChatsManager.saveApiChats(updateMessage.chats, options.override);\n \n updateMessage.updates.forEach((update: Update) => {\n this.processUpdate(update, processOpts);\n });\n break;\n \n default:\n this.log.warn('Unknown update message', updateMessage);\n }\n };\n \n private getDifference(first = false): Promise<void> {\n // this.trace('Get full diff')\n const updatesState = this.updatesState;\n let wasSyncing = updatesState.syncLoading;\n if(!wasSyncing) {\n updatesState.pendingSeqUpdates = {};\n updatesState.pendingPtsUpdates = [];\n }\n \n if(updatesState.syncPending) {\n clearTimeout(updatesState.syncPending.timeout);\n updatesState.syncPending = null;\n }\n\n const promise = apiManager.invokeApi('updates.getDifference', {\n pts: updatesState.pts, \n pts_total_limit: first /* && false */? /* 50 */1200 : undefined,\n date: updatesState.date, \n qts: -1\n }, {\n timeout: 0x7fffffff\n }).then((differenceResult) => {\n this.debug && this.log.debug('Get diff result', differenceResult);\n\n if(differenceResult._ === 'updates.differenceEmpty') {\n this.debug && this.log.debug('apply empty diff', differenceResult.seq);\n updatesState.date = differenceResult.date;\n updatesState.seq = differenceResult.seq;\n return;\n }\n\n // ! SORRY I'M SORRY I'M SORRY\n if(first) {\n rootScope.dispatchEvent('state_synchronizing');\n }\n\n if(differenceResult._ !== 'updates.differenceTooLong') {\n appUsersManager.saveApiUsers(differenceResult.users);\n appChatsManager.saveApiChats(differenceResult.chats);\n\n // Should be first because of updateMessageID\n // this.log('applying', differenceResult.other_updates.length, 'other updates')\n \n differenceResult.other_updates.forEach((update) => {\n switch(update._) {\n case 'updateChannelTooLong':\n case 'updateNewChannelMessage':\n case 'updateEditChannelMessage':\n this.processUpdate(update);\n return;\n }\n \n this.saveUpdate(update);\n });\n\n // this.log('applying', differenceResult.new_messages.length, 'new messages')\n differenceResult.new_messages.forEach((apiMessage) => {\n this.saveUpdate({\n _: 'updateNewMessage',\n message: apiMessage,\n pts: updatesState.pts,\n pts_count: 0\n });\n });\n\n const nextState = differenceResult._ === 'updates.difference' ? differenceResult.state : differenceResult.intermediate_state;\n updatesState.seq = nextState.seq;\n updatesState.pts = nextState.pts;\n updatesState.date = nextState.date;\n } else {\n updatesState.pts = differenceResult.pts;\n updatesState.date = (Date.now() / 1000 | 0) + serverTimeManager.serverTimeOffset;\n delete updatesState.seq;\n \n this.channelStates = {};\n \n this.log.warn('getDifference:', differenceResult._);\n rootScope.dispatchEvent('state_cleared');\n }\n \n // this.log('apply diff', updatesState.seq, updatesState.pts)\n \n if(differenceResult._ === 'updates.differenceSlice') {\n return this.getDifference();\n } else {\n this.debug && this.log.debug('finished get diff');\n }\n });\n\n if(!wasSyncing) {\n this.justAName(updatesState, promise);\n }\n \n return promise;\n }\n\n private getChannelDifference(channelId: number): Promise<void> {\n const channelState = this.getChannelState(channelId);\n const wasSyncing = channelState.syncLoading;\n if(!wasSyncing) {\n channelState.pendingPtsUpdates = [];\n }\n\n if(channelState.syncPending) {\n clearTimeout(channelState.syncPending.timeout);\n channelState.syncPending = null;\n }\n\n //this.log.trace('Get channel diff', appChatsManager.getChat(channelId), channelState.pts);\n const promise = apiManager.invokeApi('updates.getChannelDifference', {\n channel: appChatsManager.getChannelInput(channelId),\n filter: {_: 'channelMessagesFilterEmpty'},\n pts: channelState.pts,\n limit: 30\n }, {timeout: 0x7fffffff}).then((differenceResult) => {\n this.debug && this.log.debug('Get channel diff result', differenceResult)\n channelState.pts = 'pts' in differenceResult ? differenceResult.pts : undefined;\n \n if(differenceResult._ === 'updates.channelDifferenceEmpty') {\n this.debug && this.log.debug('apply channel empty diff', differenceResult);\n return;\n }\n \n if(differenceResult._ === 'updates.channelDifferenceTooLong') {\n this.debug && this.log.debug('channel diff too long', differenceResult);\n delete this.channelStates[channelId];\n\n this.saveUpdate({_: 'updateChannelReload', channel_id: channelId});\n return;\n }\n \n appUsersManager.saveApiUsers(differenceResult.users);\n appChatsManager.saveApiChats(differenceResult.chats);\n \n // Should be first because of updateMessageID\n this.debug && this.log.debug('applying', differenceResult.other_updates.length, 'channel other updates');\n differenceResult.other_updates.forEach((update) => {\n this.saveUpdate(update);\n });\n \n this.debug && this.log.debug('applying', differenceResult.new_messages.length, 'channel new messages');\n differenceResult.new_messages.forEach((apiMessage) => {\n this.saveUpdate({\n _: 'updateNewChannelMessage',\n message: apiMessage,\n pts: channelState.pts,\n pts_count: 0\n });\n });\n \n this.debug && this.log.debug('apply channel diff', channelState.pts);\n \n if(differenceResult._ === 'updates.channelDifference' &&\n !differenceResult.pFlags['final']) {\n return this.getChannelDifference(channelId);\n } else {\n this.debug && this.log.debug('finished channel get diff');\n }\n });\n\n if(!wasSyncing) {\n this.justAName(channelState, promise, channelId);\n }\n\n return promise;\n }\n\n private justAName(state: UpdatesState, promise: UpdatesState['syncLoading'], channelId?: number) {\n state.syncLoading = promise;\n rootScope.dispatchEvent('state_synchronizing', channelId);\n\n promise.then(() => {\n state.syncLoading = null;\n rootScope.dispatchEvent('state_synchronized', channelId);\n }, () => {\n state.syncLoading = null;\n });\n }\n \n public addChannelState(channelId: number, pts: number) {\n if(!pts) {\n throw new Error('Add channel state without pts ' + channelId);\n }\n\n if(!(channelId in this.channelStates)) {\n this.channelStates[channelId] = {\n pts,\n pendingPtsUpdates: [],\n syncPending: null,\n syncLoading: null\n };\n\n return true;\n }\n\n return false;\n }\n\n public getChannelState(channelId: number, pts?: number) {\n if(this.channelStates[channelId] === undefined) {\n this.addChannelState(channelId, pts);\n }\n\n return this.channelStates[channelId];\n }\n\n private processUpdate(update: Update, options: Partial<{\n date: number,\n seq: number,\n seqStart: number/* ,\n ignoreSyncLoading: boolean */\n }> = {}) {\n let channelId = 0;\n switch(update._) {\n case 'updateNewChannelMessage':\n case 'updateEditChannelMessage':\n channelId = -appPeersManager.getPeerId(update.message.peer_id);\n break;\n /* case 'updateDeleteChannelMessages':\n channelId = update.channel_id;\n break; */\n case 'updateChannelTooLong':\n channelId = update.channel_id;\n if(!(channelId in this.channelStates)) {\n return false;\n }\n break;\n default:\n if('channel_id' in update && 'pts' in update) {\n channelId = update.channel_id;\n }\n break;\n }\n \n const {pts, pts_count} = update as Update.updateNewMessage;\n const curState = channelId ? this.getChannelState(channelId, pts) : this.updatesState;\n \n // this.log.log('process', channelId, curState.pts, update)\n \n if(curState.syncLoading/* && !options.ignoreSyncLoading */) {\n return false;\n }\n \n if(update._ === 'updateChannelTooLong') {\n if(!curState.lastPtsUpdateTime ||\n curState.lastPtsUpdateTime < (Date.now() - SYNC_DELAY)) {\n // this.log.trace('channel too long, get diff', channelId, update)\n this.getChannelDifference(channelId);\n }\n return false;\n }\n \n if(update._ === 'updateNewMessage' ||\n update._ === 'updateEditMessage' ||\n update._ === 'updateNewChannelMessage' ||\n update._ === 'updateEditChannelMessage') {\n const message = update.message as Message.message;\n const toPeerId = appPeersManager.getPeerId(message.peer_id);\n const fwdHeader: MessageFwdHeader.messageFwdHeader = message.fwd_from || {} as any;\n let reason: string;\n if(message.from_id && !appUsersManager.hasUser(appPeersManager.getPeerId(message.from_id), message.pFlags.post/* || channelId*/) && (reason = 'author') ||\n fwdHeader.from_id && !appUsersManager.hasUser(appPeersManager.getPeerId(fwdHeader.from_id), !!(fwdHeader.from_id as Peer.peerChannel).channel_id) && (reason = 'fwdAuthor') ||\n (fwdHeader.from_id as Peer.peerChannel)?.channel_id && !appChatsManager.hasChat((fwdHeader.from_id as Peer.peerChannel).channel_id, true) && (reason = 'fwdChannel') ||\n toPeerId > 0 && !appUsersManager.hasUser(toPeerId) && (reason = 'toPeer User') ||\n toPeerId < 0 && !appChatsManager.hasChat(-toPeerId) && (reason = 'toPeer Chat')) {\n this.log.warn('Not enough data for message update', toPeerId, reason, message);\n if(channelId && appChatsManager.hasChat(channelId)) {\n this.getChannelDifference(channelId);\n } else {\n this.forceGetDifference();\n }\n return false;\n }\n } else if(channelId && !appChatsManager.hasChat(channelId)) {\n // this.log.log('skip update, missing channel', channelId, update)\n return false;\n }\n \n let popPts: boolean;\n let popSeq: boolean;\n \n if(pts) {\n const newPts = curState.pts + (pts_count || 0);\n if(newPts < pts) {\n this.debug && this.log.warn('Pts hole', curState, update, channelId && appChatsManager.getChat(channelId));\n curState.pendingPtsUpdates.push(update as Update.updateNewMessage);\n if(!curState.syncPending && !curState.syncLoading) {\n curState.syncPending = {\n timeout: window.setTimeout(() => {\n curState.syncPending = null;\n\n if(curState.syncLoading) {\n return;\n }\n\n if(channelId) {\n this.getChannelDifference(channelId);\n } else {\n this.getDifference();\n }\n }, SYNC_DELAY)\n };\n }\n\n curState.syncPending.ptsAwaiting = true;\n return false;\n }\n\n if(pts > curState.pts) {\n curState.pts = pts;\n popPts = true;\n \n curState.lastPtsUpdateTime = Date.now();\n } else if(pts_count) {\n // this.log.warn('Duplicate update', update)\n return false;\n }\n\n if(channelId && options.date && this.updatesState.date < options.date) {\n this.updatesState.date = options.date;\n }\n } else if(!channelId && options.seq > 0) {\n const seq = options.seq;\n const seqStart = options.seqStart || seq;\n \n if(seqStart !== curState.seq + 1) {\n if(seqStart > curState.seq) {\n this.debug && this.log.warn('Seq hole', curState, curState.syncPending && curState.syncPending.seqAwaiting);\n \n if(curState.pendingSeqUpdates[seqStart] === undefined) {\n curState.pendingSeqUpdates[seqStart] = {seq, date: options.date, updates: []};\n }\n curState.pendingSeqUpdates[seqStart].updates.push(update);\n \n if(!curState.syncPending) {\n curState.syncPending = {\n timeout: window.setTimeout(() => {\n curState.syncPending = null;\n\n if(curState.syncLoading) {\n return;\n }\n\n this.getDifference();\n }, SYNC_DELAY)\n };\n }\n\n if(!curState.syncPending.seqAwaiting ||\n curState.syncPending.seqAwaiting < seqStart) {\n curState.syncPending.seqAwaiting = seqStart;\n }\n return false;\n }\n }\n \n if(curState.seq !== seq) {\n curState.seq = seq;\n if(options.date && curState.date < options.date) {\n curState.date = options.date;\n }\n\n popSeq = true;\n }\n }\n \n this.saveUpdate(update);\n \n if(popPts) {\n this.popPendingPtsUpdate(channelId);\n } else if(popSeq) {\n this.popPendingSeqUpdate();\n }\n }\n\n public saveUpdate(update: Update) {\n //this.debug && this.log('saveUpdate', update);\n rootScope.dispatchEvent(update._, update as any);\n }\n \n public attach() {\n if(this.attached) return;\n\n //return;\n\n this.log('attach');\n \n this.attached = true;\n\n appStateManager.getState().then(_state => {\n const state = _state.updates;\n\n const newVersion = appStateManager.newVersion/* || '0.8.6' */;\n\n //rootScope.broadcast('state_synchronizing');\n if(!state || !state.pts || !state.date || !state.seq) {\n this.log('will get new state');\n\n this.updatesState.syncLoading = new Promise((resolve) => {\n apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult) => {\n this.updatesState.seq = stateResult.seq;\n this.updatesState.pts = stateResult.pts;\n this.updatesState.date = stateResult.date;\n this.saveUpdatesState();\n //setTimeout(() => {\n this.updatesState.syncLoading = null;\n resolve();\n //rootScope.broadcast('state_synchronized');\n //}, 1000);\n \n // ! for testing\n // updatesState.seq = 1\n // updatesState.pts = stateResult.pts - 5000\n // updatesState.date = 1\n // getDifference()\n });\n });\n } else {\n // ! for testing\n /* state.seq = 1;\n state.pts = state.pts - 15;\n state.date = 1; */\n // state.pts -= 100;\n\n /* state.date = 1628623682;\n state.pts = 2007500;\n state.seq = 503; */\n\n Object.assign(this.updatesState, state);\n \n this.log('will get difference', Object.assign({}, state));\n \n this.getDifference(true)/* .finally(() => {\n if(this.updatesState.syncLoading) {\n rootScope.broadcast('state_synchronizing');\n }\n }) */;\n }\n\n apiManager.setUpdatesProcessor(this.processUpdateMessage);\n\n // this.updatesState.syncLoading.then(() => {\n this.setProxy();\n // });\n\n if(newVersion) {\n this.updatesState.syncLoading.then(() => {\n fetch('changelogs/' + newVersion + '.md')\n .then(res => (res.status === 200 && res.ok && res.text()) || Promise.reject())\n .then(text => {\n const pre = `**Telegram Web${App.suffix} was updated to version alpha ${newVersion}**\\n\\n`;\n\n text = pre + text;\n\n const entities: MessageEntity[] = [];\n const message = RichTextProcessor.parseMarkdown(text, entities);\n\n const update: Update.updateServiceNotification = {\n _: 'updateServiceNotification',\n entities,\n message,\n type: 'local',\n pFlags: {},\n inbox_date: Date.now() / 1000 | 0,\n media: undefined\n };\n this.processLocalUpdate(update);\n })\n .catch(noop);\n });\n }\n });\n }\n}\n\nconst apiUpdatesManager = new ApiUpdatesManager();\nMOUNT_CLASS_TO.apiUpdatesManager = apiUpdatesManager;\nexport default apiUpdatesManager\n"],"sourceRoot":""}