tweb/public/4.ce83beb0ce1d5d99f24b.chunk.js.map
Eduard Kuzmenko 183b0a9a31 Build
2021-07-19 18:29:09 +03:00

1 line
130 KiB
Plaintext

{"version":3,"sources":["webpack:///./src/helpers/cleanUsername.ts","webpack:///./src/lib/appManagers/appUsersManager.ts","webpack:///./src/lib/appManagers/appChatsManager.ts","webpack:///./src/lib/appManagers/appPeersManager.ts","webpack:///./src/helpers/array.ts","webpack:///./src/lib/appManagers/apiUpdatesManager.ts","webpack:///./src/lib/searchIndex.ts","webpack:///./src/helpers/cleanSearchText.ts","webpack:///./src/lib/mtproto/mtproto_config.ts","webpack:///./src/helpers/dom/htmlToSpan.ts"],"names":["cleanUsername","username","toLowerCase","appUsersManager","storage","appStateManager","storages","users","updateUsersStatuses","timestampNow","i","this","user","status","_","expires","was_online","rootScope","dispatchEvent","id","setUserToStateIfNeeded","clear","setInterval","addEventListener","addMultipleEventsListeners","updateUserStatus","update","userId","user_id","serverTimeManager","serverTimeOffset","updateUserPhoto","forceUserOnline","photo","console","warn","updateUserName","saveApiUser","Object","assign","first_name","last_name","e","getSelf","contactsIndex","indexObject","getUserSearchText","getState","then","state","storagesResults","length","contactsList","Array","isArray","forEach","pushContact","contactsFillPromise","Promise","resolve","peerId","getFromCache","set","getUser","delete","init","usernames","_userId","isPeerNeeded","findAndSplice","undefined","Set","updatedContactsList","pushToState","promise","invokeApi","result","saveApiUsers","contacts","contact","onContactsModified","slice","resolvedPeer","appChatsManager","saveApiChats","chats","appPeersManager","getPeer","getPeerId","peer","add","requestPeer","phone","pFlags","self","format","filter","Boolean","join","query","includeSaved","fillContacts","_contactsList","results","search","has","sort","userId1","userId2","sortName1","sortName","sortName2","localeCompare","testSelfSearch","p","myId","unshift","block","invokeApiSingle","getInputPeerById","value","apiUpdatesManager","processLocalUpdate","peer_id","getOutputPeer","blocked","index","apiUsers","override","oldUser","min","fullName","searchUsername","deleted","cleanSearchText","initials","getAbbreviation","changedPhoto","changedTitle","photo_id","formatted","access_hash","key","args","isBot","support","date","now","Date","d","getDate","getMonth","getHours","getMinutes","bot","isRegularUser","isContact","allowMin","eventTimestamp","timestamp","updatesState","syncLoading","getTopPeersPromise","topPeers","correspondents","offset","limit","hash","peerIds","categories","peers","map","topPeer","contactsBlocked","count","u","concat","c","invokeApiCacheable","q","cacheSeconds","my_results","offline","showPhone","getUserInput","add_phone_privacy_exception","updates","processUpdateMessage","onContactUpdated","userIds","onChatUpdated","chatId","isChannel","updateChannelParticipant","clearCache","params","channel","channel_id","updateChatDefaultBannedRights","chat","default_banned_rights","getChat","_chatId","apiChats","saveApiChat","oldChat","title","participants_count","rights","defaultRights","action","isThread","kicked","left","megagroup","deactivated","creator","admin_rights","banned_rights","myFlags","post_messages","delete_messages","broadcast","until_date","bind","isMegagroup","good","chat_id","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","DialogColorsFg","DialogColors","DialogColorsMap","updatePeerBlocked","hasRights","getUserPhoto","getChatPhoto","migrated_to","plainText","onlyFirstName","trim","split","wrapEmojiText","getUserString","getChatString","isUser","charAt","peerParams","substr","isBroadcast","ignorePeerId","getChannelInputPeer","getChatInputPeer","pic","text","getDialogType","accumulate","arr","initialValue","reduce","acc","findAndSpliceAll","array","verify","out","idx","findIndex","push","splice","forEachReverse","callback","insertInDescendSortedArray","element","property","pos","indexOf","sortProperty","len","error","filterUnique","pendingPtsUpdates","pendingSeqUpdates","syncPending","channelStates","attached","log","Error","Warn","Log","debug","updateMessage","options","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","a","b","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","noErrorBox","stateResult","setUpdatesProcessor","setProxy","SearchIndex","cleanText","latinize","minChars","fullTexts","Map","searchText","newFoundObjs","queryWords","queryWordsLength","fullText","what","found","foundChars","word","fullTextLength","o","badCharsRe","trimRe","hasTag","replace","ch","latinizeCh","LatinizeMap","REPLIES_PEER_ID","htmlToSpan","html","span","document","createElement","innerHTML"],"mappings":"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","file":"4.ce83beb0ce1d5d99f24b.chunk.js","sourcesContent":["/*\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","/*\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 { formatPhoneNumber } from \"../../components/misc\";\r\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\r\nimport { filterUnique } from \"../../helpers/array\";\r\nimport cleanSearchText from \"../../helpers/cleanSearchText\";\r\nimport cleanUsername from \"../../helpers/cleanUsername\";\r\nimport { tsNow } from \"../../helpers/date\";\r\nimport { safeReplaceObject, isObject } from \"../../helpers/object\";\r\nimport { InputUser, User as MTUser, UserProfilePhoto, UserStatus } from \"../../layer\";\r\nimport I18n, { i18n, LangPackKey } from \"../langPack\";\r\n//import apiManager from '../mtproto/apiManager';\r\nimport apiManager from '../mtproto/mtprotoworker';\r\nimport { REPLIES_PEER_ID } from \"../mtproto/mtproto_config\";\r\nimport serverTimeManager from \"../mtproto/serverTimeManager\";\r\nimport { RichTextProcessor } from \"../richtextprocessor\";\r\nimport rootScope from \"../rootScope\";\r\nimport SearchIndex from \"../searchIndex\";\r\nimport apiUpdatesManager from \"./apiUpdatesManager\";\r\nimport appChatsManager from \"./appChatsManager\";\r\nimport appPeersManager from \"./appPeersManager\";\r\nimport appStateManager from \"./appStateManager\";\r\n\r\n// TODO: updateUserBlocked\r\n\r\nexport type User = MTUser.user;\r\n\r\nexport class AppUsersManager {\r\n private storage = appStateManager.storages.users;\r\n \r\n private users: {[userId: number]: User};\r\n private usernames: {[username: string]: number};\r\n private contactsIndex: SearchIndex<number>;\r\n private contactsFillPromise: Promise<Set<number>>;\r\n private contactsList: Set<number>;\r\n private updatedContactsList: boolean;\r\n \r\n private getTopPeersPromise: Promise<number[]>;\r\n\r\n constructor() {\r\n this.clear(true);\r\n\r\n setInterval(this.updateUsersStatuses, 60000);\r\n\r\n rootScope.addEventListener('state_synchronized', this.updateUsersStatuses);\r\n\r\n rootScope.addMultipleEventsListeners({\r\n updateUserStatus: (update) => {\r\n const userId = update.user_id;\r\n const user = this.users[userId];\r\n if(user) {\r\n user.status = update.status;\r\n if(user.status) {\r\n if('expires' in user.status) {\r\n user.status.expires -= serverTimeManager.serverTimeOffset;\r\n }\r\n\r\n if('was_online' in user.status) {\r\n user.status.was_online -= serverTimeManager.serverTimeOffset;\r\n }\r\n }\r\n\r\n //user.sortStatus = this.getUserStatusForSort(user.status);\r\n rootScope.dispatchEvent('user_update', userId);\r\n this.setUserToStateIfNeeded(user);\r\n } //////else console.warn('No user by id:', userId);\r\n },\r\n\r\n updateUserPhoto: (update) => {\r\n const userId = update.user_id;\r\n const user = this.users[userId];\r\n if(user) {\r\n this.forceUserOnline(userId);\r\n\r\n if(update.photo._ === 'userProfilePhotoEmpty') {\r\n delete user.photo;\r\n } else {\r\n user.photo = safeReplaceObject(user.photo, update.photo);\r\n }\r\n\r\n this.setUserToStateIfNeeded(user);\r\n\r\n rootScope.dispatchEvent('user_update', userId);\r\n rootScope.dispatchEvent('avatar_update', userId);\r\n } else console.warn('No user by id:', userId);\r\n },\r\n\r\n updateUserName: (update) => {\r\n const userId = update.user_id;\r\n const user = this.users[userId];\r\n if(user) {\r\n this.forceUserOnline(userId);\r\n \r\n this.saveApiUser(Object.assign({}, user, {\r\n first_name: update.first_name,\r\n last_name: update.last_name,\r\n username: update.username\r\n }), true);\r\n }\r\n }\r\n });\r\n\r\n /* case 'updateContactLink':\r\n this.onContactUpdated(update.user_id, update.my_link._ === 'contactLinkContact');\r\n break; */\r\n\r\n rootScope.addEventListener('language_change', (e) => {\r\n const userId = this.getSelf().id;\r\n this.contactsIndex.indexObject(userId, this.getUserSearchText(userId));\r\n });\r\n\r\n appStateManager.getState().then((state) => {\r\n const users = appStateManager.storagesResults.users;\r\n if(users.length) {\r\n for(let i = 0, length = users.length; i < length; ++i) {\r\n const user = users[i];\r\n if(user) {\r\n this.users[user.id] = user;\r\n }\r\n }\r\n }\r\n\r\n const contactsList = state.contactsList;\r\n if(contactsList && Array.isArray(contactsList)) {\r\n contactsList.forEach(userId => {\r\n this.pushContact(userId);\r\n });\r\n\r\n if(contactsList.length) {\r\n this.contactsFillPromise = Promise.resolve(this.contactsList);\r\n }\r\n }\r\n\r\n appStateManager.addEventListener('peerNeeded', (peerId: number) => {\r\n if(peerId < 0 || this.storage.getFromCache(peerId)) {\r\n return;\r\n }\r\n\r\n this.storage.set({\r\n [peerId]: this.getUser(peerId)\r\n });\r\n });\r\n\r\n appStateManager.addEventListener('peerUnneeded', (peerId: number) => {\r\n if(peerId < 0 || !this.storage.getFromCache(peerId)) {\r\n return;\r\n }\r\n\r\n this.storage.delete(peerId);\r\n });\r\n });\r\n }\r\n\r\n public clear(init = false) {\r\n if(!init) {\r\n const users = appStateManager.storagesResults.users;\r\n for(const _userId in this.users) {\r\n const userId = +_userId;\r\n if(!userId) continue;\r\n if(!appStateManager.isPeerNeeded(userId)) {\r\n const user = this.users[userId];\r\n if(user.username) {\r\n delete this.usernames[cleanUsername(user.username)];\r\n }\r\n\r\n users.findAndSplice((user) => user.id === userId);\r\n this.storage.delete(userId);\r\n delete this.users[userId];\r\n }\r\n }\r\n } else {\r\n this.users = {};\r\n this.usernames = {};\r\n }\r\n \r\n this.contactsIndex = new SearchIndex();\r\n this.contactsFillPromise = undefined;\r\n this.contactsList = new Set();\r\n this.updatedContactsList = false;\r\n }\r\n\r\n private onContactsModified() {\r\n const contactsList = [...this.contactsList];\r\n appStateManager.pushToState('contactsList', contactsList);\r\n }\r\n\r\n public fillContacts() {\r\n if(this.contactsFillPromise && this.updatedContactsList) {\r\n return this.contactsFillPromise;\r\n }\r\n\r\n this.updatedContactsList = true;\r\n\r\n const promise = apiManager.invokeApi('contacts.getContacts').then((result) => {\r\n if(result._ === 'contacts.contacts') {\r\n this.saveApiUsers(result.users);\r\n\r\n result.contacts.forEach((contact) => {\r\n this.pushContact(contact.user_id);\r\n });\r\n\r\n this.onContactsModified();\r\n }\r\n\r\n this.contactsFillPromise = promise;\r\n\r\n return this.contactsList;\r\n });\r\n\r\n return this.contactsFillPromise || (this.contactsFillPromise = promise);\r\n }\r\n\r\n public resolveUsername(username: string) {\r\n if(username[0] === '@') {\r\n username = username.slice(1);\r\n }\r\n\r\n username = username.toLowerCase();\r\n if(this.usernames[username]) {\r\n return Promise.resolve(this.users[this.usernames[username]]);\r\n }\r\n\r\n return apiManager.invokeApi('contacts.resolveUsername', {username}).then(resolvedPeer => {\r\n this.saveApiUsers(resolvedPeer.users);\r\n appChatsManager.saveApiChats(resolvedPeer.chats);\r\n\r\n return appPeersManager.getPeer(appPeersManager.getPeerId(resolvedPeer.peer));\r\n });\r\n }\r\n\r\n public pushContact(userId: number) {\r\n this.contactsList.add(userId);\r\n this.contactsIndex.indexObject(userId, this.getUserSearchText(userId));\r\n appStateManager.requestPeer(userId, 'contacts');\r\n }\r\n\r\n public getUserSearchText(id: number) {\r\n const user = this.users[id];\r\n if(!user) {\r\n return '';\r\n }\r\n\r\n const arr: string[] = [\r\n user.first_name,\r\n user.last_name,\r\n user.phone,\r\n user.username,\r\n user.pFlags.self ? I18n.format('SavedMessages', true) : '',\r\n user.pFlags.self ? 'Saved Messages' : ''\r\n ];\r\n\r\n return arr.filter(Boolean).join(' ');\r\n }\r\n\r\n public getContacts(query?: string, includeSaved = false) {\r\n return this.fillContacts().then(_contactsList => {\r\n let contactsList = [..._contactsList];\r\n if(query) {\r\n const results = this.contactsIndex.search(query);\r\n const filteredContactsList = [...contactsList].filter(id => results.has(id));\r\n\r\n contactsList = filteredContactsList;\r\n }\r\n\r\n contactsList.sort((userId1: number, userId2: number) => {\r\n const sortName1 = (this.users[userId1] || {}).sortName || '';\r\n const sortName2 = (this.users[userId2] || {}).sortName || '';\r\n\r\n return sortName1.localeCompare(sortName2);\r\n });\r\n\r\n if(includeSaved) {\r\n if(this.testSelfSearch(query)) {\r\n contactsList.findAndSplice(p => p === rootScope.myId);\r\n contactsList.unshift(rootScope.myId);\r\n }\r\n }\r\n\r\n /* contactsList.sort((userId1: number, userId2: number) => {\r\n const sortName1 = (this.users[userId1] || {}).sortName || '';\r\n const sortName2 = (this.users[userId2] || {}).sortName || '';\r\n if(sortName1 === sortName2) {\r\n return 0;\r\n } \r\n \r\n return sortName1 > sortName2 ? 1 : -1;\r\n }); */\r\n\r\n return contactsList;\r\n });\r\n }\r\n\r\n public toggleBlock(peerId: number, block: boolean) {\r\n return apiManager.invokeApiSingle(block ? 'contacts.block' : 'contacts.unblock', {\r\n id: appPeersManager.getInputPeerById(peerId)\r\n }).then(value => {\r\n if(value) {\r\n apiUpdatesManager.processLocalUpdate({\r\n _: 'updatePeerBlocked',\r\n peer_id: appPeersManager.getOutputPeer(peerId),\r\n blocked: block\r\n });\r\n }\r\n\r\n return value;\r\n });\r\n }\r\n\r\n public testSelfSearch(query: string) {\r\n const user = this.getSelf();\r\n const index = new SearchIndex();\r\n index.indexObject(user.id, this.getUserSearchText(user.id));\r\n return index.search(query).has(user.id);\r\n }\r\n\r\n public saveApiUsers(apiUsers: any[], override?: boolean) {\r\n apiUsers.forEach((user) => this.saveApiUser(user, override));\r\n }\r\n\r\n public saveApiUser(user: MTUser, override?: boolean) {\r\n if(user._ === 'userEmpty') return;\r\n\r\n const userId = user.id;\r\n const oldUser = this.users[userId];\r\n\r\n // ! commented block can affect performance !\r\n // if(oldUser && !override) {\r\n // console.log('saveApiUser same');\r\n // return;\r\n // }\r\n\r\n if(user.pFlags === undefined) {\r\n user.pFlags = {};\r\n }\r\n\r\n if(user.pFlags.min && oldUser !== undefined) {\r\n return;\r\n }\r\n\r\n // * exclude from state\r\n // defineNotNumerableProperties(user, ['initials', 'num', 'rFirstName', 'rFullName', 'rPhone', 'sortName', 'sortStatus']);\r\n\r\n const fullName = user.first_name + ' ' + (user.last_name || '');\r\n if(user.username) {\r\n const searchUsername = cleanUsername(user.username);\r\n this.usernames[searchUsername] = userId;\r\n }\r\n\r\n user.sortName = user.pFlags.deleted ? '' : cleanSearchText(fullName, false);\r\n\r\n user.initials = RichTextProcessor.getAbbreviation(fullName);\r\n\r\n if(user.status) {\r\n if((user.status as UserStatus.userStatusOnline).expires) {\r\n (user.status as UserStatus.userStatusOnline).expires -= serverTimeManager.serverTimeOffset;\r\n }\r\n\r\n if((user.status as UserStatus.userStatusOffline).was_online) {\r\n (user.status as UserStatus.userStatusOffline).was_online -= serverTimeManager.serverTimeOffset;\r\n }\r\n }\r\n\r\n //user.sortStatus = user.pFlags.bot ? -1 : this.getUserStatusForSort(user.status);\r\n\r\n let changedPhoto = false, changedTitle = false;\r\n if(oldUser === undefined) {\r\n this.users[userId] = user;\r\n } else {\r\n if(user.first_name !== oldUser.first_name \r\n || user.last_name !== oldUser.last_name \r\n || user.username !== oldUser.username) {\r\n changedTitle = true;\r\n }\r\n\r\n const oldPhotoId = (oldUser.photo as UserProfilePhoto.userProfilePhoto)?.photo_id;\r\n const newPhotoId = (user.photo as UserProfilePhoto.userProfilePhoto)?.photo_id;\r\n if(oldPhotoId !== newPhotoId) {\r\n changedPhoto = true;\r\n }\r\n\r\n /* if(user.pFlags.bot && user.bot_info_version !== oldUser.bot_info_version) {\r\n \r\n } */\r\n\r\n safeReplaceObject(oldUser, user);\r\n rootScope.dispatchEvent('user_update', userId);\r\n }\r\n\r\n if(changedPhoto) {\r\n rootScope.dispatchEvent('avatar_update', user.id);\r\n }\r\n\r\n if(changedTitle) {\r\n rootScope.dispatchEvent('peer_title_edit', user.id);\r\n }\r\n\r\n this.setUserToStateIfNeeded(user);\r\n }\r\n\r\n public setUserToStateIfNeeded(user: User) {\r\n if(appStateManager.isPeerNeeded(user.id)) {\r\n this.storage.set({\r\n [user.id]: user\r\n });\r\n }\r\n }\r\n\r\n public formatUserPhone(phone: string) {\r\n return '+' + formatPhoneNumber(phone).formatted;\r\n }\r\n\r\n public getUserStatusForSort(status: User['status'] | number) {\r\n if(typeof(status) === 'number') {\r\n status = this.getUser(status).status;\r\n }\r\n\r\n if(status) {\r\n const expires = status._ === 'userStatusOnline' ? status.expires : (status._ === 'userStatusOffline' ? status.was_online : 0);\r\n if(expires) {\r\n return expires;\r\n }\r\n\r\n /* const timeNow = tsNow(true);\r\n switch(status._) {\r\n case 'userStatusRecently':\r\n return timeNow - 86400 * 3;\r\n case 'userStatusLastWeek':\r\n return timeNow - 86400 * 7;\r\n case 'userStatusLastMonth':\r\n return timeNow - 86400 * 30;\r\n } */\r\n switch(status._) {\r\n case 'userStatusRecently':\r\n return 3;\r\n case 'userStatusLastWeek':\r\n return 2;\r\n case 'userStatusLastMonth':\r\n return 1;\r\n }\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n public getUser(id: any): User {\r\n if(isObject(id)) {\r\n return id;\r\n }\r\n\r\n return this.users[id] || {id: id, pFlags: {deleted: true}, access_hash: ''} as User;\r\n }\r\n\r\n public getSelf() {\r\n return this.getUser(rootScope.myId);\r\n }\r\n\r\n public getUserStatusString(userId: number): HTMLElement {\r\n let key: LangPackKey;\r\n let args: any[];\r\n\r\n switch(userId) {\r\n case REPLIES_PEER_ID:\r\n key = 'Peer.RepliesNotifications';\r\n break;\r\n case 777000:\r\n key = 'Peer.ServiceNotifications';\r\n break;\r\n default: {\r\n if(this.isBot(userId)) {\r\n key = 'Bot';\r\n break;\r\n }\r\n\r\n const user = this.getUser(userId);\r\n if(!user) {\r\n key = '' as any;\r\n break;\r\n }\r\n\r\n if(user.pFlags.support) {\r\n key = 'SupportStatus';\r\n break;\r\n }\r\n\r\n switch(user.status?._) {\r\n case 'userStatusRecently': {\r\n key = 'Lately';\r\n break;\r\n }\r\n \r\n case 'userStatusLastWeek': {\r\n key = 'WithinAWeek';\r\n break;\r\n }\r\n \r\n case 'userStatusLastMonth': {\r\n key = 'WithinAMonth';\r\n break;\r\n }\r\n \r\n case 'userStatusOffline': {\r\n const date = user.status.was_online;\r\n const now = Date.now() / 1000;\r\n \r\n if((now - date) < 60) {\r\n key = 'Peer.Status.justNow';\r\n } else if((now - date) < 3600) {\r\n key = 'Peer.Status.minAgo';\r\n const c = (now - date) / 60 | 0;\r\n args = [c];\r\n } else if(now - date < 86400) {\r\n key = 'LastSeen.HoursAgo';\r\n const c = (now - date) / 3600 | 0;\r\n args = [c];\r\n } else {\r\n key = 'Peer.Status.LastSeenAt';\r\n const d = new Date(date * 1000);\r\n args = [('0' + d.getDate()).slice(-2) + '.' + ('0' + (d.getMonth() + 1)).slice(-2), \r\n ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2)];\r\n }\r\n \r\n break;\r\n }\r\n \r\n case 'userStatusOnline': {\r\n key = 'Online';\r\n break;\r\n }\r\n \r\n default: {\r\n key = 'ALongTimeAgo';\r\n break;\r\n }\r\n }\r\n\r\n break;\r\n }\r\n }\r\n \r\n return i18n(key, args);\r\n }\r\n\r\n public isBot(id: number) {\r\n return this.users[id] && this.users[id].pFlags.bot;\r\n }\r\n\r\n public isContact(id: number) {\r\n return this.contactsList.has(id) || (this.users[id] && this.users[id].pFlags.contact);\r\n }\r\n \r\n public isRegularUser(id: number) {\r\n const user = this.users[id];\r\n return user && !this.isBot(id) && !user.pFlags.deleted && !user.pFlags.support;\r\n }\r\n\r\n public isNonContactUser(id: number) {\r\n return this.isRegularUser(id) && !this.isContact(id) && id !== rootScope.myId;\r\n }\r\n\r\n public hasUser(id: number, allowMin?: boolean) {\r\n const user = this.users[id];\r\n return isObject(user) && (allowMin || !user.pFlags.min);\r\n }\r\n\r\n public canSendToUser(id: number) {\r\n const user = this.getUser(id);\r\n return !user.pFlags.deleted && user.username !== 'replies';\r\n }\r\n\r\n public getUserPhoto(id: number) {\r\n const user = this.getUser(id);\r\n\r\n return user && user.photo || {\r\n _: 'userProfilePhotoEmpty'\r\n };\r\n }\r\n\r\n public getUserString(id: number) {\r\n const user = this.getUser(id);\r\n return 'u' + id + (user.access_hash ? '_' + user.access_hash : '');\r\n }\r\n\r\n public getUserInput(id: number): InputUser {\r\n const user = this.getUser(id);\r\n if(user.pFlags && user.pFlags.self) {\r\n return {_: 'inputUserSelf'};\r\n }\r\n\r\n return {\r\n _: 'inputUser',\r\n user_id: id,\r\n access_hash: user.access_hash\r\n };\r\n }\r\n\r\n public updateUsersStatuses = () => {\r\n const timestampNow = tsNow(true);\r\n for(const i in this.users) {\r\n const user = this.users[i];\r\n\r\n if(user.status &&\r\n user.status._ === 'userStatusOnline' &&\r\n user.status.expires < timestampNow) {\r\n\r\n user.status = {_: 'userStatusOffline', was_online: user.status.expires};\r\n rootScope.dispatchEvent('user_update', user.id);\r\n\r\n this.setUserToStateIfNeeded(user);\r\n }\r\n }\r\n };\r\n\r\n public forceUserOnline(id: number, eventTimestamp?: number) {\r\n if(this.isBot(id)) {\r\n return;\r\n }\r\n\r\n const timestamp = tsNow(true);\r\n const onlineTimeFor = 60;\r\n if(eventTimestamp) {\r\n if((timestamp - eventTimestamp) >= onlineTimeFor) {\r\n return;\r\n }\r\n } else if(apiUpdatesManager.updatesState.syncLoading) {\r\n return;\r\n }\r\n\r\n const user = this.getUser(id);\r\n if(user &&\r\n user.status &&\r\n user.status._ !== 'userStatusOnline' &&\r\n user.status._ !== 'userStatusEmpty' &&\r\n !user.pFlags.support &&\r\n !user.pFlags.deleted) {\r\n\r\n user.status = {\r\n _: 'userStatusOnline',\r\n expires: timestamp + onlineTimeFor\r\n };\r\n \r\n //user.sortStatus = this.getUserStatusForSort(user.status);\r\n rootScope.dispatchEvent('user_update', id);\r\n\r\n this.setUserToStateIfNeeded(user);\r\n }\r\n }\r\n\r\n /* function importContact (phone, firstName, lastName) {\r\n return MtpApiManager.invokeApi('contacts.importContacts', {\r\n contacts: [{\r\n _: 'inputPhoneContact',\r\n client_id: '1',\r\n phone: phone,\r\n first_name: firstName,\r\n last_name: lastName\r\n }],\r\n replace: false\r\n }).then(function (importedContactsResult) {\r\n saveApiUsers(importedContactsResult.users)\r\n\r\n var foundUserID = false\r\n angular.forEach(importedContactsResult.imported, function (importedContact) {\r\n onContactUpdated(foundUserID = importedContact.user_id, true)\r\n })\r\n\r\n return foundUserID || false\r\n })\r\n }\r\n\r\n function importContacts (contacts) {\r\n var inputContacts = [],\r\n i\r\n var j\r\n\r\n for (i = 0; i < contacts.length; i++) {\r\n for (j = 0; j < contacts[i].phones.length; j++) {\r\n inputContacts.push({\r\n _: 'inputPhoneContact',\r\n client_id: (i << 16 | j).toString(10),\r\n phone: contacts[i].phones[j],\r\n first_name: contacts[i].first_name,\r\n last_name: contacts[i].last_name\r\n })\r\n }\r\n }\r\n\r\n return MtpApiManager.invokeApi('contacts.importContacts', {\r\n contacts: inputContacts,\r\n replace: false\r\n }).then(function (importedContactsResult) {\r\n saveApiUsers(importedContactsResult.users)\r\n\r\n var result = []\r\n angular.forEach(importedContactsResult.imported, function (importedContact) {\r\n onContactUpdated(importedContact.user_id, true)\r\n result.push(importedContact.user_id)\r\n })\r\n\r\n return result\r\n })\r\n } */\r\n\r\n /* public deleteContacts(userIds: number[]) {\r\n var ids: any[] = [];\r\n userIds.forEach((userId) => {\r\n ids.push(this.getUserInput(userId));\r\n })\r\n\r\n return apiManager.invokeApi('contacts.deleteContacts', {\r\n id: ids\r\n }).then(() => {\r\n userIds.forEach((userId) => {\r\n this.onContactUpdated(userId, false);\r\n });\r\n });\r\n } */\r\n\r\n public getTopPeers(): Promise<number[]> {\r\n if(this.getTopPeersPromise) return this.getTopPeersPromise;\r\n\r\n return this.getTopPeersPromise = appStateManager.getState().then((state) => {\r\n if(state?.topPeers?.length) {\r\n return state.topPeers;\r\n }\r\n\r\n return apiManager.invokeApi('contacts.getTopPeers', {\r\n correspondents: true,\r\n offset: 0,\r\n limit: 15,\r\n hash: 0,\r\n }).then((result) => {\r\n let peerIds: number[] = [];\r\n if(result._ === 'contacts.topPeers') {\r\n //console.log(result);\r\n this.saveApiUsers(result.users);\r\n appChatsManager.saveApiChats(result.chats);\r\n\r\n if(result.categories.length) {\r\n peerIds = result.categories[0].peers.map((topPeer) => {\r\n const peerId = appPeersManager.getPeerId(topPeer.peer);\r\n appStateManager.requestPeer(peerId, 'topPeer');\r\n return peerId;\r\n });\r\n }\r\n }\r\n \r\n appStateManager.pushToState('topPeers', peerIds);\r\n \r\n return peerIds;\r\n });\r\n });\r\n }\r\n\r\n public getBlocked(offset = 0, limit = 0) {\r\n return apiManager.invokeApiSingle('contacts.getBlocked', {offset, limit}).then(contactsBlocked => {\r\n this.saveApiUsers(contactsBlocked.users);\r\n appChatsManager.saveApiChats(contactsBlocked.chats);\r\n const count = contactsBlocked._ === 'contacts.blocked' ? contactsBlocked.users.length + contactsBlocked.chats.length : contactsBlocked.count;\r\n\r\n const peerIds = contactsBlocked.users.map(u => u.id).concat(contactsBlocked.chats.map(c => -c.id));\r\n\r\n return {count, peerIds};\r\n });\r\n }\r\n\r\n /* public searchContacts(query: string, limit = 20) {\r\n return Promise.all([\r\n this.getContacts(query),\r\n apiManager.invokeApi('contacts.search', {\r\n q: query,\r\n limit\r\n })\r\n ]).then(results => {\r\n const [myContacts, peers] = results;\r\n\r\n this.saveApiUsers(peers.users);\r\n appChatsManager.saveApiChats(peers.chats);\r\n\r\n // * contacts.search returns duplicates in my_results\r\n const myResults = new Set(myContacts.concat(peers.my_results.map(p => appPeersManager.getPeerID(p))));\r\n\r\n const out = {\r\n my_results: [...myResults].slice(0, limit),\r\n results: peers.results.map(p => appPeersManager.getPeerID(p))\r\n };\r\n\r\n return out;\r\n });\r\n } */\r\n public searchContacts(query: string, limit = 20) {\r\n return apiManager.invokeApiCacheable('contacts.search', {\r\n q: query,\r\n limit\r\n }, {cacheSeconds: 60}).then(peers => {\r\n this.saveApiUsers(peers.users);\r\n appChatsManager.saveApiChats(peers.chats);\r\n\r\n const out = {\r\n my_results: filterUnique(peers.my_results.map(p => appPeersManager.getPeerId(p))), // ! contacts.search returns duplicates in my_results\r\n results: peers.results.map(p => appPeersManager.getPeerId(p))\r\n };\r\n\r\n return out;\r\n });\r\n }\r\n\r\n private onContactUpdated(userId: number, isContact: boolean) {\r\n const curIsContact = this.isContact(userId);\r\n if(isContact !== curIsContact) {\r\n if(isContact) {\r\n this.pushContact(userId);\r\n } else {\r\n this.contactsList.delete(userId);\r\n }\r\n\r\n this.onContactsModified();\r\n\r\n rootScope.dispatchEvent('contacts_update', userId);\r\n }\r\n }\r\n\r\n public updateUsername(username: string) {\r\n return apiManager.invokeApi('account.updateUsername', {\r\n username\r\n }).then((user) => {\r\n this.saveApiUser(user);\r\n });\r\n }\r\n\r\n public setUserStatus(userId: number, offline: boolean) {\r\n if(this.isBot(userId)) {\r\n return;\r\n }\r\n\r\n const user = this.users[userId];\r\n if(user) {\r\n const status: any = offline ? {\r\n _: 'userStatusOffline',\r\n was_online: tsNow(true)\r\n } : {\r\n _: 'userStatusOnline',\r\n expires: tsNow(true) + 500\r\n };\r\n\r\n user.status = status;\r\n //user.sortStatus = this.getUserStatusForSort(user.status);\r\n rootScope.dispatchEvent('user_update', userId);\r\n }\r\n }\r\n\r\n public addContact(userId: number, first_name: string, last_name: string, phone: string, showPhone?: true) {\r\n return apiManager.invokeApi('contacts.addContact', {\r\n id: this.getUserInput(userId),\r\n first_name,\r\n last_name,\r\n phone,\r\n add_phone_privacy_exception: showPhone\r\n }).then((updates) => {\r\n apiUpdatesManager.processUpdateMessage(updates, {override: true});\r\n\r\n this.onContactUpdated(userId, true);\r\n });\r\n }\r\n\r\n public deleteContacts(userIds: number[]) {\r\n return apiManager.invokeApi('contacts.deleteContacts', {\r\n id: userIds.map(userId => this.getUserInput(userId))\r\n }).then((updates) => {\r\n apiUpdatesManager.processUpdateMessage(updates, {override: true});\r\n\r\n userIds.forEach(userId => {\r\n this.onContactUpdated(userId, false);\r\n });\r\n });\r\n }\r\n}\r\n\r\nconst appUsersManager = new AppUsersManager();\r\nMOUNT_CLASS_TO.appUsersManager = appUsersManager;\r\nexport default appUsersManager\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\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\r\nimport { isObject, safeReplaceObject, copy, deepEqual } from \"../../helpers/object\";\r\nimport { ChannelParticipant, Chat, ChatAdminRights, ChatBannedRights, ChatParticipant, ChatPhoto, InputChannel, InputChatPhoto, InputFile, InputPeer, Update, Updates } from \"../../layer\";\r\nimport apiManagerProxy from \"../mtproto/mtprotoworker\";\r\nimport apiManager from '../mtproto/mtprotoworker';\r\nimport { RichTextProcessor } from \"../richtextprocessor\";\r\nimport rootScope from \"../rootScope\";\r\nimport apiUpdatesManager from \"./apiUpdatesManager\";\r\nimport appPeersManager from \"./appPeersManager\";\r\nimport appStateManager from \"./appStateManager\";\r\nimport appUsersManager from \"./appUsersManager\";\r\n\r\nexport type Channel = Chat.channel;\r\n\r\nexport type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags'] | 'change_type' | 'change_permissions' | 'delete_chat' | 'view_participants';\r\n\r\nexport class AppChatsManager {\r\n private storage = appStateManager.storages.chats;\r\n \r\n private chats: {[id: number]: Chat.channel | Chat.chat | any};\r\n //private usernames: any;\r\n //private channelAccess: any;\r\n //private megagroups: {[id: number]: true};\r\n\r\n constructor() {\r\n this.clear(true);\r\n\r\n rootScope.addMultipleEventsListeners({\r\n /* updateChannel: (update) => {\r\n const channelId = update.channel_id;\r\n //console.log('updateChannel:', update);\r\n rootScope.broadcast('channel_settings', {channelId});\r\n }, */\r\n\r\n updateChannelParticipant: (update) => {\r\n apiManagerProxy.clearCache('channels.getParticipants', (params) => {\r\n return (params.channel as InputChannel.inputChannel).channel_id === update.channel_id;\r\n });\r\n },\r\n\r\n updateChatDefaultBannedRights: (update) => {\r\n const chatId = -appPeersManager.getPeerId(update.peer);\r\n const chat: Chat.chat = this.chats[chatId];\r\n if(chat) {\r\n chat.default_banned_rights = update.default_banned_rights;\r\n rootScope.dispatchEvent('chat_update', chatId);\r\n }\r\n }\r\n });\r\n\r\n appStateManager.getState().then((state) => {\r\n const chats = appStateManager.storagesResults.chats;\r\n if(chats.length) {\r\n for(let i = 0, length = chats.length; i < length; ++i) {\r\n const chat = chats[i];\r\n if(chat) {\r\n this.chats[chat.id] = chat;\r\n }\r\n }\r\n }\r\n\r\n appStateManager.addEventListener('peerNeeded', (peerId: number) => {\r\n if(peerId > 0 || this.storage.getFromCache(-peerId)) {\r\n return;\r\n }\r\n\r\n this.storage.set({\r\n [-peerId]: this.getChat(-peerId)\r\n });\r\n });\r\n\r\n appStateManager.addEventListener('peerUnneeded', (peerId: number) => {\r\n if(peerId > 0 || !this.storage.getFromCache(-peerId)) {\r\n return;\r\n }\r\n\r\n this.storage.delete(-peerId);\r\n });\r\n });\r\n }\r\n\r\n public clear(init = false) {\r\n if(!init) {\r\n const chats = appStateManager.storagesResults.chats;\r\n for(const _chatId in this.chats) {\r\n const chatId = +_chatId;\r\n if(!chatId) continue;\r\n if(!appStateManager.isPeerNeeded(-chatId)) {\r\n /* const chat = this.chats[chatId];\r\n if(chat.username) {\r\n delete this.usernames[cleanUsername(chat.username)];\r\n } */\r\n \r\n chats.findAndSplice((chat) => chat.id === chatId);\r\n this.storage.delete(chatId);\r\n delete this.chats[chatId];\r\n }\r\n }\r\n } else {\r\n this.chats = {};\r\n }\r\n }\r\n\r\n public saveApiChats(apiChats: any[], override?: boolean) {\r\n apiChats.forEach(chat => this.saveApiChat(chat, override));\r\n }\r\n\r\n public saveApiChat(chat: Chat, override?: boolean) {\r\n if(chat._ === 'chatEmpty') return;\r\n /* if(chat._ !== 'chat' && chat._ !== 'channel') {\r\n return;\r\n } */\r\n \r\n // * exclude from state\r\n // defineNotNumerableProperties(chat, ['rTitle', 'initials']);\r\n\r\n const oldChat: Exclude<Chat, Chat.chatEmpty> = this.chats[chat.id];\r\n\r\n /* if(oldChat && !override) {\r\n return;\r\n } */\r\n\r\n if((chat as Chat.chat).pFlags === undefined) {\r\n (chat as Chat.chat).pFlags = {};\r\n }\r\n\r\n if((chat as Chat.channel).pFlags.min && oldChat !== undefined) {\r\n return;\r\n }\r\n\r\n chat.initials = RichTextProcessor.getAbbreviation(chat.title);\r\n\r\n if(chat._ === 'channel' &&\r\n chat.participants_count === undefined &&\r\n oldChat !== undefined &&\r\n (oldChat as Chat.channel).participants_count) {\r\n chat.participants_count = (oldChat as Chat.channel).participants_count;\r\n }\r\n\r\n /* if(chat.username) {\r\n let searchUsername = searchIndexManager.cleanUsername(chat.username);\r\n this.usernames[searchUsername] = chat.id;\r\n } */\r\n\r\n let changedPhoto = false, changedTitle = false;\r\n if(oldChat === undefined) {\r\n this.chats[chat.id] = chat;\r\n } else {\r\n const oldPhotoId = ((oldChat as Chat.chat).photo as ChatPhoto.chatPhoto)?.photo_id;\r\n const newPhotoId = ((chat as Chat.chat).photo as ChatPhoto.chatPhoto)?.photo_id;\r\n if(oldPhotoId !== newPhotoId) {\r\n changedPhoto = true;\r\n }\r\n\r\n if(oldChat.title !== chat.title) {\r\n changedTitle = true;\r\n }\r\n\r\n safeReplaceObject(oldChat, chat);\r\n rootScope.dispatchEvent('chat_update', chat.id);\r\n }\r\n\r\n if(changedPhoto) {\r\n rootScope.dispatchEvent('avatar_update', -chat.id);\r\n }\r\n\r\n if(changedTitle) {\r\n rootScope.dispatchEvent('peer_title_edit', -chat.id);\r\n }\r\n\r\n if(appStateManager.isPeerNeeded(-chat.id)) {\r\n this.storage.set({\r\n [chat.id]: chat\r\n });\r\n }\r\n }\r\n\r\n public getChat(id: number) {\r\n if(id < 0) id = -id;\r\n return this.chats[id] || {_: 'chatEmpty', id, deleted: true, access_hash: '', pFlags: {}/* this.channelAccess[id] */};\r\n }\r\n\r\n public combineParticipantBannedRights(id: number, rights: ChatBannedRights) {\r\n const chat: Chat.channel = this.getChat(id);\r\n\r\n if(chat.default_banned_rights) {\r\n rights = copy(rights);\r\n const defaultRights = chat.default_banned_rights.pFlags;\r\n for(let i in defaultRights) {\r\n // @ts-ignore\r\n rights.pFlags[i] = defaultRights[i];\r\n }\r\n }\r\n\r\n return rights;\r\n }\r\n\r\n public hasRights(id: number, action: ChatRights, rights?: ChatAdminRights | ChatBannedRights, isThread?: boolean) {\r\n const chat: Chat = this.getChat(id);\r\n if(chat._ === 'chatEmpty') return false;\r\n\r\n if(chat._ === 'chatForbidden' ||\r\n chat._ === 'channelForbidden' ||\r\n (chat as Chat.chat).pFlags.kicked ||\r\n (chat.pFlags.left && !(chat as Chat.channel).pFlags.megagroup)) {\r\n return false;\r\n }\r\n\r\n if((chat as Chat.chat).pFlags.deactivated && action !== 'view_messages') {\r\n return false;\r\n }\r\n\r\n if(chat.pFlags.creator && rights === undefined) {\r\n return true;\r\n }\r\n\r\n if(!rights) {\r\n rights = chat.admin_rights || (chat as Chat.channel).banned_rights || chat.default_banned_rights;\r\n\r\n if(!rights) {\r\n return false;\r\n }\r\n }\r\n\r\n let myFlags: Partial<{[flag in keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags']]: true}> = {};\r\n if(rights) {\r\n myFlags = rights.pFlags as any;\r\n }\r\n\r\n switch(action) {\r\n case 'embed_links':\r\n case 'send_games':\r\n case 'send_gifs':\r\n case 'send_inline':\r\n case 'send_media':\r\n case 'send_messages':\r\n case 'send_polls':\r\n case 'send_stickers': {\r\n if(!isThread && chat.pFlags.left) {\r\n return false;\r\n }\r\n\r\n if(rights._ === 'chatBannedRights' && myFlags[action]) {\r\n return false;\r\n }\r\n\r\n if(chat._ === 'channel') {\r\n if(!chat.pFlags.megagroup && !myFlags.post_messages) {\r\n return false;\r\n }\r\n }\r\n\r\n break;\r\n }\r\n\r\n // * revoke foreign messages\r\n case 'delete_messages': {\r\n return !!myFlags.delete_messages;\r\n }\r\n\r\n case 'pin_messages': {\r\n return rights._ === 'chatAdminRights' ? myFlags[action] || !!myFlags.post_messages : !myFlags[action];\r\n }\r\n\r\n case 'invite_users':\r\n case 'change_info': {\r\n return rights._ === 'chatAdminRights' ? myFlags[action] : !myFlags[action];\r\n }\r\n\r\n // * only creator can do that\r\n case 'change_type':\r\n case 'delete_chat': {\r\n return false;\r\n }\r\n\r\n case 'change_permissions': {\r\n return rights._ === 'chatAdminRights' && myFlags['ban_users'];\r\n }\r\n\r\n case 'view_participants': {\r\n return !!(chat._ === 'chat' || !chat.pFlags.broadcast || chat.pFlags.creator || chat.admin_rights);\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n public editChatDefaultBannedRights(id: number, banned_rights: ChatBannedRights) {\r\n const chat: Chat.chat = this.getChat(id);\r\n if(chat.default_banned_rights) {\r\n if(chat.default_banned_rights.until_date === banned_rights.until_date && deepEqual(chat.default_banned_rights.pFlags, banned_rights.pFlags)) {\r\n return Promise.resolve();\r\n }\r\n }\r\n \r\n return apiManager.invokeApi('messages.editChatDefaultBannedRights', {\r\n peer: appPeersManager.getInputPeerById(-id),\r\n banned_rights\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n /* public resolveUsername(username: string) {\r\n return this.usernames[username] || 0;\r\n } */\r\n\r\n /* public saveChannelAccess(id: number, accessHash: string) {\r\n this.channelAccess[id] = accessHash;\r\n } */\r\n\r\n /* public saveIsMegagroup(id: number) {\r\n this.megagroups[id] = true;\r\n } */\r\n\r\n public isChannel(id: number) {\r\n const chat = this.chats[id];\r\n return chat && (chat._ === 'channel' || chat._ === 'channelForbidden')/* || this.channelAccess[id] */;\r\n }\r\n\r\n public isMegagroup(id: number) {\r\n /* if(this.megagroups[id]) {\r\n return true;\r\n } */\r\n\r\n const chat = this.chats[id];\r\n return chat && chat._ === 'channel' && chat.pFlags.megagroup;\r\n }\r\n\r\n public isBroadcast(id: number) {\r\n return this.isChannel(id) && !this.isMegagroup(id);\r\n }\r\n\r\n public isInChat(id: number) {\r\n let good = true;\r\n const chat: Chat = this.getChat(id);\r\n if(chat._ === 'channelForbidden' \r\n || chat._ === 'chatForbidden' \r\n || chat._ === 'chatEmpty' \r\n || (chat as Chat.chat).pFlags.left \r\n || (chat as Chat.chat).pFlags.kicked \r\n || (chat as Chat.chat).pFlags.deactivated) {\r\n good = false;\r\n }\r\n\r\n return good;\r\n }\r\n\r\n public getChannelInput(id: number): InputChannel {\r\n const chat: Chat = this.getChat(id);\r\n if(chat._ === 'chatEmpty' || !(chat as Chat.channel).access_hash) {\r\n return {\r\n _: 'inputChannelEmpty'\r\n };\r\n } else {\r\n return {\r\n _: 'inputChannel',\r\n channel_id: id,\r\n access_hash: (chat as Chat.channel).access_hash/* || this.channelAccess[id] */ || '0'\r\n };\r\n }\r\n }\r\n\r\n public getChatInputPeer(id: number): InputPeer.inputPeerChat {\r\n return {\r\n _: 'inputPeerChat',\r\n chat_id: id\r\n };\r\n }\r\n\r\n public getChannelInputPeer(id: number): InputPeer.inputPeerChannel {\r\n return {\r\n _: 'inputPeerChannel',\r\n channel_id: id,\r\n access_hash: this.getChat(id).access_hash/* || this.channelAccess[id] */ || 0\r\n };\r\n }\r\n\r\n public hasChat(id: number, allowMin?: true) {\r\n const chat = this.chats[id]\r\n return isObject(chat) && (allowMin || !chat.pFlags.min);\r\n }\r\n\r\n public getChatPhoto(id: number) {\r\n const chat: Chat.chat = this.getChat(id);\r\n\r\n return chat && chat.photo || {\r\n _: 'chatPhotoEmpty'\r\n };\r\n }\r\n\r\n public getChatString(id: number) {\r\n const chat = this.getChat(id);\r\n if(this.isChannel(id)) {\r\n return (this.isMegagroup(id) ? 's' : 'c') + id + '_' + chat.access_hash;\r\n }\r\n return 'g' + id;\r\n }\r\n\r\n /* public wrapForFull(id: number, fullChat: any) {\r\n const chatFull = copy(fullChat);\r\n const chat = this.getChat(id);\r\n\r\n if(!chatFull.participants_count) {\r\n chatFull.participants_count = chat.participants_count;\r\n }\r\n\r\n if(chatFull.participants &&\r\n chatFull.participants._ === 'chatParticipants') {\r\n chatFull.participants.participants = this.wrapParticipants(id, chatFull.participants.participants);\r\n }\r\n\r\n if(chatFull.about) {\r\n chatFull.rAbout = RichTextProcessor.wrapRichText(chatFull.about, {noLinebreaks: true});\r\n }\r\n\r\n //chatFull.peerString = this.getChatString(id);\r\n chatFull.chat = chat;\r\n\r\n return chatFull;\r\n }\r\n\r\n public wrapParticipants(id: number, participants: any[]) {\r\n const chat = this.getChat(id);\r\n const myId = appUsersManager.getSelf().id;\r\n if(this.isChannel(id)) {\r\n const isAdmin = chat.pFlags.creator;\r\n participants.forEach((participant) => {\r\n participant.canLeave = myId === participant.user_id;\r\n participant.canKick = isAdmin && participant._ === 'channelParticipant';\r\n\r\n // just for order by last seen\r\n participant.user = appUsersManager.getUser(participant.user_id);\r\n });\r\n } else {\r\n const isAdmin = chat.pFlags.creator || chat.pFlags.admins_enabled && chat.pFlags.admin;\r\n participants.forEach((participant) => {\r\n participant.canLeave = myId === participant.user_id;\r\n participant.canKick = !participant.canLeave && (\r\n chat.pFlags.creator ||\r\n participant._ === 'chatParticipant' && (isAdmin || myId === participant.inviter_id)\r\n );\r\n\r\n // just for order by last seen\r\n participant.user = appUsersManager.getUser(participant.user_id);\r\n });\r\n }\r\n\r\n return participants;\r\n } */\r\n\r\n public createChannel(title: string, about: string): Promise<number> {\r\n return apiManager.invokeApi('channels.createChannel', {\r\n broadcast: true,\r\n title,\r\n about\r\n }).then((updates) => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n\r\n const channelId = (updates as any).chats[0].id;\r\n rootScope.dispatchEvent('history_focus', {peerId: -channelId});\r\n\r\n return channelId;\r\n });\r\n }\r\n\r\n public inviteToChannel(id: number, userIds: number[]) {\r\n const input = this.getChannelInput(id);\r\n const usersInputs = userIds.map(u => appUsersManager.getUserInput(u));\r\n\r\n return apiManager.invokeApi('channels.inviteToChannel', {\r\n channel: input,\r\n users: usersInputs\r\n }).then(updates => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n });\r\n }\r\n\r\n public createChat(title: string, userIds: number[]): Promise<number> {\r\n return apiManager.invokeApi('messages.createChat', {\r\n users: userIds.map(u => appUsersManager.getUserInput(u)),\r\n title\r\n }).then(updates => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n\r\n const chatId = (updates as any as Updates.updates).chats[0].id;\r\n rootScope.dispatchEvent('history_focus', {peerId: -chatId});\r\n\r\n return chatId;\r\n });\r\n }\r\n\r\n private onChatUpdated = (chatId: number, updates: any) => {\r\n //console.log('onChatUpdated', chatId, updates);\r\n\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n if(updates &&\r\n /* updates.updates &&\r\n updates.updates.length && */\r\n this.isChannel(chatId)) {\r\n rootScope.dispatchEvent('invalidate_participants', chatId);\r\n }\r\n };\r\n\r\n public leaveChannel(id: number) {\r\n return apiManager.invokeApi('channels.leaveChannel', {\r\n channel: this.getChannelInput(id)\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public joinChannel(id: number) {\r\n return apiManager.invokeApi('channels.joinChannel', {\r\n channel: this.getChannelInput(id)\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public addChatUser(id: number, userId: number, fwdLimit = 100) {\r\n return apiManager.invokeApi('messages.addChatUser', {\r\n chat_id: id,\r\n user_id: appUsersManager.getUserInput(userId),\r\n fwd_limit: fwdLimit\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public deleteChatUser(id: number, userId: number) {\r\n return apiManager.invokeApi('messages.deleteChatUser', {\r\n chat_id: id,\r\n user_id: appUsersManager.getUserInput(userId)\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public leaveChat(id: number) {\r\n return this.deleteChatUser(id, appUsersManager.getSelf().id);\r\n }\r\n\r\n public leave(id: number) {\r\n return this.isChannel(id) ? this.leaveChannel(id) : this.leaveChat(id);\r\n }\r\n\r\n public delete(id: number) {\r\n return this.isChannel(id) ? this.deleteChannel(id) : this.deleteChat(id);\r\n }\r\n\r\n public deleteChannel(id: number) {\r\n return apiManager.invokeApi('channels.deleteChannel', {\r\n channel: this.getChannelInput(id)\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public deleteChat(id: number) {\r\n //return this.leaveChat(id).then(() => {\r\n return apiManager.invokeApi('messages.deleteChat', {\r\n chat_id: id\r\n });\r\n //});\r\n }\r\n\r\n public migrateChat(id: number): Promise<number> {\r\n const chat: Chat = this.getChat(id);\r\n if(chat._ === 'channel') return Promise.resolve(chat.id);\r\n return apiManager.invokeApi('messages.migrateChat', {\r\n chat_id: id\r\n }).then((updates) => {\r\n this.onChatUpdated(id, updates);\r\n const update: Update.updateChannel = (updates as Updates.updates).updates.find(u => u._ === 'updateChannel') as any;\r\n return update.channel_id;\r\n });\r\n }\r\n\r\n public updateUsername(id: number, username: string) {\r\n return apiManager.invokeApi('channels.updateUsername', {\r\n channel: this.getChannelInput(id),\r\n username\r\n }).then((bool) => {\r\n if(bool) {\r\n const chat: Chat.channel = this.getChat(id);\r\n chat.username = username;\r\n }\r\n\r\n return bool;\r\n });\r\n }\r\n\r\n public editPhoto(id: number, inputFile: InputFile) {\r\n const inputChatPhoto: InputChatPhoto = {\r\n _: 'inputChatUploadedPhoto',\r\n file: inputFile\r\n };\r\n\r\n let promise: any;\r\n if(this.isChannel(id)) {\r\n promise = apiManager.invokeApi('channels.editPhoto', {\r\n channel: this.getChannelInput(id),\r\n photo: inputChatPhoto\r\n });\r\n } else {\r\n promise = apiManager.invokeApi('messages.editChatPhoto', {\r\n chat_id: id,\r\n photo: inputChatPhoto\r\n });\r\n }\r\n\r\n return promise.then((updates: any) => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n });\r\n }\r\n\r\n public editTitle(id: number, title: string) {\r\n let promise: any;\r\n\r\n if(this.isChannel(id)) {\r\n promise = apiManager.invokeApi('channels.editTitle', {\r\n channel: this.getChannelInput(id),\r\n title\r\n });\r\n } else {\r\n promise = apiManager.invokeApi('messages.editChatTitle', {\r\n chat_id: id,\r\n title\r\n });\r\n }\r\n\r\n return promise.then((updates: any) => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n });\r\n }\r\n\r\n public editAbout(id: number, about: string) {\r\n return apiManager.invokeApi('messages.editChatAbout', {\r\n peer: appPeersManager.getInputPeerById(-id),\r\n about\r\n }).then(bool => {\r\n //apiUpdatesManager.processUpdateMessage(updates);\r\n rootScope.dispatchEvent('peer_bio_edit', -id);\r\n });\r\n }\r\n\r\n public getParticipantPeerId(participant: ChannelParticipant | ChatParticipant) {\r\n const peerId = (participant as ChannelParticipant.channelParticipantBanned).peer ? \r\n appPeersManager.getPeerId((participant as ChannelParticipant.channelParticipantBanned).peer) : \r\n (participant as ChatParticipant.chatParticipant).user_id;\r\n return peerId;\r\n }\r\n\r\n public editBanned(id: number, participant: number | ChannelParticipant, banned_rights: ChatBannedRights) {\r\n const peerId = typeof(participant) === 'number' ? participant : this.getParticipantPeerId(participant);\r\n return apiManager.invokeApi('channels.editBanned', {\r\n channel: this.getChannelInput(id),\r\n participant: appPeersManager.getInputPeerById(peerId),\r\n banned_rights\r\n }).then((updates) => {\r\n this.onChatUpdated(id, updates);\r\n\r\n if(typeof(participant) !== 'number') {\r\n const timestamp = Date.now() / 1000 | 0;\r\n apiUpdatesManager.processLocalUpdate({\r\n _: 'updateChannelParticipant',\r\n channel_id: id,\r\n date: timestamp,\r\n actor_id: undefined,\r\n qts: undefined,\r\n user_id: peerId,\r\n prev_participant: participant,\r\n new_participant: Object.keys(banned_rights.pFlags).length ? {\r\n _: 'channelParticipantBanned',\r\n date: timestamp,\r\n banned_rights,\r\n kicked_by: appUsersManager.getSelf().id,\r\n peer: appPeersManager.getOutputPeer(peerId),\r\n pFlags: {}\r\n } : undefined\r\n });\r\n }\r\n });\r\n }\r\n\r\n public clearChannelParticipantBannedRights(id: number, participant: number | ChannelParticipant) {\r\n return this.editBanned(id, participant, {\r\n _: 'chatBannedRights',\r\n until_date: 0,\r\n pFlags: {}\r\n });\r\n }\r\n \r\n public kickFromChannel(id: number, participant: number | ChannelParticipant) {\r\n return this.editBanned(id, participant, {\r\n _: 'chatBannedRights',\r\n until_date: 0,\r\n pFlags: {\r\n view_messages: true\r\n }\r\n });\r\n }\r\n}\r\n\r\nconst appChatsManager = new AppChatsManager();\r\nMOUNT_CLASS_TO.appChatsManager = appChatsManager;\r\nexport default appChatsManager;\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\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 constructor() {\r\n rootScope.addMultipleEventsListeners({\r\n updatePeerBlocked: (update) => {\r\n rootScope.dispatchEvent('peer_block', {peerId: this.getPeerId(update.peer_id), blocked: update.blocked});\r\n }\r\n });\r\n }\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) 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\r\n if(onlyFirstName) {\r\n title = title.split(' ')[0];\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 'ChatList.Context.LeaveChannel';\r\n\r\n case 'megagroup':\r\n return 'ChatList.Context.LeaveGroup';\r\n\r\n case 'group':\r\n return 'ChatList.Context.DeleteAndExit';\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","/*\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 if(pos === undefined) {\r\n pos = array.indexOf(element);\r\n if(pos !== -1) {\r\n array.splice(pos, 1);\r\n }\r\n }\r\n\r\n const sortProperty: number = element[property];\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","/*\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\n//import apiManager from '../mtproto/apiManager';\r\nimport DEBUG, { MOUNT_CLASS_TO } from '../../config/debug';\r\nimport { Message, MessageFwdHeader, Peer, Update, Updates } from '../../layer';\r\nimport { logger, LogTypes } from '../logger';\r\nimport apiManager from '../mtproto/mtprotoworker';\r\nimport rootScope from '../rootScope';\r\n//import networkerFactory from '../mtproto/networkerFactory';\r\nimport appUsersManager from \"./appUsersManager\";\r\nimport appChatsManager from \"./appChatsManager\";\r\nimport appPeersManager from \"./appPeersManager\";\r\nimport appStateManager from './appStateManager';\r\nimport serverTimeManager from '../mtproto/serverTimeManager';\r\n\r\ntype UpdatesState = {\r\n pendingPtsUpdates: (Update & {pts: number, pts_count: number})[],\r\n pendingSeqUpdates?: {[seq: number]: {seq: number, date: number, updates: any[]}},\r\n syncPending: {\r\n seqAwaiting?: number,\r\n ptsAwaiting?: true,\r\n timeout: number\r\n },\r\n syncLoading: Promise<void>,\r\n\r\n seq?: number,\r\n pts?: number,\r\n date?: number,\r\n lastPtsUpdateTime?: number\r\n};\r\n\r\nconst SYNC_DELAY = 6;\r\n\r\nexport class ApiUpdatesManager {\r\n public updatesState: UpdatesState = {\r\n pendingPtsUpdates: [],\r\n pendingSeqUpdates: {},\r\n syncPending: null,\r\n syncLoading: null\r\n };\r\n\r\n private channelStates: {[channelId: number]: UpdatesState} = {};\r\n private attached = false;\r\n\r\n private log = logger('UPDATES', LogTypes.Error | LogTypes.Warn | LogTypes.Log/* | LogTypes.Debug */);\r\n private debug = DEBUG;\r\n\r\n private setProxy() {\r\n const self = this;\r\n this.updatesState = new Proxy(this.updatesState, {\r\n set: function(target: ApiUpdatesManager['updatesState'], key: keyof ApiUpdatesManager['updatesState'], value: ApiUpdatesManager['updatesState'][typeof key]) {\r\n // @ts-ignore\r\n target[key] = value;\r\n self.saveUpdatesState();\r\n return true;\r\n }\r\n });\r\n }\r\n\r\n public saveUpdatesState() {\r\n const us = this.updatesState;\r\n appStateManager.pushToState('updates', {\r\n seq: us.seq,\r\n pts: us.pts,\r\n date: us.date\r\n });\r\n }\r\n\r\n private popPendingSeqUpdate() {\r\n const state = this.updatesState;\r\n const nextSeq = state.seq + 1;\r\n const pendingUpdatesData = state.pendingSeqUpdates[nextSeq];\r\n if(!pendingUpdatesData) {\r\n return false;\r\n }\r\n\r\n const updates = pendingUpdatesData.updates;\r\n for(let i = 0, length = updates.length; i < length; ++i) {\r\n this.saveUpdate(updates[i]);\r\n }\r\n\r\n state.seq = pendingUpdatesData.seq;\r\n if(pendingUpdatesData.date && state.date < pendingUpdatesData.date) {\r\n state.date = pendingUpdatesData.date;\r\n }\r\n delete state.pendingSeqUpdates[nextSeq];\r\n \r\n if(!this.popPendingSeqUpdate() &&\r\n state.syncPending &&\r\n state.syncPending.seqAwaiting &&\r\n state.seq >= state.syncPending.seqAwaiting) {\r\n if(!state.syncPending.ptsAwaiting) {\r\n clearTimeout(state.syncPending.timeout);\r\n state.syncPending = null;\r\n } else {\r\n delete state.syncPending.seqAwaiting;\r\n }\r\n }\r\n \r\n return true;\r\n }\r\n\r\n private popPendingPtsUpdate(channelId: number) {\r\n const curState = channelId ? this.getChannelState(channelId) : this.updatesState;\r\n if(!curState.pendingPtsUpdates.length) {\r\n return false;\r\n }\r\n\r\n curState.pendingPtsUpdates.sort((a, b) => {\r\n return a.pts - b.pts;\r\n });\r\n // this.log('pop update', channelId, curState.pendingPtsUpdates)\r\n \r\n let curPts = curState.pts;\r\n let goodPts = 0;\r\n let goodIndex = 0;\r\n for(let i = 0, length = curState.pendingPtsUpdates.length; i < length; ++i) {\r\n const update = curState.pendingPtsUpdates[i];\r\n curPts += update.pts_count;\r\n if(curPts >= update.pts) {\r\n goodPts = update.pts;\r\n goodIndex = i;\r\n }\r\n }\r\n \r\n if(!goodPts) {\r\n return false;\r\n }\r\n \r\n this.debug && this.log.debug('pop pending pts updates', goodPts, curState.pendingPtsUpdates.slice(0, goodIndex + 1));\r\n \r\n curState.pts = goodPts;\r\n for(let i = 0; i <= goodIndex; ++i) {\r\n const update = curState.pendingPtsUpdates[i];\r\n\r\n // @ts-ignore\r\n this.saveUpdate(update);\r\n }\r\n curState.pendingPtsUpdates.splice(0, goodIndex + 1);\r\n \r\n if(!curState.pendingPtsUpdates.length && curState.syncPending) {\r\n if(!curState.syncPending.seqAwaiting) {\r\n clearTimeout(curState.syncPending.timeout);\r\n curState.syncPending = null;\r\n } else {\r\n delete curState.syncPending.ptsAwaiting;\r\n }\r\n }\r\n \r\n return true;\r\n }\r\n\r\n public forceGetDifference() {\r\n if(!this.updatesState.syncLoading) {\r\n this.getDifference();\r\n }\r\n }\r\n\r\n public processLocalUpdate(update: Update) {\r\n this.processUpdateMessage({\r\n _: 'updateShort',\r\n update\r\n } as Updates);\r\n }\r\n\r\n public processUpdateMessage = (updateMessage: any, options: Partial<{\r\n override: boolean\r\n }> = {}) => {\r\n // return forceGetDifference()\r\n const processOpts = {\r\n date: updateMessage.date,\r\n seq: updateMessage.seq,\r\n seqStart: updateMessage.seq_start,\r\n //ignoreSyncLoading: options.ignoreSyncLoading\r\n };\r\n\r\n this.debug && this.log.debug('processUpdateMessage', updateMessage);\r\n \r\n switch(updateMessage._) {\r\n case 'updatesTooLong':\r\n case 'new_session_created':\r\n this.forceGetDifference();\r\n break;\r\n \r\n case 'updateShort':\r\n this.processUpdate(updateMessage.update, processOpts);\r\n break;\r\n \r\n case 'updateShortMessage':\r\n case 'updateShortChatMessage': {\r\n this.debug && this.log.debug('updateShortMessage | updateShortChatMessage', {...updateMessage});\r\n const isOut = updateMessage.pFlags.out;\r\n const fromId = updateMessage.from_id || (isOut ? rootScope.myId : updateMessage.user_id);\r\n const toId = updateMessage.chat_id\r\n ? -updateMessage.chat_id\r\n : (updateMessage.user_id || rootScope.myId);\r\n \r\n this.processUpdate({\r\n _: 'updateNewMessage',\r\n message: {\r\n _: 'message',\r\n pFlags: updateMessage.pFlags,\r\n id: updateMessage.id,\r\n from_id: appPeersManager.getOutputPeer(fromId),\r\n peer_id: appPeersManager.getOutputPeer(toId),\r\n date: updateMessage.date,\r\n message: updateMessage.message,\r\n fwd_from: updateMessage.fwd_from,\r\n reply_to: updateMessage.reply_to,\r\n entities: updateMessage.entities\r\n },\r\n pts: updateMessage.pts,\r\n pts_count: updateMessage.pts_count\r\n }, processOpts);\r\n break;\r\n }\r\n \r\n case 'updatesCombined':\r\n case 'updates':\r\n appUsersManager.saveApiUsers(updateMessage.users, options.override);\r\n appChatsManager.saveApiChats(updateMessage.chats, options.override);\r\n \r\n updateMessage.updates.forEach((update: Update) => {\r\n this.processUpdate(update, processOpts);\r\n });\r\n break;\r\n \r\n default:\r\n this.log.warn('Unknown update message', updateMessage);\r\n }\r\n };\r\n \r\n private getDifference(first = false): Promise<void> {\r\n // this.trace('Get full diff')\r\n const updatesState = this.updatesState;\r\n let wasSyncing = updatesState.syncLoading;\r\n if(!wasSyncing) {\r\n updatesState.pendingSeqUpdates = {};\r\n updatesState.pendingPtsUpdates = [];\r\n }\r\n \r\n if(updatesState.syncPending) {\r\n clearTimeout(updatesState.syncPending.timeout);\r\n updatesState.syncPending = null;\r\n }\r\n\r\n const promise = apiManager.invokeApi('updates.getDifference', {\r\n pts: updatesState.pts, \r\n pts_total_limit: first /* && false */? /* 50 */1200 : undefined,\r\n date: updatesState.date, \r\n qts: -1\r\n }, {\r\n timeout: 0x7fffffff\r\n }).then((differenceResult) => {\r\n this.debug && this.log.debug('Get diff result', differenceResult);\r\n\r\n if(differenceResult._ === 'updates.differenceEmpty') {\r\n this.debug && this.log.debug('apply empty diff', differenceResult.seq);\r\n updatesState.date = differenceResult.date;\r\n updatesState.seq = differenceResult.seq;\r\n return;\r\n }\r\n\r\n // ! SORRY I'M SORRY I'M SORRY\r\n if(first) {\r\n rootScope.dispatchEvent('state_synchronizing');\r\n }\r\n\r\n if(differenceResult._ !== 'updates.differenceTooLong') {\r\n appUsersManager.saveApiUsers(differenceResult.users);\r\n appChatsManager.saveApiChats(differenceResult.chats);\r\n\r\n // Should be first because of updateMessageID\r\n // this.log('applying', differenceResult.other_updates.length, 'other updates')\r\n \r\n differenceResult.other_updates.forEach((update) => {\r\n switch(update._) {\r\n case 'updateChannelTooLong':\r\n case 'updateNewChannelMessage':\r\n case 'updateEditChannelMessage':\r\n this.processUpdate(update);\r\n return;\r\n }\r\n \r\n this.saveUpdate(update);\r\n });\r\n\r\n // this.log('applying', differenceResult.new_messages.length, 'new messages')\r\n differenceResult.new_messages.forEach((apiMessage) => {\r\n this.saveUpdate({\r\n _: 'updateNewMessage',\r\n message: apiMessage,\r\n pts: updatesState.pts,\r\n pts_count: 0\r\n });\r\n });\r\n\r\n const nextState = differenceResult._ === 'updates.difference' ? differenceResult.state : differenceResult.intermediate_state;\r\n updatesState.seq = nextState.seq;\r\n updatesState.pts = nextState.pts;\r\n updatesState.date = nextState.date;\r\n } else {\r\n updatesState.pts = differenceResult.pts;\r\n updatesState.date = (Date.now() / 1000 | 0) + serverTimeManager.serverTimeOffset;\r\n delete updatesState.seq;\r\n \r\n this.channelStates = {};\r\n \r\n this.log.warn('getDifference:', differenceResult._);\r\n rootScope.dispatchEvent('state_cleared');\r\n }\r\n \r\n // this.log('apply diff', updatesState.seq, updatesState.pts)\r\n \r\n if(differenceResult._ === 'updates.differenceSlice') {\r\n return this.getDifference();\r\n } else {\r\n this.debug && this.log.debug('finished get diff');\r\n }\r\n });\r\n\r\n if(!wasSyncing) {\r\n this.justAName(updatesState, promise);\r\n }\r\n \r\n return promise;\r\n }\r\n\r\n private getChannelDifference(channelId: number): Promise<void> {\r\n const channelState = this.getChannelState(channelId);\r\n const wasSyncing = channelState.syncLoading;\r\n if(!wasSyncing) {\r\n channelState.pendingPtsUpdates = [];\r\n }\r\n\r\n if(channelState.syncPending) {\r\n clearTimeout(channelState.syncPending.timeout);\r\n channelState.syncPending = null;\r\n }\r\n\r\n //this.log.trace('Get channel diff', appChatsManager.getChat(channelId), channelState.pts);\r\n const promise = apiManager.invokeApi('updates.getChannelDifference', {\r\n channel: appChatsManager.getChannelInput(channelId),\r\n filter: {_: 'channelMessagesFilterEmpty'},\r\n pts: channelState.pts,\r\n limit: 30\r\n }, {timeout: 0x7fffffff}).then((differenceResult) => {\r\n this.debug && this.log.debug('Get channel diff result', differenceResult)\r\n channelState.pts = 'pts' in differenceResult ? differenceResult.pts : undefined;\r\n \r\n if(differenceResult._ === 'updates.channelDifferenceEmpty') {\r\n this.debug && this.log.debug('apply channel empty diff', differenceResult);\r\n return;\r\n }\r\n \r\n if(differenceResult._ === 'updates.channelDifferenceTooLong') {\r\n this.debug && this.log.debug('channel diff too long', differenceResult);\r\n delete this.channelStates[channelId];\r\n\r\n this.saveUpdate({_: 'updateChannelReload', channel_id: channelId});\r\n return;\r\n }\r\n \r\n appUsersManager.saveApiUsers(differenceResult.users);\r\n appChatsManager.saveApiChats(differenceResult.chats);\r\n \r\n // Should be first because of updateMessageID\r\n this.debug && this.log.debug('applying', differenceResult.other_updates.length, 'channel other updates');\r\n differenceResult.other_updates.forEach((update) => {\r\n this.saveUpdate(update);\r\n });\r\n \r\n this.debug && this.log.debug('applying', differenceResult.new_messages.length, 'channel new messages');\r\n differenceResult.new_messages.forEach((apiMessage) => {\r\n this.saveUpdate({\r\n _: 'updateNewChannelMessage',\r\n message: apiMessage,\r\n pts: channelState.pts,\r\n pts_count: 0\r\n });\r\n });\r\n \r\n this.debug && this.log.debug('apply channel diff', channelState.pts);\r\n \r\n if(differenceResult._ === 'updates.channelDifference' &&\r\n !differenceResult.pFlags['final']) {\r\n return this.getChannelDifference(channelId);\r\n } else {\r\n this.debug && this.log.debug('finished channel get diff');\r\n }\r\n });\r\n\r\n if(!wasSyncing) {\r\n this.justAName(channelState, promise, channelId);\r\n }\r\n\r\n return promise;\r\n }\r\n\r\n private justAName(state: UpdatesState, promise: UpdatesState['syncLoading'], channelId?: number) {\r\n state.syncLoading = promise;\r\n rootScope.dispatchEvent('state_synchronizing', channelId);\r\n\r\n promise.then(() => {\r\n state.syncLoading = null;\r\n rootScope.dispatchEvent('state_synchronized', channelId);\r\n }, () => {\r\n state.syncLoading = null;\r\n });\r\n }\r\n \r\n public addChannelState(channelId: number, pts: number) {\r\n if(!pts) {\r\n throw new Error('Add channel state without pts ' + channelId);\r\n }\r\n\r\n if(!(channelId in this.channelStates)) {\r\n this.channelStates[channelId] = {\r\n pts,\r\n pendingPtsUpdates: [],\r\n syncPending: null,\r\n syncLoading: null\r\n };\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n public getChannelState(channelId: number, pts?: number) {\r\n if(this.channelStates[channelId] === undefined) {\r\n this.addChannelState(channelId, pts);\r\n }\r\n\r\n return this.channelStates[channelId];\r\n }\r\n\r\n private processUpdate(update: Update, options: Partial<{\r\n date: number,\r\n seq: number,\r\n seqStart: number/* ,\r\n ignoreSyncLoading: boolean */\r\n }> = {}) {\r\n let channelId = 0;\r\n switch(update._) {\r\n case 'updateNewChannelMessage':\r\n case 'updateEditChannelMessage':\r\n channelId = -appPeersManager.getPeerId(update.message.peer_id);\r\n break;\r\n /* case 'updateDeleteChannelMessages':\r\n channelId = update.channel_id;\r\n break; */\r\n case 'updateChannelTooLong':\r\n channelId = update.channel_id;\r\n if(!(channelId in this.channelStates)) {\r\n return false;\r\n }\r\n break;\r\n default:\r\n if('channel_id' in update) {\r\n channelId = update.channel_id;\r\n }\r\n break;\r\n }\r\n \r\n const {pts, pts_count} = update as Update.updateNewMessage;\r\n const curState = channelId ? this.getChannelState(channelId, pts) : this.updatesState;\r\n \r\n // this.log.log('process', channelId, curState.pts, update)\r\n \r\n if(curState.syncLoading/* && !options.ignoreSyncLoading */) {\r\n return false;\r\n }\r\n \r\n if(update._ === 'updateChannelTooLong') {\r\n if(!curState.lastPtsUpdateTime ||\r\n curState.lastPtsUpdateTime < (Date.now() - SYNC_DELAY)) {\r\n // this.log.trace('channel too long, get diff', channelId, update)\r\n this.getChannelDifference(channelId);\r\n }\r\n return false;\r\n }\r\n \r\n if(update._ === 'updateNewMessage' ||\r\n update._ === 'updateEditMessage' ||\r\n update._ === 'updateNewChannelMessage' ||\r\n update._ === 'updateEditChannelMessage') {\r\n const message = update.message as Message.message;\r\n const toPeerId = appPeersManager.getPeerId(message.peer_id);\r\n const fwdHeader: MessageFwdHeader.messageFwdHeader = message.fwd_from || {} as any;\r\n let reason: string;\r\n if(message.from_id && !appUsersManager.hasUser(appPeersManager.getPeerId(message.from_id), message.pFlags.post/* || channelId*/) && (reason = 'author') ||\r\n fwdHeader.from_id && !appUsersManager.hasUser(appPeersManager.getPeerId(fwdHeader.from_id), !!(fwdHeader.from_id as Peer.peerChannel).channel_id) && (reason = 'fwdAuthor') ||\r\n (fwdHeader.from_id as Peer.peerChannel)?.channel_id && !appChatsManager.hasChat((fwdHeader.from_id as Peer.peerChannel).channel_id, true) && (reason = 'fwdChannel') ||\r\n toPeerId > 0 && !appUsersManager.hasUser(toPeerId) && (reason = 'toPeer User') ||\r\n toPeerId < 0 && !appChatsManager.hasChat(-toPeerId) && (reason = 'toPeer Chat')) {\r\n this.log.warn('Not enough data for message update', toPeerId, reason, message);\r\n if(channelId && appChatsManager.hasChat(channelId)) {\r\n this.getChannelDifference(channelId);\r\n } else {\r\n this.forceGetDifference();\r\n }\r\n return false;\r\n }\r\n } else if(channelId && !appChatsManager.hasChat(channelId)) {\r\n // this.log.log('skip update, missing channel', channelId, update)\r\n return false;\r\n }\r\n \r\n let popPts: boolean;\r\n let popSeq: boolean;\r\n \r\n if(pts) {\r\n const newPts = curState.pts + (pts_count || 0);\r\n if(newPts < pts) {\r\n this.debug && this.log.warn('Pts hole', curState, update, channelId && appChatsManager.getChat(channelId));\r\n curState.pendingPtsUpdates.push(update as Update.updateNewMessage);\r\n if(!curState.syncPending && !curState.syncLoading) {\r\n curState.syncPending = {\r\n timeout: window.setTimeout(() => {\r\n curState.syncPending = null;\r\n\r\n if(curState.syncLoading) {\r\n return;\r\n }\r\n\r\n if(channelId) {\r\n this.getChannelDifference(channelId);\r\n } else {\r\n this.getDifference();\r\n }\r\n }, SYNC_DELAY)\r\n };\r\n }\r\n\r\n curState.syncPending.ptsAwaiting = true;\r\n return false;\r\n }\r\n\r\n if(pts > curState.pts) {\r\n curState.pts = pts;\r\n popPts = true;\r\n \r\n curState.lastPtsUpdateTime = Date.now();\r\n } else if(pts_count) {\r\n // this.log.warn('Duplicate update', update)\r\n return false;\r\n }\r\n\r\n if(channelId && options.date && this.updatesState.date < options.date) {\r\n this.updatesState.date = options.date;\r\n }\r\n } else if(!channelId && options.seq > 0) {\r\n const seq = options.seq;\r\n const seqStart = options.seqStart || seq;\r\n \r\n if(seqStart !== curState.seq + 1) {\r\n if(seqStart > curState.seq) {\r\n this.debug && this.log.warn('Seq hole', curState, curState.syncPending && curState.syncPending.seqAwaiting);\r\n \r\n if(curState.pendingSeqUpdates[seqStart] === undefined) {\r\n curState.pendingSeqUpdates[seqStart] = {seq, date: options.date, updates: []};\r\n }\r\n curState.pendingSeqUpdates[seqStart].updates.push(update);\r\n \r\n if(!curState.syncPending) {\r\n curState.syncPending = {\r\n timeout: window.setTimeout(() => {\r\n curState.syncPending = null;\r\n\r\n if(curState.syncLoading) {\r\n return;\r\n }\r\n\r\n this.getDifference();\r\n }, SYNC_DELAY)\r\n };\r\n }\r\n\r\n if(!curState.syncPending.seqAwaiting ||\r\n curState.syncPending.seqAwaiting < seqStart) {\r\n curState.syncPending.seqAwaiting = seqStart;\r\n }\r\n return false;\r\n }\r\n }\r\n \r\n if(curState.seq !== seq) {\r\n curState.seq = seq;\r\n if(options.date && curState.date < options.date) {\r\n curState.date = options.date;\r\n }\r\n\r\n popSeq = true;\r\n }\r\n }\r\n \r\n this.saveUpdate(update);\r\n \r\n if(popPts) {\r\n this.popPendingPtsUpdate(channelId);\r\n } else if(popSeq) {\r\n this.popPendingSeqUpdate();\r\n }\r\n }\r\n\r\n public saveUpdate(update: Update) {\r\n //this.debug && this.log('saveUpdate', update);\r\n rootScope.dispatchEvent(update._, update as any);\r\n }\r\n \r\n public attach() {\r\n if(this.attached) return;\r\n\r\n //return;\r\n\r\n this.log('attach');\r\n \r\n this.attached = true;\r\n\r\n appStateManager.getState().then(_state => {\r\n const state = _state.updates;\r\n\r\n //rootScope.broadcast('state_synchronizing');\r\n if(!state || !state.pts || !state.date || !state.seq) {\r\n this.log('will get new state');\r\n\r\n this.updatesState.syncLoading = new Promise((resolve) => {\r\n apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult) => {\r\n this.updatesState.seq = stateResult.seq;\r\n this.updatesState.pts = stateResult.pts;\r\n this.updatesState.date = stateResult.date;\r\n this.saveUpdatesState();\r\n //setTimeout(() => {\r\n this.updatesState.syncLoading = null;\r\n resolve();\r\n //rootScope.broadcast('state_synchronized');\r\n //}, 1000);\r\n \r\n // ! for testing\r\n // updatesState.seq = 1\r\n // updatesState.pts = stateResult.pts - 5000\r\n // updatesState.date = 1\r\n // getDifference()\r\n });\r\n });\r\n } else {\r\n // ! for testing\r\n /* state.seq = 1;\r\n state.pts = state.pts - 15;\r\n state.date = 1; */\r\n // state.pts -= 100;\r\n\r\n Object.assign(this.updatesState, state);\r\n \r\n this.log('will get difference', Object.assign({}, state));\r\n \r\n this.getDifference(true)/* .finally(() => {\r\n if(this.updatesState.syncLoading) {\r\n rootScope.broadcast('state_synchronizing');\r\n }\r\n }) */;\r\n }\r\n\r\n apiManager.setUpdatesProcessor(this.processUpdateMessage);\r\n\r\n // this.updatesState.syncLoading.then(() => {\r\n this.setProxy();\r\n // });\r\n });\r\n }\r\n}\r\n\r\nconst apiUpdatesManager = new ApiUpdatesManager();\r\nMOUNT_CLASS_TO.apiUpdatesManager = apiUpdatesManager;\r\nexport default apiUpdatesManager\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\nimport cleanSearchText from '../helpers/cleanSearchText';\r\n\r\nexport default class SearchIndex<SearchWhat> {\r\n private fullTexts: Map<SearchWhat, string> = new Map();\r\n\r\n // minChars can be 0 because it requires at least one word (one symbol) to be found\r\n constructor(private cleanText = true, private latinize = true, private minChars: number = 0) {\r\n\r\n }\r\n\r\n public indexObject(id: SearchWhat, searchText: string) {\r\n /* if(searchIndex.fullTexts.hasOwnProperty(id)) {\r\n return false;\r\n } */\r\n\r\n if(searchText.trim() && this.cleanText) {\r\n searchText = cleanSearchText(searchText, this.latinize);\r\n }\r\n\r\n if(!searchText) {\r\n this.fullTexts.delete(id);\r\n return false;\r\n }\r\n\r\n this.fullTexts.set(id, searchText);\r\n \r\n /* const shortIndexes = searchIndex.shortIndexes;\r\n searchText.split(' ').forEach((searchWord) => {\r\n let len = Math.min(searchWord.length, 3),\r\n wordPart, i;\r\n for(i = 1; i <= len; i++) {\r\n wordPart = searchWord.substr(0, i);\r\n if(shortIndexes[wordPart] === undefined) {\r\n shortIndexes[wordPart] = [id];\r\n } else {\r\n shortIndexes[wordPart].push(id);\r\n }\r\n }\r\n }); */\r\n }\r\n\r\n public search(query: string) {\r\n const fullTexts = this.fullTexts;\r\n //const shortIndexes = searchIndex.shortIndexes;\r\n\r\n if(this.cleanText) {\r\n query = cleanSearchText(query, this.latinize);\r\n }\r\n\r\n const newFoundObjs: Array<{fullText: string, fullTextLength: number, what: SearchWhat, foundChars: number}> = [];\r\n const queryWords = query.split(' ');\r\n const queryWordsLength = queryWords.length;\r\n fullTexts.forEach((fullText, what) => {\r\n let found = true;\r\n let foundChars = 0;\r\n for(let i = 0; i < queryWordsLength; ++i) { // * verify that all words are found\r\n const word = queryWords[i];\r\n const idx = fullText.indexOf(word);\r\n if(idx === -1 || (idx !== 0 && fullText[idx - 1] !== ' ')) { // * search only from word beginning\r\n found = false;\r\n break;\r\n }\r\n\r\n foundChars += word.length;\r\n }\r\n\r\n if(found) {\r\n foundChars += queryWordsLength - 1;\r\n const fullTextLength = fullText.length;\r\n if(this.minChars <= foundChars || fullTextLength <= foundChars) {\r\n newFoundObjs.push({fullText, fullTextLength, what, foundChars});\r\n }\r\n }\r\n });\r\n\r\n newFoundObjs.sort((a, b) => a.fullTextLength - b.fullTextLength || b.foundChars - a.foundChars);\r\n\r\n //newFoundObjs.sort((a, b) => a.fullText.localeCompare(b.fullText));\r\n const newFoundObjs2: Set<SearchWhat> = new Set(newFoundObjs.map(o => o.what));\r\n\r\n /* const queryWords = query.split(' ');\r\n let foundArr: number[];\r\n for(let i = 0; i < queryWords.length; i++) {\r\n const newFound = shortIndexes[queryWords[i].substr(0, 3)];\r\n if(!newFound) {\r\n foundArr = [];\r\n break;\r\n }\r\n \r\n if(foundArr === undefined || foundArr.length > newFound.length) {\r\n foundArr = newFound;\r\n }\r\n }\r\n\r\n for(let j = 0; j < foundArr.length; j++) {\r\n let found = true;\r\n let searchText = fullTexts[foundArr[j]];\r\n for(let i = 0; i < queryWords.length; i++) {\r\n if(searchText.indexOf(queryWords[i]) === -1) {\r\n found = false;\r\n break;\r\n }\r\n }\r\n\r\n if(found) {\r\n newFoundObjs[foundArr[j]] = true;\r\n }\r\n } */\r\n\r\n return newFoundObjs2;\r\n }\r\n}\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\nimport Config from \"../lib/config\";\r\n\r\nconst badCharsRe = /[`~!@#$%^&*()\\-_=+\\[\\]\\\\|{}'\";:\\/?.>,<]+/g;\r\nconst trimRe = /^\\s+|\\s$/g;\r\n\r\nexport default function cleanSearchText(text: string, latinize = true) {\r\n const hasTag = text.charAt(0) === '%';\r\n text = text.replace(badCharsRe, '').replace(trimRe, '');\r\n if(latinize) {\r\n text = text.replace(/[^A-Za-z0-9]/g, (ch) => {\r\n const latinizeCh = Config.LatinizeMap[ch];\r\n return latinizeCh !== undefined ? latinizeCh : ch;\r\n });\r\n }\r\n \r\n text = text.toLowerCase();\r\n if(hasTag) {\r\n text = '%' + text;\r\n }\r\n\r\n return text;\r\n}\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\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\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"],"sourceRoot":""}