2021-04-08 15:52:31 +02:00
/ *
* https : //github.com/morethanwords/tweb
* Copyright ( C ) 2019 - 2021 Eduard Kuzmenko
* https : //github.com/morethanwords/tweb/blob/master/LICENSE
2022-08-04 08:49:54 +02:00
*
2021-04-08 15:52:31 +02:00
* Originally from :
* https : //github.com/zhukov/webogram
* Copyright ( C ) 2014 Igor Zhukov < igor.beatle @ gmail.com >
* https : //github.com/zhukov/webogram/blob/master/LICENSE
* /
2023-01-25 15:21:38 +01:00
import type { ApiFileManager } from '../mtproto/apiFileManager' ;
import type { MediaSize } from '../../helpers/mediaSize' ;
import type { Progress } from './appDownloadManager' ;
import type { VIDEO_MIME_TYPE } from '../../environment/videoMimeTypesSupport' ;
2022-08-04 08:49:54 +02:00
import LazyLoadQueueBase from '../../components/lazyLoadQueueBase' ;
import deferredPromise , { CancellablePromise } from '../../helpers/cancellablePromise' ;
import tsNow from '../../helpers/tsNow' ;
import { randomLong } from '../../helpers/random' ;
2023-02-06 21:24:53 +01:00
import { Chat , ChatFull , Dialog as MTDialog , DialogPeer , DocumentAttribute , InputMedia , InputMessage , InputPeerNotifySettings , InputSingleMedia , Message , MessageAction , MessageEntity , MessageFwdHeader , MessageMedia , MessageReplies , MessageReplyHeader , MessagesDialogs , MessagesFilter , MessagesMessages , MethodDeclMap , NotifyPeer , PeerNotifySettings , PhotoSize , SendMessageAction , Update , Photo , Updates , ReplyMarkup , InputPeer , InputPhoto , InputDocument , InputGeoPoint , WebPage , GeoPoint , ReportReason , MessagesGetDialogs , InputChannel , InputDialogPeer , ReactionCount , MessagePeerReaction , MessagesSearchCounter , Peer , MessageReactions , Document , InputFile , Reaction , ForumTopic as MTForumTopic , MessagesForumTopics , MessagesGetReplies , MessagesGetHistory , MessagesAffectedHistory , UrlAuthResult , MessagesTranscribedAudio } from '../../layer' ;
2022-08-04 08:49:54 +02:00
import { ArgumentTypes , InvokeApiOptions } from '../../types' ;
import { logger , LogTypes } from '../logger' ;
import { ReferenceContext } from '../mtproto/referenceDatabase' ;
2023-01-06 20:27:29 +01:00
import DialogsStorage , { GLOBAL_FOLDER_ID } from '../storages/dialogs' ;
2022-08-04 08:49:54 +02:00
import { ChatRights } from './appChatsManager' ;
import { MyDocument } from './appDocsManager' ;
import { MyPhoto } from './appPhotosManager' ;
import { getFileNameByLocation } from '../../helpers/fileName' ;
import DEBUG from '../../config/debug' ;
import SlicedArray , { Slice , SliceEnd } from '../../helpers/slicedArray' ;
2023-01-06 20:27:29 +01:00
import { FOLDER_ID_ALL , GENERAL_TOPIC_ID , MUTE_UNTIL , NULL_PEER_ID , REAL_FOLDER_ID , REPLIES_HIDDEN_CHANNEL_ID , REPLIES_PEER_ID , SERVICE_PEER_ID , THUMB_TYPE_FULL } from '../mtproto/mtproto_config' ;
2022-11-22 13:57:21 +01:00
// import telegramMeWebManager from '../mtproto/telegramMeWebManager';
2022-08-04 08:49:54 +02:00
import { getMiddleware } from '../../helpers/middleware' ;
import assumeType from '../../helpers/assumeType' ;
import copy from '../../helpers/object/copy' ;
import getObjectKeysAndSort from '../../helpers/object/getObjectKeysAndSort' ;
import forEachReverse from '../../helpers/array/forEachReverse' ;
import deepEqual from '../../helpers/object/deepEqual' ;
import splitStringByLength from '../../helpers/string/splitStringByLength' ;
import debounce from '../../helpers/schedulers/debounce' ;
import { AppManager } from './manager' ;
import getPhotoMediaInput from './utils/photos/getPhotoMediaInput' ;
import getPhotoDownloadOptions from './utils/photos/getPhotoDownloadOptions' ;
import fixEmoji from '../richTextProcessor/fixEmoji' ;
import mergeEntities from '../richTextProcessor/mergeEntities' ;
import parseEntities from '../richTextProcessor/parseEntities' ;
import parseMarkdown from '../richTextProcessor/parseMarkdown' ;
import getServerMessageId from './utils/messageId/getServerMessageId' ;
import generateMessageId from './utils/messageId/generateMessageId' ;
import filterMessagesByInputFilter from './utils/messages/filterMessagesByInputFilter' ;
import ctx from '../../environment/ctx' ;
import { getEnvironment } from '../../environment/utils' ;
import getDialogIndex from './utils/dialogs/getDialogIndex' ;
import defineNotNumerableProperties from '../../helpers/object/defineNotNumerableProperties' ;
import getDocumentMediaInput from './utils/docs/getDocumentMediaInput' ;
import getDocumentInputFileName from './utils/docs/getDocumentInputFileName' ;
import getFileNameForUpload from '../../helpers/getFileNameForUpload' ;
import noop from '../../helpers/noop' ;
import appTabsManager from './appTabsManager' ;
import MTProtoMessagePort from '../mtproto/mtprotoMessagePort' ;
import getAlbumText from './utils/messages/getAlbumText' ;
import pause from '../../helpers/schedulers/pause' ;
import makeError from '../../helpers/makeError' ;
2022-08-13 14:14:06 +02:00
import getStickerEffectThumb from './utils/stickers/getStickerEffectThumb' ;
2022-08-18 13:21:19 +02:00
import getDocumentInput from './utils/docs/getDocumentInput' ;
2022-09-20 19:34:08 +02:00
import reactionsEqual from './utils/reactions/reactionsEqual' ;
2023-01-06 20:27:29 +01:00
import getPeerActiveUsernames from './utils/peers/getPeerActiveUsernames' ;
import { BroadcastEvents } from '../rootScope' ;
import setBooleanFlag from '../../helpers/object/setBooleanFlag' ;
import getMessageThreadId from './utils/messages/getMessageThreadId' ;
2022-08-04 08:49:54 +02:00
// console.trace('include');
2020-09-28 02:23:00 +02:00
// TODO: если удалить диалог находясь в папке, то он не удалится из папки и будет виден в настройках
2020-02-06 16:43:07 +01:00
2020-05-03 14:46:05 +02:00
const APITIMEOUT = 0 ;
2021-09-01 19:17:06 +02:00
const DO_NOT_READ_HISTORY = false ;
2020-05-03 14:46:05 +02:00
2023-01-11 15:43:14 +01:00
export type SendFileDetails = {
file : File | Blob | MyDocument ,
} & Partial < {
duration : number ,
width : number ,
height : number ,
objectURL : string ,
thumb : {
blob : Blob ,
url : string ,
size : MediaSize
} ,
strippedBytes : PhotoSize.photoStrippedSize [ 'bytes' ] ,
spoiler : boolean
} > ;
2020-04-14 17:46:31 +02:00
export type HistoryStorage = {
2020-02-06 16:43:07 +01:00
count : number | null ,
2022-04-13 00:51:20 +02:00
history : SlicedArray < number > ,
2020-12-23 02:18:07 +01:00
2020-12-20 04:54:35 +01:00
maxId? : number ,
2020-12-23 02:18:07 +01:00
readPromise? : Promise < void > ,
2020-12-11 03:06:16 +01:00
readMaxId? : number ,
2020-12-20 04:54:35 +01:00
readOutboxMaxId? : number ,
2021-04-15 10:44:27 +02:00
triedToReadMaxId? : number ,
2020-12-20 04:54:35 +01:00
2020-12-11 03:06:16 +01:00
maxOutId? : number ,
2021-08-03 03:44:13 +02:00
replyMarkup? : Exclude < ReplyMarkup , ReplyMarkup.replyInlineMarkup >
2020-02-06 16:43:07 +01:00
} ;
2020-04-14 17:46:31 +02:00
export type HistoryResult = {
count : number ,
2022-06-17 18:01:43 +02:00
history : number [ ] ,
isEnd : ReturnType < Slice < number > [ 'getEnds' ] > ,
2021-02-24 19:47:31 +01:00
offsetIdOffset? : number ,
2020-04-14 17:46:31 +02:00
} ;
2020-09-18 17:03:26 +02:00
export type Dialog = MTDialog . dialog ;
2023-01-06 20:27:29 +01:00
export type ForumTopic = MTForumTopic . forumTopic ;
2020-05-03 14:46:05 +02:00
2020-11-10 01:47:00 +01:00
export type MyMessage = Message . message | Message . messageService ;
2022-08-04 08:49:54 +02:00
export type MyInputMessagesFilter = 'inputMessagesFilterEmpty'
| 'inputMessagesFilterPhotos'
| 'inputMessagesFilterPhotoVideo'
| 'inputMessagesFilterVideo'
| 'inputMessagesFilterDocument'
| 'inputMessagesFilterVoice'
| 'inputMessagesFilterRoundVoice'
| 'inputMessagesFilterRoundVideo'
| 'inputMessagesFilterMusic'
| 'inputMessagesFilterUrl'
2020-10-15 00:46:29 +02:00
| 'inputMessagesFilterMyMentions'
2020-11-25 20:36:18 +01:00
| 'inputMessagesFilterChatPhotos'
| 'inputMessagesFilterPinned' ;
2020-09-28 02:23:00 +02:00
2020-12-08 20:48:44 +01:00
export type PinnedStorage = Partial < {
promise : Promise < PinnedStorage > ,
count : number ,
2020-12-11 03:06:16 +01:00
maxId : number
2020-12-08 20:48:44 +01:00
} > ;
2022-06-17 18:01:43 +02:00
export type MessagesStorage = Map < number , Message.message | Message.messageService > & { peerId : PeerId , type : MessagesStorageType , key : MessagesStorageKey } ;
export type MessagesStorageType = 'scheduled' | 'history' | 'grouped' ;
export type MessagesStorageKey = ` ${ PeerId } _ ${ MessagesStorageType } ` ;
2021-02-23 16:20:52 +01:00
2021-03-25 16:32:40 +01:00
export type MyMessageActionType = Message . messageService [ 'action' ] [ '_' ] ;
2021-07-15 17:34:34 +02:00
type PendingAfterMsg = Partial < InvokeApiOptions & {
afterMessageId : string ,
messageId : string
} > ;
2022-03-28 17:16:12 +02:00
type MapValueType < A > = A extends Map < any , infer V > ? V : never ;
export type BatchUpdates = {
'messages_reactions' : AppMessagesManager [ 'batchUpdateReactions' ] ,
'messages_views' : AppMessagesManager [ 'batchUpdateViews' ]
} ;
2022-06-17 18:01:43 +02:00
type PendingMessageDetails = {
peerId : PeerId ,
tempId : number ,
threadId : number ,
storage : MessagesStorage ,
sequential? : boolean
} ;
2022-06-30 16:14:33 +02:00
const processAfter = ( cb : ( ) = > void ) = > {
// setTimeout(cb, 0);
cb ( ) ;
} ;
2022-11-01 18:39:23 +01:00
const UPDATE_STICKERSET_ORDER = true ;
2023-01-06 20:27:29 +01:00
export type MessageSendingParams = Partial < {
threadId : number ,
replyToMsgId : number ,
scheduleDate : number ,
silent : boolean ,
sendAsPeerId : number ,
} > ;
2022-04-25 16:54:30 +02:00
export class AppMessagesManager extends AppManager {
2021-06-25 17:18:18 +02:00
private messagesStorageByPeerId : { [ peerId : string ] : MessagesStorage } ;
2022-06-17 18:01:43 +02:00
private groupedMessagesStorage : { [ groupId : string ] : MessagesStorage } ; // will be used for albums
2021-10-21 15:16:43 +02:00
private scheduledMessagesStorage : { [ peerId : PeerId ] : MessagesStorage } ;
2021-05-25 18:11:58 +02:00
private historiesStorage : {
2021-10-21 15:16:43 +02:00
[ peerId : PeerId ] : HistoryStorage
2021-06-25 17:18:18 +02:00
} ;
2021-05-25 18:11:58 +02:00
private threadsStorage : {
2021-10-21 15:16:43 +02:00
[ peerId : PeerId ] : {
2020-12-20 04:54:35 +01:00
[ threadId : string ] : HistoryStorage
}
2021-06-25 17:18:18 +02:00
} ;
2021-05-25 18:11:58 +02:00
private searchesStorage : {
2021-10-21 15:16:43 +02:00
[ peerId : PeerId ] : Partial < {
2020-12-08 20:48:44 +01:00
[ inputFilter in MyInputMessagesFilter ] : {
count? : number ,
history : number [ ]
}
} >
2021-06-25 17:18:18 +02:00
} ;
2023-01-06 20:27:29 +01:00
private pinnedMessages : { [ key : string ] : PinnedStorage } ;
2020-11-25 20:36:18 +01:00
2022-06-17 18:01:43 +02:00
private threadsServiceMessagesIdsStorage : { [ peerId_threadId : string ] : number } ;
2021-05-25 18:11:58 +02:00
private threadsToReplies : {
2020-12-22 04:02:30 +01:00
[ peerId_threadId : string ] : string ;
2021-06-25 17:18:18 +02:00
} ;
2020-12-22 04:02:30 +01:00
2021-05-25 18:11:58 +02:00
private pendingByRandomId : {
2022-06-17 18:01:43 +02:00
[ randomId : string ] : PendingMessageDetails
2020-12-18 04:07:32 +01:00
} = { } ;
2021-10-21 15:16:43 +02:00
private pendingByMessageId : { [ mid : string ] : Long } = { } ;
private pendingAfterMsgs : { [ peerId : PeerId ] : PendingAfterMsg } = { } ;
public pendingTopMsgs : { [ peerId : PeerId ] : number } = { } ;
2021-05-25 18:11:58 +02:00
private tempFinalizeCallbacks : {
2020-12-18 04:07:32 +01:00
[ tempId : string ] : {
2020-10-13 15:51:11 +02:00
[ callbackName : string ] : Partial < {
2022-08-04 08:49:54 +02:00
deferred : CancellablePromise < void > ,
2022-04-16 18:21:50 +02:00
callback : ( message : MyMessage ) = > Promise < any >
2020-10-13 15:51:11 +02:00
} >
}
} = { } ;
2022-08-04 08:49:54 +02:00
2021-11-26 10:58:12 +01:00
private sendSmthLazyLoadQueue = new LazyLoadQueueBase ( 10 ) ;
2020-02-06 16:43:07 +01:00
2022-06-17 18:01:43 +02:00
private needSingleMessages : Map < PeerId , Map < number , CancellablePromise < Message.message | Message.messageService > >> = new Map ( ) ;
2023-01-06 20:27:29 +01:00
private fetchSingleMessagesPromise : Promise < void > ;
2022-11-06 14:48:41 +01:00
private extendedMedia : Map < PeerId , Map < number , CancellablePromise < void > >> = new Map ( ) ;
2020-02-06 16:43:07 +01:00
2021-05-25 18:11:58 +02:00
private maxSeenId = 0 ;
2020-02-06 16:43:07 +01:00
2021-10-21 15:16:43 +02:00
public migratedFromTo : { [ peerId : PeerId ] : PeerId } = { } ;
public migratedToFrom : { [ peerId : PeerId ] : PeerId } = { } ;
2020-02-06 16:43:07 +01:00
2021-05-25 18:11:58 +02:00
private newDialogsHandlePromise : Promise < any > ;
2023-01-06 20:27:29 +01:00
private newDialogsToHandle : Map < PeerId , { dialog ? : Dialog , topics ? : Map < number , ForumTopic > } > = new Map ( ) ;
public newUpdatesAfterReloadToHandle : { [ key : string ] : Set < Update > } = { } ;
2021-03-08 23:15:44 +01:00
2023-01-06 20:27:29 +01:00
private notificationsHandlePromise : number ;
private notificationsToHandle : { [ key : string ] : {
2021-03-08 23:15:44 +01:00
fwdCount : number ,
2021-10-21 15:16:43 +02:00
fromId : PeerId ,
2021-03-08 23:15:44 +01:00
topMessage? : MyMessage
} } = { } ;
2020-02-06 16:43:07 +01:00
2020-06-20 03:11:24 +02:00
private reloadConversationsPromise : Promise < void > ;
2021-10-21 15:16:43 +02:00
private reloadConversationsPeers : Map < PeerId , { inputDialogPeer : InputDialogPeer , promise : CancellablePromise < Dialog > } > = new Map ( ) ;
2020-02-06 16:43:07 +01:00
2021-04-27 17:45:53 +02:00
public log = logger ( 'MESSAGES' , LogTypes . Error | LogTypes . Debug | LogTypes . Log | LogTypes . Warn ) ;
2020-06-19 13:49:55 +02:00
2021-02-10 07:06:22 +01:00
private groupedTempId = 0 ;
2023-01-06 20:27:29 +01:00
private typings : { [ key : string ] : { action : SendMessageAction , timeout? : number } } = { } ;
2021-05-09 22:29:30 +02:00
2021-06-29 03:19:53 +02:00
private middleware : ReturnType < typeof getMiddleware > ;
2023-01-06 20:27:29 +01:00
private unreadMentions : { [ key : string ] : SlicedArray < number > } = { } ;
private goToNextMentionPromises : { [ key : string ] : Promise < number > } = { } ;
2022-08-04 08:49:54 +02:00
2022-03-28 17:16:12 +02:00
private batchUpdates : {
[ k in keyof BatchUpdates ] ? : {
callback : BatchUpdates [ k ] ,
batch : ArgumentTypes < BatchUpdates [ k ] > [ 0 ]
}
} = { } ;
private batchUpdatesDebounced : ( ) = > Promise < void > ;
2021-09-01 19:17:06 +02:00
2022-06-17 18:01:43 +02:00
private uploadFilePromises : { [ fileName : string ] : CancellablePromise < any > } ;
protected after() {
this . clear ( true ) ;
2021-06-25 17:18:18 +02:00
2022-06-17 18:01:43 +02:00
this . apiUpdatesManager . addMultipleEventsListeners ( {
2021-04-24 19:06:24 +02:00
updateMessageID : this.onUpdateMessageId ,
updateNewDiscussionMessage : this.onUpdateNewMessage ,
updateNewMessage : this.onUpdateNewMessage ,
updateNewChannelMessage : this.onUpdateNewMessage ,
updateDialogUnreadMark : this.onUpdateDialogUnreadMark ,
updateEditMessage : this.onUpdateEditMessage ,
updateEditChannelMessage : this.onUpdateEditMessage ,
2022-02-06 20:35:18 +01:00
updateMessageReactions : this.onUpdateMessageReactions ,
2021-04-24 19:06:24 +02:00
updateReadChannelDiscussionInbox : this.onUpdateReadHistory ,
updateReadChannelDiscussionOutbox : this.onUpdateReadHistory ,
updateReadHistoryInbox : this.onUpdateReadHistory ,
updateReadHistoryOutbox : this.onUpdateReadHistory ,
updateReadChannelInbox : this.onUpdateReadHistory ,
updateReadChannelOutbox : this.onUpdateReadHistory ,
updateChannelReadMessagesContents : this.onUpdateReadMessagesContents ,
updateReadMessagesContents : this.onUpdateReadMessagesContents ,
updateChannelAvailableMessages : this.onUpdateChannelAvailableMessages ,
updateDeleteMessages : this.onUpdateDeleteMessages ,
updateDeleteChannelMessages : this.onUpdateDeleteMessages ,
updateChannel : this.onUpdateChannel ,
updateChannelReload : this.onUpdateChannelReload ,
updateChannelMessageViews : this.onUpdateChannelMessageViews ,
updateServiceNotification : this.onUpdateServiceNotification ,
updatePinnedMessages : this.onUpdatePinnedMessages ,
updatePinnedChannelMessages : this.onUpdatePinnedMessages ,
updateNotifySettings : this.onUpdateNotifySettings ,
updateNewScheduledMessage : this.onUpdateNewScheduledMessage ,
2022-11-06 14:48:41 +01:00
updateDeleteScheduledMessages : this.onUpdateDeleteScheduledMessages ,
2023-02-09 14:23:04 +01:00
updateMessageExtendedMedia : this.onUpdateMessageExtendedMedia ,
updateTranscribedAudio : this.onUpdateTranscribedAudio
2020-02-06 16:43:07 +01:00
} ) ;
2021-03-11 04:06:44 +01:00
// ! Invalidate notify settings, can optimize though
2022-06-17 18:01:43 +02:00
this . rootScope . addEventListener ( 'notify_peer_type_settings' , ( { key , settings } ) = > {
2021-10-21 15:16:43 +02:00
const dialogs = this . dialogsStorage . getFolderDialogs ( 0 ) . concat ( this . dialogsStorage . getFolderDialogs ( 1 ) ) ;
2023-01-06 20:27:29 +01:00
let filterFunc : ( dialog : typeof dialogs [ 0 ] ) = > boolean ;
2021-10-21 15:16:43 +02:00
if ( key === 'notifyUsers' ) filterFunc = ( dialog ) = > dialog . peerId . isUser ( ) ;
2022-04-25 16:54:30 +02:00
else if ( key === 'notifyBroadcasts' ) filterFunc = ( dialog ) = > this . appPeersManager . isBroadcast ( dialog . peerId ) ;
else filterFunc = ( dialog ) = > this . appPeersManager . isAnyGroup ( dialog . peerId ) ;
2021-10-21 15:16:43 +02:00
dialogs
. filter ( filterFunc )
2022-06-17 18:01:43 +02:00
. forEach ( ( dialog ) = > {
this . rootScope . dispatchEvent ( 'dialog_notify_settings' , dialog ) ;
2021-03-11 04:06:44 +01:00
} ) ;
} ) ;
2022-06-17 18:01:43 +02:00
this . rootScope . addEventListener ( 'webpage_updated' , ( { id , msgs } ) = > {
2021-08-03 03:44:13 +02:00
msgs . forEach ( ( { peerId , mid , isScheduled } ) = > {
2022-06-17 18:01:43 +02:00
const storage = isScheduled ? this . getScheduledMessagesStorage ( peerId ) : this . getHistoryMessagesStorage ( peerId ) ;
2021-08-03 03:44:13 +02:00
const message = this . getMessageFromStorage ( storage , mid ) as Message . message ;
2020-10-10 00:36:06 +02:00
if ( ! message ) return ;
message . media = {
2022-08-04 08:49:54 +02:00
_ : 'messageMediaWebPage' ,
2022-06-17 18:01:43 +02:00
webpage : this.appWebPagesManager.getCachedWebPage ( id )
2020-10-10 00:36:06 +02:00
} ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'message_edit' , {
storageKey : storage.key ,
2020-12-18 04:07:32 +01:00
peerId ,
2022-06-17 18:01:43 +02:00
mid ,
message
2020-04-26 03:45:07 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
} ) ;
} ) ;
2022-06-17 18:01:43 +02:00
this . rootScope . addEventListener ( 'draft_updated' , ( { peerId , threadId , draft } ) = > {
2023-01-06 20:27:29 +01:00
const dialog = this . dialogsStorage . getDialogOrTopic ( peerId , threadId ) ;
2021-09-19 14:17:55 +02:00
if ( dialog ) {
2023-01-06 20:27:29 +01:00
dialog . draft = draft ;
2021-09-19 14:17:55 +02:00
2023-01-06 20:27:29 +01:00
let drop = false ;
if ( ! draft && ! getServerMessageId ( dialog . top_message ) ) {
this . dialogsStorage . dropDialog ( peerId ) ;
drop = true ;
} else {
this . dialogsStorage . generateIndexForDialog ( dialog ) ;
this . dialogsStorage . pushDialog ( { dialog } ) ;
}
2021-09-19 14:17:55 +02:00
2023-01-06 20:27:29 +01:00
this . rootScope . dispatchEvent ( 'dialog_draft' , {
peerId ,
dialog ,
drop ,
draft
} ) ;
} else if ( threadId ) {
const chat = this . appChatsManager . getChat ( peerId . toChatId ( ) ) ;
if ( ! chat ) {
this . reloadConversation ( peerId ) ;
} else if ( ( chat as Chat . channel ) . pFlags . forum ) {
this . dialogsStorage . getForumTopicById ( peerId , threadId ) ;
2021-09-19 14:17:55 +02:00
}
2021-01-09 15:08:26 +01:00
} else {
this . reloadConversation ( peerId ) ;
2020-02-06 16:43:07 +01:00
}
2021-01-09 15:08:26 +01:00
} ) ;
2021-09-23 15:41:02 +02:00
2022-06-17 18:01:43 +02:00
this . rootScope . addEventListener ( 'poll_update' , ( { poll } ) = > {
2022-04-25 16:54:30 +02:00
const set = this . appPollsManager . pollToMessages [ poll . id ] ;
2021-09-23 15:41:02 +02:00
if ( set ) {
for ( const key of set ) {
const [ peerId , mid ] = key . split ( '_' ) ;
2021-10-21 15:16:43 +02:00
const message = this . getMessageByPeer ( peerId . toPeerId ( ) , + mid ) ;
2022-11-01 18:39:23 +01:00
if ( message ) {
this . setDialogToStateIfMessageIsTop ( message ) ;
}
2021-09-23 15:41:02 +02:00
}
}
} ) ;
2022-08-04 08:49:54 +02:00
2023-01-13 12:10:41 +01:00
// * clear forum cache
this . rootScope . addEventListener ( 'chat_toggle_forum' , ( { chatId , enabled } ) = > {
const peerId = chatId . toPeerId ( true ) ;
if ( ! enabled ) {
delete this . threadsStorage [ peerId ] ;
for ( const key in this . pinnedMessages ) {
if ( + key === peerId && key . startsWith ( peerId + '_' ) ) {
delete this . pinnedMessages [ key ] ;
}
}
}
} ) ;
2022-03-28 17:16:12 +02:00
this . batchUpdatesDebounced = debounce ( ( ) = > {
for ( const event in this . batchUpdates ) {
const details = this . batchUpdates [ event as keyof BatchUpdates ] ;
delete this . batchUpdates [ event as keyof BatchUpdates ] ;
// @ts-ignore
const result = details . callback ( details . batch ) ;
if ( result && ( ! ( result instanceof Array ) || result . length ) ) {
// @ts-ignore
rootScope . dispatchEvent ( event as keyof BatchUpdates , result ) ;
}
}
} , 33 , false , true ) ;
2022-06-17 18:01:43 +02:00
return this . appStateManager . getState ( ) . then ( ( state ) = > {
if ( state . maxSeenMsgId ) {
this . maxSeenId = state . maxSeenMsgId ;
}
} ) ;
2020-06-06 07:26:18 +02:00
}
2020-05-18 03:21:58 +02:00
2022-06-17 18:01:43 +02:00
public clear = ( init? : boolean ) = > {
2021-06-29 03:19:53 +02:00
if ( this . middleware ) {
this . middleware . clean ( ) ;
} else {
this . middleware = getMiddleware ( ) ;
2022-06-17 18:01:43 +02:00
this . uploadFilePromises = { } ;
2021-06-29 03:19:53 +02:00
}
2021-06-25 17:18:18 +02:00
this . messagesStorageByPeerId = { } ;
this . groupedMessagesStorage = { } ;
this . scheduledMessagesStorage = { } ;
this . historiesStorage = { } ;
this . threadsStorage = { } ;
this . searchesStorage = { } ;
this . pinnedMessages = { } ;
this . threadsServiceMessagesIdsStorage = { } ;
this . threadsToReplies = { } ;
2022-06-17 18:01:43 +02:00
this . dialogsStorage && this . dialogsStorage . clear ( init ) ;
this . filtersStorage && this . filtersStorage . clear ( init ) ;
} ;
2021-05-01 12:25:03 +02:00
2020-12-24 06:26:29 +01:00
public getInputEntities ( entities : MessageEntity [ ] ) {
2021-06-01 04:06:41 +02:00
const sendEntites = copy ( entities ) ;
sendEntites . forEach ( ( entity ) = > {
2021-02-04 01:30:23 +01:00
if ( entity . _ === 'messageEntityMentionName' ) {
2021-06-01 04:06:41 +02:00
( entity as any as MessageEntity . inputMessageEntityMentionName ) . _ = 'inputMessageEntityMentionName' ;
2022-04-25 16:54:30 +02:00
( entity as any as MessageEntity . inputMessageEntityMentionName ) . user_id = this . appUsersManager . getUserInput ( entity . user_id ) ;
2020-02-06 16:43:07 +01:00
}
} ) ;
return sendEntites ;
}
2022-04-16 18:21:50 +02:00
public invokeAfterMessageIsSent ( tempId : number , callbackName : string , callback : ( message : MyMessage ) = > Promise < any > ) {
2023-01-06 20:27:29 +01:00
const finalize = this . tempFinalizeCallbacks [ tempId ] ? ? = { } ;
const obj = finalize [ callbackName ] ? ? = { deferred : deferredPromise < void > ( ) } ;
2020-10-13 15:51:11 +02:00
obj . callback = callback ;
return obj . deferred ;
}
2020-12-18 04:07:32 +01:00
public editMessage ( message : any , text : string , options : Partial < {
2020-10-10 00:36:06 +02:00
noWebPage : true ,
2020-12-18 04:07:32 +01:00
newMedia : any ,
scheduleDate : number ,
entities : MessageEntity [ ]
2020-10-13 15:51:11 +02:00
} > = { } ) : Promise < void > {
2020-12-11 03:06:16 +01:00
/ * i f ( ! t h i s . c a n E d i t M e s s a g e ( m e s s a g e I d ) ) {
2020-10-10 00:36:06 +02:00
return Promise . reject ( { type : 'MESSAGE_EDIT_FORBIDDEN' } ) ;
2020-10-10 04:08:12 +02:00
} * /
2020-02-14 17:15:41 +01:00
2020-12-18 04:07:32 +01:00
const { mid , peerId } = message ;
2020-12-19 02:07:24 +01:00
if ( message . pFlags . is_outgoing ) {
2020-12-18 04:07:32 +01:00
return this . invokeAfterMessageIsSent ( mid , 'edit' , ( message ) = > {
2022-08-04 08:49:54 +02:00
// this.log('invoke editMessage callback', message);
2020-12-18 04:07:32 +01:00
return this . editMessage ( message , text , options ) ;
2020-02-14 17:15:41 +01:00
} ) ;
}
2022-08-04 08:49:54 +02:00
const entities = options . entities || [ ] ;
2020-12-24 07:50:00 +01:00
if ( text ) {
2022-04-25 16:54:30 +02:00
text = parseMarkdown ( text , entities ) ;
2020-12-24 07:50:00 +01:00
}
2020-02-14 17:15:41 +01:00
2020-12-18 04:07:32 +01:00
const schedule_date = options . scheduleDate || ( message . pFlags . is_scheduled ? message.date : undefined ) ;
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.editMessage' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2020-12-19 02:07:24 +01:00
id : message.id ,
2020-02-14 17:15:41 +01:00
message : text ,
2020-10-10 00:36:06 +02:00
media : options.newMedia ,
2020-12-24 07:50:00 +01:00
entities : entities.length ? this . getInputEntities ( entities ) : undefined ,
2020-10-10 00:36:06 +02:00
no_webpage : options.noWebPage ,
2020-12-18 04:07:32 +01:00
schedule_date
2020-02-14 17:15:41 +01:00
} ) . then ( ( updates ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2020-02-14 17:15:41 +01:00
} , ( error ) = > {
2020-10-10 00:36:06 +02:00
this . log . error ( 'editMessage error:' , error ) ;
2022-08-04 08:49:54 +02:00
2021-02-04 01:30:23 +01:00
if ( error && error . type === 'MESSAGE_NOT_MODIFIED' ) {
2020-02-14 17:15:41 +01:00
error . handled = true ;
return ;
}
2021-02-04 01:30:23 +01:00
if ( error && error . type === 'MESSAGE_EMPTY' ) {
2020-02-14 17:15:41 +01:00
error . handled = true ;
}
return Promise . reject ( error ) ;
} ) ;
}
2023-02-27 14:11:37 +01:00
public async transcribeAudio ( message : Message.message ) : Promise < MessagesTranscribedAudio > {
2023-02-06 21:24:53 +01:00
const { id , peerId } = message ;
2023-02-20 20:39:43 +01:00
const process = ( result : MessagesTranscribedAudio ) = > {
this . apiUpdatesManager . processLocalUpdate ( {
_ : 'updateTranscribedAudio' ,
msg_id : message.id ,
peer : this.appPeersManager.getOutputPeer ( peerId ) ,
pFlags : result.pFlags ,
text : result.text ,
transcription_id : result.transcription_id
2023-02-06 21:24:53 +01:00
} ) ;
2023-02-20 20:39:43 +01:00
} ;
return this . apiManager . invokeApiSingleProcess ( {
method : 'messages.transcribeAudio' ,
params : {
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
msg_id : id
} ,
processResult : ( result ) = > {
process ( result ) ;
return result ;
} ,
processError : ( error ) = > {
2023-03-02 14:24:15 +01:00
if ( error . type === 'TRANSCRIPTION_FAILED' || error . type === 'MSG_VOICE_MISSING' ) {
2023-02-20 20:39:43 +01:00
process ( {
_ : 'messages.transcribedAudio' ,
transcription_id : 0 ,
text : '' ,
pFlags : { }
} ) ;
}
throw error ;
}
} ) ;
2023-02-06 21:24:53 +01:00
}
2023-01-06 20:27:29 +01:00
public async sendText ( peerId : PeerId , text : string , options : MessageSendingParams & Partial < {
2021-08-03 03:44:13 +02:00
entities : MessageEntity [ ] ,
2021-10-21 15:16:43 +02:00
viaBotId : BotId ,
2020-12-11 03:06:16 +01:00
queryId : string ,
resultId : string ,
2020-10-10 00:36:06 +02:00
noWebPage : true ,
2021-08-03 03:44:13 +02:00
replyMarkup : ReplyMarkup ,
2020-10-10 00:36:06 +02:00
clearDraft : true ,
2021-08-03 03:44:13 +02:00
webPage : WebPage ,
2022-06-30 16:14:33 +02:00
} > = { } ) : Promise < void > {
2021-11-29 14:51:29 +01:00
if ( ! text . trim ( ) ) {
2022-06-17 18:01:43 +02:00
return ;
2020-02-06 16:43:07 +01:00
}
2022-06-30 16:14:33 +02:00
options . entities ? ? = [ ] ;
2022-08-04 08:49:54 +02:00
// this.checkSendOptions(options);
2021-01-31 02:52:14 +01:00
if ( options . threadId && ! options . replyToMsgId ) {
options . replyToMsgId = options . threadId ;
}
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
const config = await this . apiManager . getConfig ( ) ;
const MAX_LENGTH = config . message_length_max ;
2022-06-30 16:14:33 +02:00
const splitted = splitStringByLength ( text , MAX_LENGTH ) ;
text = splitted [ 0 ] ;
if ( splitted . length > 1 ) {
if ( options . webPage ? . _ === 'webPage' && ! text . includes ( options . webPage . url ) ) {
2020-10-26 02:59:49 +01:00
delete options . webPage ;
}
2020-10-15 18:07:34 +02:00
}
2022-04-25 16:54:30 +02:00
peerId = this . appPeersManager . getPeerMigratedTo ( peerId ) || peerId ;
2022-08-04 08:49:54 +02:00
const entities = options . entities ;
2020-12-11 03:06:16 +01:00
if ( ! options . viaBotId ) {
2022-04-25 16:54:30 +02:00
text = parseMarkdown ( text , entities ) ;
2022-08-04 08:49:54 +02:00
// entities = mergeEntities(entities, parseEntities(text));
2020-02-06 16:43:07 +01:00
}
2020-12-21 05:55:53 +01:00
let sendEntites = this . getInputEntities ( entities ) ;
2020-10-10 00:36:06 +02:00
if ( ! sendEntites . length ) {
sendEntites = undefined ;
}
2021-02-07 07:40:26 +01:00
const message = this . generateOutgoingMessage ( peerId , options ) ;
message . entities = entities ;
message . message = text ;
2022-06-17 18:01:43 +02:00
const replyToMsgId = options . replyToMsgId ? getServerMessageId ( options . replyToMsgId ) : undefined ;
2022-04-25 16:54:30 +02:00
const isChannel = this . appPeersManager . isChannel ( peerId ) ;
2020-02-06 16:43:07 +01:00
2020-02-13 08:51:11 +01:00
if ( options . webPage ) {
message . media = {
_ : 'messageMediaWebPage' ,
webpage : options.webPage
} ;
}
2022-09-02 19:43:54 +02:00
const toggleError = ( error? : ApiError ) = > {
this . onMessagesSendError ( [ message ] , error ) ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'messages_pending' ) ;
2020-12-24 01:59:44 +01:00
} ;
2020-02-06 16:43:07 +01:00
2020-12-24 01:59:44 +01:00
message . send = ( ) = > {
2022-09-02 19:43:54 +02:00
toggleError ( ) ;
2021-07-15 17:34:34 +02:00
const sentRequestOptions : PendingAfterMsg = { } ;
2020-12-11 03:06:16 +01:00
if ( this . pendingAfterMsgs [ peerId ] ) {
sentRequestOptions . afterMessageId = this . pendingAfterMsgs [ peerId ] . messageId ;
2020-02-06 16:43:07 +01:00
}
2022-04-25 16:54:30 +02:00
const sendAs = options . sendAsPeerId ? this . appPeersManager . getInputPeerById ( options . sendAsPeerId ) : undefined
2020-12-21 05:55:53 +01:00
let apiPromise : any ;
2020-12-11 03:06:16 +01:00
if ( options . viaBotId ) {
2022-06-17 18:01:43 +02:00
apiPromise = this . apiManager . invokeApiAfter ( 'messages.sendInlineBotResult' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2021-02-07 07:40:26 +01:00
random_id : message.random_id ,
2020-12-16 04:22:58 +01:00
reply_to_msg_id : replyToMsgId || undefined ,
2020-12-11 03:06:16 +01:00
query_id : options.queryId ,
id : options.resultId ,
2022-02-20 16:37:37 +01:00
clear_draft : options.clearDraft ,
send_as : sendAs
2020-02-06 16:43:07 +01:00
} , sentRequestOptions ) ;
} else {
2022-06-17 18:01:43 +02:00
apiPromise = this . apiManager . invokeApiAfter ( 'messages.sendMessage' , {
2020-10-10 00:36:06 +02:00
no_webpage : options.noWebPage ,
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2020-02-06 16:43:07 +01:00
message : text ,
2021-02-07 07:40:26 +01:00
random_id : message.random_id ,
2020-12-16 04:22:58 +01:00
reply_to_msg_id : replyToMsgId || undefined ,
2020-10-10 00:36:06 +02:00
entities : sendEntites ,
2020-12-18 04:07:32 +01:00
clear_draft : options.clearDraft ,
schedule_date : options.scheduleDate || undefined ,
2022-02-20 16:37:37 +01:00
silent : options.silent ,
2022-11-01 18:39:23 +01:00
send_as : sendAs ,
update_stickersets_order : UPDATE_STICKERSET_ORDER
2020-02-06 16:43:07 +01:00
} , sentRequestOptions ) ;
}
2021-05-29 14:23:45 +02:00
/ * f u n c t i o n i s < T > ( v a l u e : a n y , c o n d i t i o n : b o o l e a n ) : v a l u e i s T {
return condition ;
} * /
2022-08-04 08:49:54 +02:00
// this.log('sendText', message.mid);
2021-07-21 14:16:15 +02:00
this . pendingAfterMsgs [ peerId ] = sentRequestOptions ;
return apiPromise . then ( ( updates : Updates ) = > {
2022-08-04 08:49:54 +02:00
// this.log('sendText sent', message.mid);
// if(is<Updates.updateShortSentMessage>(updates, updates._ === 'updateShortSentMessage')) {
2021-02-04 01:30:23 +01:00
if ( updates . _ === 'updateShortSentMessage' ) {
2022-08-04 08:49:54 +02:00
// assumeType<Updates.updateShortSentMessage>(updates);
2022-01-14 23:01:50 +01:00
// * fix copying object with promise
const promise = message . promise ;
delete message . promise ;
2021-10-21 15:16:43 +02:00
const newMessage = copy ( message ) ;
2022-06-17 18:01:43 +02:00
defineNotNumerableProperties ( message , [ 'promise' ] ) ;
2022-01-14 23:01:50 +01:00
message . promise = promise ;
2021-10-21 15:16:43 +02:00
newMessage . date = updates . date ;
newMessage . id = updates . id ;
newMessage . media = updates . media ;
newMessage . entities = updates . entities ;
this . wrapMessageEntities ( newMessage ) ;
2021-05-29 14:23:45 +02:00
if ( updates . pFlags . out ) {
2021-10-21 15:16:43 +02:00
newMessage . pFlags . out = true ;
2021-05-29 14:23:45 +02:00
}
2020-12-18 04:07:32 +01:00
// * override with new updates
2020-02-06 16:43:07 +01:00
updates = {
_ : 'updates' ,
users : [ ] ,
chats : [ ] ,
seq : 0 ,
2021-08-03 03:44:13 +02:00
date : undefined ,
2020-02-06 16:43:07 +01:00
updates : [ {
2020-12-11 17:46:44 +01:00
_ : 'updateMessageID' ,
2021-02-07 07:40:26 +01:00
random_id : message.random_id ,
2021-10-21 15:16:43 +02:00
id : newMessage.id
2020-02-06 16:43:07 +01:00
} , {
2020-12-18 04:07:32 +01:00
_ : options.scheduleDate ? 'updateNewScheduledMessage' : ( isChannel ? 'updateNewChannelMessage' : 'updateNewMessage' ) ,
2021-10-21 15:16:43 +02:00
message : newMessage ,
2020-02-06 16:43:07 +01:00
pts : updates.pts ,
pts_count : updates.pts_count
} ]
2021-08-03 03:44:13 +02:00
} ;
2021-05-29 14:23:45 +02:00
} else if ( ( updates as Updates . updates ) . updates ) {
( updates as Updates . updates ) . updates . forEach ( ( update ) = > {
2021-02-04 01:30:23 +01:00
if ( update . _ === 'updateDraftMessage' ) {
2020-02-06 16:43:07 +01:00
update . local = true ;
}
} ) ;
}
2023-01-06 20:27:29 +01:00
// this.reloadConversation(peerId);
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
// setTimeout(() => {
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
// }, 5000);
2022-01-14 23:01:50 +01:00
message . promise . resolve ( ) ;
2022-09-02 19:43:54 +02:00
} , ( error : ApiError ) = > {
toggleError ( error ) ;
2022-01-14 23:01:50 +01:00
message . promise . reject ( error ) ;
2022-09-02 19:43:54 +02:00
throw error ;
2020-02-06 16:43:07 +01:00
} ) . finally ( ( ) = > {
2020-12-11 03:06:16 +01:00
if ( this . pendingAfterMsgs [ peerId ] === sentRequestOptions ) {
delete this . pendingAfterMsgs [ peerId ] ;
2020-02-06 16:43:07 +01:00
}
2020-02-10 04:37:17 +01:00
} ) ;
2021-07-21 14:16:15 +02:00
} ;
2020-02-06 16:43:07 +01:00
2021-01-09 15:08:26 +01:00
this . beforeMessageSending ( message , {
2022-08-04 08:49:54 +02:00
isScheduled : ! ! options . scheduleDate || undefined ,
2021-01-09 15:08:26 +01:00
threadId : options.threadId ,
2022-06-17 18:01:43 +02:00
clearDraft : options.clearDraft ,
sequential : true
2021-01-09 15:08:26 +01:00
} ) ;
2022-01-14 23:01:50 +01:00
2022-06-30 16:14:33 +02:00
const promises : ReturnType < AppMessagesManager [ ' sendText ' ] > [ ] = [ message . promise ] ;
for ( let i = 1 ; i < splitted . length ; ++ i ) {
promises . push ( this . sendText ( peerId , splitted [ i ] , options ) ) ;
}
return Promise . all ( promises ) . then ( noop ) ;
2020-02-06 16:43:07 +01:00
}
2023-01-11 15:43:14 +01:00
public sendFile ( peerId : PeerId , options : MessageSendingParams & SendFileDetails & Partial < {
isRoundMessage : boolean ,
isVoiceMessage : boolean ,
isGroupedItem : boolean ,
isMedia : boolean ,
2020-12-10 00:58:20 +01:00
2021-02-10 07:06:22 +01:00
groupId : string ,
2020-05-01 23:28:40 +02:00
caption : string ,
2020-12-10 00:58:20 +01:00
entities : MessageEntity [ ] ,
2022-08-18 13:21:19 +02:00
background : boolean ,
clearDraft : boolean ,
2021-08-27 00:22:14 +02:00
noSound : boolean ,
2020-06-02 00:19:35 +02:00
2021-02-10 07:06:22 +01:00
waveform : Uint8Array ,
2022-06-30 16:14:33 +02:00
// ! only for internal use
processAfter? : typeof processAfter
2023-01-11 15:43:14 +01:00
} > ) {
const file = options . file ;
2022-04-25 16:54:30 +02:00
peerId = this . appPeersManager . getPeerMigratedTo ( peerId ) || peerId ;
2021-01-31 02:52:14 +01:00
2022-08-04 08:49:54 +02:00
// this.checkSendOptions(options);
2021-02-07 07:40:26 +01:00
const message = this . generateOutgoingMessage ( peerId , options ) ;
2022-06-17 18:01:43 +02:00
const replyToMsgId = options . replyToMsgId ? getServerMessageId ( options . replyToMsgId ) : undefined ;
2021-02-07 07:40:26 +01:00
2021-10-27 17:41:23 +02:00
let attachType : 'document' | 'audio' | 'video' | 'voice' | 'photo' , apiFileName : string ;
2020-02-06 16:43:07 +01:00
2020-06-13 10:19:39 +02:00
const fileType = 'mime_type' in file ? file.mime_type : file.type ;
const fileName = file instanceof File ? file . name : '' ;
const isDocument = ! ( file instanceof File ) && ! ( file instanceof Blob ) ;
2020-02-06 16:43:07 +01:00
let caption = options . caption || '' ;
2020-06-13 10:19:39 +02:00
this . log ( 'sendFile' , file , fileType ) ;
2020-06-02 00:19:35 +02:00
2020-12-23 23:03:34 +01:00
const entities = options . entities || [ ] ;
2020-02-06 16:43:07 +01:00
if ( caption ) {
2022-04-25 16:54:30 +02:00
caption = parseMarkdown ( caption , entities ) ;
2020-02-06 16:43:07 +01:00
}
2020-09-19 13:37:19 +02:00
const attributes : DocumentAttribute [ ] = [ ] ;
2022-06-17 18:01:43 +02:00
const isPhoto = getEnvironment ( ) . IMAGE_MIME_TYPES_SUPPORTED . has ( fileType ) ;
2020-04-28 19:30:54 +02:00
2023-01-11 15:43:14 +01:00
const strippedPhotoSize : PhotoSize.photoStrippedSize = options . strippedBytes && {
_ : 'photoStrippedSize' ,
bytes : options.strippedBytes ,
type : 'i'
} ;
2020-12-10 00:58:20 +01:00
let photo : MyPhoto , document : MyDocument ;
2021-10-21 15:16:43 +02:00
let actionName : Extract < SendMessageAction [ ' _ ' ] , ' sendMessageUploadAudioAction ' | ' sendMessageUploadDocumentAction ' | ' sendMessageUploadPhotoAction ' | ' sendMessageUploadVideoAction ' > ;
2020-12-10 00:58:20 +01:00
if ( isDocument ) { // maybe it's a sticker or gif
attachType = 'document' ;
apiFileName = '' ;
} else if ( fileType . indexOf ( 'audio/' ) === 0 || [ 'video/ogg' ] . indexOf ( fileType ) >= 0 ) {
attachType = 'audio' ;
2021-02-04 01:30:23 +01:00
apiFileName = 'audio.' + ( fileType . split ( '/' ) [ 1 ] === 'ogg' ? 'ogg' : 'mp3' ) ;
2020-12-10 00:58:20 +01:00
actionName = 'sendMessageUploadAudioAction' ;
if ( options . isVoiceMessage ) {
attachType = 'voice' ;
2021-02-07 07:40:26 +01:00
message . pFlags . media_unread = true ;
2020-12-10 00:58:20 +01:00
}
2022-08-04 08:49:54 +02:00
const attribute : DocumentAttribute.documentAttributeAudio = {
2020-12-10 00:58:20 +01:00
_ : 'documentAttributeAudio' ,
pFlags : {
2023-01-11 15:43:14 +01:00
voice : options.isVoiceMessage || undefined
2020-12-10 00:58:20 +01:00
} ,
waveform : options.waveform ,
duration : options.duration || 0
} ;
attributes . push ( attribute ) ;
} else if ( ! options . isMedia ) {
2020-02-06 16:43:07 +01:00
attachType = 'document' ;
apiFileName = 'document.' + fileType . split ( '/' ) [ 1 ] ;
2020-02-08 07:03:09 +01:00
actionName = 'sendMessageUploadDocumentAction' ;
2020-09-19 13:37:19 +02:00
} else if ( isPhoto ) {
2020-02-06 16:43:07 +01:00
attachType = 'photo' ;
apiFileName = 'photo.' + fileType . split ( '/' ) [ 1 ] ;
2020-02-08 07:03:09 +01:00
actionName = 'sendMessageUploadPhotoAction' ;
2020-04-26 03:45:07 +02:00
2021-05-01 20:49:32 +02:00
const photoSize = {
_ : 'photoSize' ,
w : options.width ,
h : options.height ,
2022-08-28 18:50:04 +02:00
type : THUMB_TYPE_FULL ,
2021-05-01 20:49:32 +02:00
location : null ,
size : file.size
} as PhotoSize . photoSize ;
2020-12-10 00:58:20 +01:00
photo = {
2020-04-26 03:45:07 +02:00
_ : 'photo' ,
2021-02-07 07:40:26 +01:00
id : '' + message . id ,
2021-05-01 20:49:32 +02:00
sizes : [ photoSize ] ,
2020-04-26 03:45:07 +02:00
w : options.width ,
2020-10-22 01:59:30 +02:00
h : options.height
2020-09-19 13:37:19 +02:00
} as any ;
2020-10-22 01:59:30 +02:00
2023-01-11 15:43:14 +01:00
if ( strippedPhotoSize ) {
photo . sizes . unshift ( strippedPhotoSize ) ;
}
2022-06-17 18:01:43 +02:00
const cacheContext = this . thumbsStorage . getCacheContext ( photo , photoSize . type ) ;
2021-05-01 20:49:32 +02:00
cacheContext . downloaded = file . size ;
cacheContext . url = options . objectURL || '' ;
2022-08-04 08:49:54 +02:00
2022-04-25 16:54:30 +02:00
photo = this . appPhotosManager . savePhoto ( photo ) ;
2023-01-25 15:21:38 +01:00
} else if ( getEnvironment ( ) . VIDEO_MIME_TYPES_SUPPORTED . has ( fileType as VIDEO_MIME_TYPE ) ) {
2020-04-28 19:30:54 +02:00
attachType = 'video' ;
2020-02-06 16:43:07 +01:00
apiFileName = 'video.mp4' ;
2020-02-08 07:03:09 +01:00
actionName = 'sendMessageUploadVideoAction' ;
2020-04-28 19:30:54 +02:00
2021-08-27 00:22:14 +02:00
const videoAttribute : DocumentAttribute.documentAttributeVideo = {
2020-04-28 19:30:54 +02:00
_ : 'documentAttributeVideo' ,
2020-12-10 00:58:20 +01:00
pFlags : {
2023-01-11 15:43:14 +01:00
round_message : options.isRoundMessage || undefined ,
2021-08-27 00:22:14 +02:00
supports_streaming : true
2022-08-04 08:49:54 +02:00
} ,
2020-04-28 19:30:54 +02:00
duration : options.duration ,
w : options.width ,
h : options.height
} ;
attributes . push ( videoAttribute ) ;
2021-08-27 00:22:14 +02:00
// * must follow after video attribute
2022-08-04 08:49:54 +02:00
if ( options . noSound &&
file . size > ( 10 * 1024 ) &&
2021-08-27 00:22:14 +02:00
file . size < ( 10 * 1024 * 1024 ) ) {
attributes . push ( {
_ : 'documentAttributeAnimated'
} ) ;
}
2020-06-02 00:19:35 +02:00
} else {
attachType = 'document' ;
apiFileName = 'document.' + fileType . split ( '/' ) [ 1 ] ;
actionName = 'sendMessageUploadDocumentAction' ;
}
2020-04-28 19:30:54 +02:00
2020-06-02 00:19:35 +02:00
attributes . push ( { _ : 'documentAttributeFilename' , file_name : fileName || apiFileName } ) ;
2021-10-27 17:41:23 +02:00
if ( ( [ 'document' , 'video' , 'audio' , 'voice' ] as ( typeof attachType ) [ ] ) . indexOf ( attachType ) !== - 1 && ! isDocument ) {
2020-09-19 13:37:19 +02:00
const thumbs : PhotoSize [ ] = [ ] ;
2020-12-10 00:58:20 +01:00
document = {
2020-04-28 19:30:54 +02:00
_ : 'document' ,
2021-02-07 07:40:26 +01:00
id : '' + message . id ,
2020-04-28 19:30:54 +02:00
duration : options.duration ,
2020-09-19 13:37:19 +02:00
attributes ,
2020-04-28 19:30:54 +02:00
w : options.width ,
h : options.height ,
2020-09-19 13:37:19 +02:00
thumbs ,
2020-04-28 19:30:54 +02:00
mime_type : fileType ,
size : file.size
2020-09-18 17:03:26 +02:00
} as any ;
2020-09-19 13:37:19 +02:00
2022-04-03 21:42:12 +02:00
if ( options . objectURL ) {
2022-06-17 18:01:43 +02:00
const cacheContext = this . thumbsStorage . getCacheContext ( document ) ;
2022-04-03 21:42:12 +02:00
cacheContext . downloaded = file . size ;
cacheContext . url = options . objectURL ;
}
2020-10-22 01:59:30 +02:00
2021-05-01 20:49:32 +02:00
let thumb : PhotoSize.photoSize ;
2020-09-19 13:37:19 +02:00
if ( isPhoto ) {
attributes . push ( {
_ : 'documentAttributeImageSize' ,
w : options.width ,
h : options.height
} ) ;
2021-05-01 20:49:32 +02:00
thumb = {
2020-09-19 13:37:19 +02:00
_ : 'photoSize' ,
w : options.width ,
h : options.height ,
2022-08-28 18:50:04 +02:00
type : THUMB_TYPE_FULL ,
2021-05-01 20:49:32 +02:00
size : file.size
} ;
2020-12-24 06:26:29 +01:00
} else if ( attachType === 'video' ) {
2021-08-27 00:22:14 +02:00
if ( options . thumb ) {
2021-05-01 20:49:32 +02:00
thumb = {
2020-12-24 06:26:29 +01:00
_ : 'photoSize' ,
2021-08-27 00:22:14 +02:00
w : options.thumb.size.width ,
h : options.thumb.size.height ,
type : 'local-thumb' ,
size : options.thumb.blob.size
2021-05-01 20:49:32 +02:00
} ;
2022-06-17 18:01:43 +02:00
const thumbCacheContext = this . thumbsStorage . getCacheContext ( document , thumb . type ) ;
2021-05-01 20:49:32 +02:00
thumbCacheContext . downloaded = thumb . size ;
2021-08-27 00:22:14 +02:00
thumbCacheContext . url = options . thumb . url ;
2020-12-24 06:26:29 +01:00
}
2021-05-01 20:49:32 +02:00
}
2020-12-24 06:26:29 +01:00
2021-05-01 20:49:32 +02:00
if ( thumb ) {
thumbs . push ( thumb ) ;
2020-09-19 13:37:19 +02:00
}
2020-12-24 06:26:29 +01:00
2023-01-11 15:43:14 +01:00
if ( strippedPhotoSize ) {
thumbs . unshift ( strippedPhotoSize ) ;
}
2020-12-24 06:26:29 +01:00
/ * i f ( t h u m b s . l e n g t h ) {
const thumb = thumbs [ 0 ] as PhotoSize . photoSize ;
const docThumb = appPhotosManager . getDocumentCachedThumb ( document . id ) ;
docThumb . downloaded = thumb . size ;
docThumb . url = thumb . url ;
} * /
2022-08-04 08:49:54 +02:00
2022-04-25 16:54:30 +02:00
document = this . appDocsManager . saveDoc ( document ) ;
2020-02-06 16:43:07 +01:00
}
2021-01-08 10:55:37 +01:00
this . log ( 'sendFile' , attachType , apiFileName , file . type , options ) ;
2020-02-06 16:43:07 +01:00
2021-02-06 13:44:48 +01:00
const sentDeferred = deferredPromise < InputMedia > ( ) ;
2022-06-17 18:01:43 +02:00
// sentDeferred.cancel = () => {
// const error = new Error('Download canceled');
// error.name = 'AbortError';
// sentDeferred.reject(error);
2021-02-06 13:44:48 +01:00
2022-06-17 18:01:43 +02:00
// if(uploadPromise?.cancel) {
// uploadPromise.cancel();
// }
// };
2021-02-10 07:06:22 +01:00
2022-06-17 18:01:43 +02:00
const media : MessageMedia = isDocument ? undefined : {
2020-12-24 06:26:29 +01:00
_ : photo ? 'messageMediaPhoto' : 'messageMediaDocument' ,
pFlags : { } ,
2022-06-17 18:01:43 +02:00
// preloader,
2020-12-10 00:58:20 +01:00
photo ,
2022-06-17 18:01:43 +02:00
document
2020-02-07 15:17:39 +01:00
} ;
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
if ( media ) {
defineNotNumerableProperties ( media as any , [ 'promise' ] ) ;
( media as any ) . promise = sentDeferred ;
2023-01-11 15:43:14 +01:00
if ( options . spoiler ) {
( media as MessageMedia . messageMediaPhoto ) . pFlags . spoiler = true ;
}
2022-06-17 18:01:43 +02:00
}
2022-08-04 08:49:54 +02:00
2021-02-07 07:40:26 +01:00
message . entities = entities ;
message . message = caption ;
message . media = isDocument ? {
_ : 'messageMediaDocument' ,
pFlags : { } ,
2022-08-04 08:49:54 +02:00
document : file
2022-06-17 18:01:43 +02:00
} as MessageMedia.messageMediaDocument : media ;
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
const uploadingFileName = ! isDocument ? getFileNameForUpload ( file ) : undefined ;
message . uploadingFileName = uploadingFileName ;
if ( uploadingFileName ) {
this . uploadFilePromises [ uploadingFileName ] = sentDeferred ;
}
2020-02-06 16:43:07 +01:00
2022-09-02 19:43:54 +02:00
const toggleError = ( error? : ApiError ) = > {
this . onMessagesSendError ( [ message ] , error ) ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'messages_pending' ) ;
2020-02-06 16:43:07 +01:00
} ;
2020-08-28 17:11:25 +02:00
let uploaded = false ,
2022-06-17 18:01:43 +02:00
uploadPromise : ReturnType < ApiFileManager [ ' upload ' ] > = null ;
2020-02-06 16:43:07 +01:00
message . send = ( ) = > {
if ( isDocument ) {
2020-12-10 00:58:20 +01:00
const inputMedia : InputMedia = {
2020-02-06 16:43:07 +01:00
_ : 'inputMediaDocument' ,
2023-02-01 14:26:41 +01:00
id : getDocumentInput ( file ) ,
pFlags : { }
2020-02-06 16:43:07 +01:00
} ;
2022-08-04 08:49:54 +02:00
2020-12-10 00:58:20 +01:00
sentDeferred . resolve ( inputMedia ) ;
2020-02-06 16:43:07 +01:00
} else if ( file instanceof File || file instanceof Blob ) {
2020-12-24 01:59:44 +01:00
const load = ( ) = > {
2020-02-06 16:43:07 +01:00
if ( ! uploaded || message . error ) {
uploaded = false ;
2022-06-17 18:01:43 +02:00
uploadPromise = this . apiFileManager . upload ( { file , fileName : uploadingFileName } ) ;
uploadPromise . catch ( ( err ) = > {
if ( ! uploaded ) {
this . log ( 'cancelling upload' , media ) ;
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
this . cancelPendingMessage ( message . random_id ) ;
2023-01-06 20:27:29 +01:00
this . setTyping ( peerId , { _ : 'sendMessageCancelAction' } , undefined , options . threadId ) ;
2022-06-17 18:01:43 +02:00
sentDeferred . reject ( err ) ;
}
} ) ;
uploadPromise . addNotifyListener ( ( progress : Progress ) = > {
/ * i f ( D E B U G ) {
this . log ( 'upload progress' , progress ) ;
} * /
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
const percents = Math . max ( 1 , Math . floor ( 100 * progress . done / progress . total ) ) ;
if ( actionName ) {
2023-01-06 20:27:29 +01:00
this . setTyping ( peerId , { _ : actionName , progress : percents | 0 } , undefined , options . threadId ) ;
2022-06-17 18:01:43 +02:00
}
sentDeferred . notifyAll ( progress ) ;
} ) ;
2021-02-10 07:06:22 +01:00
sentDeferred . notifyAll ( { done : 0 , total : file.size } ) ;
2020-02-06 16:43:07 +01:00
}
2020-12-24 06:26:29 +01:00
let thumbUploadPromise : typeof uploadPromise ;
2022-06-17 18:01:43 +02:00
if ( attachType === 'video' && options . objectURL && options . thumb ? . blob ) {
thumbUploadPromise = this . apiFileManager . upload ( { file : options.thumb.blob } ) ;
2020-12-24 06:26:29 +01:00
}
2022-08-04 08:49:54 +02:00
2020-12-24 06:26:29 +01:00
uploadPromise && uploadPromise . then ( async ( inputFile ) = > {
2021-01-08 10:55:37 +01:00
/ * i f ( D E B U G ) {
this . log ( 'appMessagesManager: sendFile uploaded:' , inputFile ) ;
} * /
2020-12-24 07:50:00 +01:00
2020-02-06 16:43:07 +01:00
inputFile . name = apiFileName ;
uploaded = true ;
2020-12-10 00:58:20 +01:00
let inputMedia : InputMedia ;
2020-02-06 16:43:07 +01:00
switch ( attachType ) {
case 'photo' :
inputMedia = {
2022-08-04 08:49:54 +02:00
_ : 'inputMediaUploadedPhoto' ,
2023-01-11 15:43:14 +01:00
file : inputFile ,
pFlags : {
spoiler : options.spoiler || undefined
}
2020-02-06 16:43:07 +01:00
} ;
break ;
2020-04-28 19:30:54 +02:00
2020-02-06 16:43:07 +01:00
default :
inputMedia = {
2022-08-04 08:49:54 +02:00
_ : 'inputMediaUploadedDocument' ,
file : inputFile ,
mime_type : fileType ,
2021-10-21 15:16:43 +02:00
pFlags : {
2023-01-11 15:43:14 +01:00
force_file : actionName === 'sendMessageUploadDocumentAction' || undefined ,
spoiler : options.spoiler || undefined
2021-10-21 15:16:43 +02:00
// nosound_video: options.noSound ? true : undefined
} ,
2020-12-10 00:58:20 +01:00
attributes
2020-02-06 16:43:07 +01:00
} ;
}
2020-12-24 06:26:29 +01:00
if ( thumbUploadPromise ) {
try {
const inputFile = await thumbUploadPromise ;
( inputMedia as InputMedia . inputMediaUploadedDocument ) . thumb = inputFile ;
} catch ( err ) {
this . log . error ( 'sendFile thumb upload error:' , err ) ;
}
}
2022-08-04 08:49:54 +02:00
2020-12-10 00:58:20 +01:00
sentDeferred . resolve ( inputMedia ) ;
2022-09-02 19:43:54 +02:00
} , ( error : ApiError ) = > {
toggleError ( error ) ;
throw error ;
2020-02-06 16:43:07 +01:00
} ) ;
2022-08-04 08:49:54 +02:00
2020-12-24 01:59:44 +01:00
return sentDeferred ;
} ;
2020-02-06 16:43:07 +01:00
2020-12-24 01:59:44 +01:00
if ( options . isGroupedItem ) {
load ( ) ;
} else {
this . sendSmthLazyLoadQueue . push ( {
load
} ) ;
}
2020-02-06 16:43:07 +01:00
}
2020-12-10 00:58:20 +01:00
return sentDeferred ;
2020-02-06 16:43:07 +01:00
} ;
2021-01-09 15:08:26 +01:00
this . beforeMessageSending ( message , {
2022-08-04 08:49:54 +02:00
isGroupedItem : options.isGroupedItem ,
isScheduled : ! ! options . scheduleDate || undefined ,
2021-01-09 15:08:26 +01:00
threadId : options.threadId ,
2022-06-30 16:14:33 +02:00
clearDraft : options.clearDraft ,
processAfter : options.processAfter
2021-01-09 15:08:26 +01:00
} ) ;
2020-02-06 16:43:07 +01:00
2020-12-10 00:58:20 +01:00
if ( ! options . isGroupedItem ) {
2022-06-17 18:01:43 +02:00
sentDeferred . then ( ( inputMedia ) = > {
2023-01-06 20:27:29 +01:00
this . setTyping ( peerId , { _ : 'sendMessageCancelAction' } , undefined , options . threadId ) ;
2020-12-10 00:58:20 +01:00
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.sendMedia' , {
2020-12-10 00:58:20 +01:00
background : options.background ,
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2020-12-10 00:58:20 +01:00
media : inputMedia ,
message : caption ,
2021-02-07 07:40:26 +01:00
random_id : message.random_id ,
2020-12-18 04:07:32 +01:00
reply_to_msg_id : replyToMsgId ,
schedule_date : options.scheduleDate ,
2020-12-23 23:03:34 +01:00
silent : options.silent ,
2021-01-09 15:08:26 +01:00
entities ,
2022-02-20 16:37:37 +01:00
clear_draft : options.clearDraft ,
2022-04-25 16:54:30 +02:00
send_as : options.sendAsPeerId ? this . appPeersManager . getInputPeerById ( options . sendAsPeerId ) : undefined
2020-12-10 00:58:20 +01:00
} ) . then ( ( updates ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2022-09-02 19:43:54 +02:00
} , ( error : ApiError ) = > {
2021-02-04 01:30:23 +01:00
if ( attachType === 'photo' &&
error . code === 400 &&
( error . type === 'PHOTO_INVALID_DIMENSIONS' ||
error . type === 'PHOTO_SAVE_FILE_INVALID' ) ) {
2020-12-10 00:58:20 +01:00
error . handled = true ;
attachType = 'document' ;
message . send ( ) ;
return ;
}
2020-02-06 16:43:07 +01:00
2022-09-02 19:43:54 +02:00
toggleError ( error ) ;
2022-01-14 23:01:50 +01:00
throw error ;
2020-12-10 00:58:20 +01:00
} ) ;
} ) ;
2022-01-14 23:01:50 +01:00
sentDeferred . then ( message . promise . resolve , message . promise . reject ) ;
2020-12-10 00:58:20 +01:00
}
2022-06-17 18:01:43 +02:00
const ret : {
message : typeof message ,
promise : typeof sentDeferred
} = {
message
} as any ;
defineNotNumerableProperties ( ret , [ 'promise' ] ) ;
ret . promise = sentDeferred ;
return ret ;
2020-02-06 16:43:07 +01:00
}
2023-01-11 15:43:14 +01:00
public async sendAlbum ( peerId : PeerId , options : MessageSendingParams & {
isMedia? : boolean ,
entities? : MessageEntity [ ] ,
caption? : string ,
sendFileDetails : SendFileDetails [ ] ,
clearDraft? : boolean
} ) {
2022-08-04 08:49:54 +02:00
// this.checkSendOptions(options);
2020-12-18 04:07:32 +01:00
2021-01-31 02:52:14 +01:00
if ( options . threadId && ! options . replyToMsgId ) {
options . replyToMsgId = options . threadId ;
}
2023-01-11 15:43:14 +01:00
if ( options . sendFileDetails . length === 1 ) {
return this . sendFile ( peerId , { . . . options , . . . options . sendFileDetails [ 0 ] } ) ;
2020-12-10 00:58:20 +01:00
}
2022-04-25 16:54:30 +02:00
peerId = this . appPeersManager . getPeerMigratedTo ( peerId ) || peerId ;
2022-06-17 18:01:43 +02:00
const replyToMsgId = options . replyToMsgId ? getServerMessageId ( options . replyToMsgId ) : undefined ;
2020-05-01 23:28:40 +02:00
let caption = options . caption || '' ;
2020-12-23 23:03:34 +01:00
let entities = options . entities || [ ] ;
2020-05-01 23:28:40 +02:00
if ( caption ) {
2022-04-25 16:54:30 +02:00
caption = parseMarkdown ( caption , entities ) ;
2020-05-01 23:28:40 +02:00
}
2023-01-11 15:43:14 +01:00
this . log ( 'sendAlbum' , options ) ;
2020-05-01 23:28:40 +02:00
2021-02-10 07:06:22 +01:00
const groupId = '' + ++ this . groupedTempId ;
2022-06-30 16:14:33 +02:00
const callbacks : Array < ( ) = > void > = [ ] ;
const processAfter = ( cb : ( ) = > void ) = > {
callbacks . push ( cb ) ;
} ;
2023-01-11 15:43:14 +01:00
const messages = options . sendFileDetails . map ( ( details , idx ) = > {
const o : Parameters < AppMessagesManager [ ' sendFile ' ] > [ 1 ] = {
2020-12-10 00:58:20 +01:00
isGroupedItem : true ,
isMedia : options.isMedia ,
2020-12-18 04:07:32 +01:00
scheduleDate : options.scheduleDate ,
silent : options.silent ,
2020-12-20 04:54:35 +01:00
replyToMsgId ,
threadId : options.threadId ,
2022-02-20 16:37:37 +01:00
sendAsPeerId : options.sendAsPeerId ,
2021-02-10 07:06:22 +01:00
groupId ,
2022-06-30 16:14:33 +02:00
processAfter ,
2020-12-10 00:58:20 +01:00
. . . details
2020-05-01 23:28:40 +02:00
} ;
2020-12-10 00:58:20 +01:00
if ( idx === 0 ) {
o . caption = caption ;
o . entities = entities ;
2022-08-04 08:49:54 +02:00
// o.replyToMsgId = replyToMsgId;
2020-05-01 23:28:40 +02:00
}
2023-01-11 15:43:14 +01:00
return this . sendFile ( peerId , o ) . message ;
2020-12-10 00:58:20 +01:00
} ) ;
2020-05-01 23:28:40 +02:00
2021-08-03 03:44:13 +02:00
if ( options . clearDraft ) {
2022-06-30 16:14:33 +02:00
callbacks . push ( ( ) = > {
2022-04-25 16:54:30 +02:00
this . appDraftsManager . clearDraft ( peerId , options . threadId ) ;
2022-06-30 16:14:33 +02:00
} ) ;
2021-01-09 15:08:26 +01:00
}
2022-06-30 16:14:33 +02:00
callbacks . forEach ( ( callback ) = > {
callback ( ) ;
} ) ;
2020-12-19 02:07:24 +01:00
// * test pending
2022-08-04 08:49:54 +02:00
// return;
2020-05-01 23:28:40 +02:00
2022-09-02 19:43:54 +02:00
const toggleError = ( message : Message.message , error? : ApiError ) = > {
this . onMessagesSendError ( [ message ] , error ) ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'messages_pending' ) ;
2020-05-01 23:28:40 +02:00
} ;
2022-04-25 16:54:30 +02:00
const inputPeer = this . appPeersManager . getInputPeerById ( peerId ) ;
2021-11-26 10:58:12 +01:00
const invoke = ( multiMedia : InputSingleMedia [ ] ) = > {
2023-01-06 20:27:29 +01:00
this . setTyping ( peerId , { _ : 'sendMessageCancelAction' } , undefined , options . threadId ) ;
2020-05-01 23:28:40 +02:00
2022-01-14 23:01:50 +01:00
const deferred = deferredPromise < void > ( ) ;
2020-12-24 01:59:44 +01:00
this . sendSmthLazyLoadQueue . push ( {
load : ( ) = > {
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.sendMultiMedia' , {
2020-12-24 01:59:44 +01:00
peer : inputPeer ,
multi_media : multiMedia ,
reply_to_msg_id : replyToMsgId ,
schedule_date : options.scheduleDate ,
2021-01-09 15:08:26 +01:00
silent : options.silent ,
2022-02-20 16:37:37 +01:00
clear_draft : options.clearDraft ,
2022-11-01 18:39:23 +01:00
send_as : options.sendAsPeerId ? this . appPeersManager . getInputPeerById ( options . sendAsPeerId ) : undefined ,
update_stickersets_order : UPDATE_STICKERSET_ORDER
2020-12-24 01:59:44 +01:00
} ) . then ( ( updates ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2022-01-14 23:01:50 +01:00
deferred . resolve ( ) ;
2022-09-02 19:43:54 +02:00
} , ( error : ApiError ) = > {
messages . forEach ( ( message ) = > toggleError ( message , error ) ) ;
2022-01-14 23:01:50 +01:00
deferred . reject ( error ) ;
2020-12-24 01:59:44 +01:00
} ) ;
}
2020-05-01 23:28:40 +02:00
} ) ;
2022-01-14 23:01:50 +01:00
return deferred ;
2020-05-01 23:28:40 +02:00
} ;
2021-11-26 10:58:12 +01:00
const promises : Promise < InputSingleMedia > [ ] = messages . map ( ( message ) = > {
return ( message . send ( ) as Promise < InputMedia > ) . then ( ( inputMedia ) = > {
2023-01-11 15:43:14 +01:00
return Promise . all ( [
inputMedia ,
this . apiManager . invokeApi ( 'messages.uploadMedia' , {
peer : inputPeer ,
media : inputMedia
} )
] ) ;
2020-12-24 01:59:44 +01:00
} )
2023-01-11 15:43:14 +01:00
. then ( ( [ originalInputMedia , messageMedia ] ) = > {
2021-11-26 10:58:12 +01:00
let inputMedia : InputMedia ;
2021-02-04 01:30:23 +01:00
if ( messageMedia . _ === 'messageMediaPhoto' ) {
2022-04-25 16:54:30 +02:00
const photo = this . appPhotosManager . savePhoto ( messageMedia . photo ) ;
inputMedia = getPhotoMediaInput ( photo ) ;
2021-02-04 01:30:23 +01:00
} else if ( messageMedia . _ === 'messageMediaDocument' ) {
2022-04-25 16:54:30 +02:00
const doc = this . appDocsManager . saveDoc ( messageMedia . document ) ;
2022-06-17 18:01:43 +02:00
inputMedia = getDocumentMediaInput ( doc ) ;
2020-05-01 23:28:40 +02:00
}
2023-01-11 15:43:14 +01:00
// copy original flags
const copyProperties : ( keyof InputMedia . inputMediaPhoto ) [ ] = [
'pFlags' ,
'ttl_seconds'
] ;
copyProperties . forEach ( ( property ) = > {
// @ts-ignore
inputMedia [ property ] = originalInputMedia [ property ] ? ? inputMedia [ property ] ;
} ) ;
2020-12-24 01:59:44 +01:00
const inputSingleMedia : InputSingleMedia = {
2020-12-10 00:58:20 +01:00
_ : 'inputSingleMedia' ,
media : inputMedia ,
random_id : message.random_id ,
message : caption ,
entities
2020-12-24 01:59:44 +01:00
} ;
2020-12-10 00:58:20 +01:00
// * only 1 caption for all inputs
if ( caption ) {
caption = '' ;
entities = [ ] ;
}
2020-12-24 01:59:44 +01:00
return inputSingleMedia ;
2022-09-02 19:43:54 +02:00
} ) . catch ( ( err : ApiError ) = > {
2020-12-24 06:26:29 +01:00
this . log . error ( 'sendAlbum upload item error:' , err , message ) ;
2022-09-02 19:43:54 +02:00
toggleError ( message , err ) ;
2020-12-24 01:59:44 +01:00
throw err ;
2020-05-01 23:28:40 +02:00
} ) ;
2020-12-24 01:59:44 +01:00
} ) ;
2020-05-01 23:28:40 +02:00
2022-06-17 18:01:43 +02:00
return Promise . all ( promises ) . then ( ( inputs ) = > {
2022-01-14 23:01:50 +01:00
return invoke ( inputs . filter ( Boolean ) ) ;
2020-12-24 01:59:44 +01:00
} ) ;
2020-05-01 23:28:40 +02:00
}
2022-01-15 03:41:06 +01:00
public sendContact ( peerId : PeerId , contactPeerId : PeerId ) {
2022-04-25 16:54:30 +02:00
return this . sendOther ( peerId , this . appUsersManager . getContactMediaInput ( contactPeerId ) ) ;
2022-01-15 03:41:06 +01:00
}
2023-01-06 20:27:29 +01:00
public sendOther (
peerId : PeerId ,
inputMedia : InputMedia | { _ : 'messageMediaPending' , messageMedia : MessageMedia } ,
options : MessageSendingParams & Partial < {
viaBotId : BotId ,
replyMarkup : ReplyMarkup ,
clearDraft : true ,
queryId : string
resultId : string ,
geoPoint : GeoPoint
} > = { }
) {
2022-04-25 16:54:30 +02:00
peerId = this . appPeersManager . getPeerMigratedTo ( peerId ) || peerId ;
2020-12-11 03:06:16 +01:00
2022-08-04 08:49:54 +02:00
// this.checkSendOptions(options);
2021-02-07 07:40:26 +01:00
const message = this . generateOutgoingMessage ( peerId , options ) ;
2022-06-17 18:01:43 +02:00
const replyToMsgId = options . replyToMsgId ? getServerMessageId ( options . replyToMsgId ) : undefined ;
2020-06-16 22:48:08 +02:00
2021-07-21 14:16:15 +02:00
let media : MessageMedia ;
2020-06-16 22:48:08 +02:00
switch ( inputMedia . _ ) {
case 'inputMediaPoll' : {
2021-08-03 03:44:13 +02:00
const pollId = '' + message . id ;
inputMedia . poll . id = pollId ;
2022-04-25 16:54:30 +02:00
this . appPollsManager . savePoll ( inputMedia . poll , {
2020-06-16 22:48:08 +02:00
_ : 'pollResults' ,
flags : 4 ,
total_voters : 0 ,
pFlags : { } ,
2022-01-08 13:52:14 +01:00
recent_voters : [ ]
2020-06-16 22:48:08 +02:00
} ) ;
2022-04-25 16:54:30 +02:00
const { poll , results } = this . appPollsManager . getPoll ( pollId ) ;
2020-06-16 22:48:08 +02:00
media = {
_ : 'messageMediaPoll' ,
poll ,
results
} ;
break ;
}
2021-08-03 03:44:13 +02:00
case 'inputMediaPhoto' : {
2020-06-16 22:48:08 +02:00
media = {
_ : 'messageMediaPhoto' ,
2023-02-01 14:26:41 +01:00
photo : this.appPhotosManager.getPhoto ( ( inputMedia . id as InputPhoto . inputPhoto ) . id ) ,
pFlags : { }
2020-06-16 22:48:08 +02:00
} ;
break ;
2021-08-03 03:44:13 +02:00
}
2020-06-16 22:48:08 +02:00
2021-08-03 03:44:13 +02:00
case 'inputMediaDocument' : {
2022-04-25 16:54:30 +02:00
const doc = this . appDocsManager . getDoc ( ( inputMedia . id as InputDocument . inputDocument ) . id ) ;
2021-08-03 03:44:13 +02:00
/ * i f ( d o c . s t i c k e r & & d o c . s t i c k e r S e t I n p u t ) {
2020-06-16 22:48:08 +02:00
appStickersManager . pushPopularSticker ( doc . id ) ;
2021-08-03 03:44:13 +02:00
} * /
2020-06-16 22:48:08 +02:00
media = {
_ : 'messageMediaDocument' ,
2023-02-01 14:26:41 +01:00
document : doc ,
pFlags : { }
2020-06-16 22:48:08 +02:00
} ;
break ;
2021-08-03 03:44:13 +02:00
}
2020-06-16 22:48:08 +02:00
2021-08-03 03:44:13 +02:00
case 'inputMediaContact' : {
2020-06-16 22:48:08 +02:00
media = {
_ : 'messageMediaContact' ,
phone_number : inputMedia.phone_number ,
first_name : inputMedia.first_name ,
last_name : inputMedia.last_name ,
2021-10-21 15:16:43 +02:00
user_id : inputMedia.user_id ? ? '0' ,
2021-08-03 03:44:13 +02:00
vcard : inputMedia.vcard
2020-06-16 22:48:08 +02:00
} ;
break ;
2021-08-03 03:44:13 +02:00
}
2020-06-16 22:48:08 +02:00
2021-08-03 03:44:13 +02:00
case 'inputMediaGeoPoint' : {
2020-06-16 22:48:08 +02:00
media = {
_ : 'messageMediaGeo' ,
2021-08-03 03:44:13 +02:00
geo : options.geoPoint
2020-06-16 22:48:08 +02:00
} ;
break ;
2021-08-03 03:44:13 +02:00
}
2020-06-16 22:48:08 +02:00
2021-08-03 03:44:13 +02:00
case 'inputMediaVenue' : {
2020-06-16 22:48:08 +02:00
media = {
_ : 'messageMediaVenue' ,
2021-08-03 03:44:13 +02:00
geo : options.geoPoint ,
2020-06-16 22:48:08 +02:00
title : inputMedia.title ,
address : inputMedia.address ,
provider : inputMedia.provider ,
2021-08-03 03:44:13 +02:00
venue_id : inputMedia.venue_id ,
venue_type : inputMedia.venue_type
2020-06-16 22:48:08 +02:00
} ;
break ;
2021-08-03 03:44:13 +02:00
}
2022-08-04 08:49:54 +02:00
2021-08-03 03:44:13 +02:00
case 'messageMediaPending' : {
2022-07-18 15:00:41 +02:00
media = ( inputMedia as any ) . messageMedia ;
2021-08-03 03:44:13 +02:00
break ;
}
2020-06-16 22:48:08 +02:00
}
2021-02-07 07:40:26 +01:00
message . media = media ;
2020-06-16 22:48:08 +02:00
2022-09-02 19:43:54 +02:00
const toggleError = ( error? : ApiError ) = > {
this . onMessagesSendError ( [ message ] , error ) ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'messages_pending' ) ;
2020-06-16 22:48:08 +02:00
} ;
message . send = ( ) = > {
2021-07-15 17:34:34 +02:00
const sentRequestOptions : PendingAfterMsg = { } ;
2020-12-11 03:06:16 +01:00
if ( this . pendingAfterMsgs [ peerId ] ) {
sentRequestOptions . afterMessageId = this . pendingAfterMsgs [ peerId ] . messageId ;
2020-06-16 22:48:08 +02:00
}
2022-04-25 16:54:30 +02:00
const sendAs = options . sendAsPeerId ? this . appPeersManager . getInputPeerById ( options . sendAsPeerId ) : undefined ;
2020-06-16 22:48:08 +02:00
let apiPromise : Promise < any > ;
2020-12-11 03:06:16 +01:00
if ( options . viaBotId ) {
2022-06-17 18:01:43 +02:00
apiPromise = this . apiManager . invokeApiAfter ( 'messages.sendInlineBotResult' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2021-02-07 07:40:26 +01:00
random_id : message.random_id ,
2020-12-16 04:22:58 +01:00
reply_to_msg_id : replyToMsgId || undefined ,
2020-12-11 03:06:16 +01:00
query_id : options.queryId ,
id : options.resultId ,
2021-08-03 03:44:13 +02:00
clear_draft : options.clearDraft ,
schedule_date : options.scheduleDate ,
2022-02-20 16:37:37 +01:00
silent : options.silent ,
send_as : sendAs
2020-06-16 22:48:08 +02:00
} , sentRequestOptions ) ;
} else {
2022-06-17 18:01:43 +02:00
apiPromise = this . apiManager . invokeApiAfter ( 'messages.sendMedia' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-07-18 15:00:41 +02:00
media : inputMedia as InputMedia ,
2021-02-07 07:40:26 +01:00
random_id : message.random_id ,
2020-12-16 04:22:58 +01:00
reply_to_msg_id : replyToMsgId || undefined ,
2020-10-10 00:36:06 +02:00
message : '' ,
2020-12-18 04:07:32 +01:00
clear_draft : options.clearDraft ,
schedule_date : options.scheduleDate ,
2022-02-20 16:37:37 +01:00
silent : options.silent ,
2022-11-01 18:39:23 +01:00
send_as : sendAs ,
update_stickersets_order : UPDATE_STICKERSET_ORDER
2020-06-16 22:48:08 +02:00
} , sentRequestOptions ) ;
}
2020-10-10 00:36:06 +02:00
2021-07-21 14:16:15 +02:00
this . pendingAfterMsgs [ peerId ] = sentRequestOptions ;
return apiPromise . then ( ( updates ) = > {
2020-06-16 22:48:08 +02:00
if ( updates . updates ) {
2021-08-03 03:44:13 +02:00
updates . updates . forEach ( ( update : Update ) = > {
2021-02-04 01:30:23 +01:00
if ( update . _ === 'updateDraftMessage' ) {
2021-08-03 03:44:13 +02:00
update . local = true ;
2020-06-16 22:48:08 +02:00
}
} ) ;
}
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2022-09-02 19:43:54 +02:00
} , ( error : ApiError ) = > {
toggleError ( error ) ;
throw error ;
2020-06-16 22:48:08 +02:00
} ) . finally ( ( ) = > {
2020-12-11 03:06:16 +01:00
if ( this . pendingAfterMsgs [ peerId ] === sentRequestOptions ) {
delete this . pendingAfterMsgs [ peerId ] ;
2020-06-16 22:48:08 +02:00
}
} ) ;
2021-07-21 14:16:15 +02:00
} ;
2020-06-16 22:48:08 +02:00
2021-01-09 15:08:26 +01:00
this . beforeMessageSending ( message , {
2022-08-04 08:49:54 +02:00
isScheduled : ! ! options . scheduleDate || undefined ,
2021-01-09 15:08:26 +01:00
threadId : options.threadId ,
2022-06-17 18:01:43 +02:00
clearDraft : options.clearDraft ,
sequential : true
2021-01-09 15:08:26 +01:00
} ) ;
2022-01-14 23:01:50 +01:00
return message . promise ;
2020-12-18 04:07:32 +01:00
}
/ * p r i v a t e c h e c k S e n d O p t i o n s ( o p t i o n s : P a r t i a l < {
scheduleDate : number
} > ) {
if ( options . scheduleDate ) {
const minTimestamp = ( Date . now ( ) / 1000 | 0 ) + 10 ;
if ( options . scheduleDate <= minTimestamp ) {
delete options . scheduleDate ;
}
}
} * /
2020-06-16 22:48:08 +02:00
2023-01-06 20:27:29 +01:00
private beforeMessageSending ( message : Message.message , options : Pick < MessageSendingParams , ' threadId ' > & Partial < {
2022-08-18 13:21:19 +02:00
isGroupedItem : boolean ,
isScheduled : boolean ,
clearDraft : boolean ,
2022-06-30 16:14:33 +02:00
sequential : boolean ,
processAfter ? : ( cb : ( ) = > void ) = > void
2021-01-09 15:08:26 +01:00
} > = { } ) {
2020-12-18 04:07:32 +01:00
const messageId = message . id ;
const peerId = this . getMessagePeer ( message ) ;
2022-06-17 18:01:43 +02:00
const storage = options . isScheduled ? this . getScheduledMessagesStorage ( peerId ) : this . getHistoryMessagesStorage ( peerId ) ;
2022-09-02 19:43:54 +02:00
message . storageKey = storage . key ;
2022-08-04 08:49:54 +02:00
const callbacks : Array < ( ) = > void > = [ ] ;
2020-12-18 04:07:32 +01:00
if ( options . isScheduled ) {
2022-08-04 08:49:54 +02:00
// if(!options.isGroupedItem) {
2021-02-10 07:06:22 +01:00
this . saveMessages ( [ message ] , { storage , isScheduled : true , isOutgoing : true } ) ;
2022-06-30 16:14:33 +02:00
callbacks . push ( ( ) = > {
this . rootScope . dispatchEvent ( 'scheduled_new' , message ) ;
} ) ;
2020-12-18 04:07:32 +01:00
} else {
2021-04-14 10:30:14 +02:00
/ * i f ( o p t i o n s . t h r e a d I d & & t h i s . t h r e a d s S t o r a g e [ p e e r I d ] ) {
2020-12-29 09:08:50 +01:00
delete this . threadsStorage [ peerId ] [ options . threadId ] ;
2021-04-14 10:30:14 +02:00
} * /
2021-05-06 23:02:21 +02:00
const storages : HistoryStorage [ ] = [
this . getHistoryStorage ( peerId ) ,
options . threadId ? this . getHistoryStorage ( peerId , options . threadId ) : undefined
] ;
for ( const storage of storages ) {
if ( storage ) {
storage . history . unshift ( messageId ) ;
}
2021-04-14 10:30:14 +02:00
}
2020-12-29 09:08:50 +01:00
2021-02-10 07:06:22 +01:00
this . saveMessages ( [ message ] , { storage , isOutgoing : true } ) ;
2021-09-17 18:50:29 +02:00
this . setDialogTopMessage ( message ) ;
2023-01-06 20:27:29 +01:00
if ( options . threadId ) {
const forumTopic = this . dialogsStorage . getForumTopic ( peerId , options . threadId ) ;
if ( forumTopic ) {
this . setDialogTopMessage ( message , forumTopic ) ;
}
}
2022-06-30 16:14:33 +02:00
callbacks . push ( ( ) = > {
this . rootScope . dispatchEvent ( 'history_append' , { storageKey : storage.key , message } ) ;
} ) ;
2020-12-18 04:07:32 +01:00
}
2021-01-09 15:08:26 +01:00
2022-06-17 18:01:43 +02:00
const pending : PendingMessageDetails = this . pendingByRandomId [ message . random_id ] = {
2022-08-04 08:49:54 +02:00
peerId ,
tempId : messageId ,
threadId : options.threadId ,
2022-06-17 18:01:43 +02:00
storage ,
sequential : options.sequential
2021-04-14 10:30:14 +02:00
} ;
2020-06-16 22:48:08 +02:00
2022-11-27 14:09:10 +01:00
this . pendingTopMsgs [ peerId ] = messageId ;
2021-02-10 07:06:22 +01:00
if ( ! options . isGroupedItem && message . send ) {
2022-06-30 16:14:33 +02:00
callbacks . push ( ( ) = > {
2021-10-22 20:31:54 +02:00
if ( options . clearDraft ) {
2022-04-25 16:54:30 +02:00
this . appDraftsManager . clearDraft ( peerId , options . threadId ) ;
2021-10-22 20:31:54 +02:00
}
message . send ( ) ;
2022-06-30 16:14:33 +02:00
} ) ;
}
if ( callbacks . length ) {
( options . processAfter || processAfter ) ( ( ) = > {
for ( const callback of callbacks ) {
callback ( ) ;
}
} ) ;
2020-12-19 02:07:24 +01:00
}
2022-06-17 18:01:43 +02:00
return pending ;
2020-12-19 02:07:24 +01:00
}
2023-01-06 20:27:29 +01:00
private generateOutgoingMessage ( peerId : PeerId , options : MessageSendingParams & Partial < {
2021-10-21 15:16:43 +02:00
viaBotId : BotId ,
2021-02-10 07:06:22 +01:00
groupId : string ,
2021-08-03 03:44:13 +02:00
replyMarkup : ReplyMarkup ,
2021-02-07 07:40:26 +01:00
} > ) {
if ( options . threadId && ! options . replyToMsgId ) {
options . replyToMsgId = options . threadId ;
}
2021-09-15 10:09:24 +02:00
let postAuthor : string ;
2022-04-25 16:54:30 +02:00
const isBroadcast = this . appPeersManager . isBroadcast ( peerId ) ;
2021-09-15 10:09:24 +02:00
if ( isBroadcast ) {
2022-04-25 16:54:30 +02:00
const chat = this . appPeersManager . getPeer ( peerId ) as Chat . channel ;
2021-09-15 10:09:24 +02:00
if ( chat . pFlags . signatures ) {
2022-04-25 16:54:30 +02:00
const user = this . appUsersManager . getSelf ( ) ;
2021-09-15 10:09:24 +02:00
const fullName = user . first_name + ( user . last_name ? ' ' + user . last_name : '' ) ;
postAuthor = fullName ;
}
}
2021-07-21 14:16:15 +02:00
const message : Message.message = {
2021-02-07 07:40:26 +01:00
_ : 'message' ,
id : this.generateTempMessageId ( peerId ) ,
2022-04-25 16:54:30 +02:00
from_id : options.sendAsPeerId ? this . appPeersManager . getOutputPeer ( options . sendAsPeerId ) : this . generateFromId ( peerId ) ,
peer_id : this.appPeersManager.getOutputPeer ( peerId ) ,
2022-08-04 08:49:54 +02:00
post_author : postAuthor ,
2021-02-07 07:40:26 +01:00
pFlags : this.generateFlags ( peerId ) ,
2022-06-17 18:01:43 +02:00
date : options.scheduleDate || ( tsNow ( true ) + this . timeManager . getServerTimeOffset ( ) ) ,
2021-02-07 07:40:26 +01:00
message : '' ,
2021-02-10 07:06:22 +01:00
grouped_id : options.groupId ,
2021-02-07 07:40:26 +01:00
random_id : randomLong ( ) ,
2023-01-06 20:27:29 +01:00
reply_to : this.generateReplyHeader ( peerId , options . replyToMsgId , options . threadId ) ,
2021-02-07 07:40:26 +01:00
via_bot_id : options.viaBotId ,
2021-08-03 03:44:13 +02:00
reply_markup : options.replyMarkup ,
2021-02-07 07:40:26 +01:00
replies : this.generateReplies ( peerId ) ,
2021-09-15 10:09:24 +02:00
views : isBroadcast && 1 ,
2022-06-17 18:01:43 +02:00
pending : true
2021-02-07 07:40:26 +01:00
} ;
2022-06-17 18:01:43 +02:00
defineNotNumerableProperties ( message , [ 'send' , 'promise' ] ) ;
if ( options . groupId === undefined ) {
message . promise = deferredPromise ( ) ;
}
2021-02-07 07:40:26 +01:00
return message ;
}
2023-01-06 20:27:29 +01:00
private generateReplyHeader ( peerId : PeerId , replyToMsgId : number , replyToTopId? : number ) {
2023-01-06 21:24:07 +01:00
const isForum = this . appPeersManager . isForum ( peerId ) ;
if ( isForum && ! replyToTopId ) {
const originalMessage = this . getMessageByPeer ( peerId , replyToMsgId ) ;
if ( originalMessage ) {
replyToTopId = getMessageThreadId ( originalMessage , true ) ;
}
}
2023-01-06 20:27:29 +01:00
const header : MessageReplyHeader = {
2020-12-20 04:54:35 +01:00
_ : 'messageReplyHeader' ,
2023-01-06 20:27:29 +01:00
reply_to_msg_id : replyToMsgId || replyToTopId ,
pFlags : { }
} ;
2023-01-06 21:24:07 +01:00
if ( replyToTopId && isForum && GENERAL_TOPIC_ID !== replyToTopId ) {
2023-01-06 20:27:29 +01:00
header . pFlags . forum_topic = true ;
}
2020-12-20 04:54:35 +01:00
2021-01-31 02:52:14 +01:00
if ( replyToTopId && header . reply_to_msg_id !== replyToTopId ) {
2020-12-20 04:54:35 +01:00
header . reply_to_top_id = replyToTopId ;
}
return header ;
}
2021-10-21 15:16:43 +02:00
private generateReplies ( peerId : PeerId ) {
2021-02-07 07:40:26 +01:00
let replies : MessageReplies.messageReplies ;
2022-04-25 16:54:30 +02:00
if ( this . appPeersManager . isBroadcast ( peerId ) ) {
const channelFull = this . appProfileManager . getCachedFullChat ( peerId . toChatId ( ) ) as ChatFull . channelFull ;
2021-03-10 19:44:46 +01:00
if ( channelFull ? . linked_chat_id ) {
2021-02-07 07:40:26 +01:00
replies = {
_ : 'messageReplies' ,
flags : 1 ,
pFlags : {
comments : true
} ,
channel_id : channelFull.linked_chat_id ,
replies : 0 ,
replies_pts : 0
} ;
}
}
return replies ;
}
2020-12-21 05:55:53 +01:00
/ * *
* Generate correct from_id according to anonymous or broadcast
* /
2021-10-21 15:16:43 +02:00
private generateFromId ( peerId : PeerId ) {
2022-04-25 16:54:30 +02:00
if ( this . appPeersManager . isAnyChat ( peerId ) && ( this . appPeersManager . isBroadcast ( peerId ) || this . isAnonymousSending ( peerId ) ) ) {
2020-12-21 05:55:53 +01:00
return undefined ;
} else {
2022-04-25 16:54:30 +02:00
return this . appPeersManager . getOutputPeer ( this . appUsersManager . getSelf ( ) . id . toPeerId ( ) ) ;
2020-12-21 05:55:53 +01:00
}
}
2021-10-21 15:16:43 +02:00
private generateFlags ( peerId : PeerId ) {
2021-08-03 03:44:13 +02:00
const pFlags : Message.message [ 'pFlags' ] = { } ;
2022-04-25 16:54:30 +02:00
const fromId = this . appUsersManager . getSelf ( ) . id ;
2020-12-21 05:55:53 +01:00
if ( peerId !== fromId ) {
pFlags . out = true ;
2022-04-25 16:54:30 +02:00
if ( ! this . appPeersManager . isChannel ( peerId ) && ! this . appUsersManager . isBot ( peerId ) ) {
2020-12-21 05:55:53 +01:00
pFlags . unread = true ;
}
}
2022-04-25 16:54:30 +02:00
if ( this . appPeersManager . isBroadcast ( peerId ) ) {
2020-12-21 05:55:53 +01:00
pFlags . post = true ;
}
return pFlags ;
}
2021-10-21 15:16:43 +02:00
private generateForwardHeader ( peerId : PeerId , originalMessage : Message.message ) {
2022-04-25 16:54:30 +02:00
const myId = this . appUsersManager . getSelf ( ) . id . toPeerId ( ) ;
2022-02-13 10:29:17 +01:00
const fromId = originalMessage . fromId ;
if ( fromId === myId && originalMessage . peerId === myId && ! originalMessage . fwd_from ) {
2021-02-10 07:06:22 +01:00
return ;
}
2021-02-07 11:00:11 +01:00
const fwdHeader : MessageFwdHeader.messageFwdHeader = {
_ : 'messageFwdHeader' ,
flags : 0 ,
2023-02-01 14:26:41 +01:00
date : originalMessage.date ,
pFlags : { }
2021-02-07 11:00:11 +01:00
} ;
2022-02-13 10:29:17 +01:00
let isUserHidden = false ;
2021-02-10 07:06:22 +01:00
if ( originalMessage . fwd_from ) {
fwdHeader . from_id = originalMessage . fwd_from . from_id ;
fwdHeader . from_name = originalMessage . fwd_from . from_name ;
fwdHeader . post_author = originalMessage . fwd_from . post_author ;
} else {
fwdHeader . post_author = originalMessage . post_author ;
2022-08-04 08:49:54 +02:00
2022-02-13 10:29:17 +01:00
if ( fromId . isUser ( ) ) {
2022-04-25 16:54:30 +02:00
const userFull = this . appProfileManager . getCachedFullUser ( fromId . toUserId ( ) ) ;
2022-02-13 10:29:17 +01:00
if ( userFull ? . private_forward_name ) {
fwdHeader . from_name = userFull . private_forward_name ;
isUserHidden = true ;
}
}
if ( ! isUserHidden ) {
2022-04-25 16:54:30 +02:00
fwdHeader . from_id = this . appPeersManager . getOutputPeer ( fromId ) ;
2022-02-13 10:29:17 +01:00
}
2021-02-10 07:06:22 +01:00
}
2022-04-25 16:54:30 +02:00
if ( this . appPeersManager . isBroadcast ( originalMessage . peerId ) ) {
2021-02-07 11:00:11 +01:00
if ( originalMessage . post_author ) {
fwdHeader . post_author = originalMessage . post_author ;
}
fwdHeader . channel_post = originalMessage . id ;
}
2022-08-04 08:49:54 +02:00
2022-02-13 10:29:17 +01:00
if ( peerId === myId && ! isUserHidden ) {
2021-02-07 11:00:11 +01:00
fwdHeader . saved_from_msg_id = originalMessage . id ;
2022-04-25 16:54:30 +02:00
fwdHeader . saved_from_peer = this . appPeersManager . getOutputPeer ( originalMessage . peerId ) ;
2021-02-07 11:00:11 +01:00
}
return fwdHeader ;
}
2021-10-21 15:16:43 +02:00
public generateFakeAvatarMessage ( peerId : PeerId , photo : Photo ) {
2021-04-13 18:19:52 +02:00
const maxId = Number . MAX_SAFE_INTEGER ;
2022-02-27 20:21:21 +01:00
const message : Message.messageService = {
2021-04-13 18:19:52 +02:00
_ : 'messageService' ,
2022-02-27 20:21:21 +01:00
pFlags : { } ,
2021-04-13 18:19:52 +02:00
action : {
_ : 'messageActionChannelEditPhoto' ,
photo
} ,
2022-02-27 20:21:21 +01:00
id : maxId ,
2022-04-25 16:54:30 +02:00
peer_id : this.appPeersManager.getOutputPeer ( peerId ) ,
2021-04-13 18:19:52 +02:00
mid : maxId ,
peerId ,
date : ( photo as Photo . photo ) . date ,
fromId : peerId
2022-02-27 20:21:21 +01:00
} ;
2021-04-13 18:19:52 +02:00
2022-06-17 18:01:43 +02:00
this . getHistoryMessagesStorage ( peerId ) . set ( maxId , message ) ;
2021-04-13 18:19:52 +02:00
return message ;
}
2022-06-17 18:01:43 +02:00
public getUploadPromise ( uploadFileName : string ) {
return this . uploadFilePromises [ uploadFileName ] ;
}
2021-10-21 15:16:43 +02:00
public isAnonymousSending ( peerId : PeerId ) : boolean {
2023-01-06 20:27:29 +01:00
if ( ! peerId . isAnyChat ( ) ) {
return false ;
}
const chat = this . appPeersManager . getPeer ( peerId ) ;
return ( chat as Chat . channel ) . admin_rights ? . pFlags ? . anonymous ;
2021-09-23 17:46:03 +02:00
}
2023-01-06 20:27:29 +01:00
public setDialogTopMessage (
message : MyMessage ,
dialog : MTDialog.dialog | ForumTopic = this . getDialogOnly ( message . peerId )
) {
if ( ! dialog ) {
return ;
}
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
dialog . top_message = message . mid ;
2020-12-19 02:07:24 +01:00
2023-01-06 20:27:29 +01:00
const historyStorage = this . getHistoryStorage ( message . peerId , dialog . _ === 'forumTopic' ? dialog.id : undefined ) ;
historyStorage . maxId = message . mid ;
2020-12-19 02:07:24 +01:00
2023-01-06 20:27:29 +01:00
this . dialogsStorage . generateIndexForDialog ( dialog , false , message ) ;
this . scheduleHandleNewDialogs ( message . peerId , dialog ) ;
2020-06-16 22:48:08 +02:00
}
2020-12-18 04:07:32 +01:00
public cancelPendingMessage ( randomId : string ) {
2020-12-11 03:06:16 +01:00
const pendingData = this . pendingByRandomId [ randomId ] ;
2020-02-06 16:43:07 +01:00
2021-01-08 10:55:37 +01:00
/ * i f ( D E B U G ) {
this . log ( 'cancelPendingMessage' , randomId , pendingData ) ;
} * /
2020-02-06 16:43:07 +01:00
if ( pendingData ) {
2020-12-18 04:07:32 +01:00
const { peerId , tempId , storage } = pendingData ;
const historyStorage = this . getHistoryStorage ( peerId ) ;
2020-02-06 16:43:07 +01:00
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( {
2021-07-04 01:56:21 +02:00
_ : 'updateDeleteMessages' ,
messages : [ tempId ] ,
pts : undefined ,
pts_count : undefined
2020-02-06 16:43:07 +01:00
} ) ;
2021-05-06 23:02:21 +02:00
historyStorage . history . delete ( tempId ) ;
2020-02-06 16:43:07 +01:00
2020-12-18 04:07:32 +01:00
delete this . pendingByRandomId [ randomId ] ;
2021-10-05 22:40:07 +02:00
storage . delete ( tempId ) ;
2020-02-06 16:43:07 +01:00
return true ;
}
return false ;
}
2021-10-21 15:16:43 +02:00
/ * p u b l i c a s y n c r e f r e s h C o n v e r s a t i o n s ( ) {
2021-05-03 17:35:48 +02:00
const limit = 200 , outDialogs : Dialog [ ] = [ ] ;
2021-03-08 23:15:44 +01:00
for ( let folderId = 0 ; folderId < 2 ; ++ folderId ) {
let offsetDate = 0 ;
for ( ; ; ) {
2021-06-29 03:19:53 +02:00
const { dialogs , isEnd } = await this . getTopMessages ( limit , folderId , offsetDate ) ;
2022-08-04 08:49:54 +02:00
2021-03-08 23:15:44 +01:00
if ( dialogs . length ) {
outDialogs . push ( . . . dialogs as Dialog [ ] ) ;
const dialog = dialogs [ dialogs . length - 1 ] ;
2021-03-12 06:15:40 +01:00
// * get peerId and mid manually, because dialog can be migrated peer and it won't be saved
2022-06-17 18:01:43 +02:00
const peerId = getPeerId ( dialog . peer ) ;
const mid = generateMessageId ( dialog . top_message ) ;
2021-03-12 06:15:40 +01:00
offsetDate = this . getMessageByPeer ( peerId , mid ) . date ;
if ( ! offsetDate ) {
console . error ( 'refreshConversations: got no offsetDate' , dialog ) ;
break ;
}
2021-06-29 03:19:53 +02:00
}
2022-08-04 08:49:54 +02:00
2021-06-29 03:19:53 +02:00
if ( isEnd ) {
2021-03-08 23:15:44 +01:00
break ;
}
}
}
let obj : { [ peerId : string ] : Dialog } = { } ;
2022-06-17 18:01:43 +02:00
outDialogs . forEach ( ( dialog ) = > {
2021-03-08 23:15:44 +01:00
obj [ dialog . peerId ] = dialog ;
} ) ;
2021-06-11 14:52:53 +02:00
rootScope . dispatchEvent ( 'dialogs_multiupdate' , obj ) ;
2021-03-08 23:15:44 +01:00
return outDialogs ;
2021-10-21 15:16:43 +02:00
} * /
2023-01-17 20:28:27 +01:00
public async fillConversations ( folderId = GLOBAL_FOLDER_ID ) : Promise < void > {
2021-10-21 15:16:43 +02:00
const middleware = this . middleware . get ( ) ;
2023-01-17 20:28:27 +01:00
while ( ! this . dialogsStorage . isDialogsLoaded ( folderId ) ) {
const result = await this . getTopMessages ( { limit : 100 , folderId } ) ;
2021-10-21 15:16:43 +02:00
if ( ! middleware ( ) || result . isEnd ) {
break ;
}
}
2021-03-08 23:15:44 +01:00
}
2021-10-21 15:16:43 +02:00
/ * p u b l i c a s y n c g e t C o n v e r s a t i o n s A l l ( q u e r y = ' ' , f o l d e r I d = 0 ) {
2021-05-03 17:35:48 +02:00
const limit = 200 , outDialogs : Dialog [ ] = [ ] ;
2020-12-11 03:06:16 +01:00
for ( ; folderId < 2 ; ++ folderId ) {
2020-08-31 18:48:46 +02:00
let offsetIndex = 0 ;
for ( ; ; ) {
2021-09-03 18:33:10 +02:00
const { dialogs } = await appMessagesManager . getConversations ( query , offsetIndex , limit , folderId ) . promise ;
2022-08-04 08:49:54 +02:00
2020-08-31 18:48:46 +02:00
if ( dialogs . length ) {
outDialogs . push ( . . . dialogs ) ;
offsetIndex = dialogs [ dialogs . length - 1 ] . index || 0 ;
} else {
break ;
}
}
}
return outDialogs ;
2021-10-21 15:16:43 +02:00
} * /
2020-08-31 18:48:46 +02:00
2021-10-21 15:16:43 +02:00
public getReadMaxIdIfUnread ( peerId : PeerId , threadId? : number ) {
2020-12-20 04:54:35 +01:00
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
2023-01-06 20:27:29 +01:00
if ( threadId && ! this . appChatsManager . isForum ( peerId . toChatId ( ) ) ) {
2020-12-21 23:38:26 +01:00
const chatHistoryStorage = this . getHistoryStorage ( peerId ) ;
2021-05-08 13:31:12 +02:00
const readMaxId = Math . max ( chatHistoryStorage . readMaxId ? ? 0 , historyStorage . readMaxId ) ;
const message = this . getMessageByPeer ( peerId , historyStorage . maxId ) ; // usually message is missing, so pFlags.out won't be there anyway
2022-06-17 18:01:43 +02:00
return ! message ? . pFlags ? . out && readMaxId < historyStorage . maxId ? readMaxId : 0 ;
2020-12-21 23:38:26 +01:00
} else {
2020-12-22 08:07:37 +01:00
const message = this . getMessageByPeer ( peerId , historyStorage . maxId ) ;
2021-10-21 15:16:43 +02:00
const readMaxId = peerId . isUser ( ) ? Math . max ( historyStorage . readMaxId , historyStorage . readOutboxMaxId ) : historyStorage . readMaxId ;
2023-01-06 20:27:29 +01:00
// readMaxId can be 4294967295 (0)
return ! message ? . pFlags ? . out && readMaxId < historyStorage . maxId && getServerMessageId ( readMaxId ) ? readMaxId : 0 ;
2020-12-21 23:38:26 +01:00
}
2020-12-20 04:54:35 +01:00
}
2021-06-29 03:21:35 +02:00
// public lolSet = new Set();
2023-01-06 20:27:29 +01:00
public getTopMessages ( { limit , folderId } : {
limit : number ,
folderId : number
} ) {
2022-08-04 08:49:54 +02:00
// const dialogs = this.dialogsStorage.getFolder(folderId);
const offsetId = 0 ;
2021-10-21 15:16:43 +02:00
let offsetPeerId : PeerId ;
2020-05-18 03:21:58 +02:00
let offsetIndex = 0 ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
let offsetDate = this . dialogsStorage . getOffsetDate ( folderId ) ;
2021-03-08 23:15:44 +01:00
if ( offsetDate ) {
offsetIndex = offsetDate * 0x10000 ;
2022-06-17 18:01:43 +02:00
offsetDate += this . timeManager . getServerTimeOffset ( ) ;
2020-02-06 16:43:07 +01:00
}
2021-10-21 15:16:43 +02:00
const useLimit = 100 ;
2021-06-29 03:19:53 +02:00
const middleware = this . middleware . get ( ) ;
2023-01-06 20:27:29 +01:00
const peerId = this . dialogsStorage . isFilterIdForForum ( folderId ) ? folderId : undefined ;
2023-01-17 20:28:27 +01:00
const processResult = ( result : MessagesDialogs | MessagesForumTopics ) = > {
2023-01-06 20:27:29 +01:00
if ( ! middleware ( ) || result . _ === 'messages.dialogsNotModified' ) return null ;
2020-09-18 17:03:26 +02:00
2021-01-09 15:08:26 +01:00
if ( DEBUG ) {
2023-01-06 20:27:29 +01:00
this . log ( 'messages.getDialogs result:' , result ) ;
2021-01-09 15:08:26 +01:00
}
2020-09-19 18:32:48 +02:00
2021-06-29 03:19:53 +02:00
// can reset pinned order here
2023-01-06 20:27:29 +01:00
if ( ! peerId && ! offsetId && ! offsetDate && ! offsetPeerId && folderId !== GLOBAL_FOLDER_ID ) {
2021-05-25 12:45:35 +02:00
this . dialogsStorage . resetPinnedOrder ( folderId ) ;
}
2023-01-06 20:27:29 +01:00
if ( ! peerId && ! offsetDate ) {
2022-11-22 13:57:21 +01:00
// telegramMeWebManager.setAuthorized(true);
2022-06-17 18:01:43 +02:00
this . appDraftsManager . addMissedDialogs ( ) ;
2021-06-29 03:19:53 +02:00
}
2023-01-06 20:27:29 +01:00
this . appUsersManager . saveApiUsers ( result . users ) ;
this . appChatsManager . saveApiChats ( result . chats ) ;
this . saveMessages ( result . messages ) ;
2020-02-06 16:43:07 +01:00
2020-09-18 17:03:26 +02:00
let maxSeenIdIncremented = offsetDate ? true : false ;
let hasPrepend = false ;
2023-01-06 20:27:29 +01:00
const noIdsDialogs : BroadcastEvents [ 'dialogs_multiupdate' ] = new Map ( ) ;
const setFolderId : REAL_FOLDER_ID = folderId === GLOBAL_FOLDER_ID ? FOLDER_ID_ALL : folderId as REAL_FOLDER_ID ;
const saveGlobalOffset = ! ! peerId || folderId === GLOBAL_FOLDER_ID ;
const items : Array < Dialog | ForumTopic > =
( result as MessagesDialogs . messagesDialogsSlice ) . dialogs as Dialog [ ] ||
( result as MessagesForumTopics ) . topics as ForumTopic [ ] ;
forEachReverse ( items , ( dialog ) = > {
if ( ! dialog ) {
return ;
}
2022-08-04 08:49:54 +02:00
// const d = Object.assign({}, dialog);
2021-02-04 01:30:23 +01:00
// ! нужно передавать folderId, так как по папке !== 0 нет свойства folder_id
2023-01-06 20:27:29 +01:00
if ( ! peerId ) {
( dialog as Dialog ) . folder_id ? ? = setFolderId ;
2021-10-21 15:16:43 +02:00
}
2023-01-06 20:27:29 +01:00
this . dialogsStorage . saveDialog ( {
dialog ,
ignoreOffsetDate : true ,
saveGlobalOffset
} ) ;
if ( dialog . peerId === undefined ) {
2023-01-17 20:28:27 +01:00
this . log . error ( 'bugged dialog?' , dialog ) ;
debugger ;
2023-01-06 20:27:29 +01:00
return ;
}
2020-09-18 17:03:26 +02:00
2021-05-25 12:45:35 +02:00
if ( ! maxSeenIdIncremented &&
2022-07-26 17:24:29 +02:00
! this . appPeersManager . isChannel ( dialog . peerId || this . appPeersManager . getPeerId ( dialog . peer ) ) ) {
2021-05-25 12:45:35 +02:00
this . incrementMaxSeenId ( dialog . top_message ) ;
maxSeenIdIncremented = true ;
}
2021-06-29 03:21:35 +02:00
// if(!folderId && !dialog.folder_id) {
// this.lolSet.add(dialog.peerId);
// }
2021-06-29 03:19:53 +02:00
2022-06-17 18:01:43 +02:00
if ( offsetIndex && getDialogIndex ( dialog ) > offsetIndex ) {
2021-04-27 17:45:53 +02:00
this . scheduleHandleNewDialogs ( dialog . peerId , dialog ) ;
2020-02-06 16:43:07 +01:00
hasPrepend = true ;
}
2020-09-18 17:03:26 +02:00
// ! это может случиться, если запрос идёт не по папке 0, а по 1. почему-то read'ов нет
// ! в итоге, чтобы получить 1 диалог, делается первый запрос по папке 0, потом запрос для архивных по папке 1, и потом ещё перезагрузка архивного диалога
2023-01-06 20:27:29 +01:00
if ( ! peerId && ! getServerMessageId ( dialog . read_inbox_max_id ) && ! getServerMessageId ( dialog . read_outbox_max_id ) ) {
noIdsDialogs . set ( dialog . peerId , { dialog : dialog as Dialog } ) ;
2020-09-18 17:03:26 +02:00
2021-10-07 15:14:09 +02:00
this . log . error ( 'noIdsDialogs' , dialog , params ) ;
2023-01-11 23:21:56 +01:00
} else if ( dialog . top_message ) { // * fix sending status
const topMessage = this . getMessageByPeer ( dialog . peerId , dialog . top_message ) ;
if ( topMessage ) {
this . setMessageUnreadByDialog ( topMessage , dialog ) ;
this . dialogsStorage . setDialogToState ( dialog ) ;
}
2020-02-06 16:43:07 +01:00
}
2020-09-18 17:03:26 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
2022-08-19 21:27:29 +02:00
if ( noIdsDialogs . size ) {
2022-08-04 08:49:54 +02:00
// setTimeout(() => { // test bad situation
2022-08-19 21:27:29 +02:00
const peerIds = [ . . . noIdsDialogs . keys ( ) ] ;
2022-08-04 08:49:54 +02:00
const promises = peerIds . map ( ( peerId ) = > this . reloadConversation ( peerId ) ) ;
Promise . all ( promises ) . then ( ( ) = > {
this . rootScope . dispatchEvent ( 'dialogs_multiupdate' , noIdsDialogs ) ;
for ( let i = 0 ; i < peerIds . length ; ++ i ) {
const peerId = peerIds [ i ] ;
this . rootScope . dispatchEvent ( 'dialog_unread' , {
peerId ,
dialog : this.getDialogOnly ( peerId )
} ) ;
}
} ) ;
// }, 10e3);
2020-02-06 16:43:07 +01:00
}
2023-01-06 20:27:29 +01:00
const count = ( result as MessagesDialogs . messagesDialogsSlice ) . count ;
2020-09-18 17:03:26 +02:00
2021-06-29 03:19:53 +02:00
// exclude empty draft dialogs
2021-10-21 15:16:43 +02:00
const folderDialogs = this . dialogsStorage . getFolderDialogs ( folderId , false ) ;
2021-06-29 03:19:53 +02:00
let dialogsLength = 0 ;
2021-10-21 15:16:43 +02:00
for ( let i = 0 , length = folderDialogs . length ; i < length ; ++ i ) {
2023-01-17 20:28:27 +01:00
const dialog = folderDialogs [ i ] ;
if ( getServerMessageId ( dialog . top_message ) ) {
2021-06-29 03:19:53 +02:00
++ dialogsLength ;
2023-01-17 20:28:27 +01:00
} else {
this . log . error ( 'something strange with dialog' , dialog ) ;
2021-06-29 03:19:53 +02:00
}
}
2022-08-04 08:49:54 +02:00
const isEnd = /* limit > dialogsResult.dialogs.length || */
! count ||
2021-06-29 03:19:53 +02:00
dialogsLength >= count ||
2023-01-06 20:27:29 +01:00
! items . length ;
2021-06-29 03:19:53 +02:00
if ( isEnd ) {
2021-04-28 13:08:14 +02:00
this . dialogsStorage . setDialogsLoaded ( folderId , true ) ;
2020-02-06 16:43:07 +01:00
}
2020-05-13 17:26:40 +02:00
if ( hasPrepend ) {
this . scheduleHandleNewDialogs ( ) ;
2020-02-06 16:43:07 +01:00
} else {
2022-08-19 21:27:29 +02:00
this . rootScope . dispatchEvent ( 'dialogs_multiupdate' , new Map ( ) ) ;
2020-02-06 16:43:07 +01:00
}
2020-02-14 17:15:41 +01:00
2023-01-06 20:27:29 +01:00
const dialogs = items ;
2021-10-21 15:16:43 +02:00
const slicedDialogs = limit === useLimit ? dialogs : dialogs.slice ( 0 , limit ) ;
2021-06-29 03:19:53 +02:00
return {
2022-08-04 08:49:54 +02:00
isEnd : isEnd && slicedDialogs [ slicedDialogs . length - 1 ] === dialogs [ dialogs . length - 1 ] ,
count ,
2021-10-21 15:16:43 +02:00
dialogs : slicedDialogs
2021-06-29 03:19:53 +02:00
} ;
2023-01-17 20:28:27 +01:00
} ;
let promise : Promise < ReturnType < typeof processResult > > , params : any ;
if ( peerId ) {
promise = this . apiManager . invokeApiSingleProcess ( {
method : 'channels.getForumTopics' ,
params : params = {
channel : this.appChatsManager.getChannelInput ( peerId . toChatId ( ) ) ,
limit : useLimit ,
offset_date : offsetDate ,
offset_id : offsetId ,
offset_topic : 0
} ,
options : {
// timeout: APITIMEOUT,
noErrorBox : true
} ,
processResult : ( result ) = > {
result = this . dialogsStorage . processTopics ( peerId , result ) ;
return processResult ( result ) ;
}
} ) ;
} else {
// ! ВНИМАНИЕ: ОЧЕНЬ СЛОЖНАЯ ЛОГИКА:
// ! если делать запрос сначала по папке 0, потом по папке 1, по индексу 0 в массиве будет один и тот же диалог, с dialog.pFlags.pinned, ЛОЛ???
// ! т.е ., с запросом folder_id: 1, и exclude_pinned: 0, в результате будут ещё и закреплённые с папки 0
promise = this . apiManager . invokeApiSingleProcess ( {
method : 'messages.getDialogs' ,
params : params = {
folder_id : folderId ,
offset_date : offsetDate ,
offset_id : offsetId ,
offset_peer : this.appPeersManager.getInputPeerById ( offsetPeerId ) ,
limit : useLimit ,
hash : '0'
} ,
options : {
// timeout: APITIMEOUT,
noErrorBox : true
} ,
processResult
} ) ;
}
return promise ;
2020-02-06 16:43:07 +01:00
}
2023-01-06 20:27:29 +01:00
public async forwardMessages ( peerId : PeerId , fromPeerId : PeerId , mids : number [ ] , options : MessageSendingParams & Partial < {
2020-12-18 04:07:32 +01:00
withMyScore : true ,
2021-11-29 14:51:29 +01:00
dropAuthor : boolean ,
2023-01-06 20:27:29 +01:00
dropCaptions : boolean
2020-05-06 03:03:31 +02:00
} > = { } ) {
2022-11-28 15:21:01 +01:00
delete options . replyToMsgId ;
delete options . threadId ;
2022-04-25 16:54:30 +02:00
peerId = this . appPeersManager . getPeerMigratedTo ( peerId ) || peerId ;
2021-02-07 11:00:11 +01:00
mids = mids . slice ( ) . sort ( ( a , b ) = > a - b ) ;
2021-12-12 00:12:51 +01:00
for ( let i = 0 , length = mids . length ; i < length ; ++ i ) {
const mid = mids [ i ] ;
2022-06-17 18:01:43 +02:00
const originalMessage = this . getMessageByPeer ( fromPeerId , mid ) as Message . message ;
2021-12-12 00:12:51 +01:00
if ( originalMessage . pFlags . is_outgoing ) { // this can happen when forwarding a changelog
this . sendText ( peerId , originalMessage . message , {
entities : originalMessage.entities ,
scheduleDate : options.scheduleDate ,
silent : options.silent
} ) ;
mids . splice ( i -- , 1 ) ;
2022-06-17 18:01:43 +02:00
-- length ;
2021-12-12 00:12:51 +01:00
}
}
if ( ! mids . length ) {
return Promise . resolve ( ) ;
}
2022-06-17 18:01:43 +02:00
const config = await this . apiManager . getConfig ( ) ;
const overflowMids = mids . splice ( config . forwarded_count_max , mids . length - config . forwarded_count_max ) ;
2021-11-29 14:51:29 +01:00
if ( options . dropCaptions ) {
options . dropAuthor = true ;
}
2021-02-10 07:06:22 +01:00
const groups : {
[ groupId : string ] : {
tempId : string ,
2021-11-29 14:51:29 +01:00
messages : Message.message [ ]
2021-02-10 07:06:22 +01:00
}
} = { } ;
2022-04-16 18:21:50 +02:00
const newMids : number [ ] = [ ] ;
const newMessages = mids . map ( ( mid ) = > {
2022-06-17 18:01:43 +02:00
const originalMessage = this . getMessageByPeer ( fromPeerId , mid ) as Message . message ;
2021-04-04 20:46:09 +02:00
const message : Message.message = this . generateOutgoingMessage ( peerId , options ) ;
2022-04-16 18:21:50 +02:00
newMids . push ( message . id ) ;
2021-02-07 11:00:11 +01:00
2021-11-29 14:51:29 +01:00
const keys : Array < keyof Message.message > = [
2022-08-04 08:49:54 +02:00
'entities' ,
'media'
2021-11-29 14:51:29 +01:00
// 'reply_markup'
] ;
if ( ! options . dropAuthor ) {
message . fwd_from = this . generateForwardHeader ( peerId , originalMessage ) ;
keys . push ( 'views' , 'forwards' ) ;
2022-02-13 10:29:17 +01:00
2022-06-17 18:01:43 +02:00
if ( message . fwd_from ? . from_name && peerId === this . appPeersManager . peerId ) {
2022-02-23 14:17:03 +01:00
delete message . from_id ;
2022-02-13 10:29:17 +01:00
}
2021-11-29 14:51:29 +01:00
}
2021-11-30 17:12:53 +01:00
if ( ! options . dropCaptions || ! originalMessage . media ) {
2021-11-29 14:51:29 +01:00
keys . push ( 'message' ) ;
}
2022-04-16 18:21:50 +02:00
const replyToMid = originalMessage . reply_to ? . reply_to_msg_id ;
const replyToMessageIdx = mids . indexOf ( replyToMid ) ;
if ( replyToMid && replyToMessageIdx !== - 1 ) {
const newReplyToMid = newMids [ replyToMessageIdx ] ;
message . reply_to = {
_ : 'messageReplyHeader' ,
2023-02-01 14:26:41 +01:00
reply_to_msg_id : newReplyToMid ,
pFlags : { }
2022-04-16 18:21:50 +02:00
} ;
/ * t h i s . i n v o k e A f t e r M e s s a g e I s S e n t ( n e w R e p l y T o M i d , ' r e p l y ' , a s y n c ( o r i g i n a l M e s s a g e ) = > {
message . reply_to . reply_to_msg_id = originalMessage . mid ;
} ) ; * /
}
2022-06-17 18:01:43 +02:00
keys . forEach ( ( key ) = > {
2021-04-04 20:46:09 +02:00
// @ts-ignore
2022-08-13 14:14:06 +02:00
message [ key ] = copy ( originalMessage [ key ] ) ;
2021-02-07 11:00:11 +01:00
} ) ;
2021-04-04 20:46:09 +02:00
const document = ( message . media as MessageMedia . messageMediaDocument ) ? . document as MyDocument ;
if ( document ) {
const types : MyDocument [ 'type' ] [ ] = [ 'round' , 'voice' ] ;
if ( types . includes ( document . type ) ) {
( message as MyMessage ) . pFlags . media_unread = true ;
}
2022-08-13 14:14:06 +02:00
if ( document . sticker && ! this . rootScope . premium ) {
const effectThumb = getStickerEffectThumb ( document ) ;
if ( effectThumb ) {
( message . media as MessageMedia . messageMediaDocument ) . pFlags . nopremium = true ;
}
}
2021-04-04 20:46:09 +02:00
}
2021-02-10 07:06:22 +01:00
if ( originalMessage . grouped_id ) {
2023-01-06 20:27:29 +01:00
const group = groups [ originalMessage . grouped_id ] ? ? = { tempId : '' + ++ this . groupedTempId , messages : [ ] } ;
2021-02-10 07:06:22 +01:00
group . messages . push ( message ) ;
}
return message ;
} ) ;
for ( const groupId in groups ) {
const group = groups [ groupId ] ;
if ( group . messages . length > 1 ) {
2022-06-17 18:01:43 +02:00
group . messages . forEach ( ( message ) = > {
2021-02-10 07:06:22 +01:00
message . grouped_id = group . tempId ;
} ) ;
}
}
2022-06-17 18:01:43 +02:00
newMessages . forEach ( ( message ) = > {
2021-02-07 11:00:11 +01:00
this . beforeMessageSending ( message , {
2022-06-17 18:01:43 +02:00
isScheduled : ! ! options . scheduleDate || undefined ,
sequential : true
2021-02-07 11:00:11 +01:00
} ) ;
} ) ;
2020-05-06 03:03:31 +02:00
2021-07-15 17:34:34 +02:00
const sentRequestOptions : PendingAfterMsg = { } ;
2020-12-16 04:22:58 +01:00
if ( this . pendingAfterMsgs [ peerId ] ) {
sentRequestOptions . afterMessageId = this . pendingAfterMsgs [ peerId ] . messageId ;
}
2020-05-06 03:03:31 +02:00
2022-06-17 18:01:43 +02:00
const promise = /* true ? Promise.resolve() : */ this . apiManager . invokeApiAfter ( 'messages.forwardMessages' , {
2022-04-25 16:54:30 +02:00
from_peer : this.appPeersManager.getInputPeerById ( fromPeerId ) ,
2022-06-17 18:01:43 +02:00
id : mids.map ( ( mid ) = > getServerMessageId ( mid ) ) ,
random_id : newMessages.map ( ( message ) = > message . random_id ) ,
2022-04-25 16:54:30 +02:00
to_peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2020-12-18 04:07:32 +01:00
with_my_score : options.withMyScore ,
silent : options.silent ,
2021-11-29 14:51:29 +01:00
schedule_date : options.scheduleDate ,
drop_author : options.dropAuthor ,
2022-02-20 16:37:37 +01:00
drop_media_captions : options.dropCaptions ,
2022-04-25 16:54:30 +02:00
send_as : options.sendAsPeerId ? this . appPeersManager . getInputPeerById ( options . sendAsPeerId ) : undefined
2020-12-16 04:22:58 +01:00
} , sentRequestOptions ) . then ( ( updates ) = > {
2021-02-07 11:00:11 +01:00
this . log ( 'forwardMessages updates:' , updates ) ;
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2022-09-02 19:43:54 +02:00
} , ( error : ApiError ) = > {
this . onMessagesSendError ( newMessages , error ) ;
throw error ;
2020-12-24 01:59:44 +01:00
} ) . finally ( ( ) = > {
2020-12-16 04:22:58 +01:00
if ( this . pendingAfterMsgs [ peerId ] === sentRequestOptions ) {
delete this . pendingAfterMsgs [ peerId ] ;
2020-05-06 03:03:31 +02:00
}
2020-12-16 04:22:58 +01:00
} ) ;
2020-05-06 03:03:31 +02:00
2020-12-16 04:22:58 +01:00
this . pendingAfterMsgs [ peerId ] = sentRequestOptions ;
2022-06-17 18:01:43 +02:00
const promises : ( typeof promise ) [ ] = [ promise ] ;
if ( overflowMids . length ) {
promises . push ( this . forwardMessages ( peerId , fromPeerId , overflowMids , options ) ) ;
}
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
return Promise . all ( promises ) . then ( noop ) ;
2020-05-06 03:03:31 +02:00
}
2022-06-17 18:01:43 +02:00
public generateEmptyMessage ( mid : number ) : Message . message | Message . messageService {
return undefined ;
// return {
// _: 'messageEmpty',
// id: getServerMessageId(mid),
// mid,
// deleted: true,
// pFlags: {}
// };
}
2022-08-04 08:49:54 +02:00
2022-09-02 19:43:54 +02:00
private onMessagesSendError ( messages : Message.message [ ] , error? : ApiError ) {
messages . forEach ( ( message ) = > {
if ( message . error === error ) {
return ;
}
if ( error ) {
message . error = error ;
this . rootScope . dispatchEvent ( 'message_error' , { storageKey : message.storageKey , tempId : message.mid , error } ) ;
const dialog = this . getDialogOnly ( message . peerId ) ;
if ( dialog ) {
this . rootScope . dispatchEvent ( 'dialog_unread' , { peerId : message.peerId , dialog } ) ;
}
} else {
delete message . error ;
}
} ) ;
}
2022-06-17 18:01:43 +02:00
public getMessagesStorageByKey ( key : MessagesStorageKey ) {
const s = key . split ( '_' ) ;
const peerId : PeerId = + s [ 0 ] ;
const type : MessagesStorageType = s [ 1 ] as any ;
return type === 'scheduled' ? this . getScheduledMessagesStorage ( peerId ) : this . getHistoryMessagesStorage ( peerId ) ;
2020-02-06 16:43:07 +01:00
}
2022-06-17 18:01:43 +02:00
public getMessageFromStorage ( storage : MessagesStorage | MessagesStorageKey , mid : number ) {
if ( typeof ( storage ) === 'string' ) {
storage = this . getMessagesStorageByKey ( storage ) ;
}
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
return storage && storage . get ( mid ) /* || this.generateEmptyMessage(mid) */ ;
2021-10-22 20:31:54 +02:00
}
2022-06-17 18:01:43 +02:00
private createMessageStorage ( peerId : PeerId , type : MessagesStorageType ) {
const storage : MessagesStorage = new Map ( ) as any ;
storage . peerId = peerId ;
storage . type = type ;
storage . key = ` ${ peerId } _ ${ type } ` ;
2022-08-04 08:49:54 +02:00
2020-12-19 02:07:24 +01:00
/ * l e t n u m = 0 ;
Object . defineProperty ( storage , 'num' , {
get : ( ) = > ++ num ,
2022-08-04 08:49:54 +02:00
set : ( _num : number ) = > num = _num ,
2020-12-19 02:07:24 +01:00
enumerable : false
} ) ;
Object . defineProperty ( storage , 'generateIndex' , {
value : ( message : any ) = > {
if ( message . index === undefined ) {
message . index = ( message . date * 0x10000 ) + ( storage . num & 0xFFFF ) ;
}
} ,
enumerable : false
} ) ; * /
return storage ;
}
2022-06-17 18:01:43 +02:00
public getHistoryMessagesStorage ( peerId : PeerId ) {
2023-01-06 20:27:29 +01:00
return this . messagesStorageByPeerId [ peerId ] ? ? = this . createMessageStorage ( peerId , 'history' ) ;
2022-06-17 18:01:43 +02:00
}
public getMessagesStorage ( key : MessagesStorageKey | MessagesStorage ) : MessagesStorage {
if ( typeof ( key ) === 'object' ) {
return key ;
} else {
return this . getMessagesStorageByKey ( key ) ;
}
2020-12-16 04:22:58 +01:00
}
public getMessageById ( messageId : number ) {
for ( const peerId in this . messagesStorageByPeerId ) {
2022-04-25 16:54:30 +02:00
if ( this . appPeersManager . isChannel ( peerId . toPeerId ( ) ) ) {
2020-12-16 04:22:58 +01:00
continue ;
}
2021-10-05 22:40:07 +02:00
const message = this . messagesStorageByPeerId [ peerId ] . get ( messageId ) ;
2020-12-18 04:07:32 +01:00
if ( message ) {
return message ;
}
2020-12-16 04:22:58 +01:00
}
return this . getMessageFromStorage ( null , messageId ) ;
}
2021-10-21 15:16:43 +02:00
public getMessageByPeer ( peerId : PeerId , messageId : number ) {
2020-12-16 04:22:58 +01:00
if ( ! peerId ) {
return this . getMessageById ( messageId ) ;
}
2022-06-17 18:01:43 +02:00
return this . getMessageFromStorage ( this . getHistoryMessagesStorage ( peerId ) , messageId ) ;
2020-12-16 04:22:58 +01:00
}
2021-10-21 15:16:43 +02:00
public getMessagePeer ( message : any ) : PeerId {
2022-07-26 17:24:29 +02:00
const toId = message . peer_id && this . appPeersManager . getPeerId ( message . peer_id ) || NULL_PEER_ID ;
2020-02-06 16:43:07 +01:00
2020-12-11 03:06:16 +01:00
return toId ;
2020-02-06 16:43:07 +01:00
}
2021-10-21 15:16:43 +02:00
public getDialogOnly ( peerId : PeerId ) {
2021-04-27 17:45:53 +02:00
return this . dialogsStorage . getDialogOnly ( peerId ) ;
}
2022-06-17 18:01:43 +02:00
public cantForwardDeleteMids ( storageKey : MessagesStorageKey , mids : number [ ] ) {
const storage = this . getMessagesStorage ( storageKey ) ;
let cantForward = ! mids . length , cantDelete = ! mids . length ;
for ( const mid of mids ) {
const message = this . getMessageFromStorage ( storage , mid ) ;
if ( ! cantForward ) {
cantForward = ! this . canForward ( message ) ;
}
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
if ( ! cantDelete ) {
cantDelete = ! this . canDeleteMessage ( message ) ;
}
if ( cantForward && cantDelete ) break ;
}
return { cantForward , cantDelete } ;
}
2023-01-06 20:27:29 +01:00
public reloadConversationOrTopic ( peerId : PeerId , threadId? : number ) {
if ( threadId ) {
this . dialogsStorage . getForumTopicById ( peerId , threadId ) ;
} else {
this . reloadConversation ( peerId ) ;
}
}
2021-10-21 15:16:43 +02:00
public reloadConversation ( inputPeer? : PeerId | InputPeer ) : CancellablePromise < Dialog > ;
public reloadConversation ( inputPeer : PeerId | InputPeer ) {
let promise : CancellablePromise < Dialog > ;
if ( inputPeer !== undefined ) {
2022-07-26 17:24:29 +02:00
const peerId = this . appPeersManager . getPeerId ( inputPeer ) ;
2023-01-06 20:27:29 +01:00
this . log . warn ( 'reloadConversation' , peerId ) ;
2021-10-21 15:16:43 +02:00
let obj = this . reloadConversationsPeers . get ( peerId ) ;
if ( obj ) {
promise = obj . promise ;
}
if ( promise ) {
return promise ;
}
promise = deferredPromise ( ) ;
this . reloadConversationsPeers . set ( peerId , obj = {
2022-04-25 16:54:30 +02:00
inputDialogPeer : this.appPeersManager.getInputDialogPeerById ( inputPeer ) ,
2021-10-21 15:16:43 +02:00
promise
2021-06-29 03:19:53 +02:00
} ) ;
}
2020-02-06 16:43:07 +01:00
2021-10-21 15:16:43 +02:00
if ( this . reloadConversationsPromise ) {
return promise || this . reloadConversationsPromise ;
}
2022-06-30 16:14:33 +02:00
this . reloadConversationsPromise = pause ( 0 ) . then ( ( ) = > {
const inputDialogPeers : InputDialogPeer [ ] = [ ] ;
const promises : { [ peerId : string ] : typeof promise } = { } ;
for ( const [ peerId , { inputDialogPeer , promise } ] of this . reloadConversationsPeers ) {
inputDialogPeers . push ( inputDialogPeer ) ;
promises [ peerId ] = promise ;
}
2021-10-21 15:16:43 +02:00
2022-06-30 16:14:33 +02:00
const fullfillLeft = ( ) = > {
for ( const peerId in promises ) {
2023-01-06 20:27:29 +01:00
this . reloadConversationsPeers . delete ( + peerId ) ;
2022-06-30 16:14:33 +02:00
promises [ peerId ] . resolve ( undefined ) ;
}
} ;
2021-10-21 15:16:43 +02:00
2023-01-06 20:27:29 +01:00
const invoke = async ( ) = > {
for ( ; ; ) {
const result = await this . apiManager . invokeApi ( 'messages.getPeerDialogs' , { peers : inputDialogPeers } ) ;
const currentState = this . apiUpdatesManager . updatesState ;
const { state } = result ;
if ( currentState . pts && currentState . pts !== state . pts ) {
await pause ( 500 ) ;
continue ;
}
return result ;
}
} ;
return invoke ( ) . then ( ( result ) = > {
for ( const peerId in promises ) {
this . reloadConversationsPeers . delete ( + peerId ) ;
}
2022-06-30 16:14:33 +02:00
this . dialogsStorage . applyDialogs ( result ) ;
2021-06-29 03:19:53 +02:00
2022-06-30 16:14:33 +02:00
result . dialogs . forEach ( ( dialog ) = > {
const peerId = dialog . peerId ;
if ( peerId ) {
promises [ peerId ] . resolve ( dialog as Dialog ) ;
delete promises [ peerId ] ;
2021-06-29 03:19:53 +02:00
}
2020-06-20 03:11:24 +02:00
} ) ;
2023-01-06 20:27:29 +01:00
} , noop ) . then ( ( ) = > {
2022-06-30 16:14:33 +02:00
fullfillLeft ( ) ;
2022-08-04 08:49:54 +02:00
2022-06-30 16:14:33 +02:00
this . reloadConversationsPromise = null ;
if ( this . reloadConversationsPeers . size ) {
this . reloadConversation ( ) ;
}
} ) ;
2020-06-20 03:11:24 +02:00
} ) ;
2021-10-21 15:16:43 +02:00
return promise || this . reloadConversationsPromise ;
2020-02-06 16:43:07 +01:00
}
2023-01-06 20:27:29 +01:00
private doFlushHistory ( peerId : PeerId , just_clear? : boolean , revoke? : boolean , threadId? : number ) : Promise < true > {
let promise : Promise < true > ;
const processResult = ( affectedHistory : MessagesAffectedHistory ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( {
2020-05-13 17:26:40 +02:00
_ : 'updateShort' ,
update : {
_ : 'updatePts' ,
pts : affectedHistory.pts ,
pts_count : affectedHistory.pts_count
}
} ) ;
if ( ! affectedHistory . offset ) {
return true ;
}
2023-01-06 20:27:29 +01:00
return this . doFlushHistory ( peerId , just_clear , revoke , threadId ) ;
} ;
if ( ! threadId ) {
promise = this . apiManager . invokeApiSingleProcess ( {
method : 'messages.deleteHistory' ,
params : {
just_clear ,
revoke ,
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
max_id : 0
} ,
processResult
} ) ;
} else {
promise = this . apiManager . invokeApiSingleProcess ( {
method : 'channels.deleteTopicHistory' ,
params : {
channel : this.appChatsManager.getChannelInput ( peerId . toChatId ( ) ) ,
top_msg_id : getServerMessageId ( threadId )
} ,
processResult
} ) ;
}
return promise ;
2020-05-13 17:26:40 +02:00
}
2023-01-06 20:27:29 +01:00
public async flushHistory ( peerId : PeerId , justClear? : boolean , revoke? : boolean , threadId? : number ) {
if ( this . appPeersManager . isChannel ( peerId ) && ! threadId ) {
2020-12-18 04:07:32 +01:00
const promise = this . getHistory ( peerId , 0 , 1 ) ;
2020-05-13 17:26:40 +02:00
2022-06-17 18:01:43 +02:00
const historyResult = await promise ;
2020-05-13 17:26:40 +02:00
2021-10-21 15:16:43 +02:00
const channelId = peerId . toChatId ( ) ;
2020-12-18 04:07:32 +01:00
const maxId = historyResult . history [ 0 ] || 0 ;
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApiSingle ( 'channels.deleteHistory' , {
2022-04-25 16:54:30 +02:00
channel : this.appChatsManager.getChannelInput ( channelId ) ,
2022-06-17 18:01:43 +02:00
max_id : getServerMessageId ( maxId )
2021-11-12 16:53:59 +01:00
} ) . then ( ( bool ) = > {
if ( bool ) {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( {
2021-11-12 16:53:59 +01:00
_ : 'updateChannelAvailableMessages' ,
channel_id : channelId ,
available_min_id : maxId
} ) ;
}
2020-05-13 17:26:40 +02:00
2021-11-12 16:53:59 +01:00
return bool ;
2020-05-13 17:26:40 +02:00
} ) ;
}
2023-01-06 20:27:29 +01:00
return this . doFlushHistory ( peerId , justClear , revoke , threadId ) . then ( ( ) = > {
if ( ! threadId ) {
this . flushStoragesByPeerId ( peerId ) ;
}
2022-08-04 08:49:54 +02:00
2020-05-13 17:26:40 +02:00
if ( justClear ) {
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'dialog_flush' , { peerId , dialog : this.getDialogOnly ( peerId ) } ) ;
2020-05-13 17:26:40 +02:00
} else {
2023-01-06 20:27:29 +01:00
const key = this . getTypingKey ( peerId , threadId ) ;
delete this . notificationsToHandle [ key ] ;
delete this . typings [ key ] ;
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
if ( ! threadId ) {
const c = this . reloadConversationsPeers . get ( peerId ) ;
if ( c ) {
this . reloadConversationsPeers . delete ( peerId ) ;
c . promise . resolve ( undefined ) ;
}
2021-11-12 18:40:13 +01:00
}
2020-05-13 17:26:40 +02:00
2023-01-06 20:27:29 +01:00
this . dialogsStorage . dropDialogOnDeletion ( peerId , threadId ) ;
2020-05-13 17:26:40 +02:00
}
} ) ;
}
2022-08-19 21:27:29 +02:00
private flushStoragesByPeerId ( peerId : PeerId ) {
[
this . historiesStorage ,
this . threadsStorage ,
this . searchesStorage ,
this . pendingAfterMsgs ,
this . pendingTopMsgs
] . forEach ( ( s ) = > {
delete s [ peerId ] ;
} ) ;
2023-01-06 20:27:29 +01:00
for ( const key in this . pinnedMessages ) {
if ( + key === peerId || key . startsWith ( peerId + '_' ) ) {
delete this . pinnedMessages [ key ] ;
}
}
2022-08-19 21:27:29 +02:00
const needSingleMessages = this . needSingleMessages . get ( peerId ) ;
if ( needSingleMessages ) {
for ( const [ mid , promise ] of needSingleMessages ) {
promise . resolve ( this . generateEmptyMessage ( mid ) ) ;
}
needSingleMessages . clear ( ) ;
}
[
this . messagesStorageByPeerId ,
this . scheduledMessagesStorage
] . forEach ( ( s ) = > {
const ss = s [ peerId ] ;
if ( ss ) {
ss . clear ( ) ;
}
} ) ;
2023-01-06 20:27:29 +01:00
this . dialogsStorage . flushForumTopicsCache ( peerId ) ;
2022-08-19 21:27:29 +02:00
}
2021-10-21 15:16:43 +02:00
public hidePinnedMessages ( peerId : PeerId ) {
2020-12-08 20:48:44 +01:00
return Promise . all ( [
2022-06-17 18:01:43 +02:00
this . appStateManager . getState ( ) ,
2020-12-11 03:06:16 +01:00
this . getPinnedMessage ( peerId )
2020-12-08 20:48:44 +01:00
] )
. then ( ( [ state , pinned ] ) = > {
2020-12-11 03:06:16 +01:00
state . hiddenPinnedMessages [ peerId ] = pinned . maxId ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'peer_pinned_hidden' , { peerId , maxId : pinned.maxId } ) ;
2020-12-08 20:48:44 +01:00
} ) ;
2020-06-05 18:01:06 +02:00
}
2023-01-06 20:27:29 +01:00
public getPinnedMessagesKey ( peerId : PeerId , threadId? : number ) {
return peerId + ( threadId ? '_' + threadId : '' ) ;
}
public getPinnedMessage ( peerId : PeerId , threadId? : number ) {
const p = this . pinnedMessages [ this . getPinnedMessagesKey ( peerId , threadId ) ] ? ? = { } ;
2020-12-08 20:48:44 +01:00
if ( p . promise ) return p . promise ;
2020-12-11 03:06:16 +01:00
else if ( p . maxId ) return Promise . resolve ( p ) ;
2020-11-25 20:36:18 +01:00
2020-12-25 18:38:32 +01:00
return p . promise = this . getSearch ( {
2022-08-04 08:49:54 +02:00
peerId ,
2020-12-25 13:53:20 +01:00
inputFilter : { _ : 'inputMessagesFilterPinned' } ,
maxId : 0 ,
2023-01-06 20:27:29 +01:00
limit : 1 ,
threadId
2022-06-17 18:01:43 +02:00
} ) . then ( ( result ) = > {
2020-12-08 20:48:44 +01:00
p . count = result . count ;
2020-12-18 04:07:32 +01:00
p . maxId = result . history [ 0 ] ? . mid ;
2020-12-08 20:48:44 +01:00
return p ;
2020-11-25 20:36:18 +01:00
} ) . finally ( ( ) = > {
2020-12-08 20:48:44 +01:00
delete p . promise ;
2020-11-25 20:36:18 +01:00
} ) ;
2020-06-05 18:01:06 +02:00
}
2020-12-08 20:48:44 +01:00
2023-01-06 20:27:29 +01:00
public getPinnedMessagesCount ( peerId : PeerId , threadId? : number ) {
return this . pinnedMessages [ this . getPinnedMessagesKey ( peerId , threadId ) ] ? . count ;
2022-06-17 18:01:43 +02:00
}
2023-01-06 20:27:29 +01:00
public getPinnedMessagesMaxId ( peerId : PeerId , threadId? : number ) {
return this . pinnedMessages [ this . getPinnedMessagesKey ( peerId , threadId ) ] ? . maxId ;
2022-06-17 18:01:43 +02:00
}
2021-10-21 15:16:43 +02:00
public updatePinnedMessage ( peerId : PeerId , mid : number , unpin? : boolean , silent? : boolean , pm_oneside? : boolean ) {
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.updatePinnedMessage' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2020-11-25 20:36:18 +01:00
unpin ,
silent ,
2021-07-16 16:16:05 +02:00
pm_oneside ,
2022-06-17 18:01:43 +02:00
id : getServerMessageId ( mid )
} ) . then ( ( updates ) = > {
2022-08-04 08:49:54 +02:00
// this.log('pinned updates:', updates);
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2020-06-06 12:53:23 +02:00
} ) ;
}
2020-06-05 18:01:06 +02:00
2021-10-21 15:16:43 +02:00
public unpinAllMessages ( peerId : PeerId ) : Promise < boolean > {
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApiSingle ( 'messages.unpinAllMessages' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId )
2022-06-17 18:01:43 +02:00
} ) . then ( ( affectedHistory ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( {
2020-12-08 20:48:44 +01:00
_ : 'updateShort' ,
update : {
_ : 'updatePts' ,
pts : affectedHistory.pts ,
pts_count : affectedHistory.pts_count
}
} ) ;
if ( ! affectedHistory . offset ) {
2022-06-17 18:01:43 +02:00
const storage = this . getHistoryMessagesStorage ( peerId ) ;
2021-10-05 22:40:07 +02:00
storage . forEach ( ( message ) = > {
2022-06-17 18:01:43 +02:00
if ( ( message as Message . message ) . pFlags . pinned ) {
delete ( message as Message . message ) . pFlags . pinned ;
2020-12-08 20:48:44 +01:00
}
2021-10-05 22:40:07 +02:00
} ) ;
2020-12-08 20:48:44 +01:00
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'peer_pinned_messages' , { peerId , unpinAll : true } ) ;
2023-01-06 20:27:29 +01:00
delete this . pinnedMessages [ this . getPinnedMessagesKey ( peerId ) ] ;
2020-12-08 20:48:44 +01:00
return true ;
}
2020-12-11 03:06:16 +01:00
return this . unpinAllMessages ( peerId ) ;
2020-12-08 20:48:44 +01:00
} ) ;
}
2020-11-07 18:47:54 +01:00
public getAlbumText ( grouped_id : string ) {
2020-12-16 04:22:58 +01:00
const group = this . groupedMessagesStorage [ grouped_id ] ;
2022-06-30 16:14:33 +02:00
return getAlbumText ( Array . from ( group . values ( ) ) as Message . message [ ] ) ;
2020-11-07 18:47:54 +01:00
}
2022-06-17 18:01:43 +02:00
public getGroupsFirstMessage ( message : Message.message ) {
if ( ! message ? . grouped_id ) return message ;
2022-02-08 20:18:01 +01:00
const storage = this . groupedMessagesStorage [ message . grouped_id ] ;
let minMid = Number . MAX_SAFE_INTEGER ;
for ( const [ mid , message ] of storage ) {
if ( message . mid < minMid ) {
minMid = message . mid ;
}
}
2022-06-30 16:14:33 +02:00
return this . getMessageFromStorage ( storage , minMid ) as Message . message ;
}
public getMidsByAlbum ( groupedId : string , sort : 'asc' | 'desc' = 'asc' ) {
return getObjectKeysAndSort ( this . groupedMessagesStorage [ groupedId ] , sort ) ;
2022-02-08 20:18:01 +01:00
}
2022-06-30 16:14:33 +02:00
public getMessagesByAlbum ( groupedId : string ) {
const mids = this . getMidsByAlbum ( groupedId , 'asc' ) ;
const storage = this . groupedMessagesStorage [ groupedId ] ;
return mids . map ( ( mid ) = > this . getMessageFromStorage ( storage , mid ) as Message . message ) ;
2020-10-18 01:19:56 +02:00
}
2022-01-13 00:54:33 +01:00
public getMidsByMessage ( message : Message ) {
2022-06-17 18:01:43 +02:00
if ( ! message ) return [ ] ;
else if ( ( message as Message . message ) . grouped_id ) return this . getMidsByAlbum ( ( message as Message . message ) . grouped_id ) ;
2020-12-18 04:07:32 +01:00
else return [ message . mid ] ;
2020-10-18 01:19:56 +02:00
}
2022-02-08 20:18:01 +01:00
public filterMessages ( message : MyMessage , verify : ( message : MyMessage ) = > boolean ) {
2020-12-22 20:10:53 +01:00
const out : MyMessage [ ] = [ ] ;
2022-02-08 20:18:01 +01:00
if ( ( message as Message . message ) . grouped_id ) {
const storage = this . groupedMessagesStorage [ ( message as Message . message ) . grouped_id ] ;
2021-10-05 22:40:07 +02:00
for ( const [ mid , message ] of storage ) {
2020-12-22 20:10:53 +01:00
if ( verify ( message ) ) {
out . push ( message ) ;
}
}
} else {
if ( verify ( message ) ) {
out . push ( message ) ;
}
}
return out ;
}
2021-10-21 15:16:43 +02:00
public generateTempMessageId ( peerId : PeerId ) {
2021-04-27 17:45:53 +02:00
const dialog = this . getDialogOnly ( peerId ) ;
2022-06-17 18:01:43 +02:00
return this . appMessagesIdsManager . generateTempMessageId ( dialog ? . top_message || 0 ) ;
2020-12-19 02:07:24 +01:00
}
2023-01-11 23:21:56 +01:00
public setMessageUnreadByDialog ( message : MyMessage , dialog : Dialog | ForumTopic = this . getDialogOnly ( message . peerId ) ) {
if ( dialog && message . mid ) {
if ( message . mid > dialog [ message . pFlags . out ?
'read_outbox_max_id' :
'read_inbox_max_id' ] ) {
message . pFlags . unread = true ;
}
}
}
2022-01-08 13:52:14 +01:00
public saveMessage ( message : Message , options : Partial < {
2020-12-16 04:22:58 +01:00
storage : MessagesStorage ,
2020-12-19 02:07:24 +01:00
isScheduled : true ,
2021-04-26 16:33:51 +02:00
isOutgoing : true ,
2022-08-04 08:49:54 +02:00
// isNew: boolean, // * new - from update
2020-12-16 04:22:58 +01:00
} > = { } ) {
2022-06-17 18:01:43 +02:00
if ( ! message || message . _ === 'messageEmpty' ) {
return ;
2021-10-29 17:33:37 +02:00
}
2020-02-06 16:43:07 +01:00
2022-11-06 14:48:41 +01:00
message . pFlags ? ? = { } ;
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
// * exclude from state
// defineNotNumerableProperties(message, ['rReply', 'mid', 'savedFrom', 'fwdFromId', 'fromId', 'peerId', 'reply_to_mid', 'viaBotId']);
2020-10-17 00:31:58 +02:00
2021-10-29 17:33:37 +02:00
const peerId = this . getMessagePeer ( message ) ;
2022-06-17 18:01:43 +02:00
const storage = options . storage || this . getHistoryMessagesStorage ( peerId ) ;
2021-10-29 17:33:37 +02:00
const isChannel = message . peer_id . _ === 'peerChannel' ;
2022-04-25 16:54:30 +02:00
const isBroadcast = isChannel && this . appChatsManager . isBroadcast ( peerId . toChatId ( ) ) ;
2022-01-08 13:52:14 +01:00
const isMessage = message . _ === 'message' ;
2020-12-19 02:07:24 +01:00
2021-10-29 17:33:37 +02:00
if ( options . isOutgoing ) {
message . pFlags . is_outgoing = true ;
}
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
const mid = generateMessageId ( message . id ) ;
2021-10-29 17:33:37 +02:00
message . mid = mid ;
2020-02-06 16:43:07 +01:00
2022-01-08 13:52:14 +01:00
if ( isMessage ) {
if ( options . isScheduled ) {
message . pFlags . is_scheduled = true ;
}
if ( message . grouped_id ) {
2023-01-06 20:27:29 +01:00
const storage = this . groupedMessagesStorage [ message . grouped_id ] ? ? = this . createMessageStorage ( peerId , 'grouped' ) ;
2022-01-08 13:52:14 +01:00
storage . set ( mid , message ) ;
}
if ( message . via_bot_id ) {
// ! WARNING
message . viaBotId = message . via_bot_id as any ;
}
2021-10-29 17:33:37 +02:00
}
2020-04-28 19:30:54 +02:00
2021-10-29 17:33:37 +02:00
// this.log(dT(), 'msg unread', mid, apiMessage.pFlags.out, dialog && dialog[apiMessage.pFlags.out ? 'read_outbox_max_id' : 'read_inbox_max_id'])
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
const replyTo = message . reply_to ;
if ( replyTo ) {
if ( replyTo . reply_to_msg_id ) {
replyTo . reply_to_msg_id = message . reply_to_mid = generateMessageId ( replyTo . reply_to_msg_id ) ;
2022-08-04 08:49:54 +02:00
}
2020-12-20 04:54:35 +01:00
2023-01-06 20:27:29 +01:00
if ( replyTo . reply_to_top_id ) {
replyTo . reply_to_top_id = generateMessageId ( replyTo . reply_to_top_id ) ;
2022-06-26 21:41:43 +02:00
}
2021-10-29 17:33:37 +02:00
}
2020-12-20 04:54:35 +01:00
2022-06-17 18:01:43 +02:00
const replies = isMessage && message . replies ;
if ( replies ) {
if ( replies . max_id ) replies . max_id = generateMessageId ( replies . max_id ) ;
if ( replies . read_max_id ) replies . read_max_id = generateMessageId ( replies . read_max_id ) ;
2021-10-29 17:33:37 +02:00
}
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
const overwriting = ! ! peerId ;
if ( ! overwriting ) {
2022-06-17 18:01:43 +02:00
message . date -= this . timeManager . getServerTimeOffset ( ) ;
2021-10-29 17:33:37 +02:00
}
2022-08-04 08:49:54 +02:00
// storage.generateIndex(message);
2022-06-26 21:41:43 +02:00
const myId = this . appPeersManager . peerId ;
2022-01-08 13:52:14 +01:00
2022-06-26 21:41:43 +02:00
const fwdHeader = isMessage && ( message as Message . message ) . fwd_from ;
2020-10-02 22:33:32 +02:00
2021-10-29 17:33:37 +02:00
message . peerId = peerId ;
if ( peerId === myId /* && !message.from_id && !message.fwd_from */ ) {
2022-07-26 17:24:29 +02:00
message . fromId = fwdHeader ? ( fwdHeader . from_id ? this . appPeersManager . getPeerId ( fwdHeader . from_id ) : NULL_PEER_ID ) : myId ;
2021-10-29 17:33:37 +02:00
} else {
2022-08-04 08:49:54 +02:00
// message.fromId = message.pFlags.post || (!message.pFlags.out && !message.from_id) ? peerId : appPeersManager.getPeerId(message.from_id);
2022-07-26 17:24:29 +02:00
message . fromId = message . pFlags . post || ! message . from_id ? peerId : this.appPeersManager.getPeerId ( message . from_id ) ;
2021-10-29 17:33:37 +02:00
}
2020-02-06 16:43:07 +01:00
2023-01-16 11:57:28 +01:00
this . setMessageUnreadByDialog ( message ) ;
2021-10-29 17:33:37 +02:00
if ( fwdHeader ) {
2022-08-04 08:49:54 +02:00
// if(peerId === myID) {
if ( fwdHeader . saved_from_msg_id ) fwdHeader . saved_from_msg_id = generateMessageId ( fwdHeader . saved_from_msg_id ) ;
if ( fwdHeader . channel_post ) fwdHeader . channel_post = generateMessageId ( fwdHeader . channel_post ) ;
2021-10-29 17:33:37 +02:00
2022-08-04 08:49:54 +02:00
const peer = fwdHeader . saved_from_peer || fwdHeader . from_id ;
const msgId = fwdHeader . saved_from_msg_id || fwdHeader . channel_post ;
if ( peer && msgId ) {
const savedFromPeerId = this . appPeersManager . getPeerId ( peer ) ;
const savedFromMid = generateMessageId ( msgId ) ;
message . savedFrom = savedFromPeerId + '_' + savedFromMid ;
}
/ * i f ( p e e r I d . i s A n y C h a t ( ) | | p e e r I d = = = m y I D ) {
2021-10-29 17:33:37 +02:00
message . fromId = appPeersManager . getPeerID ( ! message . from_id || deepEqual ( message . from_id , fwdHeader . from_id ) ? fwdHeader.from_id : message.from_id ) ;
2020-10-15 11:37:03 +02:00
} * /
2021-10-29 17:33:37 +02:00
/ * } e l s e {
apiMessage . fwdPostID = fwdHeader . channel_post ;
} * /
2020-02-06 16:43:07 +01:00
2022-07-26 17:24:29 +02:00
message . fwdFromId = this . appPeersManager . getPeerId ( fwdHeader . from_id ) ;
2020-02-13 12:59:55 +01:00
2021-10-29 17:33:37 +02:00
if ( ! overwriting ) {
2022-06-17 18:01:43 +02:00
fwdHeader . date -= this . timeManager . getServerTimeOffset ( ) ;
2020-02-06 16:43:07 +01:00
}
2021-10-29 17:33:37 +02:00
}
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
const mediaContext : ReferenceContext = {
type : 'message' ,
peerId ,
messageId : mid
} ;
2020-02-06 16:43:07 +01:00
2022-01-18 16:40:07 +01:00
/ * i f ( i s M e s s a g e ) {
2022-01-08 13:52:14 +01:00
const entities = message . entities ;
2022-06-17 18:01:43 +02:00
if ( entities && entities . find ( ( entity ) = > entity . _ === 'messageEntitySpoiler' ) ) {
2022-01-08 13:52:14 +01:00
message . media = { _ : 'messageMediaUnsupported' } ;
}
2022-01-18 16:40:07 +01:00
} * /
2022-01-08 13:52:14 +01:00
2022-08-22 11:01:04 +02:00
let unsupported = false ;
2022-11-06 14:48:41 +01:00
const media = isMessage && message . media ;
if ( media ) {
switch ( media . _ ) {
2021-10-29 17:33:37 +02:00
case 'messageMediaEmpty' : {
delete message . media ;
break ;
}
2021-02-04 00:00:15 +01:00
2021-10-29 17:33:37 +02:00
case 'messageMediaPhoto' : {
2022-11-06 14:48:41 +01:00
if ( media . ttl_seconds ) {
2022-02-01 08:32:01 +01:00
unsupported = true ;
2021-10-29 17:33:37 +02:00
} else {
2022-11-06 14:48:41 +01:00
media . photo = this . appPhotosManager . savePhoto ( media . photo , mediaContext ) ;
2021-10-29 17:33:37 +02:00
}
2020-05-10 03:23:21 +02:00
2022-11-06 14:48:41 +01:00
if ( ! ( media as MessageMedia . messageMediaPhoto ) . photo ) { // * found this bug on test DC
2021-10-29 17:33:37 +02:00
delete message . media ;
}
2022-08-04 08:49:54 +02:00
2021-10-29 17:33:37 +02:00
break ;
}
2022-08-04 08:49:54 +02:00
2021-10-29 17:33:37 +02:00
case 'messageMediaPoll' : {
2022-11-06 14:48:41 +01:00
const result = this . appPollsManager . savePoll ( media . poll , media . results , message ) ;
media . poll = result . poll ;
media . results = result . results ;
2021-10-29 17:33:37 +02:00
break ;
}
2022-08-04 08:49:54 +02:00
2021-10-29 17:33:37 +02:00
case 'messageMediaDocument' : {
2022-11-06 14:48:41 +01:00
if ( media . ttl_seconds ) {
2022-02-01 08:32:01 +01:00
unsupported = true ;
2021-10-29 17:33:37 +02:00
} else {
2022-11-06 14:48:41 +01:00
const originalDoc = media . document ;
media . document = this . appDocsManager . saveDoc ( originalDoc , mediaContext ) ; // 11.04.2020 warning
2022-02-01 08:32:01 +01:00
2022-11-06 14:48:41 +01:00
if ( ! media . document && originalDoc . _ !== 'documentEmpty' ) {
2022-02-01 08:32:01 +01:00
unsupported = true ;
}
2021-10-29 17:33:37 +02:00
}
break ;
}
2022-08-04 08:49:54 +02:00
2021-10-29 17:33:37 +02:00
case 'messageMediaWebPage' : {
2022-04-25 16:54:30 +02:00
const messageKey = this . appWebPagesManager . getMessageKeyForPendingWebPage ( peerId , mid , options . isScheduled ) ;
2022-11-06 14:48:41 +01:00
media . webpage = this . appWebPagesManager . saveWebPage ( media . webpage , messageKey , mediaContext ) ;
2023-01-06 20:27:29 +01:00
if ( ! media . webpage ) {
delete message . media ;
}
2021-10-29 17:33:37 +02:00
break ;
}
2022-08-04 08:49:54 +02:00
/ * c a s e ' m e s s a g e M e d i a G a m e ' :
2021-10-29 17:33:37 +02:00
AppGamesManager . saveGame ( apiMessage . media . game , apiMessage . mid , mediaContext ) ;
apiMessage . media . handleMessage = true ;
break ; * /
case 'messageMediaInvoice' : {
2022-11-06 14:48:41 +01:00
media . photo = this . appWebDocsManager . saveWebDocument ( media . photo ) ;
const extendedMedia = media . extended_media ;
if ( extendedMedia ? . _ === 'messageExtendedMedia' ) {
const extendedMediaMedia = extendedMedia . media ;
( extendedMediaMedia as MessageMedia . messageMediaPhoto ) . photo = this . appPhotosManager . savePhoto ( ( extendedMediaMedia as MessageMedia . messageMediaPhoto ) . photo , mediaContext ) ;
( extendedMediaMedia as MessageMedia . messageMediaDocument ) . document = this . appDocsManager . saveDoc ( ( extendedMediaMedia as MessageMedia . messageMediaDocument ) . document , mediaContext ) ;
}
2022-01-08 13:52:14 +01:00
break ;
}
case 'messageMediaUnsupported' : {
2022-02-01 08:32:01 +01:00
unsupported = true ;
2021-10-29 17:33:37 +02:00
break ;
2020-02-06 16:43:07 +01:00
}
}
2022-08-22 11:01:04 +02:00
}
2022-02-01 08:32:01 +01:00
2022-08-31 06:22:16 +02:00
// if(isMessage && !unsupported && message.entities) {
// unsupported = message.entities.some((entity) => entity._ === 'messageEntityCustomEmoji');
// }
2022-08-22 11:01:04 +02:00
if ( isMessage && unsupported ) {
message . media = { _ : 'messageMediaUnsupported' } ;
message . message = '' ;
delete message . entities ;
delete message . totalEntities ;
2021-10-29 17:33:37 +02:00
}
2020-02-06 16:43:07 +01:00
2022-01-08 13:52:14 +01:00
if ( ! isMessage && message . action ) {
2021-10-29 17:33:37 +02:00
const action = message . action as MessageAction ;
2022-04-25 16:54:30 +02:00
const suffix = message . fromId === this . appUsersManager . getSelf ( ) . id ? 'You' : '' ;
2022-11-11 17:21:29 +01:00
let migrateFrom : PeerId , migrateTo : PeerId ;
2021-10-21 15:16:43 +02:00
2021-10-29 17:33:37 +02:00
if ( ( action as MessageAction . messageActionChatEditPhoto ) . photo ) {
2022-04-25 16:54:30 +02:00
( action as MessageAction . messageActionChatEditPhoto ) . photo = this . appPhotosManager . savePhoto ( ( action as MessageAction . messageActionChatEditPhoto ) . photo , mediaContext ) ;
2021-10-29 17:33:37 +02:00
}
2021-10-21 15:16:43 +02:00
2021-10-29 17:33:37 +02:00
if ( ( action as any ) . document ) {
2022-04-25 16:54:30 +02:00
( action as any ) . document = this . appDocsManager . saveDoc ( ( action as any ) . photo , mediaContext ) ;
2021-10-29 17:33:37 +02:00
}
2021-10-21 15:16:43 +02:00
2021-10-29 17:33:37 +02:00
switch ( action . _ ) {
2022-08-04 08:49:54 +02:00
// case 'messageActionChannelEditPhoto':
2021-10-29 17:33:37 +02:00
case 'messageActionChatEditPhoto' :
// action.photo = appPhotosManager.savePhoto(action.photo, mediaContext);
if ( ( action . photo as Photo . photo ) ? . video_sizes ) {
// @ts-ignore
action . _ = isBroadcast ? 'messageActionChannelEditVideo' : 'messageActionChatEditVideo' ;
} else {
if ( isBroadcast ) { // ! messageActionChannelEditPhoto не существует в принципе, это используется для перевода.
2021-10-21 15:16:43 +02:00
// @ts-ignore
2021-10-29 17:33:37 +02:00
action . _ = 'messageActionChannelEditPhoto' ;
2020-02-06 16:43:07 +01:00
}
2021-10-29 17:33:37 +02:00
}
break ;
2022-08-04 08:49:54 +02:00
2021-10-29 17:33:37 +02:00
case 'messageActionGroupCall' : {
2022-08-04 08:49:54 +02:00
// assumeType<MessageAction.messageActionGroupCall>(action);
2021-10-29 17:33:37 +02:00
2022-04-25 16:54:30 +02:00
this . appGroupCallsManager . saveGroupCall ( action . call ) ;
2021-12-11 17:37:08 +01:00
2021-10-29 17:33:37 +02:00
let type : string ;
if ( action . duration === undefined ) {
type = 'started' ;
} else {
2021-12-11 17:37:08 +01:00
type = 'ended'
}
if ( ! isBroadcast ) {
type += '_by' + suffix ;
2021-10-29 17:33:37 +02:00
}
2021-06-12 19:04:16 +02:00
2021-10-29 17:33:37 +02:00
// @ts-ignore
action . type = type ;
2021-06-12 19:04:16 +02:00
2021-10-29 17:33:37 +02:00
break ;
}
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
case 'messageActionChatEditTitle' :
/ * i f ( o p t i o n s . i s N e w ) {
const chat = appChatsManager . getChat ( peerId . toChatId ( ) ) ;
chat . title = action . title ;
appChatsManager . saveApiChat ( chat , true ) ;
} * /
2022-08-04 08:49:54 +02:00
2021-10-29 17:33:37 +02:00
if ( isBroadcast ) {
// @ts-ignore
action . _ = 'messageActionChannelEditTitle' ;
}
break ;
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
case 'messageActionChatDeletePhoto' :
if ( isBroadcast ) {
// @ts-ignore
action . _ = 'messageActionChannelDeletePhoto' ;
}
break ;
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
case 'messageActionChatAddUser' :
if ( action . users . length === 1 ) {
// @ts-ignore
action . user_id = action . users [ 0 ] ;
// @ts-ignore
if ( message . fromId === action . user_id ) {
if ( isChannel ) {
// @ts-ignore
action . _ = 'messageActionChatJoined' + suffix ;
} else {
// @ts-ignore
action . _ = 'messageActionChatReturn' + suffix ;
2020-02-06 16:43:07 +01:00
}
}
2021-10-29 17:33:37 +02:00
} else if ( action . users . length > 1 ) {
// @ts-ignore
action . _ = 'messageActionChatAddUsers' ;
}
break ;
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
case 'messageActionChatDeleteUser' :
if ( message . fromId === action . user_id ) {
// @ts-ignore
action . _ = 'messageActionChatLeave' + suffix ;
}
break ;
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
case 'messageActionChannelMigrateFrom' :
migrateFrom = action . chat_id . toPeerId ( true ) ;
migrateTo = peerId ;
break
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
case 'messageActionChatMigrateTo' :
migrateFrom = peerId ;
migrateTo = action . channel_id . toPeerId ( true ) ;
break ;
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
case 'messageActionHistoryClear' :
2022-08-04 08:49:54 +02:00
// apiMessage.deleted = true;
2021-10-29 17:33:37 +02:00
message . clear_history = true ;
delete message . pFlags . out ;
delete message . pFlags . unread ;
break ;
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
case 'messageActionPhoneCall' :
// @ts-ignore
2022-08-04 08:49:54 +02:00
action . type =
2022-01-08 13:52:14 +01:00
( action . pFlags . video ? 'video_' : '' ) +
( action . duration !== undefined ? ( message . pFlags . out ? 'out_' : 'in_' ) : '' ) +
2021-10-29 17:33:37 +02:00
(
2022-01-08 13:52:14 +01:00
action . duration !== undefined ? 'ok' : (
2022-08-04 08:49:54 +02:00
action . reason . _ === 'phoneCallDiscardReasonMissed' ?
'missed' :
'cancelled'
2022-01-08 13:52:14 +01:00
)
2021-10-29 17:33:37 +02:00
) ;
break ;
}
2022-08-04 08:49:54 +02:00
2021-10-29 17:33:37 +02:00
if ( migrateFrom &&
migrateTo &&
! this . migratedFromTo [ migrateFrom ] &&
! this . migratedToFrom [ migrateTo ] ) {
this . migrateChecks ( migrateFrom , migrateTo ) ;
}
}
/ * i f ( m e s s a g e . g r o u p e d _ i d ) {
if ( ! groups ) {
groups = new Set ( ) ;
2020-02-06 16:43:07 +01:00
}
2021-10-29 17:33:37 +02:00
groups . add ( message . grouped_id ) ;
} else {
message . rReply = this . getRichReplyText ( message ) ;
} * /
2020-11-07 18:47:54 +01:00
2022-01-08 13:52:14 +01:00
if ( isMessage && message . message . length && ! message . totalEntities ) {
2022-08-04 08:49:54 +02:00
this . wrapMessageEntities ( message ) ;
2021-10-29 17:33:37 +02:00
}
2020-05-10 03:23:21 +02:00
2021-10-29 17:33:37 +02:00
storage . set ( mid , message ) ;
2022-06-17 18:01:43 +02:00
return message ;
2021-10-29 17:33:37 +02:00
}
2020-02-06 16:43:07 +01:00
2021-10-29 17:33:37 +02:00
public saveMessages ( messages : any [ ] , options : Partial < {
storage : MessagesStorage ,
isScheduled : true ,
isOutgoing : true ,
2022-08-04 08:49:54 +02:00
// isNew: boolean, // * new - from update
2022-06-17 18:01:43 +02:00
} > = { } ) : ( Message . message | Message . messageService ) [ ] {
if ( ( messages as any ) . saved ) return messages ;
2021-10-29 17:33:37 +02:00
( messages as any ) . saved = true ;
2022-06-17 18:01:43 +02:00
messages . forEach ( ( message , idx , arr ) = > {
arr [ idx ] = this . saveMessage ( message , options ) ;
2020-05-10 03:23:21 +02:00
} ) ;
2022-06-17 18:01:43 +02:00
return messages ;
}
public async getFirstMessageToEdit ( peerId : PeerId , threadId? : number ) {
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
const slice = historyStorage . history . slice ;
if ( slice . isEnd ( SliceEnd . Bottom ) && slice . length ) {
let goodMessage : Message.message | Message . messageService ;
const myPeerId = this . appPeersManager . peerId ;
for ( const mid of slice ) {
const message = this . getMessageByPeer ( peerId , mid ) ;
const good = myPeerId === peerId ? message . fromId === myPeerId : message.pFlags.out ;
if ( good ) {
if ( await this . canEditMessage ( message , 'text' ) ) {
goodMessage = message ;
break ;
}
// * this check will allow editing only last message
2022-08-04 08:49:54 +02:00
// break;
2022-06-17 18:01:43 +02:00
}
}
return goodMessage ;
}
2020-05-10 03:23:21 +02:00
}
2021-10-29 17:33:37 +02:00
private wrapMessageEntities ( message : Message.message ) {
2021-05-29 14:23:45 +02:00
const apiEntities = message . entities ? message . entities . slice ( ) : [ ] ;
2022-04-25 16:54:30 +02:00
message . message = fixEmoji ( message . message , apiEntities ) ;
2021-05-29 14:23:45 +02:00
2022-04-25 16:54:30 +02:00
const myEntities = parseEntities ( message . message ) ;
message . totalEntities = mergeEntities ( apiEntities , myEntities ) ; // ! only in this order, otherwise bold and emoji formatting won't work
2021-12-14 15:48:42 +01:00
}
2021-10-21 15:16:43 +02:00
public reportMessages ( peerId : PeerId , mids : number [ ] , reason : ReportReason [ '_' ] , message? : string ) {
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApiSingle ( 'messages.report' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
id : mids.map ( ( mid ) = > getServerMessageId ( mid ) ) ,
2021-08-26 00:05:29 +02:00
reason : {
_ : reason
} ,
message
} ) ;
}
2021-10-21 17:51:25 +02:00
public startBot ( botId : BotId , chatId? : ChatId , startParam? : string ) {
2021-10-21 15:16:43 +02:00
const peerId = chatId ? chatId . toPeerId ( true ) : botId . toPeerId ( ) ;
2021-08-03 03:44:13 +02:00
if ( startParam ) {
const randomId = randomLong ( ) ;
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.startBot' , {
2022-04-25 16:54:30 +02:00
bot : this.appUsersManager.getUserInput ( botId ) ,
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2021-08-03 03:44:13 +02:00
random_id : randomId ,
start_param : startParam
} ) . then ( ( updates ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2021-08-03 03:44:13 +02:00
} ) ;
}
const str = '/start' ;
if ( chatId ) {
let promise : Promise < void > ;
2022-04-25 16:54:30 +02:00
if ( this . appChatsManager . isChannel ( chatId ) ) {
promise = this . appChatsManager . inviteToChannel ( chatId , [ botId ] ) ;
2021-08-03 03:44:13 +02:00
} else {
2022-04-25 16:54:30 +02:00
promise = this . appChatsManager . addChatUser ( chatId , botId , 0 ) ;
2021-08-03 03:44:13 +02:00
}
2022-11-06 14:48:41 +01:00
return promise . catch ( ( error : ApiError ) = > {
if ( error ? . type == 'USER_ALREADY_PARTICIPANT' ) {
2021-08-03 03:44:13 +02:00
error . handled = true ;
return ;
}
throw error ;
} ) . then ( ( ) = > {
2023-01-06 20:27:29 +01:00
return this . sendText ( peerId , str + '@' + this . appPeersManager . getPeerUsername ( botId . toPeerId ( ) ) ) ;
2021-08-03 03:44:13 +02:00
} ) ;
}
return this . sendText ( peerId , str ) ;
}
2021-10-21 15:16:43 +02:00
public editPeerFolders ( peerIds : PeerId [ ] , folderId : number ) {
2022-06-17 18:01:43 +02:00
this . apiManager . invokeApi ( 'folders.editPeerFolders' , {
folder_peers : peerIds.map ( ( peerId ) = > {
2020-05-13 17:26:40 +02:00
return {
_ : 'inputFolderPeer' ,
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2020-12-11 03:06:16 +01:00
folder_id : folderId
2020-05-13 17:26:40 +02:00
} ;
} )
2022-06-17 18:01:43 +02:00
} ) . then ( ( updates ) = > {
2022-08-04 08:49:54 +02:00
// this.log('editPeerFolders updates:', updates);
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ; // WARNING! возможно тут нужно добавлять channelId, и вызывать апдейт для каждого канала отдельно
2020-05-13 17:26:40 +02:00
} ) ;
}
2022-06-17 18:01:43 +02:00
public getFilter ( filterId : number ) {
return this . filtersStorage . getFilter ( filterId ) ;
}
2023-01-06 20:27:29 +01:00
public async toggleDialogPin ( options : {
peerId : PeerId ,
filterId? : number ,
topicId? : number
} ) {
const { peerId , topicId , filterId = topicId ? peerId : undefined } = options ;
if ( filterId === undefined ) {
throw new Error ( 'No filterId' ) ;
}
2020-12-11 03:06:16 +01:00
if ( filterId > 1 ) {
2021-04-27 17:45:53 +02:00
return this . filtersStorage . toggleDialogPin ( peerId , filterId ) ;
2020-06-19 13:49:55 +02:00
}
2023-01-06 20:27:29 +01:00
const dialog = this . dialogsStorage . getDialogOrTopic ( peerId , topicId ) ;
if ( ! dialog ) throw undefined ;
2020-05-13 17:26:40 +02:00
2020-10-11 14:51:23 +02:00
const pinned = dialog . pFlags ? . pinned ? undefined : true ;
2021-07-17 18:38:51 +02:00
if ( pinned ) {
2023-01-06 20:27:29 +01:00
const max = await this . apiManager . getLimit ( topicId ? 'topicPin' : ( filterId === 1 ? 'folderPin' : 'pin' ) ) ;
2021-07-17 18:38:51 +02:00
if ( this . dialogsStorage . getPinnedOrders ( filterId ) . length >= max ) {
2023-01-06 20:27:29 +01:00
throw makeError ( topicId ? 'PINNED_TOO_MUCH' : 'PINNED_DIALOGS_TOO_MUCH' ) ;
2021-07-17 18:38:51 +02:00
}
}
2023-01-06 20:27:29 +01:00
if ( topicId ) {
return this . appChatsManager . updatePinnedForumTopic ( peerId . toChatId ( ) , topicId , pinned ) ;
}
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.toggleDialogPin' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputDialogPeerById ( peerId ) ,
2020-10-11 14:51:23 +02:00
pinned
2022-06-17 18:01:43 +02:00
} ) . then ( ( bool ) = > {
2023-01-06 20:27:29 +01:00
const pFlags : Update.updateDialogPinned [ 'pFlags' ] = pinned ? { pinned } : { } ;
this . apiUpdatesManager . saveUpdate ( {
_ : 'updateDialogPinned' ,
peer : this.appPeersManager.getDialogPeer ( peerId ) ,
folder_id : filterId ,
pFlags
} ) ;
2020-05-13 17:26:40 +02:00
} ) ;
}
2021-10-21 15:16:43 +02:00
public markDialogUnread ( peerId : PeerId , read? : true ) {
2021-04-27 17:45:53 +02:00
const dialog = this . getDialogOnly ( peerId ) ;
2020-05-13 17:26:40 +02:00
if ( ! dialog ) return Promise . reject ( ) ;
2020-10-11 14:51:23 +02:00
const unread = read || dialog . pFlags ? . unread_mark ? undefined : true ;
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.markDialogUnread' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputDialogPeerById ( peerId ) ,
2020-10-11 14:51:23 +02:00
unread
2022-06-17 18:01:43 +02:00
} ) . then ( ( bool ) = > {
2020-06-19 13:49:55 +02:00
if ( bool ) {
2020-10-11 14:51:23 +02:00
const pFlags : Update.updateDialogUnreadMark [ 'pFlags' ] = unread ? { unread } : { } ;
2021-04-24 19:06:24 +02:00
this . onUpdateDialogUnreadMark ( {
2020-06-19 13:49:55 +02:00
_ : 'updateDialogUnreadMark' ,
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getDialogPeer ( peerId ) ,
2020-10-11 14:51:23 +02:00
pFlags
2020-06-19 13:49:55 +02:00
} ) ;
}
2020-05-13 17:26:40 +02:00
} ) ;
}
2021-10-21 15:16:43 +02:00
public migrateChecks ( migrateFrom : PeerId , migrateTo : PeerId ) {
2020-02-06 16:43:07 +01:00
if ( ! this . migratedFromTo [ migrateFrom ] &&
! this . migratedToFrom [ migrateTo ] &&
2022-04-25 16:54:30 +02:00
this . appChatsManager . hasChat ( migrateTo . toChatId ( ) ) ) {
2023-01-06 20:27:29 +01:00
const fromChat = this . appChatsManager . getChat ( migrateFrom . toChatId ( ) ) as Chat . chat ;
2022-06-27 22:24:56 +02:00
if ( fromChat ? . migrated_to && ( fromChat . migrated_to as InputChannel . inputChannel ) . channel_id === migrateTo . toChatId ( ) ) {
this . migratedFromTo [ migrateFrom ] = migrateTo ;
this . migratedToFrom [ migrateTo ] = migrateFrom ;
this . rootScope . dispatchEvent ( 'dialog_migrate' , { migrateFrom , migrateTo } ) ;
this . dialogsStorage . dropDialogWithEvent ( migrateFrom ) ;
2020-02-06 16:43:07 +01:00
}
}
}
2022-06-17 18:01:43 +02:00
private canMessageBeEdited ( message : Message , kind : 'text' | 'poll' ) {
if ( ( message as Message . message ) ? . pFlags ? . is_outgoing ) {
2021-04-18 13:55:56 +02:00
return false ;
}
2020-10-10 00:36:06 +02:00
const goodMedias = [
2020-02-06 16:43:07 +01:00
'messageMediaPhoto' ,
'messageMediaDocument' ,
2020-12-24 06:26:29 +01:00
'messageMediaWebPage'
2020-10-10 00:36:06 +02:00
] ;
2021-02-04 01:30:23 +01:00
if ( kind === 'poll' ) {
2020-10-10 04:08:12 +02:00
goodMedias . push ( 'messageMediaPoll' ) ;
}
2022-08-04 08:49:54 +02:00
if ( ! message ||
message . _ !== 'message' ||
2020-02-06 16:43:07 +01:00
message . deleted ||
message . fwd_from ||
message . via_bot_id ||
2021-02-04 01:30:23 +01:00
message . media && goodMedias . indexOf ( message . media . _ ) === - 1 ||
2022-04-25 16:54:30 +02:00
message . fromId && this . appUsersManager . isBot ( message . fromId ) ) {
2020-02-06 16:43:07 +01:00
return false ;
}
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
if ( message . media ? . _ === 'messageMediaDocument' &&
( ( message . media . document as Document . document ) . sticker || ( message . media . document as Document . document ) . type === 'round' ) ) {
2020-02-06 16:43:07 +01:00
return false ;
}
return true ;
}
2022-06-17 18:01:43 +02:00
public async canEditMessage ( message : Message.message | Message . messageService , kind : 'text' | 'poll' = 'text' ) {
2020-10-10 04:08:12 +02:00
if ( ! message || ! this . canMessageBeEdited ( message , kind ) ) {
2020-05-26 17:04:06 +02:00
return false ;
2020-02-14 17:15:41 +01:00
}
2020-05-26 17:04:06 +02:00
2020-11-19 00:51:39 +01:00
// * second rule for saved messages, because there is no 'out' flag
2022-04-25 16:54:30 +02:00
if ( /* message.pFlags.out || */ this . getMessagePeer ( message ) === this . appUsersManager . getSelf ( ) . id ) {
2020-05-26 17:04:06 +02:00
return true ;
2020-02-14 17:15:41 +01:00
}
2020-05-26 17:04:06 +02:00
2023-03-01 13:57:50 +01:00
const { peerId } = message ;
const canEditMessageInPeer = this . appPeersManager . isBroadcast ( peerId ) ?
this . appChatsManager . hasRights ( peerId . toChatId ( ) , 'edit_messages' ) :
(
peerId . isAnyChat ( ) && kind === 'text' ?
this . appChatsManager . hasRights ( peerId . toChatId ( ) , 'send_plain' ) || this . appChatsManager . hasRights ( peerId . toChatId ( ) , 'send_media' ) :
true
) && message . pFlags . out ;
2023-01-16 18:26:51 +01:00
2023-01-17 08:21:32 +01:00
if (
! canEditMessageInPeer || (
message . peer_id . _ !== 'peerChannel' &&
2022-08-04 08:49:54 +02:00
message . date < ( tsNow ( true ) - ( await this . apiManager . getConfig ( ) ) . edit_time_limit ) &&
2022-01-15 03:03:27 +01:00
( message as Message . message ) . media ? . _ !== 'messageMediaPoll'
2023-01-17 08:21:32 +01:00
)
2022-01-15 03:03:27 +01:00
) {
2020-05-26 17:04:06 +02:00
return false ;
2020-02-14 17:15:41 +01:00
}
2020-05-26 17:04:06 +02:00
return true ;
2020-02-14 17:15:41 +01:00
}
2021-09-17 18:50:29 +02:00
public canDeleteMessage ( message : MyMessage ) {
2020-11-12 03:11:43 +01:00
return message && (
2022-08-04 08:49:54 +02:00
message . peerId . isUser ( ) ||
message . pFlags . out ||
this . appChatsManager . getChat ( message . peerId . toChatId ( ) ) . _ === 'chat' ||
this . appChatsManager . hasRights ( message . peerId . toChatId ( ) , 'delete_messages' )
2022-09-02 19:43:54 +02:00
) && ( ! message . pFlags . is_outgoing || ! ! message . error ) ;
2020-10-21 01:25:36 +02:00
}
2021-10-21 15:16:43 +02:00
public getReplyKeyboard ( peerId : PeerId ) {
2021-08-03 03:44:13 +02:00
return this . getHistoryStorage ( peerId ) . replyMarkup ;
2021-07-02 07:17:51 +02:00
}
public mergeReplyKeyboard ( historyStorage : HistoryStorage , message : Message.messageService | Message . message ) {
2020-06-13 10:19:39 +02:00
// this.log('merge', message.mid, message.reply_markup, historyStorage.reply_markup)
2022-06-17 18:01:43 +02:00
if ( ! message ) {
return false ;
}
2022-08-04 08:49:54 +02:00
const messageReplyMarkup = ( message as Message . message ) . reply_markup ;
2021-07-02 07:17:51 +02:00
if ( ! messageReplyMarkup &&
2020-10-03 19:45:56 +02:00
! message . pFlags ? . out &&
2021-07-02 07:17:51 +02:00
! ( message as Message . messageService ) . action ) {
2020-02-06 16:43:07 +01:00
return false ;
}
2021-07-02 07:17:51 +02:00
if ( messageReplyMarkup ? . _ === 'replyInlineMarkup' ) {
2020-02-06 16:43:07 +01:00
return false ;
}
2021-07-02 07:17:51 +02:00
2021-08-03 03:44:13 +02:00
const lastReplyMarkup = historyStorage . replyMarkup ;
2020-02-06 16:43:07 +01:00
if ( messageReplyMarkup ) {
if ( lastReplyMarkup && lastReplyMarkup . mid >= message . mid ) {
return false ;
}
2020-10-10 00:36:06 +02:00
if ( messageReplyMarkup . pFlags . selective ) {
2020-02-06 16:43:07 +01:00
return false ;
}
2020-12-11 03:06:16 +01:00
if ( historyStorage . maxOutId &&
message . mid < historyStorage . maxOutId &&
2021-07-02 07:17:51 +02:00
( messageReplyMarkup as ReplyMarkup . replyKeyboardMarkup | ReplyMarkup . replyKeyboardForceReply ) . pFlags . single_use ) {
( messageReplyMarkup as ReplyMarkup . replyKeyboardMarkup | ReplyMarkup . replyKeyboardForceReply ) . pFlags . hidden = true ;
2020-02-06 16:43:07 +01:00
}
2021-07-02 07:17:51 +02:00
messageReplyMarkup . mid = message . mid ;
/ * m e s s a g e R e p l y M a r k u p = O b j e c t . a s s i g n ( {
2020-02-06 16:43:07 +01:00
mid : message.mid
2021-07-02 07:17:51 +02:00
} , messageReplyMarkup ) ; * /
2021-02-04 01:30:23 +01:00
if ( messageReplyMarkup . _ !== 'replyKeyboardHide' ) {
2022-07-26 17:24:29 +02:00
messageReplyMarkup . fromId = this . appPeersManager . getPeerId ( message . from_id ) ;
2020-02-06 16:43:07 +01:00
}
2021-07-02 07:17:51 +02:00
2021-08-03 03:44:13 +02:00
historyStorage . replyMarkup = messageReplyMarkup ;
2020-06-13 10:19:39 +02:00
// this.log('set', historyStorage.reply_markup)
2020-02-06 16:43:07 +01:00
return true ;
}
if ( message . pFlags . out ) {
if ( lastReplyMarkup ) {
2021-07-02 07:17:51 +02:00
assumeType < ReplyMarkup.replyKeyboardMarkup > ( lastReplyMarkup ) ;
2020-02-06 16:43:07 +01:00
if ( lastReplyMarkup . pFlags . single_use &&
! lastReplyMarkup . pFlags . hidden &&
2020-12-19 02:07:24 +01:00
( message . mid > lastReplyMarkup . mid || message . pFlags . is_outgoing ) &&
2021-07-02 07:17:51 +02:00
( message as Message . message ) . message ) {
2020-02-06 16:43:07 +01:00
lastReplyMarkup . pFlags . hidden = true ;
2020-06-13 10:19:39 +02:00
// this.log('set', historyStorage.reply_markup)
2020-02-06 16:43:07 +01:00
return true ;
}
2020-12-11 03:06:16 +01:00
} else if ( ! historyStorage . maxOutId ||
message . mid > historyStorage . maxOutId ) {
historyStorage . maxOutId = message . mid ;
2020-02-06 16:43:07 +01:00
}
}
2021-07-02 07:17:51 +02:00
assumeType < Message.messageService > ( message ) ;
if ( message . action ? . _ === 'messageActionChatDeleteUser' &&
2022-08-04 08:49:54 +02:00
( lastReplyMarkup ?
message . action . user_id === ( lastReplyMarkup as ReplyMarkup . replyKeyboardMarkup ) . fromId :
this . appUsersManager . isBot ( message . action . user_id )
2020-02-06 16:43:07 +01:00
)
) {
2021-08-03 03:44:13 +02:00
historyStorage . replyMarkup = {
2020-02-06 16:43:07 +01:00
_ : 'replyKeyboardHide' ,
mid : message.mid ,
pFlags : { }
} ;
2020-06-13 10:19:39 +02:00
// this.log('set', historyStorage.reply_markup)
2020-02-06 16:43:07 +01:00
return true ;
}
return false ;
}
2021-10-21 15:16:43 +02:00
public getSearchStorage ( peerId : PeerId , inputFilter : MyInputMessagesFilter ) {
2020-12-11 03:06:16 +01:00
if ( ! this . searchesStorage [ peerId ] ) this . searchesStorage [ peerId ] = { } ;
if ( ! this . searchesStorage [ peerId ] [ inputFilter ] ) this . searchesStorage [ peerId ] [ inputFilter ] = { history : [ ] } ;
return this . searchesStorage [ peerId ] [ inputFilter ] ;
2020-12-08 20:48:44 +01:00
}
2023-01-06 20:27:29 +01:00
public getSearchCounters (
peerId : PeerId ,
filters : MessagesFilter [ ] ,
canCache = true ,
threadId? : number
) : Promise < MessagesSearchCounter [ ] > {
if ( this . appPeersManager . isPeerRestricted ( peerId ) ) {
2022-02-11 23:17:35 +01:00
return Promise . resolve ( filters . map ( ( filter ) = > {
return {
_ : 'messages.searchCounter' ,
pFlags : { } ,
filter : filter ,
count : 0
} ;
} ) ) ;
}
2022-06-17 18:01:43 +02:00
const func = ( canCache ? this . apiManager.invokeApiCacheable : this.apiManager.invokeApi ) . bind ( this . apiManager ) ;
2021-04-14 10:30:14 +02:00
return func ( 'messages.getSearchCounters' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2023-01-06 20:27:29 +01:00
filters ,
top_msg_id : threadId ? getServerMessageId ( threadId ) : undefined
2020-12-08 20:48:44 +01:00
} ) ;
}
2022-06-17 18:01:43 +02:00
public filterMessagesByInputFilterFromStorage ( inputFilter : MyInputMessagesFilter , history : number [ ] , storage : MessagesStorage | MessagesStorageKey , limit : number ) {
const _storage = this . getMessagesStorage ( storage ) ;
return filterMessagesByInputFilter ( inputFilter , history . map ( ( mid ) = > _storage . get ( mid ) ) , limit ) ;
2021-10-05 22:40:07 +02:00
}
2020-12-25 18:38:32 +01:00
public getSearch ( { peerId , query , inputFilter , maxId , limit , nextRate , backLimit , threadId , folderId , minDate , maxDate } : {
2021-10-21 15:16:43 +02:00
peerId? : PeerId ,
2020-12-25 13:53:20 +01:00
maxId? : number ,
2020-12-20 04:54:35 +01:00
limit? : number ,
2020-12-25 13:53:20 +01:00
nextRate? : number ,
2020-12-20 04:54:35 +01:00
backLimit? : number ,
threadId? : number ,
2020-12-25 13:53:20 +01:00
folderId? : number ,
2020-12-20 04:54:35 +01:00
query? : string ,
inputFilter ? : {
_ : MyInputMessagesFilter
} ,
2020-12-25 18:38:32 +01:00
minDate? : number ,
maxDate? : number
} ) : Promise < {
2020-02-07 07:38:55 +01:00
count : number ,
next_rate : number ,
2020-12-08 20:48:44 +01:00
offset_id_offset : number ,
2020-12-18 04:07:32 +01:00
history : MyMessage [ ]
2020-02-07 07:38:55 +01:00
} > {
2023-01-06 20:27:29 +01:00
if ( this . appPeersManager . isPeerRestricted ( peerId ) /* || true */ ) {
2022-02-11 23:17:35 +01:00
return Promise . resolve ( {
count : 0 ,
offset_id_offset : 0 ,
next_rate : undefined ,
history : [ ]
} ) ;
}
2020-12-25 18:38:32 +01:00
if ( ! query ) query = '' ;
if ( ! inputFilter ) inputFilter = { _ : 'inputMessagesFilterEmpty' } ;
2021-01-26 02:26:28 +01:00
if ( limit === undefined ) limit = 20 ;
2020-12-25 18:38:32 +01:00
if ( ! nextRate ) nextRate = 0 ;
if ( ! backLimit ) backLimit = 0 ;
minDate = minDate ? minDate / 1000 | 0 : 0 ;
maxDate = maxDate ? maxDate / 1000 | 0 : 0 ;
2021-10-05 22:40:07 +02:00
let foundMsgs : MyMessage [ ] = [ ] ;
2020-02-06 16:43:07 +01:00
2022-08-04 08:49:54 +02:00
// this.log('search', maxId);
2020-12-08 20:48:44 +01:00
if ( backLimit ) {
limit += backLimit ;
2020-02-06 16:43:07 +01:00
}
2022-08-04 08:49:54 +02:00
// const beta = inputFilter._ === 'inputMessagesFilterPinned' && !backLimit;
2020-12-08 20:48:44 +01:00
const beta = false ;
2020-02-06 16:43:07 +01:00
2020-12-08 20:48:44 +01:00
let storage : {
count? : number ;
2022-04-13 00:51:20 +02:00
history : SlicedArray < number > ;
2020-12-08 20:48:44 +01:00
} ;
// * костыль для limit 1, если нужно и получить сообщение, и узнать количество сообщений
2020-12-20 04:54:35 +01:00
if ( peerId && ! backLimit && ! maxId && ! query && limit !== 1 && ! threadId /* && inputFilter._ !== 'inputMessagesFilterPinned' */ ) {
2022-08-04 08:49:54 +02:00
storage = beta ?
this . getSearchStorage ( peerId , inputFilter . _ ) as any :
2020-12-18 04:07:32 +01:00
this . getHistoryStorage ( peerId ) ;
2022-06-17 18:01:43 +02:00
foundMsgs = this . filterMessagesByInputFilterFromStorage ( inputFilter . _ , storage . history . slice , this . getHistoryMessagesStorage ( peerId ) , limit ) ;
2020-02-06 16:43:07 +01:00
}
2020-10-02 22:33:32 +02:00
if ( foundMsgs . length ) {
2020-12-08 20:48:44 +01:00
if ( foundMsgs . length < limit && ( beta ? storage . count !== storage.history.length : true ) ) {
2020-12-24 00:35:49 +01:00
maxId = foundMsgs [ foundMsgs . length - 1 ] . mid ;
2020-10-03 19:45:56 +02:00
limit = limit - foundMsgs . length ;
} else {
return Promise . resolve ( {
2020-12-08 20:48:44 +01:00
count : beta ? storage.count : 0 ,
2020-10-03 19:45:56 +02:00
next_rate : 0 ,
2020-12-08 20:48:44 +01:00
offset_id_offset : 0 ,
2020-10-03 19:45:56 +02:00
history : foundMsgs
} ) ;
2020-02-06 16:43:07 +01:00
}
2020-12-08 20:48:44 +01:00
} else if ( beta && storage ? . count ) {
return Promise . resolve ( {
count : storage.count ,
next_rate : 0 ,
offset_id_offset : 0 ,
history : [ ]
} ) ;
2020-02-06 16:43:07 +01:00
}
2021-04-15 12:11:56 +02:00
const canCache = false && ( [ 'inputMessagesFilterChatPhotos' , 'inputMessagesFilterPinned' ] as MyInputMessagesFilter [ ] ) . includes ( inputFilter . _ ) ;
2022-06-17 18:01:43 +02:00
const method = ( canCache ? this . apiManager.invokeApiCacheable : this.apiManager.invokeApi ) . bind ( this . apiManager ) ;
2021-04-15 10:44:27 +02:00
2020-06-13 10:19:39 +02:00
let apiPromise : Promise < any > ;
2020-12-25 13:53:20 +01:00
if ( peerId && ! nextRate && folderId === undefined /* || !query */ ) {
2021-04-15 10:44:27 +02:00
apiPromise = method ( 'messages.search' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2020-02-06 16:43:07 +01:00
q : query || '' ,
2020-12-08 20:48:44 +01:00
filter : inputFilter as any as MessagesFilter ,
2020-12-25 18:38:32 +01:00
min_date : minDate ,
max_date : maxDate ,
2020-10-02 22:33:32 +02:00
limit ,
2022-06-17 18:01:43 +02:00
offset_id : getServerMessageId ( maxId ) || 0 ,
2020-04-08 17:46:43 +02:00
add_offset : backLimit ? - backLimit : 0 ,
2020-02-06 16:43:07 +01:00
max_id : 0 ,
2020-09-17 21:33:23 +02:00
min_id : 0 ,
2021-10-21 15:16:43 +02:00
hash : '' ,
2022-06-17 18:01:43 +02:00
top_msg_id : getServerMessageId ( threadId ) || 0
2020-02-06 16:43:07 +01:00
} , {
2022-08-04 08:49:54 +02:00
// timeout: APITIMEOUT,
2020-02-06 16:43:07 +01:00
noErrorBox : true
} ) ;
} else {
2022-08-04 08:49:54 +02:00
// var offsetDate = 0;
2021-10-21 15:16:43 +02:00
let offsetPeerId : PeerId ;
2020-12-20 04:54:35 +01:00
let offsetId = 0 ;
2022-08-04 08:49:54 +02:00
const offsetMessage = maxId && this . getMessageByPeer ( peerId , maxId ) ;
2020-02-06 16:43:07 +01:00
if ( offsetMessage && offsetMessage . date ) {
2022-08-04 08:49:54 +02:00
// offsetDate = offsetMessage.date + timeManager.getServerTimeOffset();
2020-12-11 03:06:16 +01:00
offsetId = offsetMessage . id ;
offsetPeerId = this . getMessagePeer ( offsetMessage ) ;
2020-02-06 16:43:07 +01:00
}
2021-04-15 10:44:27 +02:00
apiPromise = method ( 'messages.searchGlobal' , {
2020-02-06 16:43:07 +01:00
q : query ,
2020-12-08 20:48:44 +01:00
filter : inputFilter as any as MessagesFilter ,
2020-12-25 18:38:32 +01:00
min_date : minDate ,
max_date : maxDate ,
2020-12-25 13:53:20 +01:00
offset_rate : nextRate ,
2022-04-25 16:54:30 +02:00
offset_peer : this.appPeersManager.getInputPeerById ( offsetPeerId ) ,
2020-12-16 04:22:58 +01:00
offset_id : offsetId ,
2020-12-20 04:54:35 +01:00
limit ,
2020-12-25 13:53:20 +01:00
folder_id : folderId
2020-02-06 16:43:07 +01:00
} , {
2022-08-04 08:49:54 +02:00
// timeout: APITIMEOUT,
2020-02-06 16:43:07 +01:00
noErrorBox : true
} ) ;
}
return apiPromise . then ( ( searchResult : any ) = > {
2022-04-25 16:54:30 +02:00
this . appUsersManager . saveApiUsers ( searchResult . users ) ;
this . appChatsManager . saveApiChats ( searchResult . chats ) ;
2020-02-06 16:43:07 +01:00
this . saveMessages ( searchResult . messages ) ;
2021-02-23 16:20:52 +01:00
/ * i f ( b e t a & & s t o r a g e & & ( ! m a x I d | | s t o r a g e . h i s t o r y [ s t o r a g e . h i s t o r y . l e n g t h - 1 ] = = = m a x I d ) ) {
2020-12-11 03:06:16 +01:00
const storage = this . getSearchStorage ( peerId , inputFilter . _ ) ;
2022-06-17 18:01:43 +02:00
const add = ( searchResult . messages . map ( ( m : any ) = > m . mid ) as number [ ] ) . filter ( ( mid ) = > storage . history . indexOf ( mid ) === - 1 ) ;
2020-12-08 20:48:44 +01:00
storage . history . push ( . . . add ) ;
storage . history . sort ( ( a , b ) = > b - a ) ;
storage . count = searchResult . count ;
2021-02-23 16:20:52 +01:00
} * /
2020-12-08 20:48:44 +01:00
2021-01-08 10:55:37 +01:00
if ( DEBUG ) {
this . log ( 'getSearch result:' , inputFilter , searchResult ) ;
}
2020-02-07 07:38:55 +01:00
2020-10-03 19:45:56 +02:00
const foundCount : number = searchResult . count || ( foundMsgs . length + searchResult . messages . length ) ;
2020-02-06 16:43:07 +01:00
2021-11-03 19:21:06 +01:00
searchResult . messages . forEach ( ( message : MyMessage ) = > {
2020-12-11 03:06:16 +01:00
const peerId = this . getMessagePeer ( message ) ;
2021-10-21 15:16:43 +02:00
if ( peerId . isAnyChat ( ) ) {
2023-01-06 20:27:29 +01:00
const chat = this . appChatsManager . getChat ( peerId . toChatId ( ) ) as Chat . chat ;
2020-02-06 16:43:07 +01:00
if ( chat . migrated_to ) {
2021-10-21 15:16:43 +02:00
this . migrateChecks ( peerId , ( chat . migrated_to as InputChannel . inputChannel ) . channel_id . toPeerId ( true ) ) ;
2020-02-06 16:43:07 +01:00
}
}
2020-12-08 20:48:44 +01:00
2020-12-18 04:07:32 +01:00
foundMsgs . push ( message ) ;
2020-02-06 16:43:07 +01:00
} ) ;
return {
count : foundCount ,
2020-12-24 00:35:49 +01:00
offset_id_offset : searchResult.offset_id_offset || 0 ,
2020-02-07 07:38:55 +01:00
next_rate : searchResult.next_rate ,
2020-02-06 16:43:07 +01:00
history : foundMsgs
2020-02-07 07:38:55 +01:00
} ;
2020-02-06 16:43:07 +01:00
} ) ;
}
2021-10-21 15:16:43 +02:00
public subscribeRepliesThread ( peerId : PeerId , mid : number ) {
2020-12-22 04:02:30 +01:00
const repliesKey = peerId + '_' + mid ;
for ( const threadKey in this . threadsToReplies ) {
if ( this . threadsToReplies [ threadKey ] === repliesKey ) return ;
}
this . getDiscussionMessage ( peerId , mid ) ;
}
2022-01-13 00:54:33 +01:00
public generateThreadServiceStartMessage ( message : Message.message | Message . messageService ) {
2020-12-23 02:18:07 +01:00
const threadKey = message . peerId + '_' + message . mid ;
if ( this . threadsServiceMessagesIdsStorage [ threadKey ] ) return ;
2022-06-17 18:01:43 +02:00
const maxMessageId = getServerMessageId ( Math . max ( . . . this . getMidsByMessage ( message ) ) ) ;
2020-12-23 02:18:07 +01:00
const serviceStartMessage : Message.messageService = {
_ : 'messageService' ,
2021-01-12 11:33:19 +01:00
pFlags : {
is_single : true
2021-07-08 08:07:32 +02:00
} ,
2022-06-17 18:01:43 +02:00
id : this.appMessagesIdsManager.generateTempMessageId ( maxMessageId ) ,
2020-12-23 02:18:07 +01:00
date : message.date ,
2021-10-21 15:16:43 +02:00
from_id : { _ : 'peerUser' , user_id : NULL_PEER_ID } /* message.from_id */ ,
2020-12-23 02:18:07 +01:00
peer_id : message.peer_id ,
action : {
2021-08-10 18:52:12 +02:00
_ : 'messageActionDiscussionStarted'
2020-12-23 02:18:07 +01:00
} ,
2023-01-06 20:27:29 +01:00
reply_to : this.generateReplyHeader ( message . peerId , message . id )
2020-12-23 02:18:07 +01:00
} ;
this . saveMessages ( [ serviceStartMessage ] , { isOutgoing : true } ) ;
this . threadsServiceMessagesIdsStorage [ threadKey ] = serviceStartMessage . mid ;
2022-06-17 18:01:43 +02:00
}
public getThreadServiceMessageId ( peerId : PeerId , threadId : number ) {
return this . threadsServiceMessagesIdsStorage [ peerId + '_' + threadId ] ;
}
2020-12-23 02:18:07 +01:00
2021-10-21 15:16:43 +02:00
public getDiscussionMessage ( peerId : PeerId , mid : number ) {
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApiSingle ( 'messages.getDiscussionMessage' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
msg_id : getServerMessageId ( mid )
} ) . then ( ( result ) = > {
2022-04-25 16:54:30 +02:00
this . appChatsManager . saveApiChats ( result . chats ) ;
this . appUsersManager . saveApiUsers ( result . users ) ;
2020-12-20 04:54:35 +01:00
this . saveMessages ( result . messages ) ;
2022-06-17 18:01:43 +02:00
const message = this . getMessageWithReplies ( result . messages [ 0 ] as Message . message ) ;
2020-12-22 09:18:42 +01:00
const threadKey = message . peerId + '_' + message . mid ;
2020-12-23 02:18:07 +01:00
this . generateThreadServiceStartMessage ( message ) ;
2022-08-04 08:49:54 +02:00
2020-12-20 04:54:35 +01:00
const historyStorage = this . getHistoryStorage ( message . peerId , message . mid ) ;
2023-01-06 20:27:29 +01:00
const newMaxId = result . max_id = generateMessageId ( result . max_id ) || 0 ;
2022-06-17 18:01:43 +02:00
result . read_inbox_max_id = historyStorage . readMaxId = generateMessageId ( result . read_inbox_max_id ? ? message . mid ) ;
result . read_outbox_max_id = historyStorage . readOutboxMaxId = generateMessageId ( result . read_outbox_max_id ) || 0 ;
2020-12-20 04:54:35 +01:00
2023-01-06 20:27:29 +01:00
const first = historyStorage . history . first ;
if ( historyStorage . maxId && historyStorage . maxId < newMaxId && first . isEnd ( SliceEnd . Bottom ) ) {
first . unsetEnd ( SliceEnd . Bottom ) ;
}
historyStorage . maxId = newMaxId ;
2020-12-22 09:18:42 +01:00
this . threadsToReplies [ threadKey ] = peerId + '_' + mid ;
2020-12-22 04:02:30 +01:00
2020-12-22 20:10:53 +01:00
return message ;
2020-12-20 04:54:35 +01:00
} ) ;
}
2022-06-30 16:14:33 +02:00
private handleNewMessage ( message : MyMessage ) {
this . rootScope . dispatchEvent ( 'history_multiappend' , message ) ;
2021-05-06 23:02:21 +02:00
}
2021-09-17 18:50:29 +02:00
private handleNewDialogs = ( ) = > {
2020-12-11 03:06:16 +01:00
let newMaxSeenId = 0 ;
2023-01-06 20:27:29 +01:00
const updateMap : BroadcastEvents [ 'dialogs_multiupdate' ] = new Map ( ) ;
const processDialog = ( dialog : MTDialog.dialog | ForumTopic ) = > {
const { peerId } = dialog ;
this . dialogsStorage . pushDialog ( { dialog } ) ;
if ( ! this . appPeersManager . isChannel ( peerId ) ) {
newMaxSeenId = Math . max ( newMaxSeenId , dialog . top_message || 0 ) ;
}
let cache = updateMap . get ( peerId ) ;
if ( ! cache ) {
updateMap . set ( peerId , cache = { } ) ;
}
if ( dialog . _ === 'forumTopic' ) {
( cache . topics ? ? = new Map ( ) ) . set ( dialog . id , dialog ) ;
} else {
cache . dialog = dialog ;
}
} ;
for ( const [ peerId , obj ] of this . newDialogsToHandle ) {
const isDialogDefined = 'dialog' in obj ;
const { dialog , topics } = obj ;
2022-11-19 13:56:25 +01:00
2023-01-06 20:27:29 +01:00
if ( isDialogDefined ) {
if ( ! dialog ) {
this . reloadConversation ( peerId . toPeerId ( ) ) ;
} else if ( this . dialogsStorage . getDialogOnly ( peerId ) ) { // * can be already dropped
processDialog ( dialog ) ;
}
2022-11-19 13:56:25 +01:00
}
2023-01-06 20:27:29 +01:00
if ( topics ) {
topics ? . forEach ( ( topic , id ) = > {
if ( ! topic ) {
this . dialogsStorage . getForumTopicById ( peerId , id ) ;
} else if ( this . dialogsStorage . getForumTopic ( peerId , id ) ) { // * can be already dropped
processDialog ( topic ) ;
}
} ) ;
2020-02-06 16:43:07 +01:00
}
2020-05-13 17:26:40 +02:00
}
2020-05-10 03:23:21 +02:00
2022-08-04 08:49:54 +02:00
// this.log('after order:', this.dialogsStorage[0].map((d) => d.peerId));
2020-02-06 16:43:07 +01:00
2021-02-04 01:30:23 +01:00
if ( newMaxSeenId !== 0 ) {
2020-12-11 03:06:16 +01:00
this . incrementMaxSeenId ( newMaxSeenId ) ;
2020-02-06 16:43:07 +01:00
}
2023-01-06 20:27:29 +01:00
this . rootScope . dispatchEvent ( 'dialogs_multiupdate' , updateMap ) ;
2022-08-19 21:27:29 +02:00
this . newDialogsToHandle . clear ( ) ;
2020-06-19 13:49:55 +02:00
} ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
public scheduleHandleNewDialogs ( peerId? : PeerId , dialog? : Dialog | ForumTopic | ForumTopic [ 'id' ] ) {
2021-04-27 17:45:53 +02:00
if ( peerId !== undefined ) {
2023-01-06 20:27:29 +01:00
let obj = this . newDialogsToHandle . get ( peerId ) ;
if ( ! obj ) {
this . newDialogsToHandle . set ( peerId , obj = { } ) ;
}
const isObject = typeof ( dialog ) === 'object' ;
if ( ! dialog || ( isObject && dialog . _ === 'dialog' ) ) {
obj . dialog = dialog as Dialog ;
} else {
obj . topics ? ? = new Map ( ) ;
if ( isObject ) {
obj . topics . set ( ( dialog as ForumTopic ) . id , dialog as ForumTopic ) ;
} else {
obj . topics . set ( dialog as number , undefined ) ;
}
}
2020-05-13 17:26:40 +02:00
}
2021-04-27 17:45:53 +02:00
2023-01-06 20:27:29 +01:00
return this . newDialogsHandlePromise ? ? = pause ( 0 ) . then ( ( ) = > {
2022-06-30 16:14:33 +02:00
this . newDialogsHandlePromise = undefined ;
this . handleNewDialogs ( ) ;
2021-04-27 17:45:53 +02:00
} ) ;
2020-05-13 17:26:40 +02:00
}
2023-02-27 14:11:37 +01:00
public async deleteMessages ( peerId : PeerId , mids : number [ ] , revoke? : boolean , isRecursion? : boolean ) {
2020-12-16 04:22:58 +01:00
let promise : Promise < any > ;
2023-02-27 14:11:37 +01:00
const isChannel = this . appPeersManager . isChannel ( peerId ) ;
const channelId = isChannel && peerId . toChatId ( ) ;
if ( isChannel && ! isRecursion ) {
2023-01-06 20:27:29 +01:00
const channel = this . appChatsManager . getChat ( channelId ) as Chat . channel ;
2021-08-27 00:22:14 +02:00
if ( ! channel . pFlags . creator && ! channel . admin_rights ? . pFlags ? . delete_messages ) {
mids = mids . filter ( ( mid ) = > {
const message = this . getMessageByPeer ( peerId , mid ) ;
return ! ! message . pFlags . out ;
} ) ;
2020-05-27 08:21:16 +02:00
2021-08-27 00:22:14 +02:00
if ( ! mids . length ) {
2020-12-16 04:22:58 +01:00
return ;
2020-05-27 08:21:16 +02:00
}
}
2023-02-27 14:11:37 +01:00
}
const config = await this . apiManager . getConfig ( ) ;
const overflowMids = mids . splice ( config . forwarded_count_max , mids . length - config . forwarded_count_max ) ;
const serverMessageIds = mids . map ( ( mid ) = > {
const messageId = getServerMessageId ( mid ) ;
// filter outgoing messages
return generateMessageId ( messageId ) === mid && messageId ;
} ) . filter ( Boolean ) ;
2020-05-27 08:21:16 +02:00
2023-02-27 14:11:37 +01:00
if ( isChannel ) {
2022-06-17 18:01:43 +02:00
promise = this . apiManager . invokeApi ( 'channels.deleteMessages' , {
2022-04-25 16:54:30 +02:00
channel : this.appChatsManager.getChannelInput ( channelId ) ,
2023-02-27 14:11:37 +01:00
id : serverMessageIds
2020-12-16 04:22:58 +01:00
} ) . then ( ( affectedMessages ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( {
2021-07-04 01:56:21 +02:00
_ : 'updateDeleteChannelMessages' ,
channel_id : channelId ,
messages : mids ,
pts : affectedMessages.pts ,
pts_count : affectedMessages.pts_count
2020-12-16 04:22:58 +01:00
} ) ;
} ) ;
} else {
2022-06-17 18:01:43 +02:00
promise = this . apiManager . invokeApi ( 'messages.deleteMessages' , {
2020-12-20 04:54:35 +01:00
revoke ,
2023-02-27 14:11:37 +01:00
id : serverMessageIds
2020-12-16 04:22:58 +01:00
} ) . then ( ( affectedMessages ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( {
2021-07-04 01:56:21 +02:00
_ : 'updateDeleteMessages' ,
messages : mids ,
pts : affectedMessages.pts ,
pts_count : affectedMessages.pts_count
2020-12-16 04:22:58 +01:00
} ) ;
} ) ;
2020-05-27 08:21:16 +02:00
}
2022-06-17 18:01:43 +02:00
const promises : ( typeof promise ) [ ] = [ promise ] ;
if ( overflowMids . length ) {
2023-02-27 14:11:37 +01:00
promises . push ( this . deleteMessages ( peerId , overflowMids , revoke , true ) ) ;
2022-06-17 18:01:43 +02:00
}
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
return Promise . all ( promises ) . then ( noop ) ;
2020-05-27 08:21:16 +02:00
}
2021-10-21 15:16:43 +02:00
public readHistory ( peerId : PeerId , maxId = 0 , threadId? : number , force = false ) {
2021-09-01 19:17:06 +02:00
if ( DO_NOT_READ_HISTORY ) {
return Promise . resolve ( ) ;
}
2020-02-06 16:43:07 +01:00
// console.trace('start read')
2021-01-18 19:34:41 +01:00
this . log ( 'readHistory:' , peerId , maxId , threadId ) ;
2023-01-06 20:27:29 +01:00
const readMaxId = this . getReadMaxIdIfUnread ( peerId , threadId ) ;
if ( ! readMaxId ) {
if ( threadId && ! force ) {
const forumTopic = this . dialogsStorage . getForumTopic ( peerId , threadId ) ;
if ( ! getServerMessageId ( forumTopic . read_inbox_max_id ) ) {
force = true ;
}
}
if ( ! force ) {
const dialog = this . appChatsManager . isForum ( peerId . toChatId ( ) ) && threadId ?
this . dialogsStorage . getForumTopic ( peerId , threadId ) :
this . getDialogOnly ( peerId ) ;
2022-06-17 18:01:43 +02:00
if ( dialog && this . isDialogUnread ( dialog ) ) {
force = true ;
}
}
if ( ! force ) {
this . log ( 'readHistory: isn\'t unread' ) ;
return Promise . resolve ( ) ;
}
2021-01-18 19:34:41 +01:00
}
2020-12-20 04:54:35 +01:00
2020-12-23 02:18:07 +01:00
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
2020-02-06 16:43:07 +01:00
2021-04-15 10:44:27 +02:00
if ( historyStorage . triedToReadMaxId >= maxId ) {
return Promise . resolve ( ) ;
}
2021-01-18 19:34:41 +01:00
let apiPromise : Promise < any > ;
2020-12-23 02:18:07 +01:00
if ( threadId ) {
2021-01-18 19:34:41 +01:00
if ( ! historyStorage . readPromise ) {
2022-06-17 18:01:43 +02:00
apiPromise = this . apiManager . invokeApi ( 'messages.readDiscussion' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
msg_id : getServerMessageId ( threadId ) ,
read_max_id : getServerMessageId ( maxId )
2020-12-23 02:18:07 +01:00
} ) ;
2023-01-06 20:27:29 +01:00
// apiPromise = new Promise<void>((resolve) => resolve());
2021-01-18 19:34:41 +01:00
}
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( {
2021-07-04 01:56:21 +02:00
_ : 'updateReadChannelDiscussionInbox' ,
2021-10-21 15:16:43 +02:00
channel_id : peerId.toChatId ( ) ,
2021-07-04 01:56:21 +02:00
top_msg_id : threadId ,
read_max_id : maxId
2020-12-23 02:18:07 +01:00
} ) ;
2022-04-25 16:54:30 +02:00
} else if ( this . appPeersManager . isChannel ( peerId ) ) {
2021-01-18 19:34:41 +01:00
if ( ! historyStorage . readPromise ) {
2022-06-17 18:01:43 +02:00
apiPromise = this . apiManager . invokeApi ( 'channels.readHistory' , {
2022-04-25 16:54:30 +02:00
channel : this.appChatsManager.getChannelInput ( peerId . toChatId ( ) ) ,
2022-06-17 18:01:43 +02:00
max_id : getServerMessageId ( maxId )
2020-10-03 02:35:26 +02:00
} ) ;
2021-01-18 19:34:41 +01:00
}
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( {
2021-07-04 01:56:21 +02:00
_ : 'updateReadChannelInbox' ,
max_id : maxId ,
2021-10-21 15:16:43 +02:00
channel_id : peerId.toChatId ( ) ,
2021-07-04 01:56:21 +02:00
still_unread_count : undefined ,
pts : undefined
2020-02-06 16:43:07 +01:00
} ) ;
} else {
2021-01-18 19:34:41 +01:00
if ( ! historyStorage . readPromise ) {
2022-06-17 18:01:43 +02:00
apiPromise = this . apiManager . invokeApi ( 'messages.readHistory' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
max_id : getServerMessageId ( maxId )
2021-01-18 19:34:41 +01:00
} ) . then ( ( affectedMessages ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( {
2021-01-18 19:34:41 +01:00
_ : 'updateShort' ,
update : {
_ : 'updatePts' ,
pts : affectedMessages.pts ,
pts_count : affectedMessages.pts_count
}
} ) ;
2020-02-06 16:43:07 +01:00
} ) ;
2021-01-18 19:34:41 +01:00
}
2020-05-26 17:04:06 +02:00
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( {
2021-07-04 01:56:21 +02:00
_ : 'updateReadHistoryInbox' ,
max_id : maxId ,
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getOutputPeer ( peerId ) ,
2021-07-04 01:56:21 +02:00
still_unread_count : undefined ,
pts : undefined ,
pts_count : undefined
2020-10-03 02:35:26 +02:00
} ) ;
}
2020-02-07 15:17:39 +01:00
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'notification_reset' , this . appPeersManager . getPeerString ( peerId ) ) ;
2021-03-08 23:15:44 +01:00
2021-01-18 19:34:41 +01:00
if ( historyStorage . readPromise ) {
return historyStorage . readPromise ;
}
2021-04-15 10:44:27 +02:00
historyStorage . triedToReadMaxId = maxId ;
2020-10-03 02:35:26 +02:00
apiPromise . finally ( ( ) = > {
2020-02-06 16:43:07 +01:00
delete historyStorage . readPromise ;
2021-10-05 22:40:07 +02:00
const { readMaxId } = historyStorage ;
this . log ( 'readHistory: promise finally' , maxId , readMaxId ) ;
2021-01-18 19:34:41 +01:00
2021-10-05 22:40:07 +02:00
if ( readMaxId > maxId ) {
this . readHistory ( peerId , readMaxId , threadId , true ) ;
2020-10-03 02:35:26 +02:00
}
} ) ;
2020-02-06 16:43:07 +01:00
2020-10-03 02:35:26 +02:00
return historyStorage . readPromise = apiPromise ;
2020-02-06 16:43:07 +01:00
}
2021-10-21 15:16:43 +02:00
public readAllHistory ( peerId : PeerId , threadId? : number , force = false ) {
2021-01-25 20:06:44 +01:00
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
if ( historyStorage . maxId ) {
this . readHistory ( peerId , historyStorage . maxId , threadId , force ) ; // lol
}
}
2023-01-06 20:27:29 +01:00
private getUnreadMentionsKey ( peerId : PeerId , threadId? : number ) {
return peerId + ( threadId ? ` _ ${ threadId } ` : '' ) ;
}
private fixDialogUnreadMentionsIfNoMessage ( peerId : PeerId , threadId? : number ) {
const dialog = this . dialogsStorage . getDialogOrTopic ( peerId , threadId ) ;
2021-10-21 15:16:43 +02:00
if ( dialog ? . unread_mentions_count ) {
2023-01-06 20:27:29 +01:00
this . reloadConversationOrTopic ( peerId ) ;
2021-10-21 15:16:43 +02:00
}
}
2023-01-06 20:27:29 +01:00
private modifyCachedMentions ( peerId : PeerId , mid : number , add : boolean , threadId? : number ) {
const slicedArray = this . unreadMentions [ this . getUnreadMentionsKey ( peerId , threadId ) ] ;
2021-09-01 19:17:06 +02:00
if ( ! slicedArray ) return ;
if ( add ) {
if ( slicedArray . first . isEnd ( SliceEnd . Top ) ) {
slicedArray . insertSlice ( [ mid ] ) ;
}
} else {
slicedArray . delete ( mid ) ;
}
}
2023-01-06 20:27:29 +01:00
private fixUnreadMentionsCountIfNeeded ( peerId : PeerId , slicedArray : SlicedArray < number > , threadId? : number ) {
const dialog = this . dialogsStorage . getDialogOrTopic ( peerId , threadId ) ;
2021-12-17 17:46:00 +01:00
if ( ! slicedArray . length && dialog ? . unread_mentions_count ) {
2023-01-06 20:27:29 +01:00
this . reloadConversationOrTopic ( peerId ) ;
2021-12-17 17:46:00 +01:00
}
}
2023-01-06 20:27:29 +01:00
public goToNextMention ( peerId : PeerId , threadId? : number ) {
2022-06-17 18:01:43 +02:00
/ * t h i s . g e t U n r e a d M e n t i o n s ( p e e r I d , 1 , 2 , 0 ) . t h e n ( ( m e s s a g e s ) = > {
2021-09-01 19:17:06 +02:00
console . log ( messages ) ;
} ) ; * /
2023-01-06 20:27:29 +01:00
const key = this . getUnreadMentionsKey ( peerId , threadId ) ;
const promise = this . goToNextMentionPromises [ key ] ;
2021-09-01 19:17:06 +02:00
if ( promise ) {
return promise ;
}
2023-01-06 20:27:29 +01:00
const slicedArray = this . unreadMentions [ peerId ] ? ? = new SlicedArray ( ) ;
2021-09-01 19:17:06 +02:00
const length = slicedArray . length ;
const isTopEnd = slicedArray . first . isEnd ( SliceEnd . Top ) ;
if ( ! length && isTopEnd ) {
2023-01-06 20:27:29 +01:00
this . fixUnreadMentionsCountIfNeeded ( peerId , slicedArray , threadId ) ;
2021-09-01 19:17:06 +02:00
return Promise . resolve ( ) ;
}
let loadNextPromise = Promise . resolve ( ) ;
if ( ! isTopEnd && length < 25 ) {
2023-01-06 20:27:29 +01:00
loadNextPromise = this . loadNextMentions ( peerId , threadId ) ;
2021-09-01 19:17:06 +02:00
}
2023-01-06 20:27:29 +01:00
return this . goToNextMentionPromises [ key ] = loadNextPromise . then ( ( ) = > {
2021-09-01 19:17:06 +02:00
const last = slicedArray . last ;
const mid = last && last [ last . length - 1 ] ;
if ( mid ) {
slicedArray . delete ( mid ) ;
2022-06-24 19:23:12 +02:00
return mid ;
2021-12-17 17:46:00 +01:00
} else {
2023-01-06 20:27:29 +01:00
this . fixUnreadMentionsCountIfNeeded ( peerId , slicedArray , threadId ) ;
2021-09-01 19:17:06 +02:00
}
} ) . finally ( ( ) = > {
2023-01-06 20:27:29 +01:00
delete this . goToNextMentionPromises [ key ] ;
2021-09-01 19:17:06 +02:00
} ) ;
}
2023-01-06 20:27:29 +01:00
private loadNextMentions ( peerId : PeerId , threadId? : number ) {
2021-09-01 19:17:06 +02:00
const slicedArray = this . unreadMentions [ peerId ] ;
const maxId = slicedArray . first [ 0 ] || 1 ;
const backLimit = 50 ;
const add_offset = - backLimit ;
const limit = backLimit ;
2023-01-06 20:27:29 +01:00
return this . getUnreadMentions ( peerId , maxId , add_offset , limit , undefined , undefined , threadId )
. then ( ( messages ) = > {
2021-09-01 19:17:06 +02:00
this . mergeHistoryResult ( slicedArray , messages , maxId === 1 ? 0 : maxId , limit , add_offset ) ;
} ) ;
}
2023-01-06 20:27:29 +01:00
private getUnreadMentions (
peerId : PeerId ,
offsetId : number ,
add_offset : number ,
limit : number ,
maxId = 0 ,
minId = 0 ,
threadId? : number
) {
return this . apiManager . invokeApiSingleProcess ( {
method : 'messages.getUnreadMentions' ,
params : {
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
offset_id : getServerMessageId ( offsetId ) ,
add_offset ,
limit ,
max_id : getServerMessageId ( maxId ) ,
min_id : getServerMessageId ( minId ) ,
top_msg_id : threadId ? getServerMessageId ( threadId ) : undefined
} ,
processResult : ( messagesMessages ) = > {
assumeType < Exclude < MessagesMessages , MessagesMessages.messagesMessagesNotModified > > ( messagesMessages ) ;
this . appUsersManager . saveApiUsers ( messagesMessages . users ) ;
this . appChatsManager . saveApiChats ( messagesMessages . chats ) ;
this . saveMessages ( messagesMessages . messages ) ;
return messagesMessages ;
}
2021-09-01 19:17:06 +02:00
} ) ;
}
2021-10-21 15:16:43 +02:00
public readMessages ( peerId : PeerId , msgIds : number [ ] ) {
2021-09-01 19:17:06 +02:00
if ( DO_NOT_READ_HISTORY ) {
return Promise . resolve ( ) ;
}
if ( ! msgIds . length ) {
return Promise . resolve ( ) ;
}
2022-06-17 18:01:43 +02:00
msgIds = msgIds . map ( ( mid ) = > getServerMessageId ( mid ) ) ;
2021-09-01 19:17:06 +02:00
let promise : Promise < any > , update : Update.updateChannelReadMessagesContents | Update . updateReadMessagesContents ;
2022-04-25 16:54:30 +02:00
if ( peerId . isAnyChat ( ) && this . appPeersManager . isChannel ( peerId ) ) {
2021-10-21 15:16:43 +02:00
const channelId = peerId . toChatId ( ) ;
2021-09-01 19:17:06 +02:00
update = {
_ : 'updateChannelReadMessagesContents' ,
channel_id : channelId ,
messages : msgIds
} ;
2022-06-17 18:01:43 +02:00
promise = this . apiManager . invokeApi ( 'channels.readMessageContents' , {
2022-04-25 16:54:30 +02:00
channel : this.appChatsManager.getChannelInput ( channelId ) ,
2020-12-16 04:22:58 +01:00
id : msgIds
} ) ;
} else {
2021-09-01 19:17:06 +02:00
update = {
_ : 'updateReadMessagesContents' ,
messages : msgIds ,
pts : undefined ,
pts_count : undefined
} ;
2022-06-17 18:01:43 +02:00
promise = this . apiManager . invokeApi ( 'messages.readMessageContents' , {
2020-12-16 04:22:58 +01:00
id : msgIds
} ) . then ( ( affectedMessages ) = > {
2021-09-01 19:17:06 +02:00
( update as Update . updateReadMessagesContents ) . pts = affectedMessages . pts ;
( update as Update . updateReadMessagesContents ) . pts_count = affectedMessages . pts_count ;
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( update ) ;
2020-12-16 04:22:58 +01:00
} ) ;
}
2021-09-01 19:17:06 +02:00
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( update ) ;
2021-09-01 19:17:06 +02:00
return promise ;
2020-02-06 16:43:07 +01:00
}
2021-10-21 15:16:43 +02:00
public getHistoryStorage ( peerId : PeerId , threadId? : number ) {
2020-12-20 04:54:35 +01:00
if ( threadId ) {
2022-08-04 08:49:54 +02:00
// threadId = this.getLocalMessageId(threadId);
2023-01-06 20:27:29 +01:00
return ( this . threadsStorage [ peerId ] ? ? = { } ) [ threadId ] ? ? = { count : null , history : new SlicedArray ( ) } ;
2020-12-20 04:54:35 +01:00
}
2023-01-06 20:27:29 +01:00
return this . historiesStorage [ peerId ] ? ? = { count : null , history : new SlicedArray ( ) } ;
2020-12-18 04:07:32 +01:00
}
2022-06-17 18:01:43 +02:00
public getHistoryStorageTransferable ( peerId : PeerId , threadId? : number ) {
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
const {
count ,
history ,
maxId ,
readMaxId ,
readOutboxMaxId ,
maxOutId ,
replyMarkup
} = historyStorage ;
return {
count ,
history : undefined as HistoryStorage ,
historySerialized : history.toJSON ( ) ,
maxId ,
readMaxId ,
readOutboxMaxId ,
maxOutId ,
replyMarkup
} ;
}
2023-01-06 20:27:29 +01:00
private getNotifyPeerSettings ( peerId : PeerId , threadId? : number ) {
const inputNotifyPeer = this . appPeersManager . getInputNotifyPeerById ( { peerId , ignorePeerId : true , threadId } ) ;
2022-02-06 20:35:18 +01:00
return Promise . all ( [
2022-04-25 16:54:30 +02:00
this . appNotificationsManager . getNotifyPeerTypeSettings ( ) ,
2023-01-06 20:27:29 +01:00
this . appNotificationsManager . getNotifySettings ( inputNotifyPeer )
2022-02-06 20:35:18 +01:00
] ) . then ( ( [ _ , peerTypeNotifySettings ] ) = > {
return {
2023-01-06 20:27:29 +01:00
muted : this.appNotificationsManager.isPeerLocalMuted ( { peerId , respectType : true , threadId } ) ,
2022-02-06 20:35:18 +01:00
peerTypeNotifySettings
} ;
} ) ;
}
2021-03-08 23:15:44 +01:00
private handleNotifications = ( ) = > {
2022-06-17 18:01:43 +02:00
ctx . clearTimeout ( this . notificationsHandlePromise ) ;
2023-01-06 20:27:29 +01:00
this . notificationsHandlePromise = undefined ;
2021-03-08 23:15:44 +01:00
2022-08-04 08:49:54 +02:00
// var timeout = $rootScope.idle.isIDLE && StatusManager.isOtherDeviceActive() ? 30000 : 1000;
// const timeout = 1000;
2021-03-08 23:15:44 +01:00
2023-01-06 20:27:29 +01:00
for ( const key in this . notificationsToHandle ) {
const [ peerId , threadId ] = key . split ( '_' ) ;
2022-06-17 18:01:43 +02:00
// if(rootScope.peerId === peerId && !rootScope.idle.isIDLE) {
2022-08-04 08:49:54 +02:00
// continue;
2022-06-17 18:01:43 +02:00
// }
2021-04-23 15:25:08 +02:00
2023-01-06 20:27:29 +01:00
const notifyPeerToHandle = this . notificationsToHandle [ key ] ;
this . getNotifyPeerSettings ( peerId . toPeerId ( ) , threadId ? + threadId : undefined )
. then ( ( { muted , peerTypeNotifySettings } ) = > {
2021-03-08 23:15:44 +01:00
const topMessage = notifyPeerToHandle . topMessage ;
2022-04-14 01:29:41 +02:00
if ( ( muted && ! topMessage . pFlags . mentioned ) || ! topMessage . pFlags . unread ) {
2021-03-08 23:15:44 +01:00
return ;
}
2022-08-04 08:49:54 +02:00
// setTimeout(() => {
if ( topMessage . pFlags . unread ) {
this . notifyAboutMessage ( topMessage , {
fwdCount : notifyPeerToHandle.fwdCount ,
peerTypeNotifySettings
} ) ;
}
// }, timeout);
2021-03-08 23:15:44 +01:00
} ) ;
}
this . notificationsToHandle = { } ;
} ;
2023-01-06 20:27:29 +01:00
public getUpdateAfterReloadKey ( peerId : PeerId , threadId? : number ) {
return peerId + ( threadId ? '_' + threadId : '' ) ;
}
private handleNewUpdateAfterReload ( peerId : PeerId , update : Update , threadId? : number ) {
const set = this . newUpdatesAfterReloadToHandle [ this . getUpdateAfterReloadKey ( peerId , threadId ) ] ? ? = new Set ( ) ;
if ( set . has ( update ) ) {
this . log . error ( 'here we go again' , peerId ) ;
return ;
}
( update as any ) . ignoreExisting = true ;
set . add ( update ) ;
this . scheduleHandleNewDialogs ( peerId , threadId ) ;
}
2021-04-24 19:06:24 +02:00
private onUpdateMessageId = ( update : Update.updateMessageID ) = > {
const randomId = update . random_id ;
const pendingData = this . pendingByRandomId [ randomId ] ;
2023-01-06 20:27:29 +01:00
if ( ! pendingData ) {
return ;
2021-04-24 19:06:24 +02:00
}
2023-01-06 20:27:29 +01:00
const mid = generateMessageId ( update . id ) ;
this . pendingByMessageId [ mid ] = randomId ;
// const {storage} = pendingData;
// const message = this.getMessageFromStorage(storage, mid);
// if(message) { // if message somehow already exists
// this.checkPendingMessage(message);
// }
2021-04-24 19:06:24 +02:00
} ;
2020-02-06 16:43:07 +01:00
2021-04-24 19:06:24 +02:00
private onUpdateNewMessage = ( update : Update.updateNewDiscussionMessage | Update . updateNewMessage | Update . updateNewChannelMessage ) = > {
const message = update . message as MyMessage ;
const peerId = this . getMessagePeer ( message ) ;
2022-06-17 18:01:43 +02:00
const storage = this . getHistoryMessagesStorage ( peerId ) ;
2020-12-18 04:07:32 +01:00
2021-04-24 19:06:24 +02:00
// * local update
const isLocalThreadUpdate = update . _ === 'updateNewDiscussionMessage' ;
2020-02-06 16:43:07 +01:00
2021-04-24 19:06:24 +02:00
// * temporary save the message for info (peerId, reply mids...)
2022-06-17 18:01:43 +02:00
this . saveMessages ( [ message ] , { storage : this.createMessageStorage ( peerId , 'history' ) } ) ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
// * check if sent message is already in storage
// const oldMessage = this.getMessageFromStorage(storage, message.mid);
// if(
// (message as Message.message).pFlags.is_outgoing &&
// oldMessage &&
// !(oldMessage as Message.message).pFlags.is_outgoing
// ) {
// this.checkPendingMessage(message);
// return;
// }
const isForum = this . appPeersManager . isForum ( peerId ) ;
2021-04-24 19:06:24 +02:00
const threadKey = this . getThreadKey ( message ) ;
const threadId = threadKey ? + threadKey . split ( '_' ) [ 1 ] : undefined ;
2023-01-06 20:27:29 +01:00
const dialog = this . dialogsStorage . getDialogOrTopic ( peerId , isLocalThreadUpdate ? threadId : undefined ) ;
if ( ( ! dialog || this . reloadConversationsPeers . has ( peerId ) ) && ! isLocalThreadUpdate ) {
let good = true ;
if ( peerId . isAnyChat ( ) ) {
good = this . appChatsManager . isInChat ( peerId . toChatId ( ) ) ;
}
if ( good ) {
this . handleNewUpdateAfterReload ( peerId , update ) ;
return ;
}
// return;
}
if ( threadId && ! isLocalThreadUpdate ) {
const threadStorage = this . threadsStorage [ peerId ] ? . [ threadId ] ;
2021-04-24 19:06:24 +02:00
const update = {
_ : 'updateNewDiscussionMessage' ,
message
} as Update . updateNewDiscussionMessage ;
2021-04-14 10:30:14 +02:00
2023-01-06 20:27:29 +01:00
if ( this . appChatsManager . isForum ( peerId . toChatId ( ) ) && ! this . dialogsStorage . getForumTopic ( peerId , threadId ) ) {
// this.dialogsStorage.getForumTopicById(peerId, threadId);
this . handleNewUpdateAfterReload ( peerId , update , threadId ) ;
} else if ( threadStorage ) {
this . onUpdateNewMessage ( update ) ;
}
2022-07-18 15:00:41 +02:00
}
2023-01-06 20:27:29 +01:00
if ( message . _ === 'messageService' ) {
const { action } = message ;
if ( action . _ === 'messageActionPaymentSent' && message . reply_to ) {
this . rootScope . dispatchEvent ( 'payment_sent' , {
peerId : message.reply_to.reply_to_peer_id ?
this . appPeersManager . getPeerId ( message . reply_to . reply_to_peer_id ) :
message . peerId ,
mid : message.reply_to_mid ,
receiptMessage : message
} ) ;
2021-04-24 19:06:24 +02:00
}
2021-04-14 10:30:14 +02:00
2023-01-06 20:27:29 +01:00
if ( action . _ === 'messageActionTopicEdit' && ! isLocalThreadUpdate ) {
const topic = this . dialogsStorage . getForumTopic ( peerId , threadId ) ;
if ( ! topic ) {
this . dialogsStorage . getForumTopicById ( peerId , threadId ) ;
} else {
const oldTopic = copy ( topic ) ;
2021-03-13 14:08:34 +01:00
2023-01-06 20:27:29 +01:00
if ( action . title !== undefined ) {
topic . title = action . title ;
}
2021-03-13 14:08:34 +01:00
2023-01-06 20:27:29 +01:00
if ( action . closed !== undefined ) {
setBooleanFlag ( topic . pFlags , 'closed' , action . closed ) ;
}
if ( action . hidden !== undefined ) {
setBooleanFlag ( topic . pFlags , 'hidden' , action . hidden ) ;
}
if ( action . icon_emoji_id !== undefined ) {
topic . icon_emoji_id = action . icon_emoji_id ;
}
this . scheduleHandleNewDialogs ( peerId , topic ) ;
this . dialogsStorage . processTopicUpdate ( topic , oldTopic ) ;
}
}
2021-04-24 19:06:24 +02:00
}
2020-02-06 16:43:07 +01:00
2021-04-24 19:06:24 +02:00
/ * i f ( u p d a t e . _ = = = ' u p d a t e N e w C h a n n e l M e s s a g e ' ) {
2021-10-21 15:16:43 +02:00
const chat = appChatsManager . getChat ( peerId . toChatId ( ) ) ;
2021-04-24 19:06:24 +02:00
if ( chat . pFlags && ( chat . pFlags . left || chat . pFlags . kicked ) ) {
return ;
}
} * /
2020-02-06 16:43:07 +01:00
2021-04-24 19:06:24 +02:00
this . saveMessages ( [ message ] , { storage } ) ;
// this.log.warn(dT(), 'message unread', message.mid, message.pFlags.unread)
2020-02-06 16:43:07 +01:00
2021-04-24 19:06:24 +02:00
/ * i f ( ( m e s s a g e a s M e s s a g e . m e s s a g e ) . g r o u p e d _ i d ) {
this . log ( 'updateNewMessage' , message ) ;
} * /
2021-03-04 22:56:04 +01:00
2023-01-06 20:27:29 +01:00
this . checkPendingMessage ( message ) ;
2021-04-24 19:06:24 +02:00
const historyStorage = this . getHistoryStorage ( peerId , isLocalThreadUpdate ? threadId : undefined ) ;
2021-04-14 10:30:14 +02:00
2021-04-24 19:06:24 +02:00
if ( ! isLocalThreadUpdate ) {
this . updateMessageRepliesIfNeeded ( message ) ;
}
2020-02-06 16:43:07 +01:00
2022-01-08 13:52:14 +01:00
// * so message can exist if reloadConversation came back earlier with mid
const ignoreExisting : boolean = ( update as any ) . ignoreExisting ;
const isExisting = ! ! historyStorage . history . findSlice ( message . mid ) ;
if ( isExisting ) {
if ( ! ignoreExisting ) {
return false ;
2021-05-06 23:26:47 +02:00
}
} else {
2022-01-08 13:52:14 +01:00
// * catch situation with disconnect. if message's id is lower than we already have (in bottom end slice), will sort it
const firstSlice = historyStorage . history . first ;
if ( firstSlice . isEnd ( SliceEnd . Bottom ) ) {
let i = 0 ;
for ( const length = firstSlice . length ; i < length ; ++ i ) {
if ( message . mid > firstSlice [ i ] ) {
break ;
}
}
2021-04-14 10:30:14 +02:00
2022-01-08 13:52:14 +01:00
firstSlice . splice ( i , 0 , message . mid ) ;
} else {
historyStorage . history . unshift ( message . mid ) ;
}
if ( historyStorage . count !== null ) {
2023-01-06 20:27:29 +01:00
++ historyStorage . count ;
2022-01-08 13:52:14 +01:00
}
2021-04-24 19:06:24 +02:00
}
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
if ( ! historyStorage . maxId || message . mid > historyStorage . maxId ) {
historyStorage . maxId = message . mid ;
}
2021-04-24 19:06:24 +02:00
if ( this . mergeReplyKeyboard ( historyStorage , message ) ) {
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'history_reply_markup' , { peerId } ) ;
2021-04-24 19:06:24 +02:00
}
2021-04-14 10:30:14 +02:00
2021-07-04 01:56:21 +02:00
const fromId = message . fromId ;
2021-10-21 15:16:43 +02:00
if ( fromId . isUser ( ) && ! message . pFlags . out && message . from_id ) {
2022-04-25 16:54:30 +02:00
this . appUsersManager . forceUserOnline ( fromId , message . date ) ;
2021-07-04 01:56:21 +02:00
const action : SendMessageAction = {
_ : 'sendMessageCancelAction'
} ;
let update : Update.updateUserTyping | Update . updateChatUserTyping | Update . updateChannelUserTyping ;
2021-10-21 15:16:43 +02:00
if ( peerId . isUser ( ) ) {
2021-07-04 01:56:21 +02:00
update = {
_ : 'updateUserTyping' ,
action ,
user_id : fromId
} ;
2022-04-25 16:54:30 +02:00
} else if ( this . appPeersManager . isChannel ( peerId ) ) {
2021-07-04 01:56:21 +02:00
update = {
_ : 'updateChannelUserTyping' ,
action ,
2021-10-21 15:16:43 +02:00
channel_id : peerId.toChatId ( ) ,
2022-04-25 16:54:30 +02:00
from_id : this.appPeersManager.getOutputPeer ( fromId ) ,
2022-06-17 18:01:43 +02:00
top_msg_id : threadId ? getServerMessageId ( threadId ) : undefined
2021-07-04 01:56:21 +02:00
} ;
} else {
update = {
_ : 'updateChatUserTyping' ,
action ,
2021-10-21 15:16:43 +02:00
chat_id : peerId.toChatId ( ) ,
2022-04-25 16:54:30 +02:00
from_id : this.appPeersManager.getOutputPeer ( fromId )
2021-07-04 01:56:21 +02:00
} ;
}
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( update ) ;
2021-04-24 19:06:24 +02:00
}
2020-05-13 17:26:40 +02:00
2022-06-17 18:01:43 +02:00
// commented to render the message if it's been sent faster than history_append came to main thread
// if(!pendingMessage) {
2022-08-04 08:49:54 +02:00
this . handleNewMessage ( message ) ;
2022-06-17 18:01:43 +02:00
// }
2021-03-08 23:15:44 +01:00
2023-01-06 20:27:29 +01:00
const isTopic = dialog ? . _ === 'forumTopic' ;
if ( ( isLocalThreadUpdate && ! isTopic ) || ! dialog ) {
2021-04-24 19:06:24 +02:00
return ;
}
2022-08-04 08:49:54 +02:00
2021-04-24 19:06:24 +02:00
const inboxUnread = ! message . pFlags . out && message . pFlags . unread ;
2023-01-06 20:27:29 +01:00
{
2022-01-08 13:52:14 +01:00
if ( inboxUnread && message . mid > dialog . top_message ) {
2021-10-21 15:16:43 +02:00
const releaseUnreadCount = this . dialogsStorage . prepareDialogUnreadCountModifying ( dialog ) ;
2021-08-24 18:33:04 +02:00
2021-10-21 15:16:43 +02:00
++ dialog . unread_count ;
2021-08-24 18:33:04 +02:00
if ( message . pFlags . mentioned ) {
++ dialog . unread_mentions_count ;
2023-01-06 20:27:29 +01:00
this . modifyCachedMentions ( peerId , message . mid , true , isTopic ? threadId : undefined ) ;
2021-08-24 18:33:04 +02:00
}
2021-10-21 15:16:43 +02:00
releaseUnreadCount ( ) ;
2021-04-24 19:06:24 +02:00
}
2021-08-24 18:33:04 +02:00
2022-01-08 13:52:14 +01:00
if ( message . mid >= dialog . top_message ) {
this . setDialogTopMessage ( message , dialog ) ;
}
2021-04-24 19:06:24 +02:00
}
2021-03-08 23:15:44 +01:00
2023-01-06 20:27:29 +01:00
if ( ( ( ! isLocalThreadUpdate && ! isForum ) || isTopic ) && inboxUnread ) {
const notifyPeer = threadKey || peerId ;
const notifyPeerToHandle = this . notificationsToHandle [ notifyPeer ] ? ? = {
fwdCount : 0 ,
fromId : NULL_PEER_ID
} ;
2021-03-08 23:15:44 +01:00
2021-07-04 01:56:21 +02:00
if ( notifyPeerToHandle . fromId !== fromId ) {
notifyPeerToHandle . fromId = fromId ;
2021-04-24 19:06:24 +02:00
notifyPeerToHandle . fwdCount = 0 ;
}
2021-03-08 23:15:44 +01:00
2021-04-24 19:06:24 +02:00
if ( ( message as Message . message ) . fwd_from ) {
2021-09-17 18:50:29 +02:00
++ notifyPeerToHandle . fwdCount ;
2020-05-13 17:26:40 +02:00
}
2021-04-24 19:06:24 +02:00
notifyPeerToHandle . topMessage = message ;
2020-05-13 17:26:40 +02:00
2023-01-06 20:27:29 +01:00
this . notificationsHandlePromise ? ? = ctx . setTimeout ( this . handleNotifications , 0 ) ;
2021-04-24 19:06:24 +02:00
}
} ;
2020-05-13 17:26:40 +02:00
2022-02-06 20:35:18 +01:00
private onUpdateMessageReactions = ( update : Update.updateMessageReactions ) = > {
const { peer , msg_id , reactions } = update ;
2022-06-17 18:01:43 +02:00
const mid = generateMessageId ( msg_id ) ;
2022-07-26 17:24:29 +02:00
const peerId = this . appPeersManager . getPeerId ( peer ) ;
2022-02-06 20:35:18 +01:00
const message : MyMessage = this . getMessageByPeer ( peerId , mid ) ;
2022-06-17 18:01:43 +02:00
if ( message ? . _ !== 'message' ) {
2022-02-06 20:35:18 +01:00
return ;
}
2022-02-08 20:18:01 +01:00
const recentReactions = reactions ? . recent_reactions ;
2022-02-22 14:04:41 +01:00
if ( recentReactions ? . length && message . pFlags . out ) {
2022-02-06 20:35:18 +01:00
const recentReaction = recentReactions [ recentReactions . length - 1 ] ;
const previousReactions = message . reactions ;
2022-02-08 20:18:01 +01:00
const previousRecentReactions = previousReactions ? . recent_reactions ;
2022-02-06 20:35:18 +01:00
if (
2022-07-26 17:24:29 +02:00
this . appPeersManager . getPeerId ( recentReaction . peer_id ) !== this . appPeersManager . peerId && (
2022-02-06 20:35:18 +01:00
! previousRecentReactions ||
previousRecentReactions . length <= recentReactions . length
) && (
2022-08-04 08:49:54 +02:00
! previousRecentReactions ||
2022-02-06 20:35:18 +01:00
! deepEqual ( recentReaction , previousRecentReactions [ previousRecentReactions . length - 1 ] )
)
) {
this . getNotifyPeerSettings ( peerId ) . then ( ( { muted , peerTypeNotifySettings } ) = > {
2022-04-14 01:29:41 +02:00
if ( /* muted || */ ! peerTypeNotifySettings . show_previews ) return ;
2022-02-06 20:35:18 +01:00
this . notifyAboutMessage ( message , {
2022-04-14 01:29:41 +02:00
peerReaction : recentReaction ,
2022-02-06 20:35:18 +01:00
peerTypeNotifySettings
} ) ;
} ) ;
}
}
2022-08-04 08:49:54 +02:00
2022-03-28 17:16:12 +02:00
const key = message . peerId + '_' + message . mid ;
this . pushBatchUpdate ( 'messages_reactions' , this . batchUpdateReactions , key , ( ) = > copy ( message . reactions ) ) ;
2022-03-28 18:49:07 +02:00
2022-03-28 17:41:14 +02:00
message . reactions = reactions ;
2022-02-06 20:35:18 +01:00
2022-02-08 20:18:01 +01:00
if ( ! update . local ) {
this . setDialogToStateIfMessageIsTop ( message ) ;
}
2022-02-06 20:35:18 +01:00
} ;
2021-04-24 19:06:24 +02:00
private onUpdateDialogUnreadMark = ( update : Update.updateDialogUnreadMark ) = > {
2022-08-04 08:49:54 +02:00
// this.log('updateDialogUnreadMark', update);
2022-07-26 17:24:29 +02:00
const peerId = this . appPeersManager . getPeerId ( ( update . peer as DialogPeer . dialogPeer ) . peer ) ;
2021-04-27 17:45:53 +02:00
const dialog = this . getDialogOnly ( peerId ) ;
2020-05-13 17:26:40 +02:00
2021-04-27 17:45:53 +02:00
if ( ! dialog ) {
this . scheduleHandleNewDialogs ( peerId ) ;
2021-04-24 19:06:24 +02:00
} else {
2021-10-21 15:16:43 +02:00
const releaseUnreadCount = this . dialogsStorage . prepareDialogUnreadCountModifying ( dialog ) ;
2021-04-24 19:06:24 +02:00
if ( ! update . pFlags . unread ) {
delete dialog . pFlags . unread_mark ;
} else {
dialog . pFlags . unread_mark = true ;
2020-02-06 16:43:07 +01:00
}
2021-10-21 15:16:43 +02:00
releaseUnreadCount ( ) ;
2021-04-28 21:43:25 +02:00
this . dialogsStorage . setDialogToState ( dialog ) ;
2023-01-06 20:27:29 +01:00
this . rootScope . dispatchEvent ( 'dialogs_multiupdate' , new Map ( [ [ peerId , { dialog } ] ] ) ) ;
2021-04-24 19:06:24 +02:00
}
} ;
2020-05-13 17:26:40 +02:00
2021-04-24 19:06:24 +02:00
private onUpdateEditMessage = ( update : Update.updateEditMessage | Update . updateEditChannelMessage ) = > {
const message = update . message as MyMessage ;
const peerId = this . getMessagePeer ( message ) ;
2022-06-17 18:01:43 +02:00
const mid = generateMessageId ( message . id ) ;
const storage = this . getHistoryMessagesStorage ( peerId ) ;
2021-10-05 22:40:07 +02:00
if ( ! storage . has ( mid ) ) {
2021-10-21 15:16:43 +02:00
// this.fixDialogUnreadMentionsIfNoMessage(peerId);
2021-04-24 19:06:24 +02:00
return ;
}
2020-12-18 04:07:32 +01:00
2021-04-24 19:06:24 +02:00
// console.trace(dT(), 'edit message', message)
2022-08-04 08:49:54 +02:00
2021-10-21 15:16:43 +02:00
const oldMessage : Message = this . getMessageFromStorage ( storage , mid ) ;
2021-04-24 19:06:24 +02:00
this . saveMessages ( [ message ] , { storage } ) ;
2021-10-21 15:16:43 +02:00
const newMessage : Message = this . getMessageFromStorage ( storage , mid ) ;
2020-02-06 16:43:07 +01:00
2022-06-17 18:01:43 +02:00
this . handleEditedMessage ( oldMessage , newMessage , storage ) ;
2020-02-06 16:43:07 +01:00
2021-04-27 17:45:53 +02:00
const dialog = this . getDialogOnly ( peerId ) ;
2021-10-21 15:16:43 +02:00
// if sender erased mention
/ * i f ( d i a l o g . u n r e a d _ m e n t i o n s _ c o u n t & & ( o l d M e s s a g e a s M e s s a g e . m e s s a g e ) ? . p F l a g s ? . m e n t i o n e d & & ! m e s s a g e . p F l a g s . m e n t i o n e d ) {
-- dialog . unread_mentions_count ;
this . modifyCachedMentions ( peerId , mid , false ) ;
} * /
2023-01-06 20:27:29 +01:00
const isTopMessage = dialog ? . top_message === mid ;
2022-01-08 13:52:14 +01:00
if ( ( message as Message . messageService ) . clear_history ) {
2021-04-24 19:06:24 +02:00
if ( isTopMessage ) {
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'dialog_flush' , { peerId , dialog } ) ;
2020-02-06 16:43:07 +01:00
}
2021-04-24 19:06:24 +02:00
} else {
2022-11-06 14:48:41 +01:00
let dispatchEditEvent = true ;
2022-02-06 20:35:18 +01:00
// no sense in dispatching message_edit since only reactions have changed
if ( oldMessage ? . _ === 'message' && ! deepEqual ( oldMessage . reactions , ( newMessage as Message . message ) . reactions ) ) {
const newReactions = ( newMessage as Message . message ) . reactions ;
( newMessage as Message . message ) . reactions = oldMessage . reactions ;
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processLocalUpdate ( {
2022-02-06 20:35:18 +01:00
_ : 'updateMessageReactions' ,
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getOutputPeer ( peerId ) ,
2022-02-06 20:35:18 +01:00
msg_id : message.id ,
reactions : newReactions
} ) ;
2022-11-06 14:48:41 +01:00
dispatchEditEvent = false ;
2022-02-06 20:35:18 +01:00
}
2022-11-06 14:48:41 +01:00
dispatchEditEvent && this . rootScope . dispatchEvent ( 'message_edit' , {
2022-06-17 18:01:43 +02:00
storageKey : storage.key ,
2021-04-24 19:06:24 +02:00
peerId ,
2022-06-17 18:01:43 +02:00
mid ,
message
2021-04-24 19:06:24 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
2022-09-25 19:49:33 +02:00
if ( isTopMessage ) {
2021-04-28 21:43:25 +02:00
this . dialogsStorage . setDialogToState ( dialog ) ;
2022-09-25 19:49:33 +02:00
}
2023-01-06 20:27:29 +01:00
const map : BroadcastEvents [ 'dialogs_multiupdate' ] = new Map ( ) ;
const getUpdateCache = ( ) = > {
let cache = map . get ( peerId ) ;
if ( ! cache ) {
map . set ( peerId , cache = { } ) ;
}
return cache ;
} ;
2022-09-25 19:49:33 +02:00
if ( ( isTopMessage || ( message as Message . message ) . grouped_id ) && dialog ) {
2023-01-06 20:27:29 +01:00
getUpdateCache ( ) . dialog = dialog ;
}
const threadKey = this . getThreadKey ( message ) ;
if ( threadKey ) {
const topicId = + threadKey . split ( '_' ) [ 1 ] ;
const topic = this . dialogsStorage . getForumTopic ( peerId , topicId ) ;
if ( topic ) {
( getUpdateCache ( ) . topics ? ? = new Map ( ) ) . set ( topicId , topic ) ;
}
}
if ( map . size ) {
this . rootScope . dispatchEvent ( 'dialogs_multiupdate' , map ) ;
2021-04-24 19:06:24 +02:00
}
}
} ;
2020-12-20 04:54:35 +01:00
2022-08-04 08:49:54 +02:00
private onUpdateReadHistory = ( update : Update.updateReadChannelDiscussionInbox | Update . updateReadChannelDiscussionOutbox
| Update . updateReadHistoryInbox | Update . updateReadHistoryOutbox
2021-04-24 19:06:24 +02:00
| Update . updateReadChannelInbox | Update . updateReadChannelOutbox ) = > {
const channelId = ( update as Update . updateReadChannelInbox ) . channel_id ;
2022-06-17 18:01:43 +02:00
const maxId = generateMessageId ( ( update as Update . updateReadChannelInbox ) . max_id || ( update as Update . updateReadChannelDiscussionInbox ) . read_max_id ) ;
const threadId = generateMessageId ( ( update as Update . updateReadChannelDiscussionInbox ) . top_msg_id ) ;
2022-07-26 17:24:29 +02:00
const peerId = channelId ? channelId . toPeerId ( true ) : this . appPeersManager . getPeerId ( ( update as Update . updateReadHistoryInbox ) . peer ) ;
2020-12-20 04:54:35 +01:00
2023-01-06 20:27:29 +01:00
const isOut = update . _ === 'updateReadHistoryOutbox' ||
update . _ === 'updateReadChannelOutbox' ||
update . _ === 'updateReadChannelDiscussionOutbox' ? true : undefined ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
const isForum = channelId ? this . appChatsManager . isForum ( channelId ) : false ;
2022-06-17 18:01:43 +02:00
const storage = this . getHistoryMessagesStorage ( peerId ) ;
2021-04-24 19:06:24 +02:00
const history = getObjectKeysAndSort ( storage , 'desc' ) ;
2023-01-06 20:27:29 +01:00
const foundDialog = threadId && isForum ?
this . dialogsStorage . getForumTopic ( peerId , threadId ) :
this . getDialogOnly ( peerId ) ;
2021-04-24 19:06:24 +02:00
const stillUnreadCount = ( update as Update . updateReadChannelInbox ) . still_unread_count ;
let newUnreadCount = 0 ;
2021-08-24 18:33:04 +02:00
let newUnreadMentionsCount = 0 ;
2021-04-24 19:06:24 +02:00
let foundAffected = false ;
2020-02-06 16:43:07 +01:00
2022-08-04 08:49:54 +02:00
// this.log.warn(dT(), 'read', peerId, isOut ? 'out' : 'in', maxId)
2020-12-20 04:54:35 +01:00
2021-04-24 19:06:24 +02:00
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
2020-02-06 16:43:07 +01:00
2021-10-21 15:16:43 +02:00
if ( peerId . isUser ( ) && isOut ) {
2023-01-06 20:27:29 +01:00
this . appUsersManager . forceUserOnline ( peerId . toUserId ( ) ) ;
2021-04-24 19:06:24 +02:00
}
2020-12-23 02:18:07 +01:00
2021-04-24 19:06:24 +02:00
if ( threadId ) {
const repliesKey = this . threadsToReplies [ peerId + '_' + threadId ] ;
if ( repliesKey ) {
2021-10-21 15:16:43 +02:00
const [ peerId , mid ] = repliesKey . split ( '_' ) ;
this . updateMessage ( peerId . toPeerId ( ) , + mid , 'replies_updated' ) ;
2021-04-24 19:06:24 +02:00
}
}
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
const releaseUnreadCount = foundDialog && this . dialogsStorage . prepareDialogUnreadCountModifying ( foundDialog ) ;
const readMaxId = this . getReadMaxIdIfUnread ( peerId , threadId ) ;
2021-10-21 15:16:43 +02:00
2021-04-24 19:06:24 +02:00
for ( let i = 0 , length = history . length ; i < length ; i ++ ) {
2021-10-05 22:40:07 +02:00
const mid = history [ i ] ;
if ( mid > maxId ) {
2021-04-24 19:06:24 +02:00
continue ;
}
2022-08-04 08:49:54 +02:00
2021-10-05 22:40:07 +02:00
const message : MyMessage = storage . get ( mid ) ;
2020-10-03 02:35:26 +02:00
2021-04-24 19:06:24 +02:00
if ( message . pFlags . out !== isOut ) {
continue ;
}
2020-12-20 04:54:35 +01:00
2023-01-06 20:27:29 +01:00
const messageThreadId = getMessageThreadId ( message , isForum ) ;
if ( threadId && messageThreadId !== threadId ) {
continue ;
2021-04-24 19:06:24 +02:00
}
2020-05-18 03:21:58 +02:00
2023-01-06 20:27:29 +01:00
const isUnread = message . pFlags . unread || ( readMaxId && readMaxId < mid ) ;
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
if ( ! isUnread ) {
break ;
}
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
// this.log.warn('read', messageId, isUnread, message)
delete message . pFlags . unread ;
foundAffected || = true ;
2021-08-24 18:33:04 +02:00
2023-01-06 20:27:29 +01:00
if ( ! message . pFlags . out && foundDialog ) {
if ( stillUnreadCount === undefined ) {
newUnreadCount = -- foundDialog . unread_count ;
2020-02-06 16:43:07 +01:00
}
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
if ( message . pFlags . mentioned ) {
newUnreadMentionsCount = -- foundDialog . unread_mentions_count ;
this . modifyCachedMentions ( peerId , message . mid , false ) ;
}
2021-04-24 19:06:24 +02:00
}
2023-01-06 20:27:29 +01:00
this . rootScope . dispatchEvent ( 'notification_cancel' , 'msg' + mid ) ;
2021-04-24 19:06:24 +02:00
}
2020-12-23 02:18:07 +01:00
2021-04-24 19:06:24 +02:00
if ( isOut ) historyStorage . readOutboxMaxId = maxId ;
else historyStorage . readMaxId = maxId ;
2020-12-23 02:18:07 +01:00
2023-01-06 20:27:29 +01:00
if ( foundDialog ) {
2021-04-24 19:06:24 +02:00
if ( isOut ) foundDialog . read_outbox_max_id = maxId ;
else foundDialog . read_inbox_max_id = maxId ;
2020-02-06 16:43:07 +01:00
2021-04-24 19:06:24 +02:00
if ( ! isOut ) {
2021-10-21 15:16:43 +02:00
let setCount : number ;
2021-08-24 18:33:04 +02:00
if ( stillUnreadCount !== undefined ) {
2021-10-21 15:16:43 +02:00
setCount = stillUnreadCount ;
2023-01-06 20:27:29 +01:00
} else if (
newUnreadCount < 0 ||
maxId >= foundDialog . top_message ||
! readMaxId
) {
2021-10-21 15:16:43 +02:00
setCount = 0 ;
2021-04-24 19:06:24 +02:00
} else if ( newUnreadCount && foundDialog . top_message > maxId ) {
2021-10-21 15:16:43 +02:00
setCount = newUnreadCount ;
}
if ( setCount !== undefined ) {
foundDialog . unread_count = setCount ;
2020-02-06 16:43:07 +01:00
}
2021-09-01 19:17:06 +02:00
2021-12-17 17:28:38 +01:00
if ( newUnreadMentionsCount < 0 || ! foundDialog . unread_count ) {
2021-09-01 19:17:06 +02:00
foundDialog . unread_mentions_count = 0 ;
}
2020-02-06 16:43:07 +01:00
}
2021-10-21 15:16:43 +02:00
2023-01-06 20:27:29 +01:00
releaseUnreadCount ? . ( ) ;
2021-10-21 15:16:43 +02:00
this . dialogsStorage . processDialogForFilters ( foundDialog ) ;
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'dialog_unread' , { peerId , dialog : foundDialog } ) ;
2021-04-28 21:43:25 +02:00
this . dialogsStorage . setDialogToState ( foundDialog ) ;
2023-01-06 20:27:29 +01:00
if ( ! foundAffected && stillUnreadCount === undefined && ! isOut && foundDialog . unread_count ) {
if ( foundDialog . _ === 'forumTopic' ) {
this . dialogsStorage . getForumTopicById ( peerId , threadId ) ;
} else {
this . reloadConversation ( peerId ) ;
}
}
2021-04-24 19:06:24 +02:00
}
2020-10-11 14:51:23 +02:00
2021-04-24 19:06:24 +02:00
if ( foundAffected ) {
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'messages_read' ) ;
2021-04-24 19:06:24 +02:00
}
2020-02-06 16:43:07 +01:00
2021-04-24 19:06:24 +02:00
if ( ! threadId && channelId ) {
const threadKeyPart = peerId + '_' ;
for ( const threadKey in this . threadsToReplies ) {
if ( threadKey . indexOf ( threadKeyPart ) === 0 ) {
2021-10-21 15:16:43 +02:00
const [ peerId , mid ] = this . threadsToReplies [ threadKey ] . split ( '_' ) ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'replies_updated' , this . getMessageByPeer ( peerId . toPeerId ( ) , + mid ) as Message . message ) ;
2020-02-06 16:43:07 +01:00
}
2021-04-24 19:06:24 +02:00
}
}
} ;
2021-04-14 10:30:14 +02:00
2021-04-24 19:06:24 +02:00
private onUpdateReadMessagesContents = ( update : Update.updateChannelReadMessagesContents | Update . updateReadMessagesContents ) = > {
const channelId = ( update as Update . updateChannelReadMessagesContents ) . channel_id ;
2023-01-06 20:27:29 +01:00
const topMsgId = ( update as Update . updateChannelReadMessagesContents ) . top_msg_id ;
const threadId = topMsgId ? generateMessageId ( topMsgId ) : undefined ;
2022-06-17 18:01:43 +02:00
const mids = ( update as Update . updateReadMessagesContents ) . messages . map ( ( id ) = > generateMessageId ( id ) ) ;
const peerId = channelId ? channelId . toPeerId ( true ) : this . findPeerIdByMids ( mids ) ;
2021-09-01 19:17:06 +02:00
for ( let i = 0 , length = mids . length ; i < length ; ++ i ) {
const mid = mids [ i ] ;
2021-08-24 18:33:04 +02:00
const message : MyMessage = this . getMessageByPeer ( peerId , mid ) ;
2022-06-17 18:01:43 +02:00
if ( message ) {
2021-10-21 15:16:43 +02:00
if ( message . pFlags . media_unread ) {
delete message . pFlags . media_unread ;
this . setDialogToStateIfMessageIsTop ( message ) ;
2022-08-04 08:49:54 +02:00
2021-10-21 15:16:43 +02:00
if ( ! message . pFlags . out && message . pFlags . mentioned ) {
2023-01-06 20:27:29 +01:00
this . modifyCachedMentions ( peerId , mid , false , threadId ) ;
2021-10-21 15:16:43 +02:00
}
2021-09-01 19:17:06 +02:00
}
2021-10-21 15:16:43 +02:00
} else {
2023-01-06 20:27:29 +01:00
this . fixDialogUnreadMentionsIfNoMessage ( peerId , threadId ) ;
2021-04-24 19:06:24 +02:00
}
}
2021-04-14 10:30:14 +02:00
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'messages_media_read' , { peerId , mids } ) ;
2021-04-24 19:06:24 +02:00
} ;
private onUpdateChannelAvailableMessages = ( update : Update.updateChannelAvailableMessages ) = > {
2021-10-21 15:16:43 +02:00
const peerId = update . channel_id . toPeerId ( true ) ;
2021-04-24 19:06:24 +02:00
const history = this . getHistoryStorage ( peerId ) . history . slice ;
2022-06-17 18:01:43 +02:00
const availableMinId = generateMessageId ( update . available_min_id ) ;
const messages = history . filter ( ( mid ) = > mid <= availableMinId ) ;
2020-12-18 04:07:32 +01:00
2021-04-24 19:06:24 +02:00
( update as any as Update . updateDeleteChannelMessages ) . messages = messages ;
this . onUpdateDeleteMessages ( update as any as Update . updateDeleteChannelMessages ) ;
} ;
2021-04-14 10:30:14 +02:00
2021-04-24 19:06:24 +02:00
private onUpdateDeleteMessages = ( update : Update.updateDeleteMessages | Update . updateDeleteChannelMessages ) = > {
2021-10-21 15:16:43 +02:00
const channelId = ( update as Update . updateDeleteChannelMessages ) . channel_id ;
2022-08-04 08:49:54 +02:00
// const messages = (update as any as Update.updateDeleteChannelMessages).messages;
2022-06-17 18:01:43 +02:00
const messages = ( update as any as Update . updateDeleteChannelMessages ) . messages . map ( ( id ) = > generateMessageId ( id ) ) ;
const peerId : PeerId = channelId ? channelId . toPeerId ( true ) : this . findPeerIdByMids ( messages ) ;
2022-08-04 08:49:54 +02:00
2021-04-24 19:06:24 +02:00
if ( ! peerId ) {
return ;
}
2020-11-07 18:47:54 +01:00
2022-06-17 18:01:43 +02:00
this . apiManager . clearCache ( 'messages.getSearchCounters' , ( params ) = > {
2022-07-26 17:24:29 +02:00
return this . appPeersManager . getPeerId ( params . peer ) === peerId ;
2021-04-24 19:06:24 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
const threadKeys : Set < string > = new Set ( ) , topics : Map < number , ForumTopic > = new Map ( ) ;
2021-04-24 19:06:24 +02:00
for ( const mid of messages ) {
const message = this . getMessageByPeer ( peerId , mid ) ;
const threadKey = this . getThreadKey ( message ) ;
2023-01-06 20:27:29 +01:00
if ( ! threadKey ) {
continue ;
}
const threadId = + threadKey . split ( '_' ) [ 1 ] ;
if ( this . threadsStorage [ peerId ] ? . [ threadId ] ) {
2021-04-24 19:06:24 +02:00
threadKeys . add ( threadKey ) ;
2023-01-06 20:27:29 +01:00
if ( ! topics . has ( threadId ) ) {
const topic = this . dialogsStorage . getForumTopic ( peerId , threadId ) ;
if ( topic ) {
topics . set ( threadId , topic ) ;
}
}
2021-04-24 19:06:24 +02:00
}
}
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
const historyUpdated = this . handleDeletedMessages (
peerId ,
this . getHistoryMessagesStorage ( peerId ) ,
messages
) ;
2020-02-06 16:43:07 +01:00
2022-06-17 18:01:43 +02:00
const threadsStorages = Array . from ( threadKeys ) . map ( ( threadKey ) = > {
2021-10-21 15:16:43 +02:00
const [ peerId , mid ] = threadKey . split ( '_' ) ;
return this . getHistoryStorage ( peerId . toPeerId ( ) , + mid ) ;
2021-04-24 19:06:24 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
const historyStorages = [
this . getHistoryStorage ( peerId ) ,
. . . threadsStorages
] ;
historyStorages . forEach ( ( historyStorage ) = > {
2021-09-17 18:50:29 +02:00
for ( const mid of historyUpdated . msgs ) {
historyStorage . history . delete ( mid ) ;
2021-04-24 19:06:24 +02:00
}
2022-08-04 08:49:54 +02:00
2021-09-17 18:50:29 +02:00
if ( historyUpdated . count && historyStorage . count ) {
historyStorage . count = Math . max ( 0 , historyStorage . count - historyUpdated . count ) ;
2020-02-06 16:43:07 +01:00
}
2021-04-24 19:06:24 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'history_delete' , { peerId , msgs : historyUpdated.msgs } ) ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
const dialogs : ( MTDialog . dialog | ForumTopic ) [ ] = [
. . . topics . values ( )
] ;
const dialog = this . getDialogOnly ( peerId ) ;
if ( dialog ) {
dialogs . unshift ( dialog ) ;
}
dialogs . forEach ( ( dialog ) = > {
const isTopic = dialog . _ === 'forumTopic' ;
2021-10-21 15:16:43 +02:00
const affected = historyUpdated . unreadMentions || historyUpdated . unread ;
2023-01-06 20:27:29 +01:00
const releaseUnreadCount = affected && this . dialogsStorage . prepareDialogUnreadCountModifying ( dialog ) ;
2022-08-04 08:49:54 +02:00
2021-04-24 19:06:24 +02:00
if ( historyUpdated . unread ) {
2023-01-06 20:27:29 +01:00
dialog . unread_count = Math . max ( 0 , dialog . unread_count - historyUpdated . unread ) ;
2021-09-17 18:50:29 +02:00
}
2020-05-06 03:03:31 +02:00
2021-12-17 17:28:38 +01:00
if ( historyUpdated . unreadMentions ) {
2023-01-06 20:27:29 +01:00
dialog . unread_mentions_count = ! dialog . unread_count ? 0 : Math.max ( 0 , dialog . unread_mentions_count - historyUpdated . unreadMentions ) ;
2021-12-17 17:28:38 +01:00
}
2021-10-21 15:16:43 +02:00
if ( affected ) {
releaseUnreadCount ( ) ;
2023-01-06 20:27:29 +01:00
if ( ! isTopic ) {
this . rootScope . dispatchEvent ( 'dialog_unread' , { peerId , dialog } ) ;
}
2021-04-24 19:06:24 +02:00
}
2020-05-06 03:03:31 +02:00
2023-01-06 20:27:29 +01:00
if ( historyUpdated . msgs . has ( dialog . top_message ) ) {
const historyStorage = this . getHistoryStorage ( dialog . peerId , isTopic ? dialog.id : undefined ) ;
2021-09-17 18:50:29 +02:00
const slice = historyStorage . history . first ;
if ( slice . isEnd ( SliceEnd . Bottom ) && slice . length ) {
const mid = slice [ 0 ] ;
const message = this . getMessageByPeer ( peerId , mid ) ;
2023-01-06 20:27:29 +01:00
this . setDialogTopMessage ( message , dialog ) ;
} else if ( isTopic ) {
this . dialogsStorage . getForumTopicById ( peerId , dialog . id ) ;
2021-09-17 18:50:29 +02:00
} else {
this . reloadConversation ( peerId ) ;
}
2020-02-06 16:43:07 +01:00
}
2023-01-06 20:27:29 +01:00
} ) ;
2021-04-24 19:06:24 +02:00
} ;
2020-02-06 16:43:07 +01:00
2021-04-24 19:06:24 +02:00
private onUpdateChannel = ( update : Update.updateChannel ) = > {
2021-10-21 15:16:43 +02:00
const channelId = update . channel_id ;
const peerId = channelId . toPeerId ( true ) ;
2023-01-06 20:27:29 +01:00
const channel = this . appChatsManager . getChat ( channelId ) as Chat . channel ;
2020-05-06 03:03:31 +02:00
2022-04-25 16:54:30 +02:00
const needDialog = this . appChatsManager . isInChat ( channelId ) ;
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
const canViewHistory = ! ! getPeerActiveUsernames ( channel ) [ 0 ] || ! channel . pFlags . left ;
2021-04-24 19:06:24 +02:00
const hasHistory = this . historiesStorage [ peerId ] !== undefined ;
2022-08-04 08:49:54 +02:00
2021-04-24 19:06:24 +02:00
if ( canViewHistory !== hasHistory ) {
delete this . historiesStorage [ peerId ] ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'history_forbidden' , peerId ) ;
2021-04-24 19:06:24 +02:00
}
2022-08-04 08:49:54 +02:00
2021-05-12 21:40:36 +02:00
const dialog = this . getDialogOnly ( peerId ) ;
2021-04-27 17:45:53 +02:00
if ( ! ! dialog !== needDialog ) {
2021-04-24 19:06:24 +02:00
if ( needDialog ) {
2021-09-17 18:50:29 +02:00
this . reloadConversation ( peerId ) ;
2021-04-24 19:06:24 +02:00
} else {
2021-11-12 18:40:13 +01:00
this . dialogsStorage . dropDialogOnDeletion ( peerId ) ;
2020-02-06 16:43:07 +01:00
}
2021-04-24 19:06:24 +02:00
}
2022-02-20 16:37:37 +01:00
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'channel_update' , channelId ) ;
2021-04-24 19:06:24 +02:00
} ;
2020-05-18 03:21:58 +02:00
2021-07-19 17:28:36 +02:00
private onUpdateChannelReload = ( update : Update.updateChannelReload ) = > {
2021-10-21 15:16:43 +02:00
const peerId = update . channel_id . toPeerId ( true ) ;
2020-06-05 18:01:06 +02:00
2023-01-06 20:27:29 +01:00
// if(this.appPeersManager.isForum(peerId)) {
// const cache = this.dialogsStorage.getForumTopicsCache(peerId);
// if(cache.topics.size) {
// }
// }
2022-08-19 21:27:29 +02:00
this . flushStoragesByPeerId ( peerId ) ;
2023-01-06 20:27:29 +01:00
Promise . all ( [
this . reloadConversation ( peerId )
] ) . then ( ( ) = > {
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'history_reload' , peerId ) ;
2021-04-24 19:06:24 +02:00
} ) ;
} ;
2022-08-04 08:49:54 +02:00
2021-04-24 19:06:24 +02:00
private onUpdateChannelMessageViews = ( update : Update.updateChannelMessageViews ) = > {
const views = update . views ;
2023-01-06 20:27:29 +01:00
const peerId = update . peerId ? ? update . channel_id . toPeerId ( true ) ;
2022-06-17 18:01:43 +02:00
const mid = generateMessageId ( update . id ) ;
const message = this . getMessageByPeer ( peerId , mid ) as Message . message ;
if ( message ? . views !== undefined && message . views < views ) {
2021-04-24 19:06:24 +02:00
message . views = views ;
2022-03-28 17:16:12 +02:00
this . pushBatchUpdate ( 'messages_views' , this . batchUpdateViews , message . peerId + '_' + message . mid ) ;
2021-10-21 15:16:43 +02:00
this . setDialogToStateIfMessageIsTop ( message ) ;
2021-04-24 19:06:24 +02:00
}
} ;
2020-12-08 20:48:44 +01:00
2021-04-24 19:06:24 +02:00
private onUpdateServiceNotification = ( update : Update.updateServiceNotification ) = > {
2022-08-04 08:49:54 +02:00
// this.log('updateServiceNotification', update);
2022-04-13 00:51:20 +02:00
if ( update . pFlags ? . popup ) {
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'service_notification' , update ) ;
2022-04-13 00:51:20 +02:00
return ;
}
2022-08-04 08:49:54 +02:00
2021-09-15 07:02:03 +02:00
const fromId = SERVICE_PEER_ID ;
2021-04-24 19:06:24 +02:00
const peerId = fromId ;
const messageId = this . generateTempMessageId ( peerId ) ;
2021-09-17 18:50:29 +02:00
const message : Message.message = {
2021-04-24 19:06:24 +02:00
_ : 'message' ,
id : messageId ,
2022-04-25 16:54:30 +02:00
from_id : this.appPeersManager.getOutputPeer ( fromId ) ,
peer_id : this.appPeersManager.getOutputPeer ( peerId ) ,
2021-04-24 19:06:24 +02:00
pFlags : { unread : true } ,
2022-06-17 18:01:43 +02:00
date : ( update . inbox_date || tsNow ( true ) ) + this . timeManager . getServerTimeOffset ( ) ,
2021-04-24 19:06:24 +02:00
message : update.message ,
media : update.media ,
entities : update.entities
} ;
2022-04-25 16:54:30 +02:00
if ( ! this . appUsersManager . hasUser ( fromId ) ) {
this . appUsersManager . saveApiUsers ( [ {
2021-04-24 19:06:24 +02:00
_ : 'user' ,
id : fromId ,
pFlags : { verified : true } ,
2021-09-17 18:50:29 +02:00
access_hash : '0' ,
2021-04-24 19:06:24 +02:00
first_name : 'Telegram' ,
phone : '42777'
} ] ) ;
}
this . saveMessages ( [ message ] , { isOutgoing : true } ) ;
if ( update . inbox_date ) {
this . pendingTopMsgs [ peerId ] = messageId ;
this . onUpdateNewMessage ( {
_ : 'updateNewMessage' ,
2021-10-21 15:16:43 +02:00
message ,
pts : undefined ,
pts_count : undefined
} ) ;
2021-04-24 19:06:24 +02:00
}
} ;
2020-11-25 20:36:18 +01:00
2021-04-24 19:06:24 +02:00
private onUpdatePinnedMessages = ( update : Update.updatePinnedMessages | Update . updatePinnedChannelMessages ) = > {
const channelId = update . _ === 'updatePinnedChannelMessages' ? update.channel_id : undefined ;
2022-07-26 17:24:29 +02:00
const peerId = channelId ? channelId . toPeerId ( true ) : this . appPeersManager . getPeerId ( ( update as Update . updatePinnedMessages ) . peer ) ;
2020-11-25 20:36:18 +01:00
2021-04-24 19:06:24 +02:00
/ * c o n s t s t o r a g e = t h i s . g e t S e a r c h S t o r a g e ( p e e r I d , ' i n p u t M e s s a g e s F i l t e r P i n n e d ' ) ;
if ( storage . count !== storage . history . length ) {
if ( storage . count !== undefined ) {
2022-08-04 08:49:54 +02:00
delete this . searchesStorage [ peerId ] [ 'inputMessagesFilterPinned' ] ;
2021-04-24 19:06:24 +02:00
}
2020-12-08 20:48:44 +01:00
2021-04-24 19:06:24 +02:00
rootScope . broadcast ( 'peer_pinned_messages' , peerId ) ;
break ;
} * /
2020-12-08 20:48:44 +01:00
2022-08-04 08:49:54 +02:00
const messages = update . messages . map ( ( id ) = > generateMessageId ( id ) ) ;
2020-12-22 00:51:28 +01:00
2022-06-17 18:01:43 +02:00
const storage = this . getHistoryMessagesStorage ( peerId ) ;
const missingMessages = messages . filter ( ( mid ) = > ! storage . has ( mid ) ) ;
2022-11-06 14:48:41 +01:00
const getMissingPromise = missingMessages . length ? Promise . all ( missingMessages . map ( ( mid ) = > this . reloadMessages ( peerId , mid ) ) ) : Promise . resolve ( ) ;
2021-04-24 19:06:24 +02:00
getMissingPromise . finally ( ( ) = > {
const werePinned = update . pFlags ? . pinned ;
if ( werePinned ) {
for ( const mid of messages ) {
2022-08-04 08:49:54 +02:00
// storage.history.push(mid);
2022-06-17 18:01:43 +02:00
const message = storage . get ( mid ) as Message . message ;
2021-04-24 19:06:24 +02:00
message . pFlags . pinned = true ;
}
2020-11-25 20:36:18 +01:00
2021-04-24 19:06:24 +02:00
/ * i f ( t h i s . p i n n e d M e s s a g e s [ p e e r I d ] ? . m a x I d ) {
const maxMid = Math . max ( . . . messages ) ;
this . pinnedMessages
} * /
2020-12-01 16:38:36 +01:00
2022-08-04 08:49:54 +02:00
// storage.history.sort((a, b) => b - a);
2021-04-24 19:06:24 +02:00
} else {
for ( const mid of messages ) {
2022-08-04 08:49:54 +02:00
// storage.history.findAndSplice((_mid) => _mid === mid);
2022-06-17 18:01:43 +02:00
const message = storage . get ( mid ) as Message . message ;
2021-04-24 19:06:24 +02:00
delete message . pFlags . pinned ;
2020-12-01 16:38:36 +01:00
}
2021-04-24 19:06:24 +02:00
}
2020-12-01 16:38:36 +01:00
2021-04-24 19:06:24 +02:00
/ * c o n s t i n f o = t h i s . p i n n e d M e s s a g e s [ p e e r I d ] ;
if ( info ) {
info . count += messages . length * ( werePinned ? 1 : - 1 ) ;
} * /
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
delete this . pinnedMessages [ this . getPinnedMessagesKey ( peerId ) ] ;
2022-06-17 18:01:43 +02:00
this . appStateManager . getState ( ) . then ( ( state ) = > {
2021-04-24 19:06:24 +02:00
delete state . hiddenPinnedMessages [ peerId ] ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'peer_pinned_messages' , { peerId , mids : messages , pinned : werePinned } ) ;
2021-04-24 19:06:24 +02:00
} ) ;
} ) ;
} ;
private onUpdateNotifySettings = ( update : Update.updateNotifySettings ) = > {
const { peer , notify_settings } = update ;
2023-01-06 20:27:29 +01:00
const isTopic = peer . _ === 'notifyForumTopic' ;
const isPeerType = peer . _ === 'notifyPeer' || isTopic ;
if ( ! isPeerType ) {
return ;
}
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
const peerId = this . appPeersManager . getPeerId ( peer . peer ) ;
const dialog = this . dialogsStorage . getDialogOrTopic ( peerId , isTopic ? generateMessageId ( peer . top_msg_id ) : undefined ) ;
if ( ! dialog ) {
return ;
2021-04-24 19:06:24 +02:00
}
2023-01-06 20:27:29 +01:00
dialog . notify_settings = notify_settings ;
this . rootScope . dispatchEvent ( 'dialog_notify_settings' , dialog ) ;
this . dialogsStorage . setDialogToState ( dialog ) ;
2021-04-24 19:06:24 +02:00
} ;
2020-12-16 04:22:58 +01:00
2021-04-24 19:06:24 +02:00
private onUpdateNewScheduledMessage = ( update : Update.updateNewScheduledMessage ) = > {
const message = update . message as MyMessage ;
const peerId = this . getMessagePeer ( message ) ;
2020-12-18 04:07:32 +01:00
2021-04-24 19:06:24 +02:00
const storage = this . scheduledMessagesStorage [ peerId ] ;
2022-06-17 18:01:43 +02:00
if ( ! storage ) {
return ;
}
2020-12-18 04:07:32 +01:00
2022-06-17 18:01:43 +02:00
const mid = generateMessageId ( message . id ) ;
2020-12-18 04:07:32 +01:00
2022-06-17 18:01:43 +02:00
const oldMessage = this . getMessageFromStorage ( storage , mid ) ;
this . saveMessages ( [ message ] , { storage , isScheduled : true } ) ;
const newMessage = this . getMessageFromStorage ( storage , mid ) ;
if ( oldMessage ) {
this . handleEditedMessage ( oldMessage , newMessage , storage ) ;
this . rootScope . dispatchEvent ( 'message_edit' , { storageKey : storage.key , peerId , mid : message.mid , message } ) ;
} else {
const pendingMessage = this . checkPendingMessage ( message ) ;
if ( ! pendingMessage ) {
2022-06-30 16:14:33 +02:00
this . rootScope . dispatchEvent ( 'scheduled_new' , message as Message . message ) ;
2020-12-16 04:22:58 +01:00
}
2021-04-24 19:06:24 +02:00
}
} ;
2020-12-16 04:22:58 +01:00
2021-04-24 19:06:24 +02:00
private onUpdateDeleteScheduledMessages = ( update : Update.updateDeleteScheduledMessages ) = > {
2022-07-26 17:24:29 +02:00
const peerId = this . appPeersManager . getPeerId ( update . peer ) ;
2020-12-16 04:22:58 +01:00
2021-04-24 19:06:24 +02:00
const storage = this . scheduledMessagesStorage [ peerId ] ;
if ( storage ) {
2022-06-17 18:01:43 +02:00
const mids = update . messages . map ( ( id ) = > generateMessageId ( id ) ) ;
2021-04-24 19:06:24 +02:00
this . handleDeletedMessages ( peerId , storage , mids ) ;
2020-12-16 04:22:58 +01:00
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'scheduled_delete' , { peerId , mids } ) ;
2020-12-01 16:38:36 +01:00
}
2021-04-24 19:06:24 +02:00
} ;
2020-12-01 16:38:36 +01:00
2022-11-06 14:48:41 +01:00
private onUpdateMessageExtendedMedia = ( update : Update.updateMessageExtendedMedia ) = > {
const peerId = this . appPeersManager . getPeerId ( update . peer ) ;
const mid = generateMessageId ( update . msg_id ) ;
const storage = this . getHistoryMessagesStorage ( peerId ) ;
if ( ! storage . has ( mid ) ) {
// this.fixDialogUnreadMentionsIfNoMessage(peerId);
return ;
}
const message = this . getMessageFromStorage ( storage , mid ) as Message . message ;
const messageMedia = message . media as MessageMedia . messageMediaInvoice ;
if ( messageMedia . extended_media ? . _ === 'messageExtendedMedia' ) {
return ;
}
messageMedia . extended_media = update . extended_media ;
this . onUpdateEditMessage ( {
_ : 'updateEditMessage' ,
message ,
pts : 0 ,
pts_count : 0
} ) ;
} ;
2023-02-09 14:23:04 +01:00
private onUpdateTranscribedAudio = ( update : Update.updateTranscribedAudio ) = > {
const peerId = this . appPeersManager . getPeerId ( update . peer ) ;
const text = update . text ;
const mid = generateMessageId ( update . msg_id ) ;
2023-02-20 20:39:43 +01:00
this . rootScope . dispatchEvent ( 'message_transcribed' , { peerId , mid , text , pending : update.pFlags.pending } ) ;
2023-02-09 14:23:04 +01:00
} ;
2021-09-17 18:50:29 +02:00
public setDialogToStateIfMessageIsTop ( message : MyMessage ) {
2021-10-29 01:43:00 +02:00
if ( this . isMessageIsTopMessage ( message ) ) {
this . dialogsStorage . setDialogToState ( this . getDialogOnly ( message . peerId ) ) ;
2021-04-28 21:43:25 +02:00
}
}
2021-10-29 01:43:00 +02:00
public isMessageIsTopMessage ( message : MyMessage ) {
const dialog = this . getDialogOnly ( message . peerId ) ;
return dialog && dialog . top_message === message . mid ;
}
2020-12-22 04:02:30 +01:00
private updateMessageRepliesIfNeeded ( threadMessage : MyMessage ) {
try { // * на всякий случай, скорее всего это не понадобится
2021-04-14 10:30:14 +02:00
const threadKey = this . getThreadKey ( threadMessage ) ;
if ( threadKey ) {
2020-12-22 04:02:30 +01:00
const repliesKey = this . threadsToReplies [ threadKey ] ;
if ( repliesKey ) {
2021-10-21 15:16:43 +02:00
const [ peerId , mid ] = repliesKey . split ( '_' ) ;
2020-12-22 04:02:30 +01:00
2021-10-21 15:16:43 +02:00
this . updateMessage ( peerId . toPeerId ( ) , + mid , 'replies_updated' ) ;
2020-12-22 04:02:30 +01:00
}
}
} catch ( err ) {
this . log . error ( 'incrementMessageReplies err' , err , threadMessage ) ;
}
}
2021-04-14 10:30:14 +02:00
private getThreadKey ( threadMessage : MyMessage ) {
let threadKey = '' ;
2023-01-06 20:27:29 +01:00
if ( threadMessage ? . peerId ? . isAnyChat ( ) ) {
const threadId = getMessageThreadId ( threadMessage , this . appChatsManager . isForum ( threadMessage . peerId . toChatId ( ) ) ) ;
if ( threadId ) {
threadKey = threadMessage . peerId + '_' + threadId ;
}
2021-04-14 10:30:14 +02:00
}
return threadKey ;
}
2021-10-21 15:16:43 +02:00
public updateMessage ( peerId : PeerId , mid : number , broadcastEventName ? : 'replies_updated' ) : Promise < Message.message > {
2022-11-06 14:48:41 +01:00
const promise : Promise < Message.message > = this . reloadMessages ( peerId , mid , true ) . then ( ( ) = > {
2022-06-17 18:01:43 +02:00
const message = this . getMessageByPeer ( peerId , mid ) as Message . message ;
if ( ! message ) {
return ;
}
2020-12-22 04:02:30 +01:00
if ( broadcastEventName ) {
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( broadcastEventName , message ) ;
2020-12-22 04:02:30 +01:00
}
return message ;
} ) ;
2022-08-04 08:49:54 +02:00
2020-12-22 04:02:30 +01:00
return promise ;
}
2021-09-17 18:50:29 +02:00
private checkPendingMessage ( message : MyMessage ) {
2020-12-18 04:07:32 +01:00
const randomId = this . pendingByMessageId [ message . mid ] ;
2021-09-17 18:50:29 +02:00
let pendingMessage : ReturnType < AppMessagesManager [ ' finalizePendingMessage ' ] > ;
2020-12-18 04:07:32 +01:00
if ( randomId ) {
const pendingData = this . pendingByRandomId [ randomId ] ;
if ( pendingMessage = this . finalizePendingMessage ( randomId , message ) ) {
2023-01-06 20:27:29 +01:00
this . rootScope . dispatchEvent ( 'history_update' , {
storageKey : pendingData.storage.key ,
message ,
sequential : pendingData.sequential
} ) ;
2020-12-18 04:07:32 +01:00
}
delete this . pendingByMessageId [ message . mid ] ;
}
return pendingMessage ;
}
2023-01-06 20:27:29 +01:00
public mutePeer ( options : { peerId : PeerId , muteUntil : number , threadId? : number } ) {
if ( ! ( options = this . appNotificationsManager . validatePeerSettings ( options ) ) ) {
return ;
}
const { peerId , muteUntil , threadId } = options ;
2021-03-08 23:15:44 +01:00
const settings : InputPeerNotifySettings = {
2020-12-01 16:38:36 +01:00
_ : 'inputPeerNotifySettings'
} ;
2022-01-26 14:19:23 +01:00
settings . mute_until = muteUntil ;
2021-03-08 23:15:44 +01:00
2023-01-06 20:27:29 +01:00
const peer = this . appPeersManager . getInputPeerById ( peerId ) ;
return this . appNotificationsManager . updateNotifySettings ( threadId ? {
_ : 'inputNotifyForumTopic' ,
peer ,
top_msg_id : getServerMessageId ( threadId )
} : {
2021-03-08 23:15:44 +01:00
_ : 'inputNotifyPeer' ,
2023-01-06 20:27:29 +01:00
peer
2021-03-08 23:15:44 +01:00
} , settings ) ;
2020-12-01 16:38:36 +01:00
}
2023-01-06 20:27:29 +01:00
public togglePeerMute ( { peerId , mute , threadId } : { peerId : PeerId , mute? : boolean , threadId? : number } ) {
2022-01-26 14:19:23 +01:00
if ( mute === undefined ) {
2023-01-06 20:27:29 +01:00
mute = ! this . appNotificationsManager . isPeerLocalMuted ( { peerId , respectType : false , threadId } ) ;
2022-01-26 14:19:23 +01:00
}
2023-01-06 20:27:29 +01:00
return this . mutePeer ( { peerId , muteUntil : mute ? MUTE_UNTIL : 0 , threadId } ) ;
2022-01-26 14:19:23 +01:00
}
2022-06-17 18:01:43 +02:00
private findPeerIdByMids ( mids : number [ ] ) {
for ( let length = mids . length , i = length - 1 ; i >= 0 ; -- i ) {
const mid = mids [ i ] ;
const message = this . getMessageById ( mid ) ;
if ( message ) {
return message . peerId ;
}
}
}
2021-10-21 15:16:43 +02:00
public canSendToPeer ( peerId : PeerId , threadId? : number , action : ChatRights = 'send_messages' ) {
2023-01-06 20:27:29 +01:00
if ( this . appPeersManager . isPeerRestricted ( peerId ) ) {
2022-02-11 23:17:35 +01:00
return false ;
}
2022-08-04 08:49:54 +02:00
2021-10-21 15:16:43 +02:00
if ( peerId . isAnyChat ( ) ) {
2023-01-06 20:27:29 +01:00
const chatId = peerId . toChatId ( ) ;
if ( threadId ) {
const topic = this . dialogsStorage . getForumTopic ( peerId , threadId ) ;
if ( topic ? . pFlags ? . closed && ! this . appChatsManager . hasRights ( chatId , 'manage_topics' ) ) {
return false ;
}
}
2022-08-04 08:49:54 +02:00
// const isChannel = appPeersManager.isChannel(peerId);
2023-01-06 20:27:29 +01:00
const chat = this . appChatsManager . getChat ( chatId ) as Chat . chat ;
const hasRights = /* isChannel && */ this . appChatsManager . hasRights ( chatId , action , undefined , ! ! threadId ) ;
2021-09-19 13:09:31 +02:00
return /* !isChannel || */ hasRights && ( ! chat . pFlags . left || ! ! threadId ) ;
2020-12-23 02:18:07 +01:00
} else {
2022-04-25 16:54:30 +02:00
return this . appUsersManager . canSendToUser ( peerId ) ;
2020-12-23 02:18:07 +01:00
}
2020-02-06 16:43:07 +01:00
}
2021-10-21 15:16:43 +02:00
public finalizePendingMessage ( randomId : Long , finalMessage : MyMessage ) {
2020-12-11 17:46:44 +01:00
const pendingData = this . pendingByRandomId [ randomId ] ;
2023-01-06 20:27:29 +01:00
if ( ! pendingData ) {
return ;
}
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
const { peerId , tempId , threadId , storage } = pendingData ;
2021-04-14 10:30:14 +02:00
2023-01-06 20:27:29 +01:00
[
this . getHistoryStorage ( peerId ) ,
threadId ? this . getHistoryStorage ( peerId , threadId ) : undefined
]
. filter ( Boolean )
. forEach ( ( storage ) = > {
storage . history . delete ( tempId ) ;
} ) ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
// this.log('pending', randomID, historyStorage.pending)
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
const tempMessage : MyMessage = this . getMessageFromStorage ( storage , tempId ) ;
if ( tempMessage ) {
delete finalMessage . pFlags . is_outgoing ;
delete finalMessage . pending ;
delete finalMessage . error ;
delete finalMessage . random_id ;
delete finalMessage . send ;
}
2021-10-21 15:16:43 +02:00
2023-01-06 20:27:29 +01:00
this . rootScope . dispatchEvent ( 'messages_pending' ) ;
2022-08-04 08:49:54 +02:00
2023-01-06 20:27:29 +01:00
delete this . pendingByRandomId [ randomId ] ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
this . finalizePendingMessageCallbacks ( storage , tempId , finalMessage ) ;
2020-02-06 16:43:07 +01:00
2023-01-06 20:27:29 +01:00
return tempMessage ;
2020-02-06 16:43:07 +01:00
}
2021-10-21 15:16:43 +02:00
public finalizePendingMessageCallbacks ( storage : MessagesStorage , tempId : number , message : MyMessage ) {
2020-12-11 03:06:16 +01:00
const callbacks = this . tempFinalizeCallbacks [ tempId ] ;
2022-08-04 08:49:54 +02:00
// this.log.warn(callbacks, tempId);
2020-02-14 17:15:41 +01:00
if ( callbacks !== undefined ) {
2020-10-13 15:51:11 +02:00
for ( const name in callbacks ) {
const { deferred , callback } = callbacks [ name ] ;
2022-08-04 08:49:54 +02:00
// this.log(`finalizePendingMessageCallbacks: will invoke ${name} callback`);
2020-12-18 04:07:32 +01:00
callback ( message ) . then ( deferred . resolve , deferred . reject ) ;
2020-10-13 15:51:11 +02:00
}
2020-12-11 03:06:16 +01:00
delete this . tempFinalizeCallbacks [ tempId ] ;
2020-02-14 17:15:41 +01:00
}
2020-12-01 16:38:36 +01:00
// set cached url to media
2021-10-29 17:56:57 +02:00
if ( ( message as Message . message ) . media ) {
assumeType < Message.message > ( message ) ;
2021-10-05 22:40:07 +02:00
const { photo : newPhoto , document : newDoc } = message . media as any ;
if ( newPhoto ) {
2022-04-25 16:54:30 +02:00
const photo = this . appPhotosManager . getPhoto ( '' + tempId ) ;
2021-02-04 01:30:23 +01:00
if ( /* photo._ !== 'photoEmpty' */ photo ) {
2021-05-25 18:11:58 +02:00
const newPhotoSize = newPhoto . sizes [ newPhoto . sizes . length - 1 ] ;
2022-06-17 18:01:43 +02:00
const cacheContext = this . thumbsStorage . getCacheContext ( newPhoto , newPhotoSize . type ) ;
2022-08-28 18:50:04 +02:00
const oldCacheContext = this . thumbsStorage . getCacheContext ( photo , THUMB_TYPE_FULL ) ;
2021-05-01 20:49:32 +02:00
Object . assign ( cacheContext , oldCacheContext ) ;
2021-02-06 13:44:48 +01:00
const photoSize = newPhoto . sizes [ newPhoto . sizes . length - 1 ] as PhotoSize . photoSize ;
2022-04-25 16:54:30 +02:00
const downloadOptions = getPhotoDownloadOptions ( newPhoto , photoSize ) ;
2021-02-06 13:44:48 +01:00
const fileName = getFileNameByLocation ( downloadOptions . location ) ;
2022-06-17 18:01:43 +02:00
// this.appDownloadManager.fakeDownload(fileName, oldCacheContext.url);
2020-12-01 16:38:36 +01:00
}
2021-10-05 22:40:07 +02:00
} else if ( newDoc ) {
2022-04-25 16:54:30 +02:00
const oldDoc = this . appDocsManager . getDoc ( '' + tempId ) ;
2022-04-03 21:42:12 +02:00
if ( oldDoc ) {
2022-06-17 18:01:43 +02:00
const oldCacheContext = this . thumbsStorage . getCacheContext ( oldDoc ) ;
2022-04-03 21:42:12 +02:00
if (
/* doc._ !== 'documentEmpty' && */
2022-08-04 08:49:54 +02:00
oldDoc . type &&
oldDoc . type !== 'sticker' &&
oldDoc . mime_type !== 'image/gif' &&
2022-04-03 21:42:12 +02:00
oldCacheContext . url
) {
2022-06-17 18:01:43 +02:00
const cacheContext = this . thumbsStorage . getCacheContext ( newDoc ) ;
2021-05-01 20:49:32 +02:00
Object . assign ( cacheContext , oldCacheContext ) ;
2021-02-06 13:44:48 +01:00
2022-06-17 18:01:43 +02:00
const fileName = getDocumentInputFileName ( newDoc ) ;
// this.appDownloadManager.fakeDownload(fileName, oldCacheContext.url);
2021-02-06 13:44:48 +01:00
}
2020-12-01 16:38:36 +01:00
}
2021-10-05 22:40:07 +02:00
} else if ( ( message . media as MessageMedia . messageMediaPoll ) . poll ) {
2022-04-25 16:54:30 +02:00
delete this . appPollsManager . polls [ tempId ] ;
delete this . appPollsManager . results [ tempId ] ;
2020-12-01 16:38:36 +01:00
}
}
2020-12-18 04:07:32 +01:00
const tempMessage = this . getMessageFromStorage ( storage , tempId ) ;
2021-10-05 22:40:07 +02:00
storage . delete ( tempId ) ;
2022-07-18 15:00:41 +02:00
if ( ! ( tempMessage as Message . message ) . reply_markup && ( message as Message . message ) . reply_markup ) {
setTimeout ( ( ) = > { // TODO: refactor it to normal buttons adding
if ( ! this . getMessageFromStorage ( storage , message . mid ) ) {
return ;
}
this . rootScope . dispatchEvent ( 'message_edit' , { storageKey : storage.key , peerId : message.peerId , mid : message.mid , message } ) ;
} , 0 ) ;
}
2022-08-04 08:49:54 +02:00
2021-08-03 03:44:13 +02:00
this . handleReleasingMessage ( tempMessage , storage ) ;
2020-12-18 04:07:32 +01:00
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'message_sent' , { storageKey : storage.key , tempId , tempMessage , mid : message.mid , message } ) ;
2020-02-06 16:43:07 +01:00
}
2020-12-11 03:06:16 +01:00
public incrementMaxSeenId ( maxId : number ) {
if ( ! maxId || ! ( ! this . maxSeenId || maxId > this . maxSeenId ) ) {
2020-02-06 16:43:07 +01:00
return false ;
}
2020-12-11 03:06:16 +01:00
this . maxSeenId = maxId ;
2022-06-17 18:01:43 +02:00
this . appStateManager . pushToState ( 'maxSeenMsgId' , maxId ) ;
2020-09-20 00:38:00 +02:00
2022-06-17 18:01:43 +02:00
this . apiManager . invokeApi ( 'messages.receivedMessages' , {
max_id : getServerMessageId ( maxId )
2020-02-06 16:43:07 +01:00
} ) ;
}
2022-06-17 18:01:43 +02:00
public async getMessageReactionsListAndReadParticipants (
2022-08-04 08:49:54 +02:00
message : Message.message ,
limit? : number ,
2022-09-20 19:34:08 +02:00
reaction? : Reaction ,
2022-02-08 20:18:01 +01:00
offset? : string ,
skipReadParticipants? : boolean ,
skipReactionsList? : boolean
2022-02-06 20:35:18 +01:00
) {
const emptyMessageReactionsList = {
2022-02-08 20:32:02 +01:00
reactions : [ ] as MessagePeerReaction [ ] ,
2022-02-06 20:35:18 +01:00
count : 0 ,
next_offset : undefined as string
} ;
2022-06-17 18:01:43 +02:00
const canViewMessageReadParticipants = await this . canViewMessageReadParticipants ( message ) ;
2022-02-06 20:35:18 +01:00
if ( canViewMessageReadParticipants && limit === undefined ) {
limit = 100 ;
} else if ( limit === undefined ) {
limit = 50 ;
}
return Promise . all ( [
2022-02-08 20:18:01 +01:00
canViewMessageReadParticipants && ! reaction && ! skipReadParticipants ? this . getMessageReadParticipants ( message . peerId , message . mid ) . catch ( ( ) = > [ ] as UserId [ ] ) : [ ] as UserId [ ] ,
2022-02-06 20:35:18 +01:00
2022-06-17 18:01:43 +02:00
message . reactions ? . recent_reactions ? . length && ! skipReactionsList ? this . appReactionsManager . getMessageReactionsList ( message . peerId , message . mid , limit , reaction , offset ) . catch ( ( err ) = > emptyMessageReactionsList ) : emptyMessageReactionsList
2022-02-06 20:35:18 +01:00
] ) . then ( ( [ userIds , messageReactionsList ] ) = > {
2022-06-17 18:01:43 +02:00
const readParticipantsPeerIds = userIds . map ( ( userId ) = > userId . toPeerId ( ) ) ;
2022-08-04 08:49:54 +02:00
2022-02-06 20:35:18 +01:00
const filteredReadParticipants = readParticipantsPeerIds . slice ( ) ;
forEachReverse ( filteredReadParticipants , ( peerId , idx , arr ) = > {
2022-07-26 17:24:29 +02:00
if ( messageReactionsList . reactions . some ( ( reaction ) = > this . appPeersManager . getPeerId ( reaction . peer_id ) === peerId ) ) {
2022-02-06 20:35:18 +01:00
arr . splice ( idx , 1 ) ;
}
} ) ;
2022-09-20 19:34:08 +02:00
let combined : { peerId : PeerId , reaction? : Reaction } [ ] = messageReactionsList . reactions . map ( ( reaction ) = > ( { peerId : this.appPeersManager.getPeerId ( reaction . peer_id ) , reaction : reaction.reaction } ) ) ;
2022-06-17 18:01:43 +02:00
combined = combined . concat ( filteredReadParticipants . map ( ( readPeerId ) = > ( { peerId : readPeerId } ) ) ) ;
2022-08-04 08:49:54 +02:00
2022-02-06 20:35:18 +01:00
return {
reactions : messageReactionsList.reactions ,
2022-02-08 20:18:01 +01:00
reactionsCount : messageReactionsList.count ,
2022-02-06 20:35:18 +01:00
readParticipants : readParticipantsPeerIds ,
combined : combined ,
nextOffset : messageReactionsList.next_offset
} ;
} ) ;
}
public getMessageReadParticipants ( peerId : PeerId , mid : number ) : Promise < UserId [ ] > {
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApiSingle ( 'messages.getMessageReadParticipants' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
msg_id : getServerMessageId ( mid )
} ) . then ( ( userIds ) = > { // ! convert long to number
return userIds . map ( ( userId ) = > userId . toUserId ( ) ) ;
2022-02-06 20:35:18 +01:00
} ) ;
}
2022-06-17 18:01:43 +02:00
public async canViewMessageReadParticipants ( message : Message ) {
2022-02-06 20:35:18 +01:00
if (
2022-08-04 08:49:54 +02:00
message ? . _ !== 'message' ||
message . pFlags . is_outgoing ||
! message . pFlags . out ||
2022-04-25 16:54:30 +02:00
! this . appPeersManager . isAnyGroup ( message . peerId )
2022-02-06 20:35:18 +01:00
) {
return false ;
}
2023-01-06 20:27:29 +01:00
const chat = this . appChatsManager . getChat ( message . peerId . toChatId ( ) ) as Chat . chat | Chat . channel ;
2022-08-04 08:49:54 +02:00
const appConfig = await this . apiManager . getAppConfig ( ) ;
return chat . participants_count <= appConfig . chat_read_mark_size_threshold &&
2022-06-17 18:01:43 +02:00
( tsNow ( true ) - message . date ) < appConfig . chat_read_mark_expire_period ;
2022-02-06 20:35:18 +01:00
}
2021-10-21 15:16:43 +02:00
public incrementMessageViews ( peerId : PeerId , mids : number [ ] ) {
2021-08-10 18:52:12 +02:00
if ( ! mids . length ) {
return ;
}
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApiSingle ( 'messages.getMessagesViews' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
id : mids.map ( ( mid ) = > getServerMessageId ( mid ) ) ,
2021-08-10 18:52:12 +02:00
increment : true
2022-06-17 18:01:43 +02:00
} ) . then ( ( views ) = > {
2021-08-10 18:52:12 +02:00
const updates : Update [ ] = new Array ( mids . length ) ;
for ( let i = 0 , length = mids . length ; i < length ; ++ i ) {
updates [ i ] = {
_ : 'updateChannelMessageViews' ,
2023-01-06 20:27:29 +01:00
channel_id : NULL_PEER_ID ,
peerId ,
2021-08-10 18:52:12 +02:00
id : mids [ i ] ,
views : views.views [ i ] . views
} ;
}
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( {
2021-08-10 18:52:12 +02:00
_ : 'updates' ,
updates ,
chats : views.chats ,
users : views.users
} ) ;
} ) ;
}
2021-03-08 23:15:44 +01:00
private notifyAboutMessage ( message : MyMessage , options : Partial < {
fwdCount : number ,
2022-04-14 01:29:41 +02:00
peerReaction : MessagePeerReaction ,
2021-03-08 23:15:44 +01:00
peerTypeNotifySettings : PeerNotifySettings
} > = { } ) {
const peerId = this . getMessagePeer ( message ) ;
2022-02-11 23:17:35 +01:00
2023-01-06 20:27:29 +01:00
if ( this . appPeersManager . isPeerRestricted ( peerId ) ) {
2022-02-11 23:17:35 +01:00
return ;
}
2022-06-24 19:23:12 +02:00
const tabs = appTabsManager . getTabs ( ) ;
let tab = tabs . find ( ( tab ) = > {
const { chatPeerIds } = tab . state ;
return chatPeerIds [ chatPeerIds . length - 1 ] === peerId ;
} ) ;
2023-01-25 15:21:38 +01:00
if ( ! tab && tabs . length ) {
2022-06-24 19:23:12 +02:00
tabs . sort ( ( a , b ) = > a . state . idleStartTime - b . state . idleStartTime ) ;
tab = ! tabs [ 0 ] . state . idleStartTime ? tabs [ 0 ] : tabs [ tabs . length - 1 ] ;
}
const port = MTProtoMessagePort . getInstance < false > ( ) ;
port . invokeVoid ( 'notificationBuild' , {
2022-04-25 16:54:30 +02:00
message ,
. . . options
2023-01-25 15:21:38 +01:00
} , tab ? . source ) ;
2021-03-08 23:15:44 +01:00
}
2021-10-21 15:16:43 +02:00
public getScheduledMessagesStorage ( peerId : PeerId ) {
2023-01-06 20:27:29 +01:00
return this . scheduledMessagesStorage [ peerId ] ? ? = this . createMessageStorage ( peerId , 'scheduled' ) ;
2020-12-16 04:22:58 +01:00
}
2021-10-21 15:16:43 +02:00
public getScheduledMessageByPeer ( peerId : PeerId , mid : number ) {
2021-10-05 22:40:07 +02:00
return this . getMessageFromStorage ( this . getScheduledMessagesStorage ( peerId ) , mid ) ;
}
2022-06-17 18:01:43 +02:00
public getScheduledMessages ( peerId : PeerId ) {
if ( ! this . canSendToPeer ( peerId ) ) return ;
2020-12-16 04:22:58 +01:00
2020-12-18 04:07:32 +01:00
const storage = this . getScheduledMessagesStorage ( peerId ) ;
2021-10-05 22:40:07 +02:00
if ( storage . size ) {
2022-06-17 18:01:43 +02:00
return [ . . . storage . keys ( ) ] ;
2020-12-16 04:22:58 +01:00
}
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApiSingle ( 'messages.getScheduledHistory' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2021-10-21 15:16:43 +02:00
hash : ''
2022-06-17 18:01:43 +02:00
} ) . then ( ( historyResult ) = > {
2020-12-16 04:22:58 +01:00
if ( historyResult . _ !== 'messages.messagesNotModified' ) {
2022-04-25 16:54:30 +02:00
this . appUsersManager . saveApiUsers ( historyResult . users ) ;
this . appChatsManager . saveApiChats ( historyResult . chats ) ;
2022-08-04 08:49:54 +02:00
2020-12-16 04:22:58 +01:00
const storage = this . getScheduledMessagesStorage ( peerId ) ;
this . saveMessages ( historyResult . messages , { storage , isScheduled : true } ) ;
2021-10-05 22:40:07 +02:00
return [ . . . storage . keys ( ) ] ;
2020-12-16 04:22:58 +01:00
}
2022-08-04 08:49:54 +02:00
2020-12-16 04:22:58 +01:00
return [ ] ;
} ) ;
}
2021-10-21 15:16:43 +02:00
public sendScheduledMessages ( peerId : PeerId , mids : number [ ] ) {
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.sendScheduledMessages' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
id : mids.map ( ( mid ) = > getServerMessageId ( mid ) )
} ) . then ( ( updates ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2020-12-18 04:07:32 +01:00
} ) ;
}
2021-10-21 15:16:43 +02:00
public deleteScheduledMessages ( peerId : PeerId , mids : number [ ] ) {
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.deleteScheduledMessages' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
id : mids.map ( ( mid ) = > getServerMessageId ( mid ) )
} ) . then ( ( updates ) = > {
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
2020-12-18 04:07:32 +01:00
} ) ;
}
2021-05-14 21:04:19 +02:00
public getMessageWithReplies ( message : Message.message ) {
2022-06-30 16:14:33 +02:00
return this . filterMessages ( message , ( message ) = > ! ! ( message as Message . message ) . replies ) [ 0 ] as any ;
2022-06-17 18:01:43 +02:00
}
public getMessageWithCommentReplies ( message : Message.message ) {
2021-05-14 21:04:19 +02:00
if ( message . peerId !== REPLIES_PEER_ID ) {
2022-06-17 18:01:43 +02:00
message = this . getMessageWithReplies ( message ) ;
const replies = message ? . replies ;
if ( ! ( replies && replies . pFlags . comments && replies . channel_id . toChatId ( ) !== REPLIES_HIDDEN_CHANNEL_ID ) ) {
2021-05-14 21:04:19 +02:00
return ;
}
}
return message ;
}
2021-10-21 15:16:43 +02:00
public isFetchIntervalNeeded ( peerId : PeerId ) {
2023-01-06 20:27:29 +01:00
return peerId . isAnyChat ( ) && (
! this . appChatsManager . isInChat ( peerId . toChatId ( ) ) ||
this . appChatsManager . isForum ( peerId . toChatId ( ) )
) ;
2022-02-11 23:17:35 +01:00
}
2021-10-21 15:16:43 +02:00
public async getNewHistory ( peerId : PeerId , threadId? : number ) {
2021-05-06 23:02:21 +02:00
if ( ! this . isFetchIntervalNeeded ( peerId ) ) {
return ;
}
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
const slice = historyStorage . history . slice ;
if ( ! slice . isEnd ( SliceEnd . Bottom ) ) {
return ;
}
delete historyStorage . maxId ;
slice . unsetEnd ( SliceEnd . Bottom ) ;
2021-05-25 12:45:35 +02:00
// if there is no id - then request by first id because cannot request by id 0 with backLimit
2022-06-17 18:01:43 +02:00
const historyResult = await this . getHistory ( peerId , slice [ 0 ] ? ? 1 , 0 , 50 , threadId ) ;
2021-05-06 23:02:21 +02:00
for ( let i = 0 , length = historyResult . history . length ; i < length ; ++ i ) {
2022-06-30 16:14:33 +02:00
this . handleNewMessage ( this . getMessageByPeer ( peerId , historyResult . history [ i ] ) ) ;
2021-05-06 23:02:21 +02:00
}
2022-06-17 18:01:43 +02:00
return { isBottomEnd : historyStorage.history.slice.isEnd ( SliceEnd . Bottom ) } ;
2021-05-06 23:02:21 +02:00
}
2021-02-23 16:20:52 +01:00
/ * *
* * https : //core.telegram.org/api/offsets, offset_id is inclusive
* /
2022-06-17 18:01:43 +02:00
// public getHistory(peerId: PeerId, maxId?: number, limit?: number, backLimit?: number, threadId?: number, onlyCache?: false): Promise<HistoryResult> | HistoryResult;
// public getHistory(peerId: PeerId, maxId?: number, limit?: number, backLimit?: number, threadId?: number, onlyCache?: true): HistoryResult;
public getHistory ( peerId : PeerId , maxId : number = 0 , limit? : number , backLimit? : number , threadId? : number /* , onlyCache?: boolean */ ) : Promise < HistoryResult > | HistoryResult {
2020-12-20 04:54:35 +01:00
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
2020-05-26 17:04:06 +02:00
2023-01-06 20:27:29 +01:00
if ( this . appPeersManager . isPeerRestricted ( peerId ) ) {
2022-02-11 23:17:35 +01:00
const first = historyStorage . history . first ;
first . setEnd ( SliceEnd . Both ) ;
const slice = first . slice ( 0 , 0 ) ;
slice . setEnd ( SliceEnd . Both ) ;
2022-08-04 08:49:54 +02:00
2022-02-11 23:17:35 +01:00
return {
count : 0 ,
2022-06-17 18:01:43 +02:00
history : Array.from ( slice ) ,
isEnd : slice.getEnds ( ) ,
2022-02-11 23:17:35 +01:00
offsetIdOffset : 0
} ;
}
2020-05-26 17:04:06 +02:00
let offset = 0 ;
2022-08-04 08:49:54 +02:00
/ *
2021-02-23 16:20:52 +01:00
let offsetFound = true ;
2020-02-06 16:43:07 +01:00
2020-12-22 09:18:42 +01:00
if ( maxId ) {
2021-02-23 16:20:52 +01:00
offsetFound = false ;
2020-05-26 17:04:06 +02:00
for ( ; offset < historyStorage . history . length ; offset ++ ) {
2021-02-23 16:20:52 +01:00
if ( maxId > historyStorage . history . slice [ offset ] ) {
offsetFound = true ;
2020-02-06 16:43:07 +01:00
break ;
}
}
}
2021-02-23 16:20:52 +01:00
if ( offsetFound && (
2021-02-04 01:30:23 +01:00
historyStorage . count !== null && historyStorage . history . length === historyStorage . count ||
2020-05-13 17:26:40 +02:00
historyStorage . history . length >= offset + limit
2020-02-06 16:43:07 +01:00
) ) {
if ( backLimit ) {
backLimit = Math . min ( offset , backLimit ) ;
offset = Math . max ( 0 , offset - backLimit ) ;
limit += backLimit ;
} else {
2020-05-10 03:23:21 +02:00
limit = limit ;
2020-02-06 16:43:07 +01:00
}
2020-04-14 17:46:31 +02:00
2021-02-23 16:20:52 +01:00
const history = historyStorage . history . slice . slice ( offset , offset + limit ) ;
2020-12-22 09:18:42 +01:00
return {
2020-02-06 16:43:07 +01:00
count : historyStorage.count ,
history : history ,
2020-12-22 09:18:42 +01:00
offsetIdOffset : offset
} ;
2020-02-06 16:43:07 +01:00
}
2021-02-23 16:20:52 +01:00
if ( offsetFound ) {
2020-02-06 16:43:07 +01:00
offset = 0 ;
2021-02-23 16:20:52 +01:00
} * /
if ( backLimit ) {
offset = - backLimit ;
limit += backLimit ;
2020-02-06 16:43:07 +01:00
2021-02-23 16:20:52 +01:00
/ * r e t u r n t h i s . r e q u e s t H i s t o r y ( r e q P e e r I d , m a x I d , l i m i t , o f f s e t , u n d e f i n e d , t h r e a d I d ) . t h e n ( ( h i s t o r y R e s u l t ) = > {
2020-12-18 04:07:32 +01:00
historyStorage . count = ( historyResult as MessagesMessages . messagesMessagesSlice ) . count || historyResult . messages . length ;
2020-02-06 16:43:07 +01:00
2022-06-17 18:01:43 +02:00
const history = ( historyResult . messages as MyMessage [ ] ) . map ( ( message ) = > message . mid ) ;
2020-12-22 09:18:42 +01:00
return {
2020-02-06 16:43:07 +01:00
count : historyStorage.count ,
2020-12-22 09:18:42 +01:00
history ,
offsetIdOffset : ( historyResult as MessagesMessages . messagesMessagesSlice ) . offset_id_offset || 0
} ;
2021-02-23 16:20:52 +01:00
} ) ; * /
2020-02-06 16:43:07 +01:00
}
2021-02-23 16:20:52 +01:00
const haveSlice = historyStorage . history . sliceMe ( maxId , offset , limit ) ;
2021-05-06 23:02:21 +02:00
if ( haveSlice && ( haveSlice . slice . length === limit || ( haveSlice . fulfilled & SliceEnd . Both ) === SliceEnd . Both ) ) {
2021-02-23 16:20:52 +01:00
return {
count : historyStorage.count ,
2022-06-17 18:01:43 +02:00
history : Array.from ( haveSlice . slice ) ,
isEnd : haveSlice.slice.getEnds ( ) ,
2021-02-23 16:20:52 +01:00
offsetIdOffset : haveSlice.offsetIdOffset
2022-08-04 08:49:54 +02:00
} ;
2021-02-23 16:20:52 +01:00
}
2020-02-06 16:43:07 +01:00
2022-06-17 18:01:43 +02:00
// if(onlyCache) {
// return;
// }
2021-02-23 16:20:52 +01:00
return this . fillHistoryStorage ( peerId , maxId , limit , offset , historyStorage , threadId ) . then ( ( ) = > {
const slice = historyStorage . history . sliceMe ( maxId , offset , limit ) ;
2022-06-17 18:01:43 +02:00
const f = slice ? . slice || historyStorage . history . constructSlice ( ) ;
2020-12-22 09:18:42 +01:00
return {
2020-02-06 16:43:07 +01:00
count : historyStorage.count ,
2022-06-17 18:01:43 +02:00
history : Array.from ( f ) ,
isEnd : f.getEnds ( ) ,
2021-02-23 16:20:52 +01:00
offsetIdOffset : slice?.offsetIdOffset || historyStorage . count
2020-12-22 09:18:42 +01:00
} ;
2020-02-06 16:43:07 +01:00
} ) ;
}
2021-09-01 19:17:06 +02:00
public isHistoryResultEnd ( historyResult : Exclude < MessagesMessages , MessagesMessages.messagesMessagesNotModified > , limit : number , add_offset : number ) {
const { offset_id_offset , messages } = historyResult as MessagesMessages . messagesMessagesSlice ;
const count = ( historyResult as MessagesMessages . messagesMessagesSlice ) . count || messages . length ;
const offsetIdOffset = offset_id_offset || 0 ;
const topWasMeantToLoad = add_offset < 0 ? limit + add_offset : limit ;
const isTopEnd = offsetIdOffset >= ( count - topWasMeantToLoad ) || count < topWasMeantToLoad ;
const isBottomEnd = ! offsetIdOffset || ( add_offset < 0 && ( offsetIdOffset + add_offset ) <= 0 ) ;
return { count , offsetIdOffset , isTopEnd , isBottomEnd } ;
}
2023-01-06 20:27:29 +01:00
public mergeHistoryResult (
slicedArray : SlicedArray < number > ,
2022-08-04 08:49:54 +02:00
historyResult : Parameters < AppMessagesManager [ ' isHistoryResultEnd ' ] > [ 0 ] ,
offset_id : number ,
limit : number ,
2023-01-06 20:27:29 +01:00
add_offset : number
) {
2021-09-01 19:17:06 +02:00
const { messages } = historyResult as MessagesMessages . messagesMessagesSlice ;
const isEnd = this . isHistoryResultEnd ( historyResult , limit , add_offset ) ;
const { count , offsetIdOffset , isTopEnd , isBottomEnd } = isEnd ;
const mids = messages . map ( ( message ) = > {
return ( message as MyMessage ) . mid ;
} ) ;
2022-08-04 08:49:54 +02:00
// * add bound manually.
2021-09-01 19:17:06 +02:00
// * offset_id will be inclusive only if there is 'add_offset' <= -1 (-1 - will only include the 'offset_id')
2021-11-12 18:40:13 +01:00
// * check that offset_id is not 0
2022-06-17 18:01:43 +02:00
if ( offset_id && getServerMessageId ( offset_id ) && ! mids . includes ( offset_id ) && offsetIdOffset < count ) {
2021-09-01 19:17:06 +02:00
let i = 0 ;
for ( const length = mids . length ; i < length ; ++ i ) {
if ( offset_id > mids [ i ] ) {
break ;
}
}
mids . splice ( i , 0 , offset_id ) ;
}
2020-02-06 16:43:07 +01:00
2021-09-01 19:17:06 +02:00
const slice = slicedArray . insertSlice ( mids ) || slicedArray . slice ;
if ( isTopEnd ) {
slice . setEnd ( SliceEnd . Top ) ;
}
2022-08-04 08:49:54 +02:00
2021-09-01 19:17:06 +02:00
if ( isBottomEnd ) {
slice . setEnd ( SliceEnd . Bottom ) ;
}
2021-05-06 23:02:21 +02:00
2021-09-01 19:17:06 +02:00
return { slice , mids , messages , . . . isEnd } ;
}
2021-10-21 15:16:43 +02:00
public fillHistoryStorage ( peerId : PeerId , offset_id : number , limit : number , add_offset : number , historyStorage : HistoryStorage , threadId? : number ) : Promise < void > {
2022-06-17 18:01:43 +02:00
const wasMaxId = historyStorage . maxId ;
2021-09-01 19:17:06 +02:00
return this . requestHistory ( peerId , offset_id , limit , add_offset , undefined , threadId ) . then ( ( historyResult ) = > {
const { count , isBottomEnd , slice , messages } = this . mergeHistoryResult ( historyStorage . history , historyResult , offset_id , limit , add_offset ) ;
2021-05-06 23:02:21 +02:00
2021-09-01 19:17:06 +02:00
historyStorage . count = count ;
2021-02-24 19:47:31 +01:00
2021-02-23 16:20:52 +01:00
/ * i f ( ! m a x I d & & h i s t o r y R e s u l t . m e s s a g e s . l e n g t h ) {
2020-12-22 00:51:28 +01:00
maxId = this . incrementMessageId ( ( historyResult . messages [ 0 ] as MyMessage ) . mid , 1 ) ;
2020-02-06 16:43:07 +01:00
}
2020-05-26 17:04:06 +02:00
2021-02-23 16:20:52 +01:00
const wasTotalCount = historyStorage . history . length ; * /
2020-02-06 16:43:07 +01:00
2021-09-01 19:17:06 +02:00
for ( let i = 0 , length = messages . length ; i < length ; ++ i ) {
const message = messages [ i ] as MyMessage ;
if ( this . mergeReplyKeyboard ( historyStorage , message ) ) {
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'history_reply_markup' , { peerId } ) ;
2020-02-06 16:43:07 +01:00
}
2021-05-08 20:49:50 +02:00
}
2021-09-01 19:17:06 +02:00
2021-05-08 20:49:50 +02:00
if ( isBottomEnd ) {
2022-06-17 18:01:43 +02:00
const newMaxId = slice [ 0 ] ;
if ( historyStorage . maxId === wasMaxId ) {
const first = historyStorage . history . first ;
if ( first !== slice ) {
historyStorage . history . deleteSlice ( first ) ;
}
if ( historyStorage . maxId !== newMaxId ) {
historyStorage . maxId = slice [ 0 ] ; // ! WARNING
this . reloadConversation ( peerId ) ; // when top_message is deleted but cached
}
}
2021-02-24 19:47:31 +01:00
}
2022-08-04 08:49:54 +02:00
2021-02-23 16:20:52 +01:00
/ * c o n s t i s B a c k L i m i t = o f f s e t < 0 & & - o f f s e t ! = = f u l l L i m i t ;
if ( isBackLimit ) {
return ;
}
2020-05-26 17:04:06 +02:00
const totalCount = historyStorage . history . length ;
2020-02-06 16:43:07 +01:00
fullLimit -= ( totalCount - wasTotalCount ) ;
2021-02-23 16:20:52 +01:00
const migratedNextPeer = this . migratedFromTo [ peerId ] ;
2020-12-11 03:06:16 +01:00
const migratedPrevPeer = this . migratedToFrom [ peerId ]
2020-05-26 17:04:06 +02:00
const isMigrated = migratedNextPeer !== undefined || migratedPrevPeer !== undefined ;
2020-02-06 16:43:07 +01:00
if ( isMigrated ) {
historyStorage . count = Math . max ( historyStorage . count , totalCount ) + 1 ;
2021-02-23 16:20:52 +01:00
}
2020-02-06 16:43:07 +01:00
if ( fullLimit > 0 ) {
2021-02-23 16:20:52 +01:00
maxId = historyStorage . history . slice [ totalCount - 1 ] ;
if ( isMigrated ) {
2020-02-06 16:43:07 +01:00
if ( ! historyResult . messages . length ) {
if ( migratedPrevPeer ) {
2020-12-11 03:06:16 +01:00
maxId = 0 ;
peerId = migratedPrevPeer ;
2020-02-06 16:43:07 +01:00
} else {
historyStorage . count = totalCount ;
return true ;
}
}
2020-12-20 04:54:35 +01:00
return this . fillHistoryStorage ( peerId , maxId , fullLimit , historyStorage , threadId ) ;
2021-02-23 16:20:52 +01:00
} else if ( totalCount < historyStorage . count ) {
return this . fillHistoryStorage ( peerId , maxId , fullLimit , offset , historyStorage , threadId ) ;
2020-02-06 16:43:07 +01:00
}
2021-02-23 16:20:52 +01:00
} * /
2020-02-06 16:43:07 +01:00
} ) ;
}
2021-10-21 15:16:43 +02:00
public requestHistory ( peerId : PeerId , maxId : number , limit = 0 , offset = 0 , offsetDate = 0 , threadId = 0 ) : Promise < Exclude < MessagesMessages , MessagesMessages.messagesMessagesNotModified > > {
2022-08-04 08:49:54 +02:00
// console.trace('requestHistory', peerId, maxId, limit, offset);
2020-02-06 16:43:07 +01:00
2022-08-04 08:49:54 +02:00
// rootScope.broadcast('history_request');
2020-12-20 04:54:35 +01:00
2023-01-06 20:27:29 +01:00
const options : MessagesGetReplies | MessagesGetHistory = {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2022-06-17 18:01:43 +02:00
offset_id : getServerMessageId ( maxId ) || 0 ,
2020-06-13 10:19:39 +02:00
offset_date : offsetDate ,
add_offset : offset ,
2020-12-22 09:18:42 +01:00
limit ,
2020-02-06 16:43:07 +01:00
max_id : 0 ,
min_id : 0 ,
hash : 0
2020-12-20 04:54:35 +01:00
} ;
2021-02-23 16:20:52 +01:00
if ( threadId ) {
2023-01-06 20:27:29 +01:00
( options as MessagesGetReplies ) . msg_id = getServerMessageId ( threadId ) || 0 ;
2021-02-23 16:20:52 +01:00
}
2022-06-17 18:01:43 +02:00
const promise : ReturnType < AppMessagesManager [ ' requestHistory ' ] > = this . apiManager . invokeApiSingle ( threadId ? 'messages.getReplies' : 'messages.getHistory' , options , {
2022-08-04 08:49:54 +02:00
// timeout: APITIMEOUT,
2020-02-06 16:43:07 +01:00
noErrorBox : true
2020-12-20 04:54:35 +01:00
} ) as any ;
2020-12-18 04:07:32 +01:00
return promise . then ( ( historyResult ) = > {
2021-01-08 10:55:37 +01:00
if ( DEBUG ) {
this . log ( 'requestHistory result:' , peerId , historyResult , maxId , limit , offset ) ;
}
2020-02-13 16:42:39 +01:00
2022-04-25 16:54:30 +02:00
this . appUsersManager . saveApiUsers ( historyResult . users ) ;
this . appChatsManager . saveApiChats ( historyResult . chats ) ;
2020-02-06 16:43:07 +01:00
this . saveMessages ( historyResult . messages ) ;
2023-01-06 20:27:29 +01:00
if ( 'pts' in historyResult ) {
this . apiUpdatesManager . addChannelState ( peerId . toChatId ( ) , historyResult . pts ) ;
2020-02-06 16:43:07 +01:00
}
2021-05-06 23:02:21 +02:00
let length = historyResult . messages . length , count = ( historyResult as MessagesMessages . messagesMessagesSlice ) . count ;
2022-06-17 18:01:43 +02:00
if ( length && ! historyResult . messages [ length - 1 ] ) {
2020-02-06 16:43:07 +01:00
historyResult . messages . splice ( length - 1 , 1 ) ;
length -- ;
2021-05-06 23:02:21 +02:00
count -- ;
2020-02-06 16:43:07 +01:00
}
2020-04-28 19:30:54 +02:00
// will load more history if last message is album grouped (because it can be not last item)
// historyResult.messages: desc sorted
2021-05-06 23:02:21 +02:00
const historyStorage = this . getHistoryStorage ( peerId , threadId ) ;
const oldestMessage : Message.message = historyResult . messages [ length - 1 ] as any ;
if ( length && oldestMessage . grouped_id ) {
const foundSlice = historyStorage . history . findSlice ( oldestMessage . mid ) ;
if ( foundSlice && ( foundSlice . slice . length + historyResult . messages . length ) < count ) {
return this . requestHistory ( peerId , oldestMessage . mid , 10 , 0 , offsetDate , threadId ) . then ( ( _historyResult ) = > {
return historyResult ;
} ) ;
}
2020-04-28 19:30:54 +02:00
}
2020-12-22 09:18:42 +01:00
return historyResult ;
2020-02-06 16:43:07 +01:00
} , ( error ) = > {
2022-08-04 08:49:54 +02:00
switch ( error . type ) {
2020-02-06 16:43:07 +01:00
case 'CHANNEL_PRIVATE' :
2022-04-25 16:54:30 +02:00
let channel = this . appChatsManager . getChat ( peerId . toChatId ( ) ) ;
2023-01-06 20:27:29 +01:00
if ( channel . _ === 'channel' ) {
channel = {
_ : 'channelForbidden' ,
id : peerId.toChatId ( ) ,
access_hash : channel.access_hash ,
title : channel.title ,
pFlags : channel.pFlags
} ;
}
2022-04-25 16:54:30 +02:00
this . apiUpdatesManager . processUpdateMessage ( {
2020-02-06 16:43:07 +01:00
_ : 'updates' ,
updates : [ {
_ : 'updateChannel' ,
2021-10-21 15:16:43 +02:00
channel_id : peerId.toChatId ( )
2020-02-06 16:43:07 +01:00
} ] ,
chats : [ channel ] ,
users : [ ]
} ) ;
break ;
}
2020-05-26 17:04:06 +02:00
throw error ;
2020-02-06 16:43:07 +01:00
} ) ;
}
public fetchSingleMessages() {
if ( this . fetchSingleMessagesPromise ) {
return this . fetchSingleMessagesPromise ;
}
2022-06-30 16:14:33 +02:00
return this . fetchSingleMessagesPromise = pause ( 0 ) . then ( ( ) = > {
const requestPromises : Promise < void > [ ] = [ ] ;
2022-08-04 08:49:54 +02:00
2022-06-30 16:14:33 +02:00
for ( const [ peerId , map ] of this . needSingleMessages ) {
const mids = [ . . . map . keys ( ) ] ;
const msgIds : InputMessage [ ] = mids . map ( ( mid ) = > {
return {
_ : 'inputMessageID' ,
id : getServerMessageId ( mid )
} ;
} ) ;
2022-08-04 08:49:54 +02:00
2022-06-30 16:14:33 +02:00
let promise : Promise < MethodDeclMap [ ' channels.getMessages ' ] [ ' res ' ] | MethodDeclMap [ ' messages.getMessages ' ] [ ' res ' ] > ;
if ( peerId . isAnyChat ( ) && this . appPeersManager . isChannel ( peerId ) ) {
promise = this . apiManager . invokeApiSingle ( 'channels.getMessages' , {
channel : this.appChatsManager.getChannelInput ( peerId . toChatId ( ) ) ,
id : msgIds
2020-09-28 02:23:00 +02:00
} ) ;
2022-06-30 16:14:33 +02:00
} else {
promise = this . apiManager . invokeApiSingle ( 'messages.getMessages' , {
id : msgIds
} ) ;
}
2021-10-21 15:16:43 +02:00
2022-06-30 16:14:33 +02:00
const after = promise . then ( ( getMessagesResult ) = > {
assumeType < Exclude < MessagesMessages.messagesMessages , MessagesMessages.messagesMessagesNotModified > > ( getMessagesResult ) ;
2021-10-21 15:16:43 +02:00
2022-06-30 16:14:33 +02:00
this . appUsersManager . saveApiUsers ( getMessagesResult . users ) ;
this . appChatsManager . saveApiChats ( getMessagesResult . chats ) ;
const messages = this . saveMessages ( getMessagesResult . messages ) ;
2022-06-17 18:01:43 +02:00
2022-06-30 16:14:33 +02:00
for ( let i = 0 ; i < messages . length ; ++ i ) {
const message = messages [ i ] ;
if ( ! message ) {
continue ;
2021-10-22 20:31:54 +02:00
}
2022-06-30 16:14:33 +02:00
const mid = generateMessageId ( message . id ) ;
const promise = map . get ( mid ) ;
promise . resolve ( message ) ;
map . delete ( mid ) ;
}
if ( map . size ) {
for ( const [ mid , promise ] of map ) {
promise . resolve ( this . generateEmptyMessage ( mid ) ) ;
2020-09-28 02:23:00 +02:00
}
2022-06-30 16:14:33 +02:00
}
} ) . finally ( ( ) = > {
this . rootScope . dispatchEvent ( 'messages_downloaded' , { peerId , mids } ) ;
} ) ;
2022-08-04 08:49:54 +02:00
2022-06-30 16:14:33 +02:00
requestPromises . push ( after ) ;
}
2020-02-06 16:43:07 +01:00
2022-06-30 16:14:33 +02:00
this . needSingleMessages . clear ( ) ;
2021-10-21 15:16:43 +02:00
2022-06-30 16:14:33 +02:00
return Promise . all ( requestPromises ) . then ( noop , noop ) . then ( ( ) = > {
2023-01-06 20:27:29 +01:00
this . fetchSingleMessagesPromise = undefined ;
2022-06-30 16:14:33 +02:00
if ( this . needSingleMessages . size ) this . fetchSingleMessages ( ) ;
} ) ;
2020-02-06 16:43:07 +01:00
} ) ;
}
2022-11-06 14:48:41 +01:00
public reloadMessages ( peerId : PeerId , mid : number , overwrite? : boolean ) : Promise < MyMessage > ;
public reloadMessages ( peerId : PeerId , mid : number [ ] , overwrite? : boolean ) : Promise < MyMessage [ ] > ;
public reloadMessages ( peerId : PeerId , mid : number | number [ ] , overwrite? : boolean ) : Promise < MyMessage | MyMessage [ ] > {
if ( Array . isArray ( mid ) ) {
return Promise . all ( mid . map ( ( mid ) = > {
return this . reloadMessages ( peerId , mid , overwrite ) ;
} ) ) ;
}
2021-10-21 15:16:43 +02:00
const message = this . getMessageByPeer ( peerId , mid ) ;
2022-06-17 18:01:43 +02:00
if ( message && ! overwrite ) {
this . rootScope . dispatchEvent ( 'messages_downloaded' , { peerId , mids : [ mid ] } ) ;
2021-10-21 15:16:43 +02:00
return Promise . resolve ( message ) ;
} else {
let map = this . needSingleMessages . get ( peerId ) ;
if ( ! map ) {
this . needSingleMessages . set ( peerId , map = new Map ( ) ) ;
}
let promise = map . get ( mid ) ;
if ( promise ) {
return promise ;
}
promise = deferredPromise ( ) ;
map . set ( mid , promise ) ;
this . fetchSingleMessages ( ) ;
return promise ;
2020-06-05 18:01:06 +02:00
}
2020-02-06 16:43:07 +01:00
}
2020-06-06 07:26:18 +02:00
2022-11-06 14:48:41 +01:00
public getExtendedMedia ( peerId : PeerId , mids : number [ ] ) {
let map = this . extendedMedia . get ( peerId ) ;
if ( ! map ) {
this . extendedMedia . set ( peerId , map = new Map ( ) ) ;
}
const deferred = deferredPromise < void > ( ) ;
const toRequest : number [ ] = [ ] ;
const promises = mids . map ( ( mid ) = > {
let promise = map . get ( mid ) ;
if ( ! promise ) {
map . set ( mid , promise = deferred ) ;
toRequest . push ( mid ) ;
promise . then ( ( ) = > {
map . delete ( mid ) ;
if ( ! map . size && this . extendedMedia . get ( peerId ) === map ) {
this . extendedMedia . delete ( peerId ) ;
}
} ) ;
}
return promise ;
} ) ;
if ( ! toRequest . length ) {
deferred . resolve ( ) ;
} else {
this . apiManager . invokeApi ( 'messages.getExtendedMedia' , {
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
id : toRequest.map ( ( mid ) = > getServerMessageId ( mid ) )
} ) . then ( ( updates ) = > {
this . apiUpdatesManager . processUpdateMessage ( updates ) ;
deferred . resolve ( ) ;
} ) ;
}
return Promise . all ( promises ) ;
}
2022-06-17 18:01:43 +02:00
public fetchMessageReplyTo ( message : MyMessage ) {
2021-10-29 01:43:00 +02:00
if ( ! message . reply_to_mid ) return Promise . resolve ( this . generateEmptyMessage ( 0 ) ) ;
2022-07-26 17:24:29 +02:00
const replyToPeerId = message . reply_to . reply_to_peer_id ? this . appPeersManager . getPeerId ( message . reply_to . reply_to_peer_id ) : message . peerId ;
2022-11-06 14:48:41 +01:00
return this . reloadMessages ( replyToPeerId , message . reply_to_mid ) . then ( ( originalMessage ) = > {
2022-06-17 18:01:43 +02:00
if ( ! originalMessage ) { // ! break the infinite loop
message = this . getMessageByPeer ( message . peerId , message . mid ) ; // message can come from other thread
2021-10-29 01:43:00 +02:00
delete message . reply_to_mid ; // ! WARNING!
}
2022-07-01 15:43:33 +02:00
if ( message . _ === 'messageService' ) {
const peerId = message . peerId ;
this . rootScope . dispatchEvent ( 'message_edit' , {
storageKey : ` ${ peerId } _history ` ,
peerId : peerId ,
mid : message.mid ,
message
} ) ;
if ( this . isMessageIsTopMessage ( message ) ) {
2023-01-06 20:27:29 +01:00
this . rootScope . dispatchEvent ( 'dialogs_multiupdate' , new Map ( [ [ peerId , { dialog : this.getDialogOnly ( peerId ) } ] ] ) ) ;
2022-07-01 15:43:33 +02:00
}
}
2021-10-29 01:43:00 +02:00
return originalMessage ;
} ) ;
}
2023-01-06 20:27:29 +01:00
private getTypingKey ( peerId : PeerId , threadId? : number ) {
return threadId ? ` ${ peerId } _ ${ threadId } ` : peerId ;
}
public setTyping (
peerId : PeerId ,
action : SendMessageAction ,
force? : boolean ,
threadId? : number
) : Promise < boolean > {
if ( threadId && ! this . appPeersManager . isForum ( peerId ) ) {
threadId = undefined ;
}
const key = this . getTypingKey ( peerId , threadId ) ;
let typing = this . typings [ key ] ;
2022-06-17 18:01:43 +02:00
if (
2022-08-04 08:49:54 +02:00
! peerId ||
! this . canSendToPeer ( peerId ) ||
2022-06-17 18:01:43 +02:00
peerId === this . appPeersManager . peerId ||
2022-01-23 20:45:34 +01:00
// (!force && deepEqual(typing?.action, action))
( ! force && typing ? . action ? . _ === action . _ )
2021-05-09 22:29:30 +02:00
) {
return Promise . resolve ( false ) ;
}
if ( typing ? . timeout ) {
clearTimeout ( typing . timeout ) ;
}
2023-01-06 20:27:29 +01:00
typing = this . typings [ key ] = {
2022-01-23 20:45:34 +01:00
action
2021-05-09 22:29:30 +02:00
} ;
2022-06-17 18:01:43 +02:00
return this . apiManager . invokeApi ( 'messages.setTyping' , {
2022-04-25 16:54:30 +02:00
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
2023-01-06 20:27:29 +01:00
action ,
top_msg_id : threadId ? getServerMessageId ( threadId ) : undefined
2021-05-09 22:29:30 +02:00
} ) . finally ( ( ) = > {
2023-01-06 20:27:29 +01:00
if ( typing === this . typings [ key ] ) {
2022-06-17 18:01:43 +02:00
typing . timeout = ctx . setTimeout ( ( ) = > {
2023-01-06 20:27:29 +01:00
delete this . typings [ key ] ;
2021-05-09 22:29:30 +02:00
} , 6000 ) ;
}
} ) ;
2020-06-06 07:26:18 +02:00
}
2020-12-18 04:07:32 +01:00
2021-08-03 03:44:13 +02:00
private handleReleasingMessage ( message : MyMessage , storage : MessagesStorage ) {
2021-07-21 14:16:15 +02:00
const media = ( message as Message . message ) . media ;
if ( media ) {
2021-08-03 03:44:13 +02:00
const c = ( media as MessageMedia . messageMediaWebPage ) . webpage as WebPage . webPage || media as MessageMedia . messageMediaPhoto | MessageMedia . messageMediaDocument ;
const smth : Photo.photo | MyDocument = ( c as MessageMedia . messageMediaPhoto ) . photo as any || ( c as MessageMedia . messageMediaDocument ) . document as any ;
2021-07-15 17:34:34 +02:00
if ( smth ? . file_reference ) {
2022-04-25 16:54:30 +02:00
this . referenceDatabase . deleteContext ( smth . file_reference , { type : 'message' , peerId : message.peerId , messageId : message.mid } ) ;
2021-07-15 17:34:34 +02:00
}
2021-10-29 17:56:57 +02:00
if ( 'webpage' in media && media . webpage ) {
2021-08-03 03:44:13 +02:00
const isScheduled = this . getScheduledMessagesStorage ( message . peerId ) === storage ;
2022-04-25 16:54:30 +02:00
const messageKey = this . appWebPagesManager . getMessageKeyForPendingWebPage ( message . peerId , message . mid , isScheduled ) ;
this . appWebPagesManager . deleteWebPageFromPending ( media . webpage , messageKey ) ;
2021-07-15 17:34:34 +02:00
}
2021-09-23 15:41:02 +02:00
if ( ( media as MessageMedia . messageMediaPoll ) . poll ) {
2022-04-25 16:54:30 +02:00
this . appPollsManager . updatePollToMessage ( message as Message . message , false ) ;
2021-09-23 15:41:02 +02:00
}
2021-07-15 17:34:34 +02:00
}
}
2021-10-21 15:16:43 +02:00
private handleDeletedMessages ( peerId : PeerId , storage : MessagesStorage , messages : number [ ] ) {
2020-12-18 04:07:32 +01:00
const history : {
2022-08-04 08:49:54 +02:00
count : number ,
unread : number ,
unreadMentions : number ,
2021-08-24 18:33:04 +02:00
msgs : Set < number > ,
2020-12-18 04:07:32 +01:00
albums ? : { [ groupId : string ] : Set < number > } ,
2021-08-24 18:33:04 +02:00
} = {
2022-08-04 08:49:54 +02:00
count : 0 ,
unread : 0 ,
unreadMentions : 0 ,
2021-08-24 18:33:04 +02:00
msgs : new Set ( )
} ;
2020-12-18 04:07:32 +01:00
for ( const mid of messages ) {
const message : MyMessage = this . getMessageFromStorage ( storage , mid ) ;
2022-06-17 18:01:43 +02:00
if ( ! message ) {
2021-10-21 15:16:43 +02:00
this . fixDialogUnreadMentionsIfNoMessage ( peerId ) ;
continue ;
}
2020-12-18 04:07:32 +01:00
2021-08-03 03:44:13 +02:00
this . handleReleasingMessage ( message , storage ) ;
2020-12-18 04:07:32 +01:00
2020-12-22 04:02:30 +01:00
this . updateMessageRepliesIfNeeded ( message ) ;
2021-02-10 07:06:22 +01:00
if ( ! message . pFlags . out && ! message . pFlags . is_outgoing && message . pFlags . unread ) {
2021-08-24 18:33:04 +02:00
++ history . unread ;
2022-06-17 18:01:43 +02:00
this . rootScope . dispatchEvent ( 'notification_cancel' , 'msg' + mid ) ;
2021-08-24 18:33:04 +02:00
if ( message . pFlags . mentioned ) {
++ history . unreadMentions ;
2021-09-01 19:17:06 +02:00
this . modifyCachedMentions ( peerId , mid , false ) ;
2021-08-24 18:33:04 +02:00
}
2020-12-18 04:07:32 +01:00
}
2021-08-24 18:33:04 +02:00
++ history . count ;
history . msgs . add ( mid ) ;
2020-12-18 04:07:32 +01:00
message . deleted = true ;
2021-09-17 18:50:29 +02:00
const groupedId = ( message as Message . message ) . grouped_id ;
if ( groupedId ) {
const groupedStorage = this . groupedMessagesStorage [ groupedId ] ;
2020-12-18 04:07:32 +01:00
if ( groupedStorage ) {
2021-10-05 22:40:07 +02:00
groupedStorage . delete ( mid ) ;
2020-12-18 04:07:32 +01:00
if ( ! history . albums ) history . albums = { } ;
2021-09-17 18:50:29 +02:00
( history . albums [ groupedId ] || ( history . albums [ groupedId ] = new Set ( ) ) ) . add ( mid ) ;
2020-12-18 04:07:32 +01:00
2021-10-05 22:40:07 +02:00
if ( ! groupedStorage . size ) {
2020-12-18 04:07:32 +01:00
delete history . albums ;
2021-09-17 18:50:29 +02:00
delete this . groupedMessagesStorage [ groupedId ] ;
2020-12-18 04:07:32 +01:00
}
}
}
2021-10-05 22:40:07 +02:00
storage . delete ( mid ) ;
2020-12-18 04:07:32 +01:00
}
if ( history . albums ) {
2022-06-17 18:01:43 +02:00
for ( const groupedId in history . albums ) {
this . dispatchAlbumEdit ( groupedId , storage , [ . . . history . albums [ groupedId ] ] ) ;
2020-12-18 04:07:32 +01:00
/ * c o n s t m i d s = t h i s . g e t M i d s B y A l b u m ( g r o u p I d ) ;
if ( mids . length ) {
const mid = Math . max ( . . . mids ) ;
rootScope . $broadcast ( 'message_edit' , { peerId , mid , justMedia : false } ) ;
} * /
}
}
return history ;
}
2022-08-04 08:49:54 +02:00
2022-06-17 18:01:43 +02:00
private handleEditedMessage ( oldMessage : Message , newMessage : Message , storage : MessagesStorage ) {
2021-10-21 15:16:43 +02:00
if ( oldMessage . _ === 'message' ) {
if ( ( oldMessage . media as MessageMedia . messageMediaWebPage ) ? . webpage ) {
2022-04-25 16:54:30 +02:00
const messageKey = this . appWebPagesManager . getMessageKeyForPendingWebPage ( oldMessage . peerId , oldMessage . mid , ! ! oldMessage . pFlags . is_scheduled ) ;
this . appWebPagesManager . deleteWebPageFromPending ( ( oldMessage . media as MessageMedia . messageMediaWebPage ) . webpage , messageKey ) ;
2021-10-21 15:16:43 +02:00
}
2022-06-17 18:01:43 +02:00
const groupedId = oldMessage . grouped_id ;
if ( groupedId ) {
this . dispatchAlbumEdit ( groupedId , storage , [ ] ) ;
}
2020-12-18 04:07:32 +01:00
}
}
2021-08-18 16:48:13 +02:00
2022-06-17 18:01:43 +02:00
private dispatchAlbumEdit ( groupedId : string , storage : MessagesStorage , deletedMids? : number [ ] ) {
const mids = this . getMidsByAlbum ( groupedId ) ;
const messages = mids . map ( ( mid ) = > this . getMessageFromStorage ( storage , mid ) ) as Message . message [ ] ;
this . rootScope . dispatchEvent ( 'album_edit' , { peerId : messages [ 0 ] . peerId , groupId : groupedId , deletedMids : deletedMids || [ ] , messages } ) ;
}
2023-01-06 20:27:29 +01:00
public getDialogUnreadCount ( dialog : Dialog | ForumTopic ) {
2023-01-13 12:10:41 +01:00
let unreadCount = dialog . unread_count ;
if ( ! this . dialogsStorage . isTopic ( dialog ) && this . appPeersManager . isForum ( dialog . peerId ) ) {
const forumUnreadCount = this . dialogsStorage . getForumUnreadCount ( dialog . peerId ) ;
if ( forumUnreadCount instanceof Promise ) {
unreadCount = 0 ;
} else {
unreadCount = forumUnreadCount . count ;
}
}
2023-01-25 15:21:38 +01:00
return unreadCount || + ! ! ( dialog as Dialog ) . pFlags ? . unread_mark ;
2021-10-21 15:16:43 +02:00
}
2023-01-06 20:27:29 +01:00
public isDialogUnread ( dialog : Dialog | ForumTopic ) {
2021-10-21 15:16:43 +02:00
return ! ! this . getDialogUnreadCount ( dialog ) ;
}
2022-01-08 13:52:14 +01:00
public canForward ( message : Message.message | Message . messageService ) {
2022-06-17 18:01:43 +02:00
return message ? . _ === 'message' && ! ( message as Message . message ) . pFlags . noforwards && ! this . appPeersManager . noForwards ( message . peerId ) ;
2022-01-08 13:52:14 +01:00
}
2022-03-28 17:16:12 +02:00
private pushBatchUpdate < E extends keyof BatchUpdates , C extends BatchUpdates [ E ] > (
2022-08-04 08:49:54 +02:00
event : E ,
callback : C ,
key : string ,
2022-03-28 17:16:12 +02:00
getElementCallback ? : ( ) = > MapValueType < ArgumentTypes < C > [ 0 ] >
) {
let details = this . batchUpdates [ event ] ;
if ( ! details ) {
// @ts-ignore
details = this . batchUpdates [ event ] = {
callback ,
batch : new Map ( )
} ;
}
if ( ! details . batch . has ( key ) ) {
// @ts-ignore
details . batch . set ( key , getElementCallback ? getElementCallback ( ) : undefined ) ;
this . batchUpdatesDebounced ( ) ;
}
}
private getMessagesFromMap < T extends Map < any , any > > ( map : T ) {
const newMap : Map < Message.message , MapValueType < T > > = new Map ( ) ;
for ( const [ key , value ] of map ) {
const [ peerIdStr , mid ] = key . split ( '_' ) ;
2022-06-17 18:01:43 +02:00
const message = this . getMessageByPeer ( peerIdStr . toPeerId ( ) , + mid ) as Message . message ;
if ( ! message ) {
2022-03-28 17:16:12 +02:00
continue ;
}
newMap . set ( message , value ) ;
}
return newMap ;
}
private batchUpdateViews = ( batch : Map < string , undefined > ) = > {
const toDispatch : { peerId : PeerId , mid : number , views : number } [ ] = [ ] ;
const map = this . getMessagesFromMap ( batch ) ;
for ( const [ message ] of map ) {
toDispatch . push ( {
peerId : message.peerId ,
mid : message.mid ,
views : message.views
} )
}
return toDispatch ;
} ;
private batchUpdateReactions = ( batch : Map < string , MessageReactions > ) = > {
const toDispatch : { message : Message.message , changedResults : ReactionCount.reactionCount [ ] } [ ] = [ ] ;
const map = this . getMessagesFromMap ( batch ) ;
2022-03-28 18:49:07 +02:00
for ( const [ message , previousReactions ] of map ) {
const results = message . reactions ? . results ? ? [ ] ;
const previousResults = previousReactions ? . results ? ? [ ] ;
2022-06-17 18:01:43 +02:00
const changedResults = results . filter ( ( reactionCount ) = > {
2022-09-20 19:34:08 +02:00
const previousReactionCount = previousResults . find ( ( _reactionCount ) = > reactionsEqual ( _reactionCount . reaction , reactionCount . reaction ) ) ;
2022-03-28 17:16:12 +02:00
return (
message . pFlags . out && (
2022-08-04 08:49:54 +02:00
! previousReactionCount ||
2022-03-28 17:16:12 +02:00
reactionCount . count > previousReactionCount . count
)
) || (
2022-09-20 19:34:08 +02:00
reactionCount . chosen_order !== undefined && (
2022-08-04 08:49:54 +02:00
! previousReactionCount ||
2022-09-20 19:34:08 +02:00
previousReactionCount . chosen_order === undefined
2022-03-28 17:16:12 +02:00
)
) ;
} ) ;
toDispatch . push ( { message , changedResults } ) ;
}
return toDispatch ;
} ;
2022-06-17 18:01:43 +02:00
public saveDefaultSendAs ( peerId : PeerId , sendAsPeerId : PeerId ) {
const channelFull = this . appProfileManager . getCachedFullChat ( peerId . toChatId ( ) ) as ChatFull . channelFull ;
channelFull . default_send_as = this . appPeersManager . getOutputPeer ( sendAsPeerId ) ;
return this . apiManager . invokeApi ( 'messages.saveDefaultSendAs' , {
peer : this.appPeersManager.getInputPeerById ( peerId ) ,
send_as : this.appPeersManager.getInputPeerById ( sendAsPeerId )
} ) ;
}
2020-02-06 16:43:07 +01:00
}