2020-02-11 16:35:57 +01:00
import ProgressivePreloader from "../../components/preloader" ;
2020-09-23 22:29:53 +02:00
import { CancellablePromise , deferredPromise } from "../../helpers/cancellablePromise" ;
2020-11-07 04:48:07 +01:00
import { tsNow } from "../../helpers/date" ;
2020-12-08 20:48:44 +01:00
import { copy , defineNotNumerableProperties , safeReplaceObject , getObjectKeysAndSort } from "../../helpers/object" ;
2020-10-29 18:11:09 +01:00
import { randomLong } from "../../helpers/random" ;
2020-11-07 04:48:07 +01:00
import { splitStringByLength , limitSymbols } from "../../helpers/string" ;
2020-12-10 00:58:20 +01:00
import { Dialog as MTDialog , DialogPeer , DocumentAttribute , InputMedia , InputMessage , InputNotifyPeer , InputPeerNotifySettings , InputSingleMedia , Message , MessageAction , MessageEntity , MessagesDialogs , MessagesFilter , MessagesMessages , MessagesPeerDialogs , MethodDeclMap , NotifyPeer , PhotoSize , SendMessageAction , Update } from "../../layer" ;
2020-11-10 01:47:00 +01:00
import { InvokeApiOptions } from "../../types" ;
2020-10-29 17:26:08 +01:00
import { langPack } from "../langPack" ;
2020-10-28 17:11:57 +01:00
import { logger , LogLevels } from "../logger" ;
2020-10-10 00:36:06 +02:00
import type { ApiFileManager } from '../mtproto/apiFileManager' ;
//import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker' ;
2020-11-11 18:01:38 +01:00
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config" ;
2020-09-28 02:23:00 +02:00
import referenceDatabase , { ReferenceContext } from "../mtproto/referenceDatabase" ;
2020-11-10 01:47:00 +01:00
import serverTimeManager from "../mtproto/serverTimeManager" ;
2020-10-10 00:36:06 +02:00
import { RichTextProcessor } from "../richtextprocessor" ;
2020-11-15 04:33:47 +01:00
import rootScope from "../rootScope" ;
2020-10-10 00:36:06 +02:00
import searchIndexManager from '../searchIndexManager' ;
import AppStorage from '../storage' ;
2020-11-10 01:47:00 +01:00
import DialogsStorage from "../storages/dialogs" ;
import FiltersStorage from "../storages/filters" ;
2020-10-10 00:36:06 +02:00
//import { telegramMeWebService } from "../mtproto/mtproto";
import apiUpdatesManager from "./apiUpdatesManager" ;
import appChatsManager from "./appChatsManager" ;
import appDocsManager , { MyDocument } from "./appDocsManager" ;
import appDownloadManager from "./appDownloadManager" ;
import appMessagesIDsManager from "./appMessagesIDsManager" ;
import appPeersManager from "./appPeersManager" ;
import appPhotosManager , { MyPhoto } from "./appPhotosManager" ;
import appPollsManager from "./appPollsManager" ;
2020-10-02 22:33:32 +02:00
import appStateManager from "./appStateManager" ;
2020-10-10 00:36:06 +02:00
import appUsersManager from "./appUsersManager" ;
import appWebPagesManager from "./appWebPagesManager" ;
2020-06-06 22:38:48 +02:00
//console.trace('include');
2020-09-18 17:03:26 +02:00
// TODO: если удалить сообщение в непрогруженном диалоге, то при обновлении, из-за стейта, последнего сообщения в чатлисте не будет
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 ;
2020-04-14 17:46:31 +02:00
export type HistoryStorage = {
2020-02-06 16:43:07 +01:00
count : number | null ,
history : number [ ] ,
pending : number [ ] ,
2020-05-20 16:25:23 +02:00
2020-05-26 17:04:06 +02:00
readPromise? : Promise < boolean > ,
2020-10-03 02:35:26 +02:00
readMaxID? : number ,
2020-05-20 16:25:23 +02:00
maxOutID? : number ,
reply_markup? : any
2020-02-06 16:43:07 +01:00
} ;
2020-04-14 17:46:31 +02:00
export type HistoryResult = {
count : number ,
history : number [ ] ,
unreadOffset : number ,
unreadSkip : boolean
} ;
2020-09-18 17:03:26 +02:00
export type Dialog = MTDialog . dialog ;
2020-05-03 14:46:05 +02:00
2020-11-10 01:47:00 +01:00
export type MyMessage = Message . message | Message . messageService ;
2020-10-02 22:33:32 +02:00
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 ,
maxID : number
} > ;
2020-02-06 16:43:07 +01:00
export class AppMessagesManager {
2020-09-28 02:23:00 +02:00
public messagesStorage : { [ mid : string ] : any } = { } ;
2020-10-03 02:35:26 +02:00
public messagesStorageByPeerID : { [ peerID : string ] : AppMessagesManager [ 'messagesStorage' ] } = { } ;
2020-10-26 02:59:49 +01:00
public groupedMessagesStorage : { [ groupID : string ] : { [ mid : string ] : any } } = { } ; // will be used for albums
2020-02-06 16:43:07 +01:00
public historiesStorage : {
[ peerID : string ] : HistoryStorage
} = { } ;
2020-12-08 20:48:44 +01:00
public searchesStorage : {
[ peerID : string ] : Partial < {
[ inputFilter in MyInputMessagesFilter ] : {
count? : number ,
history : number [ ]
}
} >
} = { } ;
public pinnedMessages : { [ peerID : string ] : PinnedStorage } = { } ;
2020-11-25 20:36:18 +01:00
2020-05-01 23:28:40 +02:00
public pendingByRandomID : { [ randomID : string ] : [ number , number ] } = { } ;
2020-02-06 16:43:07 +01:00
public pendingByMessageID : any = { } ;
public pendingAfterMsgs : any = { } ;
2020-09-18 17:03:26 +02:00
public pendingTopMsgs : { [ peerID : string ] : number } = { } ;
2020-02-06 16:43:07 +01:00
public sendFilePromise : CancellablePromise < void > = Promise . resolve ( ) ;
public tempID = - 1 ;
2020-10-13 15:51:11 +02:00
public tempFinalizeCallbacks : {
[ mid : string ] : {
[ callbackName : string ] : Partial < {
deferred : CancellablePromise < void > ,
callback : ( mid : number ) = > Promise < any >
} >
}
} = { } ;
2020-02-06 16:43:07 +01:00
2020-09-20 00:38:00 +02:00
public needSingleMessages : number [ ] = [ ] ;
2020-09-28 02:23:00 +02:00
private fetchSingleMessagesPromise : Promise < void > = null ;
2020-02-06 16:43:07 +01:00
public maxSeenID = 0 ;
2020-05-10 03:23:21 +02:00
public migratedFromTo : { [ peerID : number ] : number } = { } ;
public migratedToFrom : { [ peerID : number ] : number } = { } ;
2020-02-06 16:43:07 +01:00
public newMessagesHandlePromise = 0 ;
2020-09-20 00:38:00 +02:00
public newMessagesToHandle : { [ peerID : string ] : number [ ] } = { } ;
2020-02-06 16:43:07 +01:00
public newDialogsHandlePromise = 0 ;
2020-05-10 03:23:21 +02:00
public newDialogsToHandle : { [ peerID : string ] : { reload : true } | Dialog } = { } ;
2020-02-06 16:43:07 +01:00
public newUpdatesAfterReloadToHandle : any = { } ;
2020-06-20 03:11:24 +02:00
private reloadConversationsPromise : Promise < void > ;
private reloadConversationsPeers : number [ ] = [ ] ;
2020-02-06 16:43:07 +01:00
2020-05-30 08:44:54 +02:00
private dialogsIndex = searchIndexManager . createIndex ( ) ;
private cachedResults : {
query : string ,
count : number ,
2020-10-08 00:20:38 +02:00
dialogs : Dialog [ ] ,
folderID : number
2020-05-30 08:44:54 +02:00
} = {
query : '' ,
count : 0 ,
2020-10-08 00:20:38 +02:00
dialogs : [ ] ,
folderID : 0
2020-05-30 08:44:54 +02:00
} ;
2020-10-28 17:11:57 +01:00
private log = logger ( 'MESSAGES' /* , LogLevels.error | LogLevels.debug | LogLevels.log | LogLevels.warn */ ) ;
2020-06-19 13:49:55 +02:00
2020-11-10 01:47:00 +01:00
public dialogsStorage : DialogsStorage ;
public filtersStorage : FiltersStorage ;
2020-06-13 10:19:39 +02:00
2020-02-06 16:43:07 +01:00
constructor ( ) {
2020-11-10 01:47:00 +01:00
this . dialogsStorage = new DialogsStorage ( this , appMessagesIDsManager , appChatsManager , appPeersManager , serverTimeManager ) ;
2020-11-15 04:33:47 +01:00
this . filtersStorage = new FiltersStorage ( appPeersManager , appUsersManager , /* apiManager, */ rootScope ) ;
2020-11-10 01:47:00 +01:00
2020-11-15 04:33:47 +01:00
rootScope . on ( 'apiUpdate' , ( e ) = > {
2020-06-19 13:49:55 +02:00
this . handleUpdate ( e . detail ) ;
2020-02-06 16:43:07 +01:00
} ) ;
2020-11-15 04:33:47 +01:00
rootScope . on ( 'webpage_updated' , ( e ) = > {
2020-10-10 00:36:06 +02:00
const eventData = e . detail ;
2020-09-28 02:23:00 +02:00
eventData . msgs . forEach ( ( msgID ) = > {
2020-10-10 00:36:06 +02:00
const message = this . getMessage ( msgID ) as Message . message ;
if ( ! message ) return ;
message . media = {
_ : 'messageMediaWebPage' ,
webpage : appWebPagesManager.getWebPage ( eventData . id )
} ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'message_edit' , {
2020-04-26 03:45:07 +02:00
peerID : this.getMessagePeer ( message ) ,
mid : msgID ,
justMedia : true
} ) ;
2020-02-06 16:43:07 +01:00
} ) ;
} ) ;
2020-11-15 04:33:47 +01:00
/ * r o o t S c o p e . $ o n ( ' d r a f t _ u p d a t e d ' , ( e ) = > {
2020-02-06 16:43:07 +01:00
let eventData = e . detail ; ;
var peerID = eventData . peerID ;
var draft = eventData . draft ;
var dialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
if ( dialog ) {
var topDate ;
if ( draft && draft . date ) {
topDate = draft . date ;
} else {
2020-05-18 03:21:58 +02:00
var channelID = appPeersManager . isChannel ( peerID ) ? - peerID : 0
2020-02-06 16:43:07 +01:00
var topDate = this . getMessage ( dialog . top_message ) . date ;
if ( channelID ) {
var channel = appChatsManager . getChat ( channelID ) ;
if ( ! topDate || channel . date && channel . date > topDate ) {
topDate = channel . date ;
}
}
}
if ( ! dialog . pFlags . pinned ) {
2020-06-19 13:49:55 +02:00
dialog . index = this . dialogsStorage . generateDialogIndex ( topDate ) ;
2020-02-06 16:43:07 +01:00
}
2020-06-19 13:49:55 +02:00
this . dialogsStorage . pushDialog ( dialog ) ;
2020-02-06 16:43:07 +01:00
2020-11-15 04:33:47 +01:00
rootScope . $broadcast ( 'dialog_draft' , {
2020-09-20 00:38:00 +02:00
peerID ,
draft ,
2020-02-06 16:43:07 +01:00
index : dialog.index
} ) ;
}
2020-09-20 00:38:00 +02:00
} ) ; * /
2020-10-02 22:33:32 +02:00
appStateManager . addListener ( 'save' , ( ) = > {
const messages : any [ ] = [ ] ;
const dialogs : Dialog [ ] = [ ] ;
for ( const folderID in this . dialogsStorage . byFolders ) {
const folder = this . dialogsStorage . getFolder ( + folderID ) ;
for ( let dialog of folder ) {
const historyStorage = this . historiesStorage [ dialog . peerID ] ;
const history = [ ] . concat ( historyStorage ? . pending ? ? [ ] , historyStorage ? . history ? ? [ ] ) ;
dialog = copy ( dialog ) ;
let removeUnread = 0 ;
for ( const mid of history ) {
const message = this . getMessage ( mid ) ;
if ( /* message._ != 'messageEmpty' && */ message . id > 0 ) {
messages . push ( message ) ;
if ( message . fromID != dialog . peerID ) {
appStateManager . setPeer ( message . fromID , appPeersManager . getPeer ( message . fromID ) ) ;
}
dialog . top_message = message . mid ;
break ;
} else if ( message . pFlags && message . pFlags . unread ) {
++ removeUnread ;
}
}
if ( removeUnread && dialog . unread_count ) dialog . unread_count -= removeUnread ;
dialogs . push ( dialog ) ;
appStateManager . setPeer ( dialog . peerID , appPeersManager . getPeer ( dialog . peerID ) ) ;
}
}
appStateManager . pushToState ( 'dialogs' , dialogs ) ;
appStateManager . pushToState ( 'messages' , messages ) ;
appStateManager . pushToState ( 'filters' , this . filtersStorage . filters ) ;
appStateManager . pushToState ( 'allDialogsLoaded' , this . dialogsStorage . allDialogsLoaded ) ;
appStateManager . pushToState ( 'maxSeenMsgID' , this . maxSeenID ) ;
} ) ;
appStateManager . getState ( ) . then ( state = > {
if ( state . maxSeenMsgID && ! appMessagesIDsManager . getMessageIDInfo ( state . maxSeenMsgID ) [ 1 ] ) {
this . maxSeenID = state . maxSeenMsgID ;
}
const messages = state . messages ;
if ( messages ) {
/ * l e t t e m p I D = t h i s . t e m p I D ;
for ( let message of messages ) {
if ( message . id < tempID ) {
tempID = message . id ;
}
}
if ( tempID != this . tempID ) {
this . log ( 'Set tempID to:' , tempID ) ;
this . tempID = tempID ;
} * /
this . saveMessages ( messages ) ;
}
if ( state . allDialogsLoaded ) {
this . dialogsStorage . allDialogsLoaded = state . allDialogsLoaded ;
}
if ( state . filters ) {
for ( const filterID in state . filters ) {
this . filtersStorage . saveDialogFilter ( state . filters [ filterID ] , false ) ;
}
}
if ( state . dialogs ) {
state . dialogs . forEachReverse ( dialog = > {
this . saveConversation ( dialog ) ;
2020-10-31 19:43:42 +01:00
// ! WARNING, убрать это когда нужно будет делать чтобы pending сообщения сохранялись
const message = this . getMessage ( dialog . top_message ) ;
if ( message . deleted ) {
this . reloadConversation ( dialog . peerID ) ;
}
2020-10-02 22:33:32 +02:00
} ) ;
}
} ) ;
2020-06-06 07:26:18 +02:00
}
2020-05-18 03:21:58 +02:00
2020-02-06 16:43:07 +01:00
public getInputEntities ( entities : any ) {
var sendEntites = copy ( entities ) ;
sendEntites . forEach ( ( entity : any ) = > {
if ( entity . _ == 'messageEntityMentionName' ) {
entity . _ = 'inputMessageEntityMentionName' ;
entity . user_id = appUsersManager . getUserInput ( entity . user_id ) ;
}
} ) ;
return sendEntites ;
}
2020-10-13 15:51:11 +02:00
public invokeAfterMessageIsSent ( messageID : number , callbackName : string , callback : ( mid : number ) = > Promise < any > ) {
const finalize = this . tempFinalizeCallbacks [ messageID ] ? ? ( this . tempFinalizeCallbacks [ messageID ] = { } ) ;
const obj = finalize [ callbackName ] ? ? ( finalize [ callbackName ] = { deferred : deferredPromise < void > ( ) } ) ;
obj . callback = callback ;
return obj . deferred ;
}
2020-10-10 00:36:06 +02:00
public editMessage ( messageID : number , text : string , options : Partial < {
noWebPage : true ,
newMedia : any
2020-10-13 15:51:11 +02:00
} > = { } ) : Promise < void > {
2020-10-10 04:08:12 +02: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
if ( messageID < 0 ) {
2020-10-13 15:51:11 +02:00
return this . invokeAfterMessageIsSent ( messageID , 'edit' , ( mid ) = > {
this . log ( 'invoke editMessage callback' , mid ) ;
return this . editMessage ( mid , text , options ) ;
2020-02-14 17:15:41 +01:00
} ) ;
}
2020-10-10 00:36:06 +02:00
let entities : any [ ] ;
if ( typeof ( text ) === 'string' ) {
entities = [ ] ;
text = RichTextProcessor . parseMarkdown ( text , entities ) ;
2020-02-14 17:15:41 +01:00
}
2020-10-10 00:36:06 +02:00
const message = this . getMessage ( messageID ) ;
const peerID = this . getMessagePeer ( message ) ;
2020-02-14 17:15:41 +01:00
return apiManager . invokeApi ( 'messages.editMessage' , {
2020-05-18 03:21:58 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
2020-02-14 17:15:41 +01:00
id : appMessagesIDsManager.getMessageLocalID ( messageID ) ,
message : text ,
2020-10-10 00:36:06 +02:00
media : options.newMedia ,
entities : entities ? this . getInputEntities ( entities ) : undefined ,
no_webpage : options.noWebPage ,
2020-02-14 17:15:41 +01:00
} ) . then ( ( updates ) = > {
2020-05-10 03:23:21 +02:00
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 ) ;
2020-02-14 17:15:41 +01:00
if ( error && error . type == 'MESSAGE_NOT_MODIFIED' ) {
error . handled = true ;
return ;
}
if ( error && error . type == 'MESSAGE_EMPTY' ) {
error . handled = true ;
}
return Promise . reject ( error ) ;
} ) ;
}
2020-05-18 03:21:58 +02:00
public sendText ( peerID : number , text : string , options : Partial < {
entities : any [ ] ,
replyToMsgID : number ,
viaBotID : number ,
2020-09-17 21:33:23 +02:00
queryID : string ,
resultID : string ,
2020-10-10 00:36:06 +02:00
noWebPage : true ,
2020-05-18 03:21:58 +02:00
reply_markup : any ,
2020-10-10 00:36:06 +02:00
clearDraft : true ,
2020-05-18 03:21:58 +02:00
webPage : any
} > = { } ) {
2020-10-15 18:07:34 +02:00
if ( typeof ( text ) != 'string' || ! text . length ) {
2020-02-06 16:43:07 +01:00
return ;
}
2020-10-15 18:07:34 +02:00
const MAX_LENGTH = 4096 ;
if ( text . length > MAX_LENGTH ) {
const splitted = splitStringByLength ( text , MAX_LENGTH ) ;
text = splitted [ 0 ] ;
2020-10-26 02:59:49 +01:00
if ( splitted . length > 1 ) {
delete options . webPage ;
}
2020-10-15 18:07:34 +02:00
for ( let i = 1 ; i < splitted . length ; ++ i ) {
2020-10-15 18:54:54 +02:00
setTimeout ( ( ) = > {
2020-10-15 18:07:34 +02:00
this . sendText ( peerID , splitted [ i ] , options ) ;
2020-10-15 18:54:54 +02:00
} , i ) ;
2020-10-15 18:07:34 +02:00
}
}
2020-05-18 03:21:58 +02:00
peerID = appPeersManager . getPeerMigratedTo ( peerID ) || peerID ;
2020-02-06 16:43:07 +01:00
var entities = options . entities || [ ] ;
if ( ! options . viaBotID ) {
text = RichTextProcessor . parseMarkdown ( text , entities ) ;
}
var sendEntites = this . getInputEntities ( entities ) ;
2020-10-10 00:36:06 +02:00
if ( ! sendEntites . length ) {
sendEntites = undefined ;
}
2020-02-06 16:43:07 +01:00
var messageID = this . tempID -- ;
2020-10-29 18:11:09 +01:00
var randomIDS = randomLong ( ) ;
2020-02-06 16:43:07 +01:00
var historyStorage = this . historiesStorage [ peerID ] ;
var pFlags : any = { } ;
var replyToMsgID = options . replyToMsgID ;
2020-05-18 03:21:58 +02:00
var isChannel = appPeersManager . isChannel ( peerID ) ;
var isMegagroup = isChannel && appPeersManager . isMegagroup ( peerID ) ;
2020-02-06 16:43:07 +01:00
var asChannel = isChannel && ! isMegagroup ? true : false ;
var message : any ;
if ( historyStorage === undefined ) {
2020-02-10 04:37:17 +01:00
historyStorage = this . historiesStorage [ peerID ] = { count : null , history : [ ] , pending : [ ] } ;
2020-02-06 16:43:07 +01:00
}
var fromID = appUsersManager . getSelf ( ) . id ;
if ( peerID != fromID ) {
pFlags . out = true ;
if ( ! isChannel && ! appUsersManager . isBot ( peerID ) ) {
pFlags . unread = true ;
}
}
if ( asChannel ) {
2020-02-10 04:37:17 +01:00
fromID = 0 ;
pFlags . post = true ;
2020-02-06 16:43:07 +01:00
}
message = {
_ : 'message' ,
id : messageID ,
2020-10-02 22:33:32 +02:00
from_id : appPeersManager.getOutputPeer ( fromID ) ,
peer_id : appPeersManager.getOutputPeer ( peerID ) ,
2020-02-06 16:43:07 +01:00
pFlags : pFlags ,
2020-02-11 16:35:57 +01:00
date : tsNow ( true ) + serverTimeManager . serverTimeOffset ,
2020-02-06 16:43:07 +01:00
message : text ,
random_id : randomIDS ,
2020-10-03 19:45:56 +02:00
reply_to : { reply_to_msg_id : replyToMsgID } ,
2020-02-06 16:43:07 +01:00
via_bot_id : options.viaBotID ,
reply_markup : options.reply_markup ,
entities : entities ,
views : asChannel && 1 ,
pending : true
} ;
2020-02-13 08:51:11 +01:00
if ( options . webPage ) {
message . media = {
_ : 'messageMediaWebPage' ,
webpage : options.webPage
} ;
}
2020-02-06 16:43:07 +01:00
var toggleError = ( on : any ) = > {
if ( on ) {
message . error = true ;
} else {
delete message . error ;
}
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_pending' ) ;
2020-02-06 16:43:07 +01:00
}
message . send = ( ) = > {
toggleError ( false ) ;
var sentRequestOptions : any = { } ;
if ( this . pendingAfterMsgs [ peerID ] ) {
sentRequestOptions . afterMessageID = this . pendingAfterMsgs [ peerID ] . messageID ;
}
var apiPromise : any ;
if ( options . viaBotID ) {
2020-10-15 18:54:54 +02:00
apiPromise = apiManager . invokeApiAfter ( 'messages.sendInlineBotResult' , {
2020-05-18 03:21:58 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
2020-10-29 18:11:09 +01:00
random_id : randomIDS ,
2020-10-10 00:36:06 +02:00
reply_to_msg_id : replyToMsgID ? appMessagesIDsManager . getMessageLocalID ( replyToMsgID ) : undefined ,
2020-02-06 16:43:07 +01:00
query_id : options.queryID ,
2020-10-10 00:36:06 +02:00
id : options.resultID ,
clear_draft : options.clearDraft
2020-02-06 16:43:07 +01:00
} , sentRequestOptions ) ;
} else {
2020-10-15 18:54:54 +02:00
apiPromise = apiManager . invokeApiAfter ( 'messages.sendMessage' , {
2020-10-10 00:36:06 +02:00
no_webpage : options.noWebPage ,
2020-05-18 03:21:58 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
2020-02-06 16:43:07 +01:00
message : text ,
2020-10-29 18:11:09 +01:00
random_id : randomIDS ,
2020-10-10 00:36:06 +02:00
reply_to_msg_id : replyToMsgID ? appMessagesIDsManager . getMessageLocalID ( replyToMsgID ) : undefined ,
entities : sendEntites ,
clear_draft : options.clearDraft
2020-02-06 16:43:07 +01:00
} , sentRequestOptions ) ;
}
2020-06-13 10:19:39 +02:00
// this.log(flags, entities)
2020-02-06 16:43:07 +01:00
apiPromise . then ( ( updates : any ) = > {
if ( updates . _ == 'updateShortSentMessage' ) {
message . date = updates . date ;
message . id = updates . id ;
message . media = updates . media ;
message . entities = updates . entities ;
updates = {
_ : 'updates' ,
users : [ ] ,
chats : [ ] ,
seq : 0 ,
updates : [ {
_ : 'updateMessageID' ,
random_id : randomIDS ,
id : updates.id
} , {
_ : isChannel
? 'updateNewChannelMessage'
: 'updateNewMessage' ,
message : message ,
pts : updates.pts ,
pts_count : updates.pts_count
} ]
} ;
} else if ( updates . updates ) {
updates . updates . forEach ( ( update : any ) = > {
if ( update . _ == 'updateDraftMessage' ) {
update . local = true ;
}
} ) ;
}
// Testing bad situations
// var upd = angular.copy(updates)
// updates.updates.splice(0, 1)
apiUpdatesManager . processUpdateMessage ( updates ) ;
// $timeout(function () {
// ApiUpdatesManager.processUpdateMessage(upd)
// }, 5000)
} , ( /* error: any */ ) = > {
toggleError ( true ) ;
} ) . finally ( ( ) = > {
if ( this . pendingAfterMsgs [ peerID ] === sentRequestOptions ) {
delete this . pendingAfterMsgs [ peerID ] ;
}
2020-02-10 04:37:17 +01:00
} ) ;
2020-02-06 16:43:07 +01:00
this . pendingAfterMsgs [ peerID ] = sentRequestOptions ;
}
this . saveMessages ( [ message ] ) ;
historyStorage . pending . unshift ( messageID ) ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_append' , { peerID , messageID , my : true } ) ;
2020-02-06 16:43:07 +01:00
setTimeout ( ( ) = > message . send ( ) , 0 ) ;
// setTimeout(function () {
// message.send()
// }, 5000)
/* if(options.clearDraft) { / / WARNING
DraftsManager . clearDraft ( peerID )
} * /
this . pendingByRandomID [ randomIDS ] = [ peerID , messageID ] ;
}
2020-09-17 21:33:23 +02:00
public sendFile ( peerID : number , file : File | Blob | MyDocument , options : Partial < {
2020-12-10 00:58:20 +01:00
isRoundMessage : true ,
isVoiceMessage : true ,
isGroupedItem : true ,
isMedia : true ,
2020-05-01 23:28:40 +02:00
replyToMsgID : number ,
caption : string ,
2020-12-10 00:58:20 +01:00
entities : MessageEntity [ ] ,
2020-05-01 23:28:40 +02:00
width : number ,
height : number ,
objectURL : string ,
duration : number ,
2020-12-10 00:58:20 +01:00
background : true ,
2020-06-02 00:19:35 +02:00
waveform : Uint8Array
2020-05-01 23:28:40 +02:00
} > = { } ) {
2020-05-18 03:21:58 +02:00
peerID = appPeersManager . getPeerMigratedTo ( peerID ) || peerID ;
2020-12-10 00:58:20 +01:00
const messageID = this . tempID -- ;
const randomIDS = randomLong ( ) ;
const historyStorage = this . historiesStorage [ peerID ] ? ? ( this . historiesStorage [ peerID ] = { count : null , history : [ ] , pending : [ ] } ) ;
const pFlags : any = { } ;
const replyToMsgID = options . replyToMsgID ;
const isChannel = appPeersManager . isChannel ( peerID ) ;
const isMegagroup = isChannel && appPeersManager . isMegagroup ( peerID ) ;
const asChannel = ! ! ( isChannel && ! isMegagroup ) ;
let attachType : string , 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-11-10 01:47:00 +01:00
const date = tsNow ( true ) + serverTimeManager . serverTimeOffset ;
2020-04-26 03:45:07 +02:00
2020-06-13 10:19:39 +02:00
this . log ( 'sendFile' , file , fileType ) ;
2020-06-02 00:19:35 +02:00
2020-02-06 16:43:07 +01:00
if ( caption ) {
let entities = options . entities || [ ] ;
caption = RichTextProcessor . parseMarkdown ( caption , entities ) ;
}
2020-09-19 13:37:19 +02:00
const attributes : DocumentAttribute [ ] = [ ] ;
const isPhoto = [ 'image/jpeg' , 'image/png' , 'image/bmp' ] . indexOf ( fileType ) >= 0 ;
2020-04-28 19:30:54 +02:00
2020-12-10 00:58:20 +01:00
let photo : MyPhoto , document : MyDocument ;
2020-02-08 07:03:09 +01:00
let actionName = '' ;
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' ;
apiFileName = 'audio.' + ( fileType . split ( '/' ) [ 1 ] == 'ogg' ? 'ogg' : 'mp3' ) ;
actionName = 'sendMessageUploadAudioAction' ;
if ( options . isVoiceMessage ) {
attachType = 'voice' ;
pFlags . media_unread = true ;
}
let attribute : DocumentAttribute.documentAttributeAudio = {
_ : 'documentAttributeAudio' ,
pFlags : {
voice : options.isVoiceMessage
} ,
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
2020-12-10 00:58:20 +01:00
photo = {
2020-04-26 03:45:07 +02:00
_ : 'photo' ,
id : '' + messageID ,
sizes : [ {
_ : 'photoSize' ,
w : options.width ,
h : options.height ,
2020-09-19 13:37:19 +02:00
type : 'full' ,
location : null ,
2020-04-26 03:45:07 +02:00
size : file.size
2020-09-19 13:37:19 +02:00
} ] ,
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
defineNotNumerableProperties ( photo , [ 'downloaded' , 'url' ] ) ;
photo . downloaded = file . size ;
photo . url = options . objectURL || '' ;
2020-04-26 03:45:07 +02:00
appPhotosManager . savePhoto ( photo ) ;
2020-04-28 19:30:54 +02:00
} else if ( fileType . indexOf ( 'video/' ) === 0 ) {
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
2020-09-19 13:37:19 +02:00
let videoAttribute : DocumentAttribute.documentAttributeVideo = {
2020-04-28 19:30:54 +02:00
_ : 'documentAttributeVideo' ,
2020-12-10 00:58:20 +01:00
pFlags : {
round_message : options.isRoundMessage
2020-04-28 19:30:54 +02:00
} ,
duration : options.duration ,
w : options.width ,
h : options.height
} ;
attributes . push ( videoAttribute ) ;
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 } ) ;
2020-06-13 10:19:39 +02:00
if ( [ 'document' , 'video' , 'audio' , 'voice' ] . 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' ,
id : '' + messageID ,
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
2020-12-10 00:58:20 +01:00
defineNotNumerableProperties ( document , [ 'downloaded' , 'url' ] ) ;
2020-10-22 01:59:30 +02:00
// @ts-ignore
2020-12-10 00:58:20 +01:00
document . downloaded = file . size ;
document . url = options . objectURL || '' ;
2020-10-22 01:59:30 +02:00
2020-09-19 13:37:19 +02:00
if ( isPhoto ) {
attributes . push ( {
_ : 'documentAttributeImageSize' ,
w : options.width ,
h : options.height
} ) ;
thumbs . push ( {
_ : 'photoSize' ,
w : options.width ,
h : options.height ,
type : 'full' ,
location : null ,
size : file.size ,
url : options.objectURL
} ) ;
}
2020-04-28 19:30:54 +02:00
2020-12-10 00:58:20 +01:00
appDocsManager . saveDoc ( document ) ;
2020-02-06 16:43:07 +01:00
}
2020-06-13 10:19:39 +02:00
this . log ( 'AMM: sendFile' , attachType , apiFileName , file . type , options ) ;
2020-02-06 16:43:07 +01:00
2020-12-10 00:58:20 +01:00
let fromID = appUsersManager . getSelf ( ) . id ;
2020-02-06 16:43:07 +01:00
if ( peerID != fromID ) {
pFlags . out = true ;
if ( ! isChannel && ! appUsersManager . isBot ( peerID ) ) {
pFlags . unread = true ;
}
}
if ( asChannel ) {
fromID = 0 ;
pFlags . post = true ;
}
2020-10-16 12:08:28 +02:00
const preloader = new ProgressivePreloader ( null , true , false , 'prepend' ) ;
2020-02-07 15:17:39 +01:00
2020-08-28 17:11:25 +02:00
const media = {
2020-02-06 16:43:07 +01:00
_ : 'messageMediaPending' ,
2020-12-10 00:58:20 +01:00
type : options . isGroupedItem && options . isMedia ? 'album' : attachType ,
2020-02-06 16:43:07 +01:00
file_name : fileName || apiFileName ,
size : file.size ,
2020-12-10 00:58:20 +01:00
file ,
preloader ,
photo ,
document ,
2020-02-11 07:22:12 +01:00
w : options.width ,
h : options.height ,
2020-08-28 17:11:25 +02:00
url : options.objectURL
2020-02-07 15:17:39 +01:00
} ;
2020-08-28 17:11:25 +02:00
const message : any = {
2020-02-06 16:43:07 +01:00
_ : 'message' ,
id : messageID ,
2020-10-02 22:33:32 +02:00
from_id : appPeersManager.getOutputPeer ( fromID ) ,
peer_id : appPeersManager.getOutputPeer ( peerID ) ,
2020-12-10 00:58:20 +01:00
pFlags ,
date ,
2020-02-06 16:43:07 +01:00
message : caption ,
2020-06-13 10:19:39 +02:00
media : isDocument ? {
2020-02-06 16:43:07 +01:00
_ : 'messageMediaDocument' ,
pFlags : { } ,
document : file
2020-06-13 10:19:39 +02:00
} : media ,
2020-02-06 16:43:07 +01:00
random_id : randomIDS ,
2020-10-03 19:45:56 +02:00
reply_to : { reply_to_msg_id : replyToMsgID } ,
2020-02-06 16:43:07 +01:00
views : asChannel && 1 ,
pending : true
} ;
2020-08-28 17:11:25 +02:00
const toggleError = ( on : boolean ) = > {
2020-02-06 16:43:07 +01:00
if ( on ) {
message . error = true ;
} else {
delete message . error ;
}
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_pending' ) ;
2020-02-06 16:43:07 +01:00
} ;
2020-08-28 17:11:25 +02:00
let uploaded = false ,
2020-08-21 13:17:16 +02:00
uploadPromise : ReturnType < ApiFileManager [ ' uploadFile ' ] > = null ;
2020-02-06 16:43:07 +01:00
2020-12-10 00:58:20 +01:00
const sentDeferred = deferredPromise < InputMedia > ( ) ;
2020-02-06 16:43:07 +01:00
message . send = ( ) = > {
if ( isDocument ) {
2020-09-17 21:33:23 +02:00
const { id , access_hash , file_reference } = file as MyDocument ;
2020-02-06 16:43:07 +01:00
2020-12-10 00:58:20 +01:00
const inputMedia : InputMedia = {
2020-02-06 16:43:07 +01:00
_ : 'inputMediaDocument' ,
id : {
_ : 'inputDocument' ,
2020-12-10 00:58:20 +01:00
id ,
access_hash ,
file_reference
2020-02-06 16:43:07 +01: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-08-28 17:11:25 +02:00
const deferred = deferredPromise < void > ( ) ;
2020-02-06 16:43:07 +01:00
this . sendFilePromise . then ( ( ) = > {
if ( ! uploaded || message . error ) {
uploaded = false ;
2020-08-28 17:11:25 +02:00
uploadPromise = appDownloadManager . upload ( file ) ;
preloader . attachPromise ( uploadPromise ) ;
2020-02-06 16:43:07 +01:00
}
uploadPromise && uploadPromise . then ( ( inputFile ) = > {
2020-06-13 10:19:39 +02:00
this . log ( 'appMessagesManager: sendFile uploaded:' , inputFile ) ;
2020-04-26 03:45:07 +02: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 = {
_ : 'inputMediaUploadedPhoto' ,
file : inputFile
} ;
break ;
2020-04-28 19:30:54 +02:00
2020-02-06 16:43:07 +01:00
default :
inputMedia = {
_ : 'inputMediaUploadedDocument' ,
file : inputFile ,
mime_type : fileType ,
2020-12-10 00:58:20 +01:00
attributes
2020-02-06 16:43:07 +01:00
} ;
}
2020-12-10 00:58:20 +01:00
sentDeferred . resolve ( inputMedia ) ;
2020-02-06 16:43:07 +01:00
} , ( /* error */ ) = > {
toggleError ( true ) ;
} ) ;
2020-08-28 17:11:25 +02:00
uploadPromise . addNotifyListener ( ( progress : { done : number , total : number } ) = > {
2020-06-13 10:19:39 +02:00
this . log ( 'upload progress' , progress ) ;
2020-08-28 17:11:25 +02:00
const percents = Math . max ( 1 , Math . floor ( 100 * progress . done / progress . total ) ) ;
2020-10-28 17:11:57 +01:00
this . setTyping ( peerID , { _ : actionName , progress : percents | 0 } ) ;
2020-08-28 17:11:25 +02:00
} ) ;
uploadPromise . catch ( err = > {
if ( err . name === 'AbortError' && ! uploaded ) {
this . log ( 'cancelling upload' , media ) ;
2020-02-06 16:43:07 +01:00
deferred . resolve ( ) ;
2020-12-10 00:58:20 +01:00
sentDeferred . reject ( err ) ;
2020-02-06 16:43:07 +01:00
this . cancelPendingMessage ( randomIDS ) ;
2020-10-28 17:11:57 +01:00
this . setTyping ( peerID , 'sendMessageCancelAction' ) ;
2020-02-06 16:43:07 +01:00
}
2020-02-07 15:17:39 +01:00
} ) ;
2020-08-28 17:11:25 +02:00
uploadPromise . finally ( deferred . resolve ) ;
2020-02-06 16:43:07 +01:00
} ) ;
this . sendFilePromise = deferred ;
}
2020-12-10 00:58:20 +01:00
return sentDeferred ;
2020-02-06 16:43:07 +01:00
} ;
historyStorage . pending . unshift ( messageID ) ;
2020-12-10 00:58:20 +01:00
this . pendingByRandomID [ randomIDS ] = [ peerID , messageID ] ;
2020-02-06 16:43:07 +01:00
2020-12-10 00:58:20 +01:00
if ( ! options . isGroupedItem ) {
this . saveMessages ( [ message ] ) ;
rootScope . broadcast ( 'history_append' , { peerID , messageID , my : true } ) ;
setTimeout ( message . send , 0 ) ;
sentDeferred . then ( inputMedia = > {
this . setTyping ( peerID , 'sendMessageCancelAction' ) ;
return apiManager . invokeApi ( 'messages.sendMedia' , {
background : options.background ,
clear_draft : true ,
peer : appPeersManager.getInputPeerByID ( peerID ) ,
media : inputMedia ,
message : caption ,
random_id : randomIDS ,
reply_to_msg_id : appMessagesIDsManager.getMessageLocalID ( replyToMsgID )
} ) . then ( ( updates ) = > {
apiUpdatesManager . processUpdateMessage ( updates ) ;
} , ( error ) = > {
if ( attachType == 'photo' &&
error . code == 400 &&
( error . type == 'PHOTO_INVALID_DIMENSIONS' ||
error . type == 'PHOTO_SAVE_FILE_INVALID' ) ) {
error . handled = true ;
attachType = 'document' ;
message . send ( ) ;
return ;
}
2020-02-06 16:43:07 +01:00
2020-12-10 00:58:20 +01:00
toggleError ( true ) ;
} ) ;
} ) ;
}
return { message , promise : sentDeferred } ;
2020-02-06 16:43:07 +01:00
}
2020-05-01 23:28:40 +02:00
public async sendAlbum ( peerID : number , files : File [ ] , options : Partial < {
2020-12-10 00:58:20 +01:00
isMedia : true ,
entities : MessageEntity [ ] ,
2020-05-01 23:28:40 +02:00
replyToMsgID : number ,
caption : string ,
sendFileDetails : Partial < {
duration : number ,
width : number ,
height : number ,
objectURL : string ,
} > [ ]
} > = { } ) {
2020-12-10 00:58:20 +01:00
if ( files . length === 1 ) {
return this . sendFile ( peerID , files [ 0 ] , { . . . options , . . . options . sendFileDetails [ 0 ] } ) ;
}
2020-05-18 03:21:58 +02:00
peerID = appPeersManager . getPeerMigratedTo ( peerID ) || peerID ;
2020-12-10 00:58:20 +01:00
const replyToMsgID = options . replyToMsgID ;
2020-05-01 23:28:40 +02:00
let caption = options . caption || '' ;
2020-12-10 00:58:20 +01:00
let entities : MessageEntity [ ] ;
2020-05-01 23:28:40 +02:00
if ( caption ) {
2020-12-10 00:58:20 +01:00
entities = options . entities || [ ] ;
2020-05-01 23:28:40 +02:00
caption = RichTextProcessor . parseMarkdown ( caption , entities ) ;
}
2020-06-13 10:19:39 +02:00
this . log ( 'AMM: sendAlbum' , files , options ) ;
2020-05-01 23:28:40 +02:00
2020-12-10 00:58:20 +01:00
const messages = files . map ( ( file , idx ) = > {
const details = options . sendFileDetails [ idx ] ;
const o : any = {
isGroupedItem : true ,
isMedia : options.isMedia ,
. . . 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 ;
o . replyToMsgID = replyToMsgID ;
2020-05-01 23:28:40 +02:00
}
2020-12-10 00:58:20 +01:00
return this . sendFile ( peerID , file , o ) . message ;
} ) ;
2020-05-01 23:28:40 +02:00
2020-12-10 00:58:20 +01:00
const groupID = messages [ 0 ] . id ;
messages . forEach ( message = > {
message . grouped_id = groupID ;
2020-05-01 23:28:40 +02:00
} ) ;
2020-12-10 00:58:20 +01:00
this . saveMessages ( messages ) ;
2020-05-01 23:28:40 +02:00
2020-12-10 00:58:20 +01:00
rootScope . broadcast ( 'history_append' , { peerID , messageID : groupID , my : true } ) ;
//return;
2020-05-01 23:28:40 +02:00
2020-12-10 00:58:20 +01:00
const toggleError = ( message : any , on : boolean ) = > {
2020-05-01 23:28:40 +02:00
if ( on ) {
message . error = true ;
} else {
delete message . error ;
}
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_pending' ) ;
2020-05-01 23:28:40 +02:00
} ;
2020-12-10 00:58:20 +01:00
const inputPeer = appPeersManager . getInputPeerByID ( peerID ) ;
const invoke = ( multiMedia : any [ ] ) = > {
2020-10-28 17:11:57 +01:00
this . setTyping ( peerID , 'sendMessageCancelAction' ) ;
2020-05-01 23:28:40 +02:00
return apiManager . invokeApi ( 'messages.sendMultiMedia' , {
peer : inputPeer ,
multi_media : multiMedia ,
reply_to_msg_id : appMessagesIDsManager.getMessageLocalID ( replyToMsgID )
} ) . then ( ( updates ) = > {
apiUpdatesManager . processUpdateMessage ( updates ) ;
} , ( error ) = > {
messages . forEach ( message = > toggleError ( message , true ) ) ;
} ) ;
} ;
2020-12-10 00:58:20 +01:00
const inputs : InputSingleMedia [ ] = [ ] ;
for ( const message of messages ) {
const inputMedia : InputMedia = await message . send ( ) ;
this . log ( 'sendAlbum uploaded item:' , inputMedia ) ;
2020-08-28 17:11:25 +02:00
2020-12-10 00:58:20 +01:00
await apiManager . invokeApi ( 'messages.uploadMedia' , {
peer : inputPeer ,
media : inputMedia
} ) . then ( messageMedia = > {
2020-05-01 23:28:40 +02:00
let inputMedia : any ;
2020-12-10 00:58:20 +01:00
if ( messageMedia . _ == 'messageMediaPhoto' ) {
const photo = appPhotosManager . savePhoto ( messageMedia . photo ) ;
inputMedia = appPhotosManager . getInput ( photo ) ;
} else if ( messageMedia . _ == 'messageMediaDocument' ) {
const doc = appDocsManager . saveDoc ( messageMedia . document ) ;
inputMedia = appDocsManager . getMediaInput ( doc ) ;
2020-05-01 23:28:40 +02:00
}
2020-12-10 00:58:20 +01:00
inputs . push ( {
_ : 'inputSingleMedia' ,
media : inputMedia ,
random_id : message.random_id ,
message : caption ,
entities
2020-05-01 23:28:40 +02:00
} ) ;
2020-12-10 00:58:20 +01:00
// * only 1 caption for all inputs
if ( caption ) {
caption = '' ;
entities = [ ] ;
}
2020-05-01 23:28:40 +02:00
} , ( ) = > {
toggleError ( message , true ) ;
} ) ;
}
invoke ( inputs ) ;
}
2020-06-16 22:48:08 +02:00
public sendOther ( peerID : number , inputMedia : any , options : Partial < {
replyToMsgID : number ,
viaBotID : number ,
reply_markup : any ,
2020-10-10 00:36:06 +02:00
clearDraft : true ,
2020-09-17 21:33:23 +02:00
queryID : string
resultID : string
2020-06-16 22:48:08 +02:00
} > = { } ) {
peerID = appPeersManager . getPeerMigratedTo ( peerID ) || peerID ;
const messageID = this . tempID -- ;
2020-10-29 18:11:09 +01:00
const randomIDS = randomLong ( ) ;
2020-06-16 22:48:08 +02:00
const historyStorage = this . historiesStorage [ peerID ] ? ? ( this . historiesStorage [ peerID ] = { count : null , history : [ ] , pending : [ ] } ) ;
const replyToMsgID = options . replyToMsgID ;
const isChannel = appPeersManager . isChannel ( peerID ) ;
const isMegagroup = isChannel && appPeersManager . isMegagroup ( peerID ) ;
const asChannel = isChannel && ! isMegagroup ? true : false ;
let fromID = appUsersManager . getSelf ( ) . id ;
let media ;
switch ( inputMedia . _ ) {
case 'inputMediaPoll' : {
inputMedia . poll . id = messageID ;
appPollsManager . savePoll ( inputMedia . poll , {
_ : 'pollResults' ,
flags : 4 ,
total_voters : 0 ,
pFlags : { } ,
} ) ;
const { poll , results } = appPollsManager . getPoll ( '' + messageID ) ;
media = {
_ : 'messageMediaPoll' ,
poll ,
results
} ;
break ;
}
/ * c a s e ' i n p u t M e d i a P h o t o ' :
media = {
_ : 'messageMediaPhoto' ,
photo : appPhotosManager.getPhoto ( inputMedia . id . id ) ,
caption : inputMedia.caption || ''
} ;
break ;
case 'inputMediaDocument' :
var doc = appDocsManager . getDoc ( inputMedia . id . id ) ;
if ( doc . sticker && doc . stickerSetInput ) {
appStickersManager . pushPopularSticker ( doc . id ) ;
}
media = {
_ : 'messageMediaDocument' ,
'document' : doc ,
caption : inputMedia.caption || ''
} ;
break ;
case 'inputMediaContact' :
media = {
_ : 'messageMediaContact' ,
phone_number : inputMedia.phone_number ,
first_name : inputMedia.first_name ,
last_name : inputMedia.last_name ,
user_id : 0
} ;
break ;
case 'inputMediaGeoPoint' :
media = {
_ : 'messageMediaGeo' ,
geo : {
_ : 'geoPoint' ,
'lat' : inputMedia . geo_point [ 'lat' ] ,
'long' : inputMedia . geo_point [ 'long' ]
}
} ;
break ;
case 'inputMediaVenue' :
media = {
_ : 'messageMediaVenue' ,
geo : {
_ : 'geoPoint' ,
'lat' : inputMedia . geo_point [ 'lat' ] ,
'long' : inputMedia . geo_point [ 'long' ]
} ,
title : inputMedia.title ,
address : inputMedia.address ,
provider : inputMedia.provider ,
venue_id : inputMedia.venue_id
} ;
break ;
case 'messageMediaPending' :
media = inputMedia ;
break ; * /
}
let pFlags : any = { } ;
if ( peerID != fromID ) {
pFlags . out = true ;
if ( ! appUsersManager . isBot ( peerID ) ) {
pFlags . unread = true ;
}
}
2020-10-10 00:36:06 +02:00
2020-06-16 22:48:08 +02:00
if ( asChannel ) {
fromID = 0 ;
pFlags . post = true ;
}
const message : any = {
_ : 'message' ,
id : messageID ,
2020-10-02 22:33:32 +02:00
from_id : appPeersManager.getOutputPeer ( fromID ) ,
peer_id : appPeersManager.getOutputPeer ( peerID ) ,
2020-06-16 22:48:08 +02:00
pFlags : pFlags ,
2020-11-10 01:47:00 +01:00
date : tsNow ( true ) + serverTimeManager . serverTimeOffset ,
2020-06-16 22:48:08 +02:00
message : '' ,
media : media ,
random_id : randomIDS ,
2020-10-03 19:45:56 +02:00
reply_to : { reply_to_msg_id : replyToMsgID } ,
2020-06-16 22:48:08 +02:00
via_bot_id : options.viaBotID ,
reply_markup : options.reply_markup ,
views : asChannel && 1 ,
pending : true ,
} ;
let toggleError = ( on : boolean ) = > {
/ * c o n s t h i s t o r y M e s s a g e = t h i s . m e s s a g e s F o r H i s t o r y [ m e s s a g e I D ] ;
if ( on ) {
message . error = true
if ( historyMessage ) {
historyMessage . error = true
}
} else {
delete message . error
if ( historyMessage ) {
delete historyMessage . error
}
} * /
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_pending' ) ;
2020-06-16 22:48:08 +02:00
} ;
message . send = ( ) = > {
const sentRequestOptions : any = { } ;
if ( this . pendingAfterMsgs [ peerID ] ) {
sentRequestOptions . afterMessageID = this . pendingAfterMsgs [ peerID ] . messageID ;
}
let apiPromise : Promise < any > ;
if ( options . viaBotID ) {
2020-10-15 18:54:54 +02:00
apiPromise = apiManager . invokeApiAfter ( 'messages.sendInlineBotResult' , {
2020-06-16 22:48:08 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
2020-10-29 18:11:09 +01:00
random_id : randomIDS ,
2020-10-10 00:36:06 +02:00
reply_to_msg_id : replyToMsgID ? appMessagesIDsManager . getMessageLocalID ( replyToMsgID ) : undefined ,
2020-06-16 22:48:08 +02:00
query_id : options.queryID ,
2020-10-10 00:36:06 +02:00
id : options.resultID ,
clear_draft : options.clearDraft
2020-06-16 22:48:08 +02:00
} , sentRequestOptions ) ;
} else {
2020-10-15 18:54:54 +02:00
apiPromise = apiManager . invokeApiAfter ( 'messages.sendMedia' , {
2020-06-16 22:48:08 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
media : inputMedia ,
2020-10-29 18:11:09 +01:00
random_id : randomIDS ,
2020-10-10 00:36:06 +02:00
reply_to_msg_id : replyToMsgID ? appMessagesIDsManager . getMessageLocalID ( replyToMsgID ) : undefined ,
message : '' ,
clear_draft : options.clearDraft
2020-06-16 22:48:08 +02:00
} , sentRequestOptions ) ;
}
2020-10-10 00:36:06 +02:00
2020-06-16 22:48:08 +02:00
apiPromise . then ( ( updates ) = > {
if ( updates . updates ) {
updates . updates . forEach ( ( update : any ) = > {
if ( update . _ == 'updateDraftMessage' ) {
update . local = true
}
} ) ;
}
apiUpdatesManager . processUpdateMessage ( updates ) ;
} , ( error ) = > {
toggleError ( true ) ;
} ) . finally ( ( ) = > {
if ( this . pendingAfterMsgs [ peerID ] === sentRequestOptions ) {
delete this . pendingAfterMsgs [ peerID ] ;
}
} ) ;
this . pendingAfterMsgs [ peerID ] = sentRequestOptions ;
}
this . saveMessages ( [ message ] ) ;
historyStorage . pending . unshift ( messageID ) ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_append' , { peerID , messageID , my : true } ) ;
2020-06-16 22:48:08 +02:00
setTimeout ( message . send , 0 ) ;
/ * i f ( o p t i o n s . c l e a r D r a f t ) {
DraftsManager . clearDraft ( peerID )
} * /
this . pendingByRandomID [ randomIDS ] = [ peerID , messageID ] ;
}
2020-02-06 16:43:07 +01:00
public cancelPendingMessage ( randomID : string ) {
2020-10-10 00:36:06 +02:00
const pendingData = this . pendingByRandomID [ randomID ] ;
2020-02-06 16:43:07 +01:00
2020-06-13 10:19:39 +02:00
this . log ( 'cancelPendingMessage' , randomID , pendingData ) ;
2020-02-06 16:43:07 +01:00
if ( pendingData ) {
2020-10-10 00:36:06 +02:00
const peerID = pendingData [ 0 ] ;
const tempID = pendingData [ 1 ] ;
const historyStorage = this . historiesStorage [ peerID ] ;
const pos = historyStorage . pending . indexOf ( tempID ) ;
2020-02-06 16:43:07 +01:00
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateDeleteMessages' ,
messages : [ tempID ]
}
} ) ;
if ( pos != - 1 ) {
historyStorage . pending . splice ( pos , 1 ) ;
}
delete this . messagesStorage [ tempID ] ;
return true ;
}
return false ;
}
2020-10-15 22:58:14 +02:00
public async getConversationsAll ( query = '' , folderID = 0 ) {
2020-08-31 18:48:46 +02:00
const limit = 100 , outDialogs : Dialog [ ] = [ ] ;
2020-10-15 22:58:14 +02:00
for ( ; folderID < 2 ; ++ folderID ) {
2020-08-31 18:48:46 +02:00
let offsetIndex = 0 ;
for ( ; ; ) {
const { dialogs } = await appMessagesManager . getConversations ( query , offsetIndex , limit , folderID ) ;
if ( dialogs . length ) {
outDialogs . push ( . . . dialogs ) ;
offsetIndex = dialogs [ dialogs . length - 1 ] . index || 0 ;
} else {
break ;
}
}
}
return outDialogs ;
}
2020-05-30 08:44:54 +02:00
public getConversations ( query = '' , offsetIndex? : number , limit = 20 , folderID = 0 ) {
2020-06-19 13:49:55 +02:00
const realFolderID = folderID > 1 ? 0 : folderID ;
let curDialogStorage = this . dialogsStorage . getFolder ( folderID ) ;
2020-02-06 16:43:07 +01:00
2020-05-30 08:44:54 +02:00
if ( query ) {
2020-10-08 00:20:38 +02:00
if ( ! limit || this . cachedResults . query !== query || this . cachedResults . folderID != folderID ) {
this . cachedResults . query = query ;
this . cachedResults . folderID = folderID ;
2020-05-30 08:44:54 +02:00
const results = searchIndexManager . search ( query , this . dialogsIndex ) ;
this . cachedResults . dialogs = [ ] ;
2020-10-08 00:20:38 +02:00
2020-06-19 13:49:55 +02:00
for ( const peerID in this . dialogsStorage . dialogs ) {
const dialog = this . dialogsStorage . dialogs [ peerID ] ;
2020-10-08 00:20:38 +02:00
if ( results [ dialog . peerID ] && dialog . folder_id == folderID ) {
2020-06-19 13:49:55 +02:00
this . cachedResults . dialogs . push ( dialog ) ;
}
2020-05-30 08:44:54 +02:00
}
2020-10-08 00:20:38 +02:00
this . cachedResults . dialogs . sort ( ( d1 , d2 ) = > d2 . index - d1 . index ) ;
2020-05-30 08:44:54 +02:00
this . cachedResults . count = this . cachedResults . dialogs . length ;
}
curDialogStorage = this . cachedResults . dialogs ;
} else {
this . cachedResults . query = '' ;
}
2020-05-06 03:03:31 +02:00
let offset = 0 ;
2020-02-06 16:43:07 +01:00
if ( offsetIndex > 0 ) {
2020-02-12 14:48:30 +01:00
for ( ; offset < curDialogStorage . length ; offset ++ ) {
if ( offsetIndex > curDialogStorage [ offset ] . index ) {
2020-02-06 16:43:07 +01:00
break ;
}
}
}
2020-06-19 13:49:55 +02:00
if ( query || this . dialogsStorage . allDialogsLoaded [ realFolderID ] || curDialogStorage . length >= offset + limit ) {
2020-02-06 16:43:07 +01:00
return Promise . resolve ( {
2020-02-14 17:15:41 +01:00
dialogs : curDialogStorage.slice ( offset , offset + limit ) ,
2020-11-11 18:01:38 +01:00
count : this.dialogsStorage.allDialogsLoaded [ realFolderID ] ? curDialogStorage.length : null ,
isEnd : this.dialogsStorage.allDialogsLoaded [ realFolderID ] && ( offset + limit ) >= curDialogStorage . length
2020-02-06 16:43:07 +01:00
} ) ;
}
2020-06-19 13:49:55 +02:00
return this . getTopMessages ( limit , realFolderID ) . then ( totalCount = > {
2020-05-30 08:44:54 +02:00
//const curDialogStorage = this.dialogsStorage[folderID];
2020-02-12 14:48:30 +01:00
offset = 0 ;
2020-02-06 16:43:07 +01:00
if ( offsetIndex > 0 ) {
2020-05-06 03:03:31 +02:00
for ( ; offset < curDialogStorage . length ; offset ++ ) {
2020-02-12 14:48:30 +01:00
if ( offsetIndex > curDialogStorage [ offset ] . index ) {
2020-02-06 16:43:07 +01:00
break ;
}
}
}
2020-06-13 10:19:39 +02:00
//this.log.warn(offset, offset + limit, curDialogStorage.dialogs.length, this.dialogsStorage.dialogs.length);
2020-02-06 16:43:07 +01:00
return {
2020-02-14 17:15:41 +01:00
dialogs : curDialogStorage.slice ( offset , offset + limit ) ,
2020-11-11 18:01:38 +01:00
count : totalCount ,
isEnd : this.dialogsStorage.allDialogsLoaded [ realFolderID ] && ( offset + limit ) >= curDialogStorage . length
2020-02-06 16:43:07 +01:00
} ;
} ) ;
}
2020-05-06 03:03:31 +02:00
public getTopMessages ( limit : number , folderID : number ) : Promise < number > {
2020-06-19 13:49:55 +02:00
const dialogs = this . dialogsStorage . getFolder ( folderID ) ;
2020-05-18 03:21:58 +02:00
let offsetID = 0 ;
let offsetDate = 0 ;
let offsetPeerID = 0 ;
let offsetIndex = 0 ;
let flags = 0 ;
2020-02-06 16:43:07 +01:00
2020-06-19 13:49:55 +02:00
if ( this . dialogsStorage . dialogsOffsetDate [ folderID ] ) {
offsetDate = this . dialogsStorage . dialogsOffsetDate [ folderID ] + serverTimeManager . serverTimeOffset ;
offsetIndex = this . dialogsStorage . dialogsOffsetDate [ folderID ] * 0x10000 ;
2020-05-30 08:44:54 +02:00
//flags |= 1; // means pinned already loaded
2020-02-06 16:43:07 +01:00
}
2020-09-20 00:38:00 +02:00
/ * i f ( t h i s . d i a l o g s S t o r a g e . d i a l o g s O f f s e t D a t e [ 0 ] ) {
flags |= 1 ; // means pinned already loaded
} * /
2020-05-30 08:44:54 +02:00
//if(folderID > 0) {
//flags |= 1;
2020-02-12 14:48:30 +01:00
flags |= 2 ;
2020-05-30 08:44:54 +02:00
//}
2020-02-06 16:43:07 +01:00
2020-09-19 18:32:48 +02:00
// ! ВНИМАНИЕ: ОЧЕНЬ СЛОЖНАЯ ЛОГИКА:
2020-09-20 00:38:00 +02:00
// ! если делать запрос сначала по папке 0, потом по папке 1, по индексу 0 в массиве будет один и тот же диалог, с dialog.pFlags.pinned, ЛОЛ???
// ! т.е ., с запросом folder_id: 1, и exclude_pinned: 0, в результате будут ещё и закреплённые с папки 0
2020-02-11 16:35:57 +01:00
return apiManager . invokeApi ( 'messages.getDialogs' , {
2020-09-20 00:38:00 +02:00
flags ,
2020-02-12 14:48:30 +01:00
folder_id : folderID ,
2020-02-06 16:43:07 +01:00
offset_date : offsetDate ,
offset_id : appMessagesIDsManager.getMessageLocalID ( offsetID ) ,
2020-05-18 03:21:58 +02:00
offset_peer : appPeersManager.getInputPeerByID ( offsetPeerID ) ,
2020-09-20 00:38:00 +02:00
limit ,
2020-05-30 08:44:54 +02:00
hash : 0
2020-02-06 16:43:07 +01:00
} , {
2020-09-18 17:52:21 +02:00
//timeout: APITIMEOUT,
noErrorBox : true
2020-09-18 17:03:26 +02:00
} ) . then ( ( dialogsResult ) = > {
if ( dialogsResult . _ == 'messages.dialogsNotModified' ) return null ;
2020-09-20 00:38:00 +02:00
//this.log.error('messages.getDialogs result:', dialogsResult.dialogs, {...dialogsResult.dialogs[0]});
2020-09-19 18:32:48 +02:00
2020-10-02 22:33:32 +02:00
/ * i f ( ! o f f s e t D a t e ) {
2020-02-06 16:43:07 +01:00
telegramMeWebService . setAuthorized ( true ) ;
2020-10-02 22:33:32 +02:00
} * /
2020-02-06 16:43:07 +01:00
appUsersManager . saveApiUsers ( dialogsResult . users ) ;
appChatsManager . saveApiChats ( dialogsResult . chats ) ;
this . saveMessages ( dialogsResult . messages ) ;
2020-09-18 17:03:26 +02:00
let maxSeenIdIncremented = offsetDate ? true : false ;
let hasPrepend = false ;
2020-09-20 00:38:00 +02:00
const noIDsDialogs : { [ peerID : number ] : Dialog } = { } ;
2020-09-18 17:03:26 +02:00
( dialogsResult . dialogs as Dialog [ ] ) . forEachReverse ( dialog = > {
//const d = Object.assign({}, dialog);
// ! нужно передавать folderID, так как по папке != 0 нет свойства folder_id
this . saveConversation ( dialog , folderID ) ;
2020-09-19 18:32:48 +02:00
/ * i f ( d i a l o g . p e e r I D = = - 1 2 1 3 5 1 1 2 9 4 ) {
2020-09-18 17:03:26 +02:00
this . log . error ( 'lun bot' , folderID , d ) ;
} * /
2020-02-06 16:43:07 +01:00
if ( offsetIndex && dialog . index > offsetIndex ) {
this . newDialogsToHandle [ dialog . peerID ] = dialog ;
hasPrepend = true ;
}
2020-09-18 17:03:26 +02:00
// ! это может случиться, если запрос идёт не по папке 0, а по 1. почему-то read'ов нет
// ! в итоге, чтобы получить 1 диалог, делается первый запрос по папке 0, потом запрос для архивных по папке 1, и потом ещё перезагрузка архивного диалога
2020-02-06 16:43:07 +01:00
if ( ! dialog . read_inbox_max_id && ! dialog . read_outbox_max_id ) {
noIDsDialogs [ dialog . peerID ] = dialog ;
2020-09-18 17:03:26 +02:00
2020-09-19 18:32:48 +02:00
/ * i f ( d i a l o g . p e e r I D = = - 1 2 1 3 5 1 1 2 9 4 ) {
2020-09-18 17:03:26 +02:00
this . log . error ( 'lun bot' , folderID ) ;
} * /
2020-02-06 16:43:07 +01:00
}
if ( ! maxSeenIdIncremented &&
2020-05-18 03:21:58 +02:00
! appPeersManager . isChannel ( appPeersManager . getPeerID ( dialog . peer ) ) ) {
2020-02-06 16:43:07 +01:00
this . incrementMaxSeenID ( dialog . top_message ) ;
maxSeenIdIncremented = true ;
}
2020-09-18 17:03:26 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
if ( Object . keys ( noIDsDialogs ) . length ) {
//setTimeout(() => { // test bad situation
this . reloadConversation ( Object . keys ( noIDsDialogs ) . map ( id = > + id ) ) . then ( ( ) = > {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialogs_multiupdate' , noIDsDialogs ) ;
2020-02-06 16:43:07 +01:00
for ( let peerID in noIDsDialogs ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_unread' , { peerID : + peerID } ) ;
2020-02-06 16:43:07 +01:00
}
} ) ;
//}, 10e3);
}
2020-09-18 17:03:26 +02:00
const count = ( dialogsResult as MessagesDialogs . messagesDialogsSlice ) . count ;
2020-02-06 16:43:07 +01:00
if ( ! dialogsResult . dialogs . length ||
2020-09-18 17:03:26 +02:00
! count ||
dialogs . length >= count ) {
2020-06-19 13:49:55 +02:00
this . dialogsStorage . allDialogsLoaded [ 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 {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialogs_multiupdate' , { } ) ;
2020-02-06 16:43:07 +01:00
}
2020-02-14 17:15:41 +01:00
2020-09-18 17:03:26 +02:00
return count ;
2020-02-06 16:43:07 +01:00
} ) ;
}
2020-05-06 03:03:31 +02:00
public forwardMessages ( peerID : number , mids : number [ ] , options : Partial < {
2020-10-11 23:21:42 +02:00
withMyScore : true
2020-05-06 03:03:31 +02:00
} > = { } ) {
2020-05-18 03:21:58 +02:00
peerID = appPeersManager . getPeerMigratedTo ( peerID ) || peerID ;
2020-10-21 01:25:36 +02:00
mids = mids . slice ( ) . sort ( ( a , b ) = > a - b ) ;
2020-05-06 03:03:31 +02:00
2020-10-11 23:21:42 +02:00
const splitted = appMessagesIDsManager . splitMessageIDsByChannels ( mids ) ;
const promises : Promise < void > [ ] = [ ] ;
2020-05-06 03:03:31 +02:00
2020-10-11 23:21:42 +02:00
for ( const channelID in splitted . msgIDs ) {
const msgIDs = splitted . msgIDs [ channelID ] ;
2020-10-29 18:11:09 +01:00
const randomIDs : string [ ] = msgIDs . map ( ( ) = > randomLong ( ) ) ;
2020-05-06 03:03:31 +02:00
2020-10-11 23:21:42 +02:00
const sentRequestOptions : InvokeApiOptions = { } ;
2020-05-06 03:03:31 +02:00
if ( this . pendingAfterMsgs [ peerID ] ) {
sentRequestOptions . afterMessageID = this . pendingAfterMsgs [ peerID ] . messageID ;
}
2020-10-15 18:54:54 +02:00
const promise = apiManager . invokeApiAfter ( 'messages.forwardMessages' , {
2020-05-18 03:21:58 +02:00
from_peer : appPeersManager.getInputPeerByID ( - channelID ) ,
2020-05-06 03:03:31 +02:00
id : msgIDs ,
2020-10-29 18:11:09 +01:00
random_id : randomIDs ,
2020-10-11 23:21:42 +02:00
to_peer : appPeersManager.getInputPeerByID ( peerID ) ,
with_my_score : options.withMyScore
2020-05-06 03:03:31 +02:00
} , sentRequestOptions ) . then ( ( updates ) = > {
apiUpdatesManager . processUpdateMessage ( updates ) ;
} , ( ) = > { } ) . then ( ( ) = > {
if ( this . pendingAfterMsgs [ peerID ] === sentRequestOptions ) {
delete this . pendingAfterMsgs [ peerID ] ;
}
} ) ;
this . pendingAfterMsgs [ peerID ] = sentRequestOptions ;
promises . push ( promise ) ;
}
return Promise . all ( promises ) ;
}
2020-09-28 02:23:00 +02:00
public getMessage ( messageID : number ) /* : Message */ {
2020-02-06 16:43:07 +01:00
return this . messagesStorage [ messageID ] || {
_ : 'messageEmpty' ,
2020-09-28 02:23:00 +02:00
id : messageID ,
2020-10-03 19:45:56 +02:00
deleted : true ,
pFlags : { }
2020-02-06 16:43:07 +01:00
} ;
}
public getMessagePeer ( message : any ) : number {
2020-10-02 22:33:32 +02:00
var toID = message . peer_id && appPeersManager . getPeerID ( message . peer_id ) || 0 ;
2020-02-06 16:43:07 +01:00
2020-10-02 22:33:32 +02:00
return toID ;
2020-02-06 16:43:07 +01:00
}
2020-05-03 14:46:05 +02:00
public getDialogByPeerID ( peerID : number ) : [ Dialog , number ] | [ ] {
2020-06-19 13:49:55 +02:00
return this . dialogsStorage . getDialog ( peerID ) ;
2020-02-06 16:43:07 +01:00
}
public reloadConversation ( peerID : number | number [ ] ) {
2020-06-20 03:11:24 +02:00
[ ] . concat ( peerID ) . forEach ( peerID = > {
if ( ! this . reloadConversationsPeers . includes ( peerID ) ) {
this . reloadConversationsPeers . push ( peerID ) ;
this . log ( 'will reloadConversation' , peerID ) ;
}
} ) ;
2020-02-06 16:43:07 +01:00
2020-06-20 03:11:24 +02:00
if ( this . reloadConversationsPromise ) return this . reloadConversationsPromise ;
return this . reloadConversationsPromise = new Promise ( ( resolve , reject ) = > {
setTimeout ( ( ) = > {
2020-09-17 21:33:23 +02:00
const peers = this . reloadConversationsPeers . map ( peerID = > appPeersManager . getInputDialogPeerByID ( peerID ) ) ;
2020-06-20 03:11:24 +02:00
this . reloadConversationsPeers . length = 0 ;
apiManager . invokeApi ( 'messages.getPeerDialogs' , { peers } ) . then ( ( result ) = > {
this . applyConversations ( result ) ;
resolve ( ) ;
} , reject ) . finally ( ( ) = > {
this . reloadConversationsPromise = null ;
} ) ;
} , 0 ) ;
} ) ;
2020-02-06 16:43:07 +01:00
}
2020-10-16 18:53:57 +02:00
private doFlushHistory ( inputPeer : any , justClear? : true ) : Promise < true > {
2020-05-13 17:26:40 +02:00
return apiManager . invokeApi ( 'messages.deleteHistory' , {
2020-10-16 18:53:57 +02:00
just_clear : justClear ,
2020-05-13 17:26:40 +02:00
peer : inputPeer ,
max_id : 0
} ) . then ( ( affectedHistory ) = > {
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updatePts' ,
pts : affectedHistory.pts ,
pts_count : affectedHistory.pts_count
}
} ) ;
if ( ! affectedHistory . offset ) {
return true ;
}
return this . doFlushHistory ( inputPeer , justClear ) ;
} )
}
2020-10-16 18:53:57 +02:00
public async flushHistory ( peerID : number , justClear? : true ) {
2020-05-18 03:21:58 +02:00
if ( appPeersManager . isChannel ( peerID ) ) {
2020-05-13 17:26:40 +02:00
let promise = this . getHistory ( peerID , 0 , 1 ) ;
let historyResult = promise instanceof Promise ? await promise : promise ;
let channelID = - peerID ;
let maxID = appMessagesIDsManager . getMessageLocalID ( historyResult . history [ 0 ] || 0 ) ;
return apiManager . invokeApi ( 'channels.deleteHistory' , {
channel : appChatsManager.getChannelInput ( channelID ) ,
max_id : maxID
} ) . then ( ( ) = > {
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateChannelAvailableMessages' ,
channel_id : channelID ,
available_min_id : maxID
}
} ) ;
return true ;
} ) ;
}
2020-05-18 03:21:58 +02:00
return this . doFlushHistory ( appPeersManager . getInputPeerByID ( peerID ) , justClear ) . then ( ( ) = > {
2020-05-13 17:26:40 +02:00
delete this . historiesStorage [ peerID ] ;
for ( let mid in this . messagesStorage ) {
let message = this . messagesStorage [ mid ] ;
if ( message . peerID == peerID ) {
delete this . messagesStorage [ mid ] ;
}
}
if ( justClear ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_flush' , { peerID } ) ;
2020-05-13 17:26:40 +02:00
} else {
2020-06-19 13:49:55 +02:00
this . dialogsStorage . dropDialog ( peerID ) ;
2020-05-13 17:26:40 +02:00
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_drop' , { peerID } ) ;
2020-05-13 17:26:40 +02:00
}
} ) ;
}
2020-12-08 20:48:44 +01:00
public hidePinnedMessages ( peerID : number ) {
return Promise . all ( [
appStateManager . getState ( ) ,
this . getPinnedMessage ( peerID )
] )
. then ( ( [ state , pinned ] ) = > {
state . hiddenPinnedMessages [ peerID ] = pinned . maxID ;
rootScope . broadcast ( 'peer_pinned_hidden' , { peerID , maxID : pinned.maxID } ) ;
} ) ;
2020-06-05 18:01:06 +02:00
}
2020-12-08 20:48:44 +01:00
public getPinnedMessage ( peerID : number ) {
const p = this . pinnedMessages [ peerID ] ? ? ( this . pinnedMessages [ peerID ] = { } ) ;
if ( p . promise ) return p . promise ;
else if ( p . maxID ) return Promise . resolve ( p ) ;
2020-11-25 20:36:18 +01:00
2020-12-08 20:48:44 +01:00
return p . promise = this . getSearch ( peerID , '' , { _ : 'inputMessagesFilterPinned' } , 0 , 1 ) . then ( result = > {
p . count = result . count ;
p . maxID = result . history [ 0 ] ;
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
2020-11-25 20:36:18 +01:00
public updatePinnedMessage ( peerID : number , mid : number , unpin? : true , silent? : true , oneSide? : true ) {
2020-12-08 20:48:44 +01:00
return apiManager . invokeApi ( 'messages.updatePinnedMessage' , {
2020-06-06 12:53:23 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
2020-11-25 20:36:18 +01:00
unpin ,
silent ,
pm_oneside : oneSide ,
id : mid
2020-06-06 12:53:23 +02:00
} ) . then ( updates = > {
2020-11-25 20:36:18 +01:00
this . log ( 'pinned updates:' , updates ) ;
2020-06-06 12:53:23 +02:00
apiUpdatesManager . processUpdateMessage ( updates ) ;
} ) ;
}
2020-06-05 18:01:06 +02:00
2020-12-08 20:48:44 +01:00
public unpinAllMessages ( peerID : number ) : Promise < boolean > {
return apiManager . invokeApi ( 'messages.unpinAllMessages' , {
peer : appPeersManager.getInputPeerByID ( peerID )
} ) . then ( affectedHistory = > {
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updatePts' ,
pts : affectedHistory.pts ,
pts_count : affectedHistory.pts_count
}
} ) ;
if ( ! affectedHistory . offset ) {
const storage = this . messagesStorageByPeerID [ peerID ] ;
for ( const mid in storage ) {
const message = storage [ mid ] ;
if ( message . pFlags . pinned ) {
delete message . pFlags . pinned ;
}
}
rootScope . broadcast ( 'peer_pinned_messages' , peerID ) ;
delete this . pinnedMessages [ peerID ] ;
return true ;
}
return this . unpinAllMessages ( peerID ) ;
} ) ;
}
2020-11-07 18:47:54 +01:00
public getAlbumText ( grouped_id : string ) {
const group = appMessagesManager . groupedMessagesStorage [ grouped_id ] ;
let foundMessages = 0 , message : string , totalEntities : MessageEntity [ ] ;
for ( const i in group ) {
const m = group [ i ] ;
if ( m . message ) {
if ( ++ foundMessages > 1 ) break ;
message = m . message ;
totalEntities = m . totalEntities ;
}
}
if ( foundMessages > 1 ) {
message = undefined ;
totalEntities = undefined ;
}
return { message , totalEntities } ;
}
2020-10-18 01:19:56 +02:00
public getMidsByAlbum ( grouped_id : string ) {
2020-11-07 18:47:54 +01:00
return getObjectKeysAndSort ( this . groupedMessagesStorage [ grouped_id ] , 'asc' ) ;
//return Object.keys(this.groupedMessagesStorage[grouped_id]).map(id => +id).sort((a, b) => a - b);
2020-10-18 01:19:56 +02:00
}
public getMidsByMid ( mid : number ) {
const message = this . messagesStorage [ mid ] ;
if ( message ? . grouped_id ) return this . getMidsByAlbum ( message . grouped_id ) ;
else return [ mid ] ;
}
2020-12-08 20:48:44 +01:00
public saveMessages ( messages : any [ ] ) {
2020-11-07 18:47:54 +01:00
let albums : Set < string > ;
2020-10-17 00:31:58 +02:00
messages . forEach ( ( message ) = > {
if ( message . pFlags === undefined ) {
message . pFlags = { } ;
2020-02-06 16:43:07 +01:00
}
2020-10-17 00:31:58 +02:00
if ( message . _ == 'messageEmpty' ) {
2020-02-06 16:43:07 +01:00
return ;
}
2020-10-17 00:31:58 +02:00
// * exclude from state
2020-10-22 01:59:30 +02:00
// defineNotNumerableProperties(message, ['rReply', 'mid', 'savedFrom', 'fwdFromID', 'fromID', 'peerID', 'reply_to_mid', 'viaBotID']);
2020-10-17 00:31:58 +02:00
const peerID = this . getMessagePeer ( message ) ;
const isChannel = message . peer_id . _ == 'peerChannel' ;
2020-05-26 17:04:06 +02:00
const channelID = isChannel ? - peerID : 0 ;
const isBroadcast = isChannel && appChatsManager . isBroadcast ( channelID ) ;
2020-02-06 16:43:07 +01:00
2020-10-17 00:31:58 +02:00
const mid = appMessagesIDsManager . getFullMessageID ( message . id , channelID ) ;
message . mid = mid ;
2020-02-06 16:43:07 +01:00
2020-10-17 00:31:58 +02:00
if ( message . grouped_id ) {
const storage = this . groupedMessagesStorage [ message . grouped_id ] ? ? ( this . groupedMessagesStorage [ message . grouped_id ] = { } ) ;
storage [ mid ] = message ;
2020-04-28 19:30:54 +02:00
}
2020-05-26 17:04:06 +02:00
const dialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
2020-02-06 16:43:07 +01:00
if ( dialog && mid > 0 ) {
2020-10-17 00:31:58 +02:00
if ( mid > dialog [ message . pFlags . out
2020-02-06 16:43:07 +01:00
? 'read_outbox_max_id'
2020-10-03 02:35:26 +02:00
: 'read_inbox_max_id' ] ) {
2020-10-17 00:31:58 +02:00
message . pFlags . unread = true ;
2020-10-03 02:35:26 +02:00
}
2020-02-06 16:43:07 +01:00
}
2020-06-13 10:19:39 +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
2020-10-17 00:31:58 +02:00
if ( message . reply_to && message . reply_to . reply_to_msg_id ) {
message . reply_to_mid = appMessagesIDsManager . getFullMessageID ( message . reply_to . reply_to_msg_id , channelID ) ;
2020-02-06 16:43:07 +01:00
}
2020-10-17 00:31:58 +02:00
message . date -= serverTimeManager . serverTimeOffset ;
2020-02-06 16:43:07 +01:00
2020-10-02 22:33:32 +02:00
const myID = appUsersManager . getSelf ( ) . id ;
2020-10-17 00:31:58 +02:00
message . peerID = peerID ;
2020-11-08 02:34:28 +01:00
if ( message . peerID == myID /* && !message.from_id && !message.fwd_from */ ) {
2020-11-11 18:01:38 +01:00
message . fromID = message . fwd_from ? ( message . fwd_from . from_id ? appPeersManager . getPeerID ( message . fwd_from . from_id ) : 0 ) : myID ;
2020-10-02 22:33:32 +02:00
} else {
2020-10-17 00:31:58 +02:00
message . fromID = message . pFlags . post || ( ! message . pFlags . out && ! message . from_id ) ? peerID : appPeersManager.getPeerID ( message . from_id ) ;
2020-10-02 22:33:32 +02:00
}
2020-02-06 16:43:07 +01:00
2020-10-17 00:31:58 +02:00
const fwdHeader = message . fwd_from ;
2020-02-06 16:43:07 +01:00
if ( fwdHeader ) {
2020-10-15 11:37:03 +02:00
//if(peerID == myID) {
2020-02-06 16:43:07 +01:00
if ( fwdHeader . saved_from_peer && fwdHeader . saved_from_msg_id ) {
2020-05-26 17:04:06 +02:00
const savedFromPeerID = appPeersManager . getPeerID ( fwdHeader . saved_from_peer ) ;
const savedFromMid = appMessagesIDsManager . getFullMessageID ( fwdHeader . saved_from_msg_id ,
2020-05-18 03:21:58 +02:00
appPeersManager . isChannel ( savedFromPeerID ) ? - savedFromPeerID : 0 ) ;
2020-10-17 00:31:58 +02:00
message . savedFrom = savedFromPeerID + '_' + savedFromMid ;
2020-02-06 16:43:07 +01:00
}
2020-11-08 02:34:28 +01:00
/ * i f ( p e e r I D < 0 | | p e e r I D = = m y I D ) {
2020-10-20 01:39:36 +02:00
message . fromID = appPeersManager . getPeerID ( ! message . from_id || deepEqual ( message . from_id , fwdHeader . from_id ) ? fwdHeader.from_id : message.from_id ) ;
2020-11-08 02:34:28 +01:00
} * /
2020-10-15 11:37:03 +02:00
/ * } e l s e {
2020-02-06 16:43:07 +01:00
apiMessage . fwdPostID = fwdHeader . channel_post ;
2020-10-15 11:37:03 +02:00
} * /
2020-02-06 16:43:07 +01:00
2020-10-17 00:31:58 +02:00
message . fwdFromID = appPeersManager . getPeerID ( fwdHeader . from_id ) ;
2020-02-13 12:59:55 +01:00
2020-02-11 16:35:57 +01:00
fwdHeader . date -= serverTimeManager . serverTimeOffset ;
2020-02-06 16:43:07 +01:00
}
2020-10-17 00:31:58 +02:00
if ( message . via_bot_id > 0 ) {
message . viaBotID = message . via_bot_id ;
2020-02-06 16:43:07 +01:00
}
2020-09-28 02:23:00 +02:00
const mediaContext : ReferenceContext = {
type : 'message' ,
messageID : mid
2020-02-06 16:43:07 +01:00
} ;
2020-10-17 00:31:58 +02:00
if ( message . media ) {
switch ( message . media . _ ) {
2020-02-06 16:43:07 +01:00
case 'messageMediaEmpty' :
2020-10-17 00:31:58 +02:00
delete message . media ;
2020-02-06 16:43:07 +01:00
break ;
case 'messageMediaPhoto' :
2020-10-17 00:31:58 +02:00
if ( message . media . ttl_seconds ) {
message . media = { _ : 'messageMediaUnsupportedWeb' } ;
2020-02-06 16:43:07 +01:00
} else {
2020-10-17 00:31:58 +02:00
message . media . photo = appPhotosManager . savePhoto ( message . media . photo , mediaContext ) ;
2020-04-15 22:55:08 +02:00
//appPhotosManager.savePhoto(apiMessage.media.photo, mediaContext);
2020-02-06 16:43:07 +01:00
}
2020-05-09 14:02:07 +02:00
break ;
case 'messageMediaPoll' :
2020-10-17 00:31:58 +02:00
message . media . poll = appPollsManager . savePoll ( message . media . poll , message . media . results ) ;
2020-05-09 14:02:07 +02:00
break ;
2020-02-06 16:43:07 +01:00
case 'messageMediaDocument' :
2020-10-17 00:31:58 +02:00
if ( message . media . ttl_seconds ) {
message . media = { _ : 'messageMediaUnsupportedWeb' } ;
2020-02-06 16:43:07 +01:00
} else {
2020-10-17 00:31:58 +02:00
message . media . document = appDocsManager . saveDoc ( message . media . document , mediaContext ) ; // 11.04.2020 warning
2020-02-06 16:43:07 +01:00
}
2020-05-10 03:23:21 +02:00
2020-02-06 16:43:07 +01:00
break ;
case 'messageMediaWebPage' :
2020-02-13 08:51:11 +01:00
/ * i f ( a p i M e s s a g e . m e d i a . w e b p a g e . d o c u m e n t ) {
2020-02-06 16:43:07 +01:00
appDocsManager . saveDoc ( apiMessage . media . webpage . document , mediaContext ) ;
2020-02-13 08:51:11 +01:00
} * /
2020-10-17 00:31:58 +02:00
appWebPagesManager . saveWebPage ( message . media . webpage , message . mid , mediaContext ) ;
2020-02-06 16:43:07 +01:00
break ;
2020-02-13 08:51:11 +01:00
/ * c a s e ' m e s s a g e M e d i a G a m e ' :
2020-02-06 16:43:07 +01:00
AppGamesManager . saveGame ( apiMessage . media . game , apiMessage . mid , mediaContext ) ;
apiMessage . media . handleMessage = true ;
break ; * /
case 'messageMediaInvoice' :
2020-10-17 00:31:58 +02:00
message . media = { _ : 'messageMediaUnsupportedWeb' } ;
2020-02-06 16:43:07 +01:00
break ;
case 'messageMediaGeoLive' :
2020-10-17 00:31:58 +02:00
message . media . _ = 'messageMediaGeo' ;
2020-02-06 16:43:07 +01:00
break ;
}
}
2020-10-17 00:31:58 +02:00
if ( message . action ) {
2020-10-15 00:46:29 +02:00
let migrateFrom : number ;
let migrateTo : number ;
2020-10-17 00:31:58 +02:00
switch ( message . action . _ ) {
2020-10-15 00:46:29 +02:00
//case 'messageActionChannelEditPhoto':
2020-02-06 16:43:07 +01:00
case 'messageActionChatEditPhoto' :
2020-10-17 00:31:58 +02:00
message . action . photo = appPhotosManager . savePhoto ( message . action . photo , mediaContext ) ;
2020-04-15 22:55:08 +02:00
//appPhotosManager.savePhoto(apiMessage.action.photo, mediaContext);
2020-10-15 00:46:29 +02:00
if ( isBroadcast ) { // ! messageActionChannelEditPhoto не существует в принципе, это используется для перевода.
2020-10-17 00:31:58 +02:00
message . action . _ = 'messageActionChannelEditPhoto' ;
2020-02-06 16:43:07 +01:00
}
break ;
case 'messageActionChatEditTitle' :
if ( isBroadcast ) {
2020-10-17 00:31:58 +02:00
message . action . _ = 'messageActionChannelEditTitle' ;
2020-02-06 16:43:07 +01:00
}
break ;
case 'messageActionChatDeletePhoto' :
if ( isBroadcast ) {
2020-10-17 00:31:58 +02:00
message . action . _ = 'messageActionChannelDeletePhoto' ;
2020-02-06 16:43:07 +01:00
}
break ;
case 'messageActionChatAddUser' :
2020-10-17 00:31:58 +02:00
if ( message . action . users . length == 1 ) {
message . action . user_id = message . action . users [ 0 ] ;
if ( message . fromID == message . action . user_id ) {
2020-02-06 16:43:07 +01:00
if ( isChannel ) {
2020-10-17 00:31:58 +02:00
message . action . _ = 'messageActionChatJoined' ;
2020-02-06 16:43:07 +01:00
} else {
2020-10-17 00:31:58 +02:00
message . action . _ = 'messageActionChatReturn' ;
2020-02-06 16:43:07 +01:00
}
}
2020-10-17 00:31:58 +02:00
} else if ( message . action . users . length > 1 ) {
message . action . _ = 'messageActionChatAddUsers' ;
2020-02-06 16:43:07 +01:00
}
break ;
case 'messageActionChatDeleteUser' :
2020-10-17 00:31:58 +02:00
if ( message . fromID == message . action . user_id ) {
message . action . _ = 'messageActionChatLeave' ;
2020-02-06 16:43:07 +01:00
}
break ;
case 'messageActionChannelMigrateFrom' :
2020-10-17 00:31:58 +02:00
migrateFrom = - message . action . chat_id ;
2020-02-06 16:43:07 +01:00
migrateTo = - channelID ;
break
case 'messageActionChatMigrateTo' :
migrateFrom = - channelID ;
2020-10-17 00:31:58 +02:00
migrateTo = - message . action . channel_id ;
2020-02-06 16:43:07 +01:00
break ;
case 'messageActionHistoryClear' :
2020-08-19 17:26:19 +02:00
//apiMessage.deleted = true;
2020-10-17 00:31:58 +02:00
message . clear_history = true ;
delete message . pFlags . out ;
delete message . pFlags . unread ;
2020-02-06 16:43:07 +01:00
break ;
case 'messageActionPhoneCall' :
2020-10-17 00:31:58 +02:00
delete message . fromID ;
message . action . type =
( message . pFlags . out ? 'out_' : 'in_' ) +
2020-02-06 16:43:07 +01:00
(
2020-10-17 00:31:58 +02:00
message . action . reason . _ == 'phoneCallDiscardReasonMissed' ||
message . action . reason . _ == 'phoneCallDiscardReasonBusy'
2020-02-06 16:43:07 +01:00
? 'missed'
: 'ok'
) ;
break ;
}
if ( migrateFrom &&
migrateTo &&
! this . migratedFromTo [ migrateFrom ] &&
! this . migratedToFrom [ migrateTo ] ) {
this . migrateChecks ( migrateFrom , migrateTo ) ;
}
}
2020-11-07 18:47:54 +01:00
if ( message . grouped_id ) {
if ( ! albums ) {
albums = new Set ( ) ;
}
albums . add ( message . grouped_id ) ;
} else {
message . rReply = this . getRichReplyText ( message ) ;
}
2020-05-10 03:23:21 +02:00
2020-10-17 00:31:58 +02:00
if ( message . message && message . message . length && ! message . totalEntities ) {
const myEntities = RichTextProcessor . parseEntities ( message . message ) ;
const apiEntities = message . entities || [ ] ;
message . totalEntities = RichTextProcessor . mergeEntities ( myEntities , apiEntities , ! message . pending ) ;
2020-02-06 16:43:07 +01:00
}
2020-11-08 02:34:28 +01:00
//if(!options.isEdited) {
2020-10-17 00:31:58 +02:00
this . messagesStorage [ mid ] = message ;
( this . messagesStorageByPeerID [ peerID ] ? ? ( this . messagesStorageByPeerID [ peerID ] = { } ) ) [ mid ] = message ;
2020-11-08 02:34:28 +01:00
//}
2020-05-10 03:23:21 +02:00
} ) ;
2020-11-07 18:47:54 +01:00
if ( albums ) {
albums . forEach ( groupID = > {
const mids = this . groupedMessagesStorage [ groupID ] ;
for ( const mid in mids ) {
const message = this . messagesStorage [ mid ] ;
message . rReply = this . getRichReplyText ( message ) ;
}
} ) ;
}
2020-05-10 03:23:21 +02:00
}
2020-05-13 17:26:40 +02:00
public getRichReplyText ( message : any , text : string = message . message ) {
2020-05-10 03:23:21 +02:00
let messageText = '' ;
if ( message . media ) {
2020-05-30 08:44:54 +02:00
if ( message . grouped_id ) {
2020-11-07 18:47:54 +01:00
text = this . getAlbumText ( message . grouped_id ) . message ;
messageText += '<i>Album' + ( text ? ', ' : '' ) + '</i>' ;
2020-05-30 08:44:54 +02:00
} else switch ( message . media . _ ) {
2020-05-10 03:23:21 +02:00
case 'messageMediaPhoto' :
2020-05-30 08:44:54 +02:00
messageText += '<i>Photo' + ( message . message ? ', ' : '' ) + '</i>' ;
2020-05-10 03:23:21 +02:00
break ;
2020-10-21 01:25:36 +02:00
case 'messageMediaDice' :
messageText += RichTextProcessor . wrapEmojiText ( message . media . emoticon ) ;
break ;
2020-05-10 03:23:21 +02:00
case 'messageMediaGeo' :
messageText += '<i>Geolocation</i>' ;
break ;
case 'messageMediaPoll' :
messageText += '<i>' + message . media . poll . rReply + '</i>' ;
break ;
case 'messageMediaContact' :
messageText += '<i>Contact</i>' ;
break ;
case 'messageMediaDocument' :
let document = message . media . document ;
if ( document . type == 'video' ) {
messageText = '<i>Video' + ( message . message ? ', ' : '' ) + '</i>' ;
} else if ( document . type == 'voice' ) {
messageText = '<i>Voice message</i>' ;
} else if ( document . type == 'gif' ) {
messageText = '<i>GIF' + ( message . message ? ', ' : '' ) + '</i>' ;
} else if ( document . type == 'round' ) {
messageText = '<i>Video message' + ( message . message ? ', ' : '' ) + '</i>' ;
2020-05-27 08:21:16 +02:00
} else if ( document . type == 'sticker' ) {
messageText = ( document . stickerEmoji || '' ) + '<i>Sticker</i>' ;
2020-11-19 00:51:39 +01:00
text = '' ;
2020-05-27 08:21:16 +02:00
} else {
2020-11-08 02:03:16 +01:00
messageText = '<i>' + document . file_name + ( message . message ? ', ' : '' ) + '</i>' ;
2020-05-10 03:23:21 +02:00
}
2020-05-27 08:21:16 +02:00
break ;
2020-05-10 03:23:21 +02:00
default :
2020-10-21 01:25:36 +02:00
//messageText += message.media._;
2020-06-13 10:19:39 +02:00
///////this.log.warn('Got unknown message.media type!', message);
2020-05-10 03:23:21 +02:00
break ;
}
}
if ( message . action ) {
2020-10-22 01:59:30 +02:00
const str = this . wrapMessageActionText ( message ) ;
2020-05-30 08:44:54 +02:00
2020-08-19 17:26:19 +02:00
messageText = str ? '<i>' + str + '</i>' : '' ;
2020-05-10 03:23:21 +02:00
}
let messageWrapped = '' ;
if ( text ) {
2020-09-26 00:47:43 +02:00
// * 80 for chatlist in landscape orientation
2020-10-03 19:45:56 +02:00
text = limitSymbols ( text , 75 , 80 ) ;
2020-09-23 22:29:53 +02:00
2020-11-08 02:34:28 +01:00
const entities = RichTextProcessor . parseEntities ( text . replace ( /\n/g , ' ' ) ) ;
2020-05-10 03:23:21 +02:00
messageWrapped = RichTextProcessor . wrapRichText ( text , {
2020-10-03 19:45:56 +02:00
noLinebreaks : true ,
2020-11-08 02:34:28 +01:00
entities ,
2020-11-08 02:03:16 +01:00
noLinks : true ,
2020-05-10 03:23:21 +02:00
noTextFormat : true
} ) ;
}
return messageText + messageWrapped ;
2020-02-06 16:43:07 +01:00
}
2020-10-22 01:59:30 +02:00
public wrapMessageActionText ( message : any ) {
2020-10-31 00:30:43 +01:00
const action = message . action as MessageAction ;
2020-10-22 01:59:30 +02:00
let str = '' ;
2020-10-31 00:30:43 +01:00
if ( ( action as MessageAction . messageActionCustomAction ) . message ) {
str = RichTextProcessor . wrapRichText ( ( action as MessageAction . messageActionCustomAction ) . message , { noLinebreaks : true } ) ;
2020-10-22 01:59:30 +02:00
} else {
let _ = action . _ ;
let suffix = '' ;
let l = '' ;
const getNameDivHTML = ( peerID : number ) = > {
const title = appPeersManager . getPeerTitle ( peerID ) ;
return title ? ` <div class="name inline" data-peer-i-d=" ${ peerID } "> ${ title } </div> ` : '' ;
} ;
2020-10-31 00:30:43 +01:00
switch ( action . _ ) {
2020-10-22 01:59:30 +02:00
case "messageActionPhoneCall" : {
2020-10-31 00:30:43 +01:00
_ += '.' + ( action as any ) . type ;
2020-10-22 01:59:30 +02:00
const duration = action . duration ;
if ( duration ) {
const d : string [ ] = [ ] ;
d . push ( duration % 60 + ' s' ) ;
if ( duration >= 60 ) d . push ( ( duration / 60 | 0 ) + ' min' ) ;
//if(duration >= 3600) d.push((duration / 3600 | 0) + ' h');
suffix = ' (' + d . reverse ( ) . join ( ' ' ) + ')' ;
}
return langPack [ _ ] + suffix ;
}
case 'messageActionChatDeleteUser' :
2020-10-31 00:30:43 +01:00
// @ts-ignore
2020-10-22 01:59:30 +02:00
case 'messageActionChatAddUsers' :
case 'messageActionChatAddUser' : {
2020-10-31 00:30:43 +01:00
const users : number [ ] = ( action as MessageAction . messageActionChatAddUser ) . users || [ ( action as MessageAction . messageActionChatDeleteUser ) . user_id ] ;
2020-10-22 01:59:30 +02:00
l = langPack [ _ ] . replace ( '{}' , users . map ( ( userID : number ) = > getNameDivHTML ( userID ) ) . join ( ', ' ) ) ;
break ;
}
2020-10-31 00:30:43 +01:00
case 'messageActionBotAllowed' : {
const anchorHTML = RichTextProcessor . wrapRichText ( action . domain , {
entities : [ {
_ : 'messageEntityUrl' ,
length : action.domain.length ,
offset : 0
} ]
} ) ;
l = langPack [ _ ] . replace ( '{}' , anchorHTML ) ;
break ;
}
2020-10-22 01:59:30 +02:00
default :
str = langPack [ _ ] || ` [ ${ action . _ } ] ` ;
break ;
}
if ( ! l ) {
l = langPack [ _ ] ;
if ( ! l ) {
l = '[' + _ + ']' ;
}
}
str = l [ 0 ] . toUpperCase ( ) == l [ 0 ] ? l : getNameDivHTML ( message . fromID ) + l + ( suffix ? ' ' : '' ) ;
}
//this.log('message action:', action);
return str ;
}
2020-05-13 17:26:40 +02:00
public editPeerFolders ( peerIDs : number [ ] , folderID : number ) {
apiManager . invokeApi ( 'folders.editPeerFolders' , {
folder_peers : peerIDs.map ( peerID = > {
return {
_ : 'inputFolderPeer' ,
2020-05-18 03:21:58 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
2020-05-13 17:26:40 +02:00
folder_id : folderID
} ;
} )
} ) . then ( updates = > {
2020-06-13 10:19:39 +02:00
this . log ( 'editPeerFolders updates:' , updates ) ;
2020-05-13 17:26:40 +02:00
apiUpdatesManager . processUpdateMessage ( updates ) ; // WARNING! возможно тут нужно добавлять channelID, и вызывать апдейт для каждого канала отдельно
} ) ;
}
2020-06-19 13:49:55 +02:00
public toggleDialogPin ( peerID : number , filterID? : number ) {
if ( filterID > 1 ) {
this . filtersStorage . toggleDialogPin ( peerID , filterID ) ;
return ;
}
const dialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
2020-05-13 17:26:40 +02:00
if ( ! dialog ) return Promise . reject ( ) ;
2020-10-11 14:51:23 +02:00
const pinned = dialog . pFlags ? . pinned ? undefined : true ;
2020-05-13 17:26:40 +02:00
return apiManager . invokeApi ( 'messages.toggleDialogPin' , {
2020-10-11 14:51:23 +02:00
peer : appPeersManager.getInputDialogPeerByID ( peerID ) ,
pinned
2020-05-13 17:26:40 +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.updateDialogPinned [ 'pFlags' ] = pinned ? { pinned } : { } ;
2020-06-19 13:49:55 +02:00
this . handleUpdate ( {
_ : 'updateDialogPinned' ,
2020-10-11 14:51:23 +02:00
peer : appPeersManager.getDialogPeer ( peerID ) ,
folder_id : filterID ,
pFlags
2020-06-19 13:49:55 +02:00
} ) ;
}
2020-05-13 17:26:40 +02:00
} ) ;
}
2020-06-05 18:01:06 +02:00
public markDialogUnread ( peerID : number , read? : boolean ) {
2020-09-17 21:33:23 +02:00
const dialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
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 ;
2020-05-13 17:26:40 +02:00
return apiManager . invokeApi ( 'messages.markDialogUnread' , {
2020-10-11 14:51:23 +02:00
peer : appPeersManager.getInputDialogPeerByID ( peerID ) ,
unread
2020-05-13 17:26:40 +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 } : { } ;
2020-06-19 13:49:55 +02:00
this . handleUpdate ( {
_ : 'updateDialogUnreadMark' ,
2020-10-11 14:51:23 +02:00
peer : appPeersManager.getDialogPeer ( peerID ) ,
pFlags
2020-06-19 13:49:55 +02:00
} ) ;
}
2020-05-13 17:26:40 +02:00
} ) ;
}
2020-05-06 03:03:31 +02:00
public migrateChecks ( migrateFrom : number , migrateTo : number ) {
2020-02-06 16:43:07 +01:00
if ( ! this . migratedFromTo [ migrateFrom ] &&
! this . migratedToFrom [ migrateTo ] &&
appChatsManager . hasChat ( - migrateTo ) ) {
2020-06-19 13:49:55 +02:00
const fromChat = appChatsManager . getChat ( - migrateFrom ) ;
2020-02-06 16:43:07 +01:00
if ( fromChat &&
fromChat . migrated_to &&
fromChat . migrated_to . channel_id == - migrateTo ) {
this . migratedFromTo [ migrateFrom ] = migrateTo ;
this . migratedToFrom [ migrateTo ] = migrateFrom ;
setTimeout ( ( ) = > {
2020-06-19 13:49:55 +02:00
const dropped = this . dialogsStorage . dropDialog ( migrateFrom ) ;
if ( dropped . length ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_drop' , { peerID : migrateFrom , dialog : dropped [ 0 ] } ) ;
2020-02-06 16:43:07 +01:00
}
2020-05-06 03:03:31 +02:00
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_migrate' , { migrateFrom , migrateTo } ) ;
2020-02-06 16:43:07 +01:00
} , 100 ) ;
}
}
}
2020-10-10 04:08:12 +02:00
public canMessageBeEdited ( message : any , kind : 'text' | 'poll' ) {
2020-10-10 00:36:06 +02:00
const goodMedias = [
2020-02-06 16:43:07 +01:00
'messageMediaPhoto' ,
'messageMediaDocument' ,
'messageMediaWebPage' ,
2020-10-10 04:08:12 +02:00
'messageMediaPending'
2020-10-10 00:36:06 +02:00
] ;
2020-10-10 04:08:12 +02:00
if ( kind == 'poll' ) {
goodMedias . push ( 'messageMediaPoll' ) ;
}
2020-02-06 16:43:07 +01:00
if ( message . _ != 'message' ||
message . deleted ||
message . fwd_from ||
message . via_bot_id ||
message . media && goodMedias . indexOf ( message . media . _ ) == - 1 ||
message . fromID && appUsersManager . isBot ( message . fromID ) ) {
return false ;
}
2020-10-10 00:36:06 +02:00
2020-02-06 16:43:07 +01:00
if ( message . media &&
message . media . _ == 'messageMediaDocument' &&
message . media . document . sticker ) {
return false ;
}
return true ;
}
2020-10-10 04:08:12 +02:00
public canEditMessage ( messageID : number , kind : 'text' | 'poll' = 'text' ) {
2020-05-26 17:04:06 +02:00
if ( ! this . messagesStorage [ messageID ] ) {
return false ;
2020-02-14 17:15:41 +01:00
}
2020-05-26 17:04:06 +02:00
const message = this . messagesStorage [ messageID ] ;
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
if ( message . pFlags . out || this . getMessagePeer ( message ) == 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
2020-10-10 00:36:06 +02:00
if ( ( message . date < tsNow ( true ) - ( 2 * 86400 ) && message . media ? . _ != 'messageMediaPoll' ) || ! message . pFlags . out ) {
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
}
2020-10-21 01:25:36 +02:00
public canDeleteMessage ( messageID : number ) {
const message = this . messagesStorage [ messageID ] ;
2020-11-12 03:11:43 +01:00
return message && (
message . peerID > 0
2020-11-15 04:33:47 +01:00
|| message . fromID == rootScope . myID
2020-11-12 03:11:43 +01:00
|| appChatsManager . getChat ( message . peerID ) . _ == 'chat'
|| appChatsManager . hasRights ( message . peerID , 'deleteRevoke' )
) ;
2020-10-21 01:25:36 +02:00
}
2020-09-18 17:03:26 +02:00
public applyConversations ( dialogsResult : MessagesPeerDialogs.messagesPeerDialogs ) {
// * В эту функцию попадут только те диалоги, в которых есть read_inbox_max_id и read_outbox_max_id, в отличие от тех, что будут в getTopMessages
2020-11-21 07:37:04 +01:00
// ! fix 'dialogFolder', maybe there is better way to do it, this only can happen by 'messages.getPinnedDialogs' by folder_id: 0
dialogsResult . dialogs . forEachReverse ( ( dialog , idx ) = > {
if ( dialog . _ == 'dialogFolder' ) {
dialogsResult . dialogs . splice ( idx , 1 ) ;
}
} ) ;
2020-02-06 16:43:07 +01:00
appUsersManager . saveApiUsers ( dialogsResult . users ) ;
appChatsManager . saveApiChats ( dialogsResult . chats ) ;
this . saveMessages ( dialogsResult . messages ) ;
2020-06-13 10:19:39 +02:00
//this.log('applyConversation', dialogsResult);
2020-02-06 16:43:07 +01:00
2020-05-26 17:04:06 +02:00
const updatedDialogs : { [ peerID : number ] : Dialog } = { } ;
2020-09-18 17:03:26 +02:00
( dialogsResult . dialogs as Dialog [ ] ) . forEach ( ( dialog ) = > {
2020-05-26 17:04:06 +02:00
const peerID = appPeersManager . getPeerID ( dialog . peer ) ;
let topMessage = dialog . top_message ;
2020-09-18 17:03:26 +02:00
const topPendingMessage = this . pendingTopMsgs [ peerID ] ;
if ( topPendingMessage ) {
2020-09-28 02:23:00 +02:00
if ( ! topMessage
|| ( this . getMessage ( topPendingMessage ) as MyMessage ) . date > ( this . getMessage ( topMessage ) as MyMessage ) . date ) {
2020-09-18 17:03:26 +02:00
dialog . top_message = topMessage = topPendingMessage ;
2020-02-06 16:43:07 +01:00
}
}
2020-09-18 17:03:26 +02:00
/ * c o n s t d = O b j e c t . a s s i g n ( { } , d i a l o g ) ;
if ( peerID == 239602833 ) {
this . log . error ( 'applyConversation lun' , dialog , d ) ;
} * /
2020-02-06 16:43:07 +01:00
if ( topMessage ) {
2020-11-11 18:01:38 +01:00
//const wasDialogBefore = this.getDialogByPeerID(peerID)[0];
2020-02-15 09:22:33 +01:00
// here need to just replace, not FULL replace dialog! WARNING
2020-09-18 17:03:26 +02:00
/ * i f ( w a s D i a l o g B e f o r e ? . p F l a g s ? . p i n n e d & & ! d i a l o g ? . p F l a g s ? . p i n n e d ) {
this . log . error ( 'here need to just replace, not FULL replace dialog! WARNING' , wasDialogBefore , dialog ) ;
2020-02-15 09:22:33 +01:00
if ( ! dialog . pFlags ) dialog . pFlags = { } ;
dialog . pFlags . pinned = true ;
2020-09-18 17:03:26 +02:00
} * /
2020-02-15 09:22:33 +01:00
2020-02-06 16:43:07 +01:00
this . saveConversation ( dialog ) ;
2020-09-18 17:03:26 +02:00
2020-11-11 18:01:38 +01:00
/ * i f ( w a s D i a l o g B e f o r e ) {
2020-11-15 04:33:47 +01:00
rootScope . $broadcast ( 'dialog_top' , dialog ) ;
2020-11-11 18:01:38 +01:00
} else { * /
2020-11-21 07:37:04 +01:00
//if(wasDialogBefore?.top_message != topMessage) {
updatedDialogs [ peerID ] = dialog ;
//}
2020-11-11 18:01:38 +01:00
//}
2020-02-06 16:43:07 +01:00
} else {
2020-06-19 13:49:55 +02:00
const dropped = this . dialogsStorage . dropDialog ( peerID ) ;
if ( dropped . length ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_drop' , { peerID : peerID , dialog : dropped [ 0 ] } ) ;
2020-02-06 16:43:07 +01:00
}
}
if ( this . newUpdatesAfterReloadToHandle [ peerID ] !== undefined ) {
2020-05-26 17:04:06 +02:00
for ( const i in this . newUpdatesAfterReloadToHandle [ peerID ] ) {
const update = this . newUpdatesAfterReloadToHandle [ peerID ] [ i ] ;
2020-02-06 16:43:07 +01:00
this . handleUpdate ( update ) ;
}
delete this . newUpdatesAfterReloadToHandle [ peerID ] ;
}
} ) ;
2020-11-21 07:37:04 +01:00
if ( Object . keys ( updatedDialogs ) . length ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialogs_multiupdate' , updatedDialogs ) ;
2020-02-06 16:43:07 +01:00
}
}
2020-09-18 17:03:26 +02:00
public saveConversation ( dialog : Dialog , folderID = 0 ) {
2020-05-30 08:44:54 +02:00
const peerID = appPeersManager . getPeerID ( dialog . peer ) ;
2020-02-06 16:43:07 +01:00
if ( ! peerID ) {
return false ;
}
2020-09-18 17:03:26 +02:00
if ( dialog . _ != 'dialog' /* || peerID == 239602833 */ ) {
console . error ( 'saveConversation not regular dialog' , dialog , Object . assign ( { } , dialog ) ) ;
}
2020-05-30 08:44:54 +02:00
const channelID = appPeersManager . isChannel ( peerID ) ? - peerID : 0 ;
const peerText = appPeersManager . getPeerSearchText ( peerID ) ;
searchIndexManager . indexObject ( peerID , peerText , this . dialogsIndex ) ;
2020-02-06 16:43:07 +01:00
2020-05-30 08:44:54 +02:00
let mid : number , message ;
2020-02-06 16:43:07 +01:00
if ( dialog . top_message ) {
2020-05-30 08:44:54 +02:00
mid = appMessagesIDsManager . getFullMessageID ( dialog . top_message , channelID ) ;
message = this . getMessage ( mid ) ;
2020-02-06 16:43:07 +01:00
} else {
2020-05-30 08:44:54 +02:00
mid = this . tempID -- ;
message = {
2020-02-06 16:43:07 +01:00
_ : 'message' ,
id : mid ,
mid : mid ,
2020-10-02 22:33:32 +02:00
from_id : appPeersManager.getOutputPeer ( appUsersManager . getSelf ( ) . id ) ,
peer_id : appPeersManager.getOutputPeer ( peerID ) ,
2020-02-06 16:43:07 +01:00
deleted : true ,
2020-10-03 02:35:26 +02:00
pFlags : { out : true } ,
2020-02-06 16:43:07 +01:00
date : 0 ,
message : ''
2020-05-30 08:44:54 +02:00
} ;
2020-02-06 16:43:07 +01:00
this . saveMessages ( [ message ] ) ;
}
2020-10-03 19:45:56 +02:00
if ( ! message ? . pFlags ) {
this . log . error ( 'saveConversation no message:' , dialog , message ) ;
}
2020-02-06 16:43:07 +01:00
if ( ! channelID && peerID < 0 ) {
2020-05-30 08:44:54 +02:00
const chat = appChatsManager . getChat ( - peerID ) ;
2020-02-06 16:43:07 +01:00
if ( chat && chat . migrated_to && chat . pFlags . deactivated ) {
2020-05-30 08:44:54 +02:00
const migratedToPeer = appPeersManager . getPeerID ( chat . migrated_to ) ;
2020-02-06 16:43:07 +01:00
this . migratedFromTo [ peerID ] = migratedToPeer ;
this . migratedToFrom [ migratedToPeer ] = peerID ;
return ;
}
}
dialog . top_message = mid ;
dialog . read_inbox_max_id = appMessagesIDsManager . getFullMessageID ( dialog . read_inbox_max_id , channelID ) ;
dialog . read_outbox_max_id = appMessagesIDsManager . getFullMessageID ( dialog . read_outbox_max_id , channelID ) ;
2020-09-18 17:03:26 +02:00
if ( ! dialog . hasOwnProperty ( 'folder_id' ) ) {
if ( dialog . _ == 'dialog' ) {
2020-09-19 18:32:48 +02:00
// ! СЛОЖНО ! СМОТРИ В getTopMessages
const wasDialogBefore = this . getDialogByPeerID ( peerID ) [ 0 ] ;
dialog . folder_id = wasDialogBefore ? wasDialogBefore.folder_id : folderID ;
2020-09-18 17:03:26 +02:00
} / * else if ( dialog . _ == 'dialogFolder' ) {
dialog . folder_id = dialog . folder . id ;
} * /
}
2020-02-06 16:43:07 +01:00
dialog . peerID = peerID ;
2020-06-19 13:49:55 +02:00
this . dialogsStorage . generateIndexForDialog ( dialog ) ;
this . dialogsStorage . pushDialog ( dialog , message . date ) ;
2020-02-06 16:43:07 +01:00
// Because we saved message without dialog present
if ( message . mid > 0 ) {
2020-05-03 14:46:05 +02:00
if ( message . mid > dialog [ message . pFlags . out ? 'read_outbox_max_id' : 'read_inbox_max_id' ] ) message . pFlags . unread = true ;
2020-10-03 02:35:26 +02:00
else delete message . pFlags . unread ;
2020-02-06 16:43:07 +01:00
}
2020-10-26 02:59:49 +01:00
let historyStorage = this . historiesStorage [ peerID ] ;
if ( historyStorage === undefined /* && !message.deleted */ ) { // warning
historyStorage = this . historiesStorage [ peerID ] = { count : null , history : [ ] , pending : [ ] } ;
2020-05-20 16:25:23 +02:00
historyStorage [ mid > 0 ? 'history' : 'pending' ] . push ( mid ) ;
2020-10-03 02:35:26 +02:00
/ * i f ( m i d < 0 & & m e s s a g e . p F l a g s . u n r e a d ) {
2020-02-06 16:43:07 +01:00
dialog . unread_count ++ ;
2020-10-03 02:35:26 +02:00
} * /
2020-02-06 16:43:07 +01:00
if ( this . mergeReplyKeyboard ( historyStorage , message ) ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_reply_markup' , { peerID } ) ;
2020-02-06 16:43:07 +01:00
}
2020-10-26 02:59:49 +01:00
} else if ( ! historyStorage . history . length && ! historyStorage . pending . length ) {
historyStorage [ mid > 0 ? 'history' : 'pending' ] . push ( mid ) ;
2020-02-06 16:43:07 +01:00
}
if ( channelID && dialog . pts ) {
apiUpdatesManager . addChannelState ( channelID , dialog . pts ) ;
}
2020-06-19 13:49:55 +02:00
//if(this.filtersStorage.inited) {
//this.filtersStorage.processDialog(dialog);
//}
2020-02-06 16:43:07 +01:00
}
2020-05-20 16:25:23 +02:00
public mergeReplyKeyboard ( historyStorage : HistoryStorage , message : any ) {
2020-06-13 10:19:39 +02:00
// this.log('merge', message.mid, message.reply_markup, historyStorage.reply_markup)
2020-02-06 16:43:07 +01:00
if ( ! message . reply_markup &&
2020-10-03 19:45:56 +02:00
! message . pFlags ? . out &&
2020-02-06 16:43:07 +01:00
! message . action ) {
return false ;
}
if ( message . reply_markup &&
message . reply_markup . _ == 'replyInlineMarkup' ) {
return false ;
}
var messageReplyMarkup = message . reply_markup ;
var lastReplyMarkup = historyStorage . reply_markup ;
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 ;
}
if ( historyStorage . maxOutID &&
message . mid < historyStorage . maxOutID &&
messageReplyMarkup . pFlags . single_use ) {
messageReplyMarkup . pFlags . hidden = true ;
}
messageReplyMarkup = Object . assign ( {
mid : message.mid
} , messageReplyMarkup ) ;
if ( messageReplyMarkup . _ != 'replyKeyboardHide' ) {
2020-10-02 22:33:32 +02:00
messageReplyMarkup . fromID = appPeersManager . getPeerID ( message . from_id ) ;
2020-02-06 16:43:07 +01:00
}
historyStorage . reply_markup = 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 ) {
if ( lastReplyMarkup . pFlags . single_use &&
! lastReplyMarkup . pFlags . hidden &&
( message . mid > lastReplyMarkup . mid || message . mid < 0 ) &&
message . message ) {
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 ;
}
} else if ( ! historyStorage . maxOutID ||
message . mid > historyStorage . maxOutID ) {
historyStorage . maxOutID = message . mid ;
}
}
if ( message . action &&
message . action . _ == 'messageActionChatDeleteUser' &&
( lastReplyMarkup
? message . action . user_id == lastReplyMarkup . fromID
: appUsersManager . isBot ( message . action . user_id )
)
) {
historyStorage . reply_markup = {
_ : '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 ;
}
2020-12-08 20:48:44 +01:00
public getSearchStorage ( peerID : number , inputFilter : MyInputMessagesFilter ) {
if ( ! this . searchesStorage [ peerID ] ) this . searchesStorage [ peerID ] = { } ;
if ( ! this . searchesStorage [ peerID ] [ inputFilter ] ) this . searchesStorage [ peerID ] [ inputFilter ] = { history : [ ] } ;
return this . searchesStorage [ peerID ] [ inputFilter ] ;
}
public getSearchCounters ( peerID : number , filters : MessagesFilter [ ] ) {
return apiManager . invokeApi ( 'messages.getSearchCounters' , {
peer : appPeersManager.getInputPeerByID ( peerID ) ,
filters
} ) ;
}
2020-02-06 16:43:07 +01:00
public getSearch ( peerID = 0 , query : string = '' , inputFilter : {
2020-12-08 20:48:44 +01:00
_ : MyInputMessagesFilter
2020-10-02 22:33:32 +02:00
} = { _ : 'inputMessagesFilterEmpty' } , maxID : number , limit = 20 , offsetRate = 0 , backLimit = 0 ) : 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-02-07 07:38:55 +01:00
history : number [ ]
} > {
2020-10-03 19:45:56 +02:00
const foundMsgs : number [ ] = [ ] ;
2020-02-06 16:43:07 +01:00
2020-12-08 20:48:44 +01:00
//this.log('search', maxID);
if ( backLimit ) {
limit += backLimit ;
2020-02-06 16:43:07 +01:00
}
2020-12-08 20:48:44 +01:00
//const beta = inputFilter._ == 'inputMessagesFilterPinned' && !backLimit;
const beta = false ;
2020-02-06 16:43:07 +01:00
2020-12-08 20:48:44 +01:00
let storage : {
count? : number ;
history : number [ ] ;
} ;
// * костыль для limit 1, если нужно и получить сообщение, и узнать количество сообщений
if ( peerID && ! backLimit && ! maxID && ! query && limit !== 1 /* && inputFilter._ !== 'inputMessagesFilterPinned' */ ) {
storage = beta ?
this . getSearchStorage ( peerID , inputFilter . _ ) :
this . historiesStorage [ peerID ] ;
2020-11-25 20:36:18 +01:00
let filtering = true ;
2020-02-06 16:43:07 +01:00
2020-12-08 20:48:44 +01:00
const history = maxID ? storage . history . slice ( storage . history . indexOf ( maxID ) + 1 ) : storage . history ;
if ( storage !== undefined && history . length ) {
const neededContents : {
2020-10-02 22:33:32 +02:00
[ messageMediaType : string ] : boolean
2020-02-06 16:43:07 +01:00
} = { } ,
2020-12-08 20:48:44 +01:00
neededDocTypes : string [ ] = [ ] ,
excludeDocTypes : string [ ] = [ ] / * ,
neededFlags : string [ ] = [ ] * / ;
2020-02-06 16:43:07 +01:00
switch ( inputFilter . _ ) {
case 'inputMessagesFilterPhotos' :
neededContents [ 'messageMediaPhoto' ] = true ;
break ;
case 'inputMessagesFilterPhotoVideo' :
neededContents [ 'messageMediaPhoto' ] = true ;
neededContents [ 'messageMediaDocument' ] = true ;
2020-08-29 13:45:37 +02:00
neededDocTypes . push ( 'video' ) ;
2020-02-06 16:43:07 +01:00
break ;
case 'inputMessagesFilterVideo' :
neededContents [ 'messageMediaDocument' ] = true ;
2020-08-29 13:45:37 +02:00
neededDocTypes . push ( 'video' ) ;
2020-02-06 16:43:07 +01:00
break ;
case 'inputMessagesFilterDocument' :
neededContents [ 'messageMediaDocument' ] = true ;
2020-11-08 00:56:37 +01:00
excludeDocTypes . push ( 'video' ) ;
2020-02-06 16:43:07 +01:00
break ;
case 'inputMessagesFilterVoice' :
neededContents [ 'messageMediaDocument' ] = true ;
2020-08-29 13:45:37 +02:00
neededDocTypes . push ( 'voice' ) ;
break ;
case 'inputMessagesFilterRoundVoice' :
neededContents [ 'messageMediaDocument' ] = true ;
neededDocTypes . push ( 'round' , 'voice' ) ;
2020-02-06 16:43:07 +01:00
break ;
case 'inputMessagesFilterRoundVideo' :
neededContents [ 'messageMediaDocument' ] = true ;
2020-08-29 13:45:37 +02:00
neededDocTypes . push ( 'round' ) ;
2020-02-06 16:43:07 +01:00
break ;
case 'inputMessagesFilterMusic' :
neededContents [ 'messageMediaDocument' ] = true ;
2020-08-29 13:45:37 +02:00
neededDocTypes . push ( 'audio' ) ;
2020-02-06 16:43:07 +01:00
break ;
case 'inputMessagesFilterUrl' :
neededContents [ 'url' ] = true ;
break ;
2020-10-15 00:46:29 +02:00
case 'inputMessagesFilterChatPhotos' :
neededContents [ 'avatar' ] = true ;
break ;
2020-12-08 20:48:44 +01:00
/ * c a s e ' 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 ' :
neededFlags . push ( 'pinned' ) ;
break ; * /
2020-10-03 19:45:56 +02:00
/ * c a s e ' i n p u t M e s s a g e s F i l t e r M y M e n t i o n s ' :
2020-02-06 16:43:07 +01:00
neededContents [ 'mentioned' ] = true ;
2020-10-03 19:45:56 +02:00
break ; * /
2020-02-06 16:43:07 +01:00
default :
2020-11-25 20:36:18 +01:00
filtering = false ;
break ;
/ * r e t u r n P r o m i s e . r e s o l v e ( {
2020-02-06 16:43:07 +01:00
count : 0 ,
2020-02-07 07:38:55 +01:00
next_rate : 0 ,
2020-02-06 16:43:07 +01:00
history : [ ] as number [ ]
2020-11-25 20:36:18 +01:00
} ) ; * /
2020-02-06 16:43:07 +01:00
}
2020-11-25 20:36:18 +01:00
if ( filtering ) {
2020-12-08 20:48:44 +01:00
for ( let i = 0 , length = history . length ; i < length ; i ++ ) {
const message = this . messagesStorage [ history [ i ] ] ;
2020-11-25 20:36:18 +01:00
//|| (neededContents['mentioned'] && message.totalEntities.find((e: any) => e._ == 'messageEntityMention'));
let found = false ;
if ( message . media && neededContents [ message . media . _ ] && ! message . fwd_from ) {
if ( message . media . _ == 'messageMediaDocument' ) {
if ( ( neededDocTypes . length && ! neededDocTypes . includes ( message . media . document . type ) )
|| excludeDocTypes . includes ( message . media . document . type ) ) {
continue ;
}
2020-11-08 00:56:37 +01:00
}
2020-11-25 20:36:18 +01:00
found = true ;
} else if ( neededContents [ 'url' ] && message . message ) {
const goodEntities = [ 'messageEntityTextUrl' , 'messageEntityUrl' ] ;
if ( ( message . totalEntities as MessageEntity [ ] ) . find ( e = > goodEntities . includes ( e . _ ) ) || RichTextProcessor . matchUrl ( message . message ) ) {
found = true ;
}
} else if ( neededContents [ 'avatar' ] && message . action && [ 'messageActionChannelEditPhoto' , 'messageActionChatEditPhoto' ] . includes ( message . action . _ ) ) {
2020-11-08 00:56:37 +01:00
found = true ;
2020-12-08 20:48:44 +01:00
} / * else if ( neededFlags . find ( flag = > message . pFlags [ flag ] ) ) {
found = true ;
} * /
2020-11-25 20:36:18 +01:00
if ( found ) {
foundMsgs . push ( message . mid ) ;
if ( foundMsgs . length >= limit ) {
break ;
}
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-10-03 19:45:56 +02:00
maxID = foundMsgs [ foundMsgs . length - 1 ] ;
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
}
2020-06-13 10:19:39 +02:00
let apiPromise : Promise < any > ;
2020-02-06 16:43:07 +01:00
if ( peerID || ! query ) {
2020-02-11 16:35:57 +01:00
apiPromise = apiManager . invokeApi ( 'messages.search' , {
2020-05-18 03:21:58 +02:00
peer : 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-02-06 16:43:07 +01:00
min_date : 0 ,
max_date : 0 ,
2020-10-02 22:33:32 +02:00
limit ,
2020-02-06 16:43:07 +01:00
offset_id : appMessagesIDsManager.getMessageLocalID ( 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 ,
hash : 0
2020-02-06 16:43:07 +01:00
} , {
2020-09-18 17:52:21 +02:00
//timeout: APITIMEOUT,
2020-02-06 16:43:07 +01:00
noErrorBox : true
} ) ;
} else {
var offsetDate = 0 ;
var offsetPeerID = 0 ;
var offsetID = 0 ;
var offsetMessage = maxID && this . getMessage ( maxID ) ;
if ( offsetMessage && offsetMessage . date ) {
2020-11-10 01:47:00 +01:00
offsetDate = offsetMessage . date + serverTimeManager . serverTimeOffset ;
2020-02-06 16:43:07 +01:00
offsetID = offsetMessage . id ;
offsetPeerID = this . getMessagePeer ( offsetMessage ) ;
}
2020-02-11 16:35:57 +01:00
apiPromise = apiManager . invokeApi ( '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-10-02 22:33:32 +02:00
min_date : 0 ,
max_date : 0 ,
2020-02-07 07:38:55 +01:00
offset_rate : offsetRate ,
2020-05-18 03:21:58 +02:00
offset_peer : appPeersManager.getInputPeerByID ( offsetPeerID ) ,
2020-02-06 16:43:07 +01:00
offset_id : appMessagesIDsManager.getMessageLocalID ( offsetID ) ,
2020-10-02 22:33:32 +02:00
limit
2020-02-06 16:43:07 +01:00
} , {
2020-09-18 17:52:21 +02:00
//timeout: APITIMEOUT,
2020-02-06 16:43:07 +01:00
noErrorBox : true
} ) ;
}
return apiPromise . then ( ( searchResult : any ) = > {
appUsersManager . saveApiUsers ( searchResult . users ) ;
appChatsManager . saveApiChats ( searchResult . chats ) ;
this . saveMessages ( searchResult . messages ) ;
2020-12-08 20:48:44 +01:00
if ( beta && storage && ( ! maxID || storage . history [ storage . history . length - 1 ] == maxID ) ) {
const storage = this . getSearchStorage ( peerID , inputFilter . _ ) ;
const add = ( searchResult . messages . map ( ( m : any ) = > m . mid ) as number [ ] ) . filter ( mid = > storage . history . indexOf ( mid ) === - 1 ) ;
storage . history . push ( . . . add ) ;
storage . history . sort ( ( a , b ) = > b - a ) ;
storage . count = searchResult . count ;
}
2020-10-03 19:45:56 +02:00
this . log ( 'messages.search 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
searchResult . messages . forEach ( ( message : any ) = > {
2020-10-03 19:45:56 +02:00
const peerID = this . getMessagePeer ( message ) ;
2020-02-06 16:43:07 +01:00
if ( peerID < 0 ) {
2020-10-03 19:45:56 +02:00
const chat = appChatsManager . getChat ( - peerID ) ;
2020-02-06 16:43:07 +01:00
if ( chat . migrated_to ) {
this . migrateChecks ( peerID , - chat . migrated_to . channel_id ) ;
}
}
2020-12-08 20:48:44 +01:00
2020-02-06 16:43:07 +01:00
foundMsgs . push ( message . mid ) ;
} ) ;
return {
count : foundCount ,
2020-12-08 20:48:44 +01:00
offset_id_offset : searchResult.offset_id_offset ,
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
} ) ;
}
2020-06-19 13:49:55 +02:00
handleNewMessages = ( ) = > {
2020-02-06 16:43:07 +01:00
clearTimeout ( this . newMessagesHandlePromise ) ;
this . newMessagesHandlePromise = 0 ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_multiappend' , this . newMessagesToHandle ) ;
2020-02-06 16:43:07 +01:00
this . newMessagesToHandle = { } ;
2020-06-19 13:49:55 +02:00
} ;
2020-02-06 16:43:07 +01:00
2020-06-19 13:49:55 +02:00
handleNewDialogs = ( ) = > {
2020-02-06 16:43:07 +01:00
clearTimeout ( this . newDialogsHandlePromise ) ;
this . newDialogsHandlePromise = 0 ;
2020-05-10 03:23:21 +02:00
let newMaxSeenID = 0 ;
2020-06-19 13:49:55 +02:00
for ( const peerID in this . newDialogsToHandle ) {
const dialog = this . newDialogsToHandle [ peerID ] ;
2020-05-10 03:23:21 +02:00
if ( 'reload' in dialog ) {
2020-02-06 16:43:07 +01:00
this . reloadConversation ( + peerID ) ;
delete this . newDialogsToHandle [ peerID ] ;
} else {
2020-06-19 13:49:55 +02:00
this . dialogsStorage . pushDialog ( dialog ) ;
2020-05-18 03:21:58 +02:00
if ( ! appPeersManager . isChannel ( + peerID ) ) {
2020-02-06 16:43:07 +01:00
newMaxSeenID = Math . max ( newMaxSeenID , dialog . top_message || 0 ) ;
}
}
2020-05-13 17:26:40 +02:00
}
2020-05-10 03:23:21 +02:00
2020-06-13 10:19:39 +02:00
//this.log('after order:', this.dialogsStorage[0].map(d => d.peerID));
2020-02-06 16:43:07 +01:00
if ( newMaxSeenID != 0 ) {
this . incrementMaxSeenID ( newMaxSeenID ) ;
}
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialogs_multiupdate' , this . newDialogsToHandle as any ) ;
2020-02-06 16:43:07 +01:00
this . newDialogsToHandle = { } ;
2020-06-19 13:49:55 +02:00
} ;
2020-02-06 16:43:07 +01:00
2020-05-13 17:26:40 +02:00
public scheduleHandleNewDialogs() {
if ( ! this . newDialogsHandlePromise ) {
2020-06-19 13:49:55 +02:00
this . newDialogsHandlePromise = window . setTimeout ( this . handleNewDialogs , 0 ) ;
2020-05-13 17:26:40 +02:00
}
}
2020-05-27 08:21:16 +02:00
public deleteMessages ( messageIDs : number [ ] , revoke : boolean ) {
const splitted = appMessagesIDsManager . splitMessageIDsByChannels ( messageIDs ) ;
const promises : Promise < any > [ ] = [ ] ;
for ( const channelIDStr in splitted . msgIDs ) {
const channelID = + channelIDStr ;
let msgIDs = splitted . msgIDs [ channelID ] ;
let promise : Promise < any > ;
if ( channelID > 0 ) {
const channel = appChatsManager . getChat ( channelID ) ;
if ( ! channel . pFlags . creator && ! ( channel . pFlags . editor && channel . pFlags . megagroup ) ) {
const goodMsgIDs : number [ ] = [ ] ;
if ( channel . pFlags . editor || channel . pFlags . megagroup ) {
msgIDs . forEach ( ( msgID , i ) = > {
const message = this . getMessage ( splitted . mids [ channelID ] [ i ] ) ;
if ( message . pFlags . out ) {
goodMsgIDs . push ( msgID ) ;
}
} ) ;
}
if ( ! goodMsgIDs . length ) {
return ;
}
msgIDs = goodMsgIDs ;
}
promise = apiManager . invokeApi ( 'channels.deleteMessages' , {
channel : appChatsManager.getChannelInput ( channelID ) ,
id : msgIDs
} ) . then ( ( affectedMessages ) = > {
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateDeleteChannelMessages' ,
channel_id : channelID ,
messages : msgIDs ,
pts : affectedMessages.pts ,
pts_count : affectedMessages.pts_count
}
} ) ;
} ) ;
} else {
promise = apiManager . invokeApi ( 'messages.deleteMessages' , {
2020-10-26 02:59:49 +01:00
revoke : revoke || undefined ,
2020-05-27 08:21:16 +02:00
id : msgIDs
} ) . then ( ( affectedMessages ) = > {
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateDeleteMessages' ,
messages : msgIDs ,
pts : affectedMessages.pts ,
pts_count : affectedMessages.pts_count
}
} ) ;
} ) ;
}
promises . push ( promise ) ;
}
return Promise . all ( promises ) ;
}
2020-10-03 02:35:26 +02:00
public readHistory ( peerID : number , maxID = 0 ) {
2020-02-06 16:43:07 +01:00
// console.trace('start read')
2020-05-26 17:04:06 +02:00
const isChannel = appPeersManager . isChannel ( peerID ) ;
const historyStorage = this . historiesStorage [ peerID ] ;
const foundDialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
2020-02-06 16:43:07 +01:00
if ( ! foundDialog || ! foundDialog . unread_count ) {
if ( ! historyStorage || ! historyStorage . history . length ) {
2020-02-07 15:17:39 +01:00
return Promise . resolve ( false ) ;
2020-02-06 16:43:07 +01:00
}
2020-05-26 17:04:06 +02:00
let foundUnread = ! ! historyStorage . history . find ( messageID = > {
const message = this . messagesStorage [ messageID ] ;
return message && ! message . pFlags . out && message . pFlags . unread ;
} ) ;
2020-02-06 16:43:07 +01:00
if ( ! foundUnread ) {
2020-02-07 15:17:39 +01:00
return Promise . resolve ( false ) ;
2020-02-06 16:43:07 +01:00
}
}
2020-10-03 02:35:26 +02:00
if ( isChannel ) {
maxID = appMessagesIDsManager . getMessageLocalID ( maxID ) ;
}
if ( ! historyStorage . readMaxID || maxID > historyStorage . readMaxID ) {
historyStorage . readMaxID = maxID ;
}
2020-02-06 16:43:07 +01:00
if ( historyStorage . readPromise ) {
2020-05-26 17:04:06 +02:00
return historyStorage . readPromise ;
2020-02-06 16:43:07 +01:00
}
2020-10-03 02:35:26 +02:00
let apiPromise : Promise < boolean > ;
2020-02-06 16:43:07 +01:00
if ( isChannel ) {
2020-02-11 16:35:57 +01:00
apiPromise = apiManager . invokeApi ( 'channels.readHistory' , {
2020-02-06 16:43:07 +01:00
channel : appChatsManager.getChannelInput ( - peerID ) ,
max_id : maxID
2020-10-03 02:35:26 +02:00
} ) . then ( ( res ) = > {
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateReadChannelInbox' ,
max_id : maxID ,
channel_id : - peerID
}
} ) ;
return res ;
2020-02-06 16:43:07 +01:00
} ) ;
} else {
2020-02-11 16:35:57 +01:00
apiPromise = apiManager . invokeApi ( 'messages.readHistory' , {
2020-05-18 03:21:58 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
2020-02-06 16:43:07 +01:00
max_id : maxID
2020-09-20 00:38:00 +02:00
} ) . then ( ( affectedMessages ) = > {
2020-02-06 16:43:07 +01:00
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updatePts' ,
pts : affectedMessages.pts ,
pts_count : affectedMessages.pts_count
}
} ) ;
2020-05-26 17:04:06 +02:00
2020-10-03 02:35:26 +02:00
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateReadHistoryInbox' ,
max_id : maxID ,
peer : appPeersManager.getOutputPeer ( peerID )
2020-05-26 17:04:06 +02:00
}
2020-10-03 02:35:26 +02:00
} ) ;
2020-02-07 15:17:39 +01:00
return true ;
2020-10-03 02:35:26 +02:00
} ) ;
}
2020-02-07 15:17:39 +01:00
2020-10-03 02:35:26 +02:00
apiPromise . finally ( ( ) = > {
2020-02-06 16:43:07 +01:00
delete historyStorage . readPromise ;
2020-10-03 02:35:26 +02:00
if ( historyStorage . readMaxID > maxID ) {
this . readHistory ( peerID , historyStorage . readMaxID ) ;
} else {
delete historyStorage . readMaxID ;
}
} ) ;
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
}
public readMessages ( messageIDs : number [ ] ) {
2020-10-08 22:49:08 +02:00
const splitted = appMessagesIDsManager . splitMessageIDsByChannels ( messageIDs ) ;
2020-02-06 16:43:07 +01:00
Object . keys ( splitted . msgIDs ) . forEach ( ( channelID : number | string ) = > {
channelID = + channelID ;
2020-10-08 22:49:08 +02:00
const msgIDs = splitted . msgIDs [ channelID ] ;
2020-02-06 16:43:07 +01:00
if ( channelID > 0 ) {
2020-02-11 16:35:57 +01:00
apiManager . invokeApi ( 'channels.readMessageContents' , {
2020-02-06 16:43:07 +01:00
channel : appChatsManager.getChannelInput ( channelID ) ,
id : msgIDs
} ) . then ( ( ) = > {
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateChannelReadMessagesContents' ,
channel_id : channelID ,
messages : msgIDs
}
} ) ;
} ) ;
} else {
2020-02-11 16:35:57 +01:00
apiManager . invokeApi ( 'messages.readMessageContents' , {
2020-02-06 16:43:07 +01:00
id : msgIDs
2020-09-20 00:38:00 +02:00
} ) . then ( ( affectedMessages ) = > {
2020-02-06 16:43:07 +01:00
apiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateReadMessagesContents' ,
messages : msgIDs ,
pts : affectedMessages.pts ,
pts_count : affectedMessages.pts_count
}
} ) ;
} ) ;
}
} ) ;
}
2020-10-11 14:51:23 +02:00
public handleUpdate ( update : Update ) {
2020-11-10 01:47:00 +01:00
this . log . debug ( 'handleUpdate' , update . _ ) ;
2020-02-06 16:43:07 +01:00
switch ( update . _ ) {
case 'updateMessageID' : {
2020-10-11 14:51:23 +02:00
const randomID = update . random_id ;
const pendingData = this . pendingByRandomID [ randomID ] ;
2020-06-13 10:19:39 +02:00
//this.log('AMM updateMessageID:', update, pendingData);
2020-02-06 16:43:07 +01:00
if ( pendingData ) {
2020-10-11 14:51:23 +02:00
const peerID : number = pendingData [ 0 ] ;
const tempID = pendingData [ 1 ] ;
const channelID = appPeersManager . isChannel ( peerID ) ? - peerID : 0 ;
const mid = appMessagesIDsManager . getFullMessageID ( update . id , channelID ) ;
const message = this . messagesStorage [ mid ] ;
2020-02-06 16:43:07 +01:00
if ( message ) {
2020-10-11 14:51:23 +02:00
const historyStorage = this . historiesStorage [ peerID ] ;
const pos = historyStorage . pending . indexOf ( tempID ) ;
2020-02-06 16:43:07 +01:00
if ( pos != - 1 ) {
historyStorage . pending . splice ( pos , 1 ) ;
}
delete this . messagesStorage [ tempID ] ;
this . finalizePendingMessageCallbacks ( tempID , mid ) ;
} else {
this . pendingByMessageID [ mid ] = randomID ;
}
}
break ;
}
case 'updateNewMessage' :
case 'updateNewChannelMessage' : {
2020-10-11 14:51:23 +02:00
const message = update . message as MyMessage ;
const peerID = this . getMessagePeer ( message ) ;
const foundDialog = this . getDialogByPeerID ( peerID ) ;
2020-02-06 16:43:07 +01:00
if ( ! foundDialog . length ) {
2020-10-03 02:35:26 +02:00
this . newDialogsToHandle [ peerID ] = { reload : true } ;
2020-05-13 17:26:40 +02:00
this . scheduleHandleNewDialogs ( ) ;
2020-02-06 16:43:07 +01:00
if ( this . newUpdatesAfterReloadToHandle [ peerID ] === undefined ) {
this . newUpdatesAfterReloadToHandle [ peerID ] = [ ] ;
}
this . newUpdatesAfterReloadToHandle [ peerID ] . push ( update ) ;
break ;
}
if ( update . _ == 'updateNewChannelMessage' ) {
2020-10-11 14:51:23 +02:00
const chat = appChatsManager . getChat ( - peerID ) ;
2020-02-06 16:43:07 +01:00
if ( chat . pFlags && ( chat . pFlags . left || chat . pFlags . kicked ) ) {
break ;
}
}
2020-10-03 02:35:26 +02:00
this . saveMessages ( [ message ] ) ;
2020-06-13 10:19:39 +02:00
// this.log.warn(dT(), 'message unread', message.mid, message.pFlags.unread)
2020-02-06 16:43:07 +01:00
2020-10-11 14:51:23 +02:00
let historyStorage = this . historiesStorage [ peerID ] ;
2020-02-06 16:43:07 +01:00
if ( historyStorage === undefined ) {
historyStorage = this . historiesStorage [ peerID ] = {
count : null ,
history : [ ] ,
pending : [ ]
} ;
}
2020-10-11 14:51:23 +02:00
const history = message . mid > 0 ? historyStorage.history : historyStorage.pending ;
2020-02-06 16:43:07 +01:00
if ( history . indexOf ( message . mid ) != - 1 ) {
return false ;
}
2020-10-11 14:51:23 +02:00
const topMsgID = history [ 0 ] ;
2020-02-06 16:43:07 +01:00
history . unshift ( message . mid ) ;
if ( message . mid > 0 && message . mid < topMsgID ) {
2020-09-20 00:38:00 +02:00
history . sort ( ( a , b ) = > {
2020-02-06 16:43:07 +01:00
return b - a ;
} ) ;
}
if ( message . mid > 0 &&
historyStorage . count !== null ) {
historyStorage . count ++ ;
}
if ( this . mergeReplyKeyboard ( historyStorage , message ) ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_reply_markup' , { peerID } ) ;
2020-02-06 16:43:07 +01:00
}
if ( ! message . pFlags . out && message . from_id ) {
2020-11-18 05:44:34 +01:00
appUsersManager . forceUserOnline ( appPeersManager . getPeerID ( message . from_id ) , message . date ) ;
2020-02-06 16:43:07 +01:00
}
2020-10-11 14:51:23 +02:00
const randomID = this . pendingByMessageID [ message . mid ] ;
let pendingMessage : any ;
2020-02-06 16:43:07 +01:00
if ( randomID ) {
if ( pendingMessage = this . finalizePendingMessage ( randomID , message ) ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_update' , { peerID , mid : message.mid } ) ;
2020-02-06 16:43:07 +01:00
}
delete this . pendingByMessageID [ message . mid ] ;
}
if ( ! pendingMessage ) {
if ( this . newMessagesToHandle [ peerID ] === undefined ) {
this . newMessagesToHandle [ peerID ] = [ ] ;
}
this . newMessagesToHandle [ peerID ] . push ( message . mid ) ;
if ( ! this . newMessagesHandlePromise ) {
2020-06-19 13:49:55 +02:00
this . newMessagesHandlePromise = window . setTimeout ( this . handleNewMessages , 0 ) ;
2020-02-06 16:43:07 +01:00
}
}
2020-10-11 14:51:23 +02:00
const inboxUnread = ! message . pFlags . out && message . pFlags . unread ;
const dialog = foundDialog [ 0 ] ;
2020-02-06 16:43:07 +01:00
dialog . top_message = message . mid ;
if ( inboxUnread ) {
dialog . unread_count ++ ;
}
if ( ! dialog . pFlags . pinned || ! dialog . index ) {
2020-06-19 13:49:55 +02:00
dialog . index = this . dialogsStorage . generateDialogIndex ( message . date ) ;
2020-02-06 16:43:07 +01:00
}
this . newDialogsToHandle [ peerID ] = dialog ;
2020-05-13 17:26:40 +02:00
this . scheduleHandleNewDialogs ( ) ;
break ;
}
case 'updateDialogUnreadMark' : {
2020-06-13 10:19:39 +02:00
this . log ( 'updateDialogUnreadMark' , update ) ;
2020-10-11 14:51:23 +02:00
const peerID = appPeersManager . getPeerID ( ( update . peer as DialogPeer . dialogPeer ) . peer ) ;
const foundDialog = this . getDialogByPeerID ( peerID ) ;
2020-05-13 17:26:40 +02:00
if ( ! foundDialog . length ) {
this . newDialogsToHandle [ peerID ] = { reload : true } ;
this . scheduleHandleNewDialogs ( ) ;
} else {
2020-10-11 14:51:23 +02:00
const dialog = foundDialog [ 0 ] ;
2020-05-13 17:26:40 +02:00
if ( ! update . pFlags . unread ) {
delete dialog . pFlags . unread_mark ;
} else {
dialog . pFlags . unread_mark = true ;
}
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialogs_multiupdate' , { peerID : dialog } ) ;
2020-02-06 16:43:07 +01:00
}
break ;
}
2020-06-19 13:49:55 +02:00
case 'updateFolderPeers' : { // only 0 and 1 folders
2020-06-13 10:19:39 +02:00
this . log ( 'updateFolderPeers' , update ) ;
2020-06-19 13:49:55 +02:00
const peers = update . folder_peers ;
2020-05-13 17:26:40 +02:00
this . scheduleHandleNewDialogs ( ) ;
2020-11-18 05:44:34 +01:00
peers . forEach ( ( folderPeer ) = > {
2020-06-19 13:49:55 +02:00
const { folder_id , peer } = folderPeer ;
2020-05-13 17:26:40 +02:00
2020-06-19 13:49:55 +02:00
const peerID = appPeersManager . getPeerID ( peer ) ;
const dropped = this . dialogsStorage . dropDialog ( peerID ) ;
if ( ! dropped . length ) {
2020-05-13 17:26:40 +02:00
this . newDialogsToHandle [ peerID ] = { reload : true } ;
} else {
2020-06-19 13:49:55 +02:00
const dialog = dropped [ 0 ] ;
2020-05-13 17:26:40 +02:00
this . newDialogsToHandle [ peerID ] = dialog ;
2020-06-19 13:49:55 +02:00
if ( dialog . pFlags ? . pinned ) {
delete dialog . pFlags . pinned ;
2020-06-20 03:11:24 +02:00
this . dialogsStorage . pinnedOrders [ folder_id ] . findAndSplice ( p = > p == dialog . peerID ) ;
2020-06-19 13:49:55 +02:00
}
2020-05-13 17:26:40 +02:00
dialog . folder_id = folder_id ;
2020-06-19 13:49:55 +02:00
this . dialogsStorage . generateIndexForDialog ( dialog ) ;
this . dialogsStorage . pushDialog ( dialog ) ; // need for simultaneously updatePinnedDialogs
2020-05-13 17:26:40 +02:00
}
} ) ;
break ;
}
2020-05-10 03:23:21 +02:00
case 'updateDialogPinned' : {
2020-06-20 03:11:24 +02:00
const folderID = update . folder_id ? ? 0 ;
2020-06-13 10:19:39 +02:00
this . log ( 'updateDialogPinned' , update ) ;
2020-10-11 14:51:23 +02:00
const peerID = appPeersManager . getPeerID ( ( update . peer as DialogPeer . dialogPeer ) . peer ) ;
2020-06-19 13:49:55 +02:00
const foundDialog = this . getDialogByPeerID ( peerID ) ;
// этот код внизу никогда не сработает, в папках за пиннед отвечает updateDialogFilter
/ * i f ( u p d a t e . f o l d e r _ i d > 1 ) {
const filter = this . filtersStorage . filters [ update . folder_id ] ;
if ( update . pFlags . pinned ) {
filter . pinned_peers . unshift ( peerID ) ;
} else {
filter . pinned_peers . findAndSplice ( p = > p == peerID ) ;
}
} * /
2020-05-10 03:23:21 +02:00
2020-05-13 17:26:40 +02:00
this . scheduleHandleNewDialogs ( ) ;
2020-05-10 03:23:21 +02:00
if ( ! foundDialog . length ) {
2020-02-06 16:43:07 +01:00
this . newDialogsToHandle [ peerID ] = { reload : true } ;
2020-05-10 03:23:21 +02:00
} else {
2020-06-19 13:49:55 +02:00
const dialog = foundDialog [ 0 ] ;
2020-05-10 03:23:21 +02:00
this . newDialogsToHandle [ peerID ] = dialog ;
if ( ! update . pFlags . pinned ) {
delete dialog . pFlags . pinned ;
2020-06-20 03:11:24 +02:00
this . dialogsStorage . pinnedOrders [ folderID ] . findAndSplice ( p = > p == dialog . peerID ) ;
2020-05-10 03:23:21 +02:00
} else { // means set
dialog . pFlags . pinned = true ;
}
2020-06-19 13:49:55 +02:00
this . dialogsStorage . generateIndexForDialog ( dialog ) ;
2020-05-10 03:23:21 +02:00
}
2020-02-06 16:43:07 +01:00
break ;
}
case 'updatePinnedDialogs' : {
2020-06-19 13:49:55 +02:00
const folderID = update . folder_id ? ? 0 ;
2020-11-21 07:37:04 +01:00
const handleOrder = ( order : number [ ] ) = > {
this . dialogsStorage . pinnedOrders [ folderID ] . length = 0 ;
let willHandle = false ;
order . reverse ( ) ; // index must be higher
order . forEach ( ( peerID ) = > {
newPinned [ peerID ] = true ;
const foundDialog = this . getDialogByPeerID ( peerID ) ;
if ( ! foundDialog . length ) {
this . newDialogsToHandle [ peerID ] = { reload : true } ;
willHandle = true ;
return ;
}
const dialog = foundDialog [ 0 ] ;
dialog . pFlags . pinned = true ;
this . dialogsStorage . generateIndexForDialog ( dialog ) ;
this . newDialogsToHandle [ peerID ] = dialog ;
willHandle = true ;
} ) ;
this . dialogsStorage . getFolder ( folderID ) . forEach ( dialog = > {
const peerID = dialog . peerID ;
if ( dialog . pFlags . pinned && ! newPinned [ peerID ] ) {
this . newDialogsToHandle [ peerID ] = { reload : true } ;
willHandle = true ;
}
} ) ;
if ( willHandle ) {
this . scheduleHandleNewDialogs ( ) ;
}
} ;
2020-06-19 13:49:55 +02:00
2020-06-13 10:19:39 +02:00
this . log ( 'updatePinnedDialogs' , update ) ;
2020-06-19 13:49:55 +02:00
const newPinned : { [ peerID : number ] : true } = { } ;
2020-02-06 16:43:07 +01:00
if ( ! update . order ) {
2020-06-19 13:49:55 +02:00
apiManager . invokeApi ( 'messages.getPinnedDialogs' , {
folder_id : folderID
2020-09-18 17:03:26 +02:00
} ) . then ( ( dialogsResult ) = > {
2020-11-21 07:37:04 +01:00
// * for test reordering and rendering
// dialogsResult.dialogs.reverse();
2020-02-06 16:43:07 +01:00
this . applyConversations ( dialogsResult ) ;
2020-11-21 07:37:04 +01:00
handleOrder ( dialogsResult . dialogs . map ( d = > d . peerID ) ) ;
/ * d i a l o g s R e s u l t . d i a l o g s . f o r E a c h ( ( d i a l o g ) = > {
2020-02-06 16:43:07 +01:00
newPinned [ dialog . peerID ] = true ;
} ) ;
2020-09-20 00:38:00 +02:00
this . dialogsStorage . getFolder ( folderID ) . forEach ( ( dialog ) = > {
2020-06-19 13:49:55 +02:00
const peerID = dialog . peerID ;
2020-02-06 16:43:07 +01:00
if ( dialog . pFlags . pinned && ! newPinned [ peerID ] ) {
this . newDialogsToHandle [ peerID ] = { reload : true } ;
2020-05-13 17:26:40 +02:00
this . scheduleHandleNewDialogs ( ) ;
2020-02-06 16:43:07 +01:00
}
2020-11-21 07:37:04 +01:00
} ) ; * /
2020-02-06 16:43:07 +01:00
} ) ;
2020-06-19 13:49:55 +02:00
2020-02-06 16:43:07 +01:00
break ;
}
2020-06-13 10:19:39 +02:00
//this.log('before order:', this.dialogsStorage[0].map(d => d.peerID));
2020-05-10 03:23:21 +02:00
2020-11-21 07:37:04 +01:00
handleOrder ( update . order . map ( peer = > appPeersManager . getPeerID ( ( peer as DialogPeer . dialogPeer ) . peer ) ) ) ;
2020-05-10 03:23:21 +02:00
2020-02-06 16:43:07 +01:00
break ;
2020-05-10 03:23:21 +02:00
}
2020-02-06 16:43:07 +01:00
case 'updateEditMessage' :
case 'updateEditChannelMessage' : {
2020-10-11 14:51:23 +02:00
const message = update . message as MyMessage ;
const peerID = this . getMessagePeer ( message ) ;
const channelID = message . peer_id . _ == 'peerChannel' ? - peerID : 0 ;
const mid = appMessagesIDsManager . getFullMessageID ( message . id , channelID ) ;
2020-02-06 16:43:07 +01:00
if ( this . messagesStorage [ mid ] === undefined ) {
break ;
}
// console.trace(dT(), 'edit message', message)
2020-11-08 02:34:28 +01:00
this . saveMessages ( [ message ] /* , {isEdited: true} */ ) ;
2020-02-06 16:43:07 +01:00
safeReplaceObject ( this . messagesStorage [ mid ] , message ) ;
2020-10-11 14:51:23 +02:00
const dialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
const isTopMessage = dialog && dialog . top_message == mid ;
// @ts-ignore
2020-02-13 08:51:11 +01:00
if ( message . clear_history ) { // that's will never happen
2020-02-06 16:43:07 +01:00
if ( isTopMessage ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_flush' , { peerID : peerID } ) ;
2020-02-06 16:43:07 +01:00
}
} else {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'message_edit' , {
2020-11-07 18:47:54 +01:00
peerID ,
mid ,
2020-02-13 08:51:11 +01:00
justMedia : false
2020-02-06 16:43:07 +01:00
} ) ;
2020-11-07 18:47:54 +01:00
const groupID = ( message as Message . message ) . grouped_id ;
2020-11-25 20:36:18 +01:00
/ * i f ( t h i s . p i n n e d M e s s a g e s S t o r a g e [ p e e r I D ] ) {
2020-11-07 18:47:54 +01:00
let pinnedMid : number ;
if ( groupID ) {
const mids = this . getMidsByAlbum ( groupID ) ;
2020-11-25 20:36:18 +01:00
pinnedMid = mids . find ( mid = > this . pinnedMessagesStorage [ peerID ] == mid ) ;
} else if ( this . pinnedMessagesStorage [ peerID ] == mid ) {
2020-11-07 18:47:54 +01:00
pinnedMid = mid ;
}
if ( pinnedMid ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'peer_pinned_message' , peerID ) ;
2020-11-07 18:47:54 +01:00
}
2020-11-25 20:36:18 +01:00
} * /
2020-11-07 18:47:54 +01:00
if ( isTopMessage || groupID ) {
2020-10-11 14:51:23 +02:00
const updatedDialogs : { [ peerID : number ] : Dialog } = { } ;
2020-02-06 16:43:07 +01:00
updatedDialogs [ peerID ] = dialog ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialogs_multiupdate' , updatedDialogs ) ;
2020-02-06 16:43:07 +01:00
}
}
break ;
}
case 'updateReadHistoryInbox' :
case 'updateReadHistoryOutbox' :
case 'updateReadChannelInbox' :
case 'updateReadChannelOutbox' : {
2020-10-11 14:51:23 +02:00
const channelID : number = ( update as Update . updateReadChannelInbox ) . channel_id ;
2020-10-03 02:35:26 +02:00
const maxID = appMessagesIDsManager . getFullMessageID ( update . max_id , channelID ) ;
2020-10-11 14:51:23 +02:00
const peerID = channelID ? - channelID : appPeersManager.getPeerID ( ( update as Update . updateReadHistoryInbox ) . peer ) ;
2020-10-03 02:35:26 +02:00
const isOut = update . _ == 'updateReadHistoryOutbox' || update . _ == 'updateReadChannelOutbox' ? true : undefined ;
const foundDialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
const history = getObjectKeysAndSort ( this . messagesStorageByPeerID [ peerID ] || { } , 'desc' ) ;
let newUnreadCount = 0 ;
let foundAffected = false ;
2020-02-06 16:43:07 +01:00
2020-06-13 10:19:39 +02:00
//this.log.warn(dT(), 'read', peerID, isOut ? 'out' : 'in', maxID)
2020-02-06 16:43:07 +01:00
if ( peerID > 0 && isOut ) {
appUsersManager . forceUserOnline ( peerID ) ;
}
2020-10-03 02:35:26 +02:00
for ( let i = 0 , length = history . length ; i < length ; i ++ ) {
const messageID = history [ i ] ;
2020-02-06 16:43:07 +01:00
if ( messageID > maxID ) {
continue ;
}
2020-05-23 07:31:18 +02:00
2020-10-03 02:35:26 +02:00
const message = this . messagesStorage [ messageID ] ;
2020-05-23 07:31:18 +02:00
if ( ! message ) {
continue ;
}
2020-02-06 16:43:07 +01:00
if ( message . pFlags . out != isOut ) {
continue ;
}
2020-10-03 02:35:26 +02:00
2020-02-06 16:43:07 +01:00
if ( ! message . pFlags . unread ) {
break ;
}
2020-10-03 02:35:26 +02:00
2020-06-13 10:19:39 +02:00
// this.log.warn('read', messageID, message.pFlags.unread, message)
2020-02-06 16:43:07 +01:00
if ( message && message . pFlags . unread ) {
2020-10-03 02:35:26 +02:00
delete message . pFlags . unread ;
2020-04-26 03:45:07 +02:00
if ( ! foundAffected ) {
foundAffected = true ;
2020-02-06 16:43:07 +01:00
}
2020-05-18 03:21:58 +02:00
2020-02-06 16:43:07 +01:00
if ( ! message . pFlags . out ) {
2020-10-03 02:35:26 +02:00
if ( foundDialog ) {
newUnreadCount = -- foundDialog . unread_count ;
2020-02-06 16:43:07 +01:00
}
//NotificationsManager.cancel('msg' + messageID); // warning
}
}
}
2020-10-03 02:35:26 +02:00
if ( foundDialog ) {
if ( ! isOut && newUnreadCount && foundDialog . top_message <= maxID ) {
newUnreadCount = foundDialog . unread_count = 0 ;
2020-02-06 16:43:07 +01:00
}
2020-02-07 03:10:08 +01:00
2020-10-03 02:35:26 +02:00
foundDialog [ isOut ? 'read_outbox_max_id' : 'read_inbox_max_id' ] = maxID ;
2020-02-06 16:43:07 +01:00
}
// need be commented for read out messages
//if(newUnreadCount != 0 || !isOut) { // fix 16.11.2019 (maybe not)
2020-06-13 10:19:39 +02:00
//////////this.log.warn(dT(), 'cnt', peerID, newUnreadCount, isOut, foundDialog, update, foundAffected);
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_unread' , { peerID , count : newUnreadCount } ) ;
2020-02-06 16:43:07 +01:00
//}
if ( foundAffected ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_read' ) ;
2020-02-06 16:43:07 +01:00
}
break ;
}
case 'updateChannelReadMessagesContents' : {
2020-10-08 22:49:08 +02:00
const channelID : number = update . channel_id ;
const newMessages : number [ ] = [ ] ;
2020-02-06 16:43:07 +01:00
update . messages . forEach ( ( msgID : number ) = > {
newMessages . push ( appMessagesIDsManager . getFullMessageID ( msgID , channelID ) ) ;
} ) ;
update . messages = newMessages ;
}
case 'updateReadMessagesContents' : {
2020-10-08 22:49:08 +02:00
const messages : number [ ] = update . messages ;
for ( const messageID of messages ) {
const message = this . messagesStorage [ messageID ] ;
if ( message ) {
2020-02-06 16:43:07 +01:00
delete message . pFlags . media_unread ;
}
}
2020-10-08 22:49:08 +02:00
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_media_read' , messages ) ;
2020-02-06 16:43:07 +01:00
break ;
}
case 'updateChannelAvailableMessages' : {
2020-10-11 14:51:23 +02:00
const channelID : number = update . channel_id ;
const messages : number [ ] = [ ] ;
const peerID : number = - channelID ;
const history = ( this . historiesStorage [ peerID ] || { } ) . history || [ ] ;
2020-02-06 16:43:07 +01:00
if ( history . length ) {
history . forEach ( ( msgID : number ) = > {
if ( ! update . available_min_id ||
appMessagesIDsManager . getMessageLocalID ( msgID ) <= update . available_min_id ) {
messages . push ( msgID ) ;
}
} ) ;
}
2020-10-11 14:51:23 +02:00
( update as any as Update . updateDeleteChannelMessages ) . messages = messages ;
2020-02-06 16:43:07 +01:00
}
case 'updateDeleteMessages' :
case 'updateDeleteChannelMessages' : {
2020-11-07 18:47:54 +01:00
const historiesUpdated : {
[ peerID : number ] : {
count : number ,
unread : number ,
msgs : { [ mid : number ] : true } ,
albums ? : { [ groupID : string ] : Set < number > } ,
}
} = { } ;
2020-10-11 14:51:23 +02:00
const channelID : number = ( update as Update . updateDeleteChannelMessages ) . channel_id ;
const messages = ( update as any as Update . updateDeleteChannelMessages ) . messages ;
2020-05-18 03:21:58 +02:00
2020-10-26 02:59:49 +01:00
for ( const _messageID of messages ) {
const mid = appMessagesIDsManager . getFullMessageID ( _messageID , channelID ) ;
const message : MyMessage = this . messagesStorage [ mid ] ;
2020-02-06 16:43:07 +01:00
if ( message ) {
2020-10-11 14:51:23 +02:00
const peerID = this . getMessagePeer ( message ) ;
const history = historiesUpdated [ peerID ] || ( historiesUpdated [ peerID ] = { count : 0 , unread : 0 , msgs : { } } ) ;
2020-02-06 16:43:07 +01:00
2020-09-28 02:23:00 +02:00
if ( ( message as Message . message ) . media ) {
// @ts-ignore
2020-10-11 14:51:23 +02:00
const c = message . media . webpage || message . media ;
2020-09-28 02:23:00 +02:00
const smth = c . photo || c . document ;
2020-09-29 04:03:26 +02:00
if ( smth ? . file_reference ) {
2020-10-26 02:59:49 +01:00
referenceDatabase . deleteContext ( smth . file_reference , { type : 'message' , messageID : mid } ) ;
2020-09-28 02:23:00 +02:00
}
}
2020-02-06 16:43:07 +01:00
if ( ! message . pFlags . out && message . pFlags . unread ) {
history . unread ++ ;
}
history . count ++ ;
2020-10-26 02:59:49 +01:00
history . msgs [ mid ] = true ;
message . deleted = true ;
delete this . messagesStorage [ mid ] ;
delete this . messagesStorageByPeerID [ peerID ] [ mid ] ;
if ( message . _ != 'messageService' && message . grouped_id ) {
const groupedStorage = this . groupedMessagesStorage [ message . grouped_id ] ;
if ( groupedStorage ) {
delete groupedStorage [ mid ] ;
2020-11-07 18:47:54 +01:00
if ( ! history . albums ) history . albums = { } ;
( history . albums [ message . grouped_id ] || ( history . albums [ message . grouped_id ] = new Set ( ) ) ) . add ( mid ) ;
2020-10-26 02:59:49 +01:00
if ( ! Object . keys ( groupedStorage ) . length ) {
2020-11-07 18:47:54 +01:00
delete history . albums ;
2020-10-26 02:59:49 +01:00
delete this . groupedMessagesStorage [ message . grouped_id ] ;
}
}
}
2020-11-25 20:36:18 +01:00
/ * i f ( t h i s . p i n n e d M e s s a g e s S t o r a g e [ p e e r I D ] = = m i d ) {
2020-10-26 02:59:49 +01:00
this . savePinnedMessage ( peerID , 0 ) ;
2020-11-25 20:36:18 +01:00
} * /
2020-02-06 16:43:07 +01:00
2020-10-11 14:51:23 +02:00
const peerMessagesToHandle = this . newMessagesToHandle [ peerID ] ;
2020-02-06 16:43:07 +01:00
if ( peerMessagesToHandle && peerMessagesToHandle . length ) {
2020-10-26 02:59:49 +01:00
const peerMessagesHandlePos = peerMessagesToHandle . indexOf ( mid ) ;
2020-02-06 16:43:07 +01:00
if ( peerMessagesHandlePos != - 1 ) {
peerMessagesToHandle . splice ( peerMessagesHandlePos ) ;
}
}
}
}
2020-09-18 17:03:26 +02:00
Object . keys ( historiesUpdated ) . forEach ( _peerID = > {
const peerID = + _peerID ;
2020-10-11 14:51:23 +02:00
const updatedData = historiesUpdated [ peerID ] ;
2020-11-07 18:47:54 +01:00
if ( updatedData . albums ) {
for ( const groupID in updatedData . albums ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'album_edit' , { peerID , groupID , deletedMids : [ . . . updatedData . albums [ groupID ] ] } ) ;
2020-11-07 18:47:54 +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 ) ;
2020-11-15 04:33:47 +01:00
rootScope . $broadcast ( 'message_edit' , { peerID , mid , justMedia : false } ) ;
2020-11-07 18:47:54 +01:00
} * /
}
}
2020-10-11 14:51:23 +02:00
const historyStorage = this . historiesStorage [ peerID ] ;
2020-02-06 16:43:07 +01:00
if ( historyStorage !== undefined ) {
2020-10-26 02:59:49 +01:00
const newHistory = historyStorage . history . filter ( mid = > ! updatedData . msgs [ mid ] ) ;
const newPending = historyStorage . pending . filter ( mid = > ! updatedData . msgs [ mid ] ) ;
2020-02-06 16:43:07 +01:00
historyStorage . history = newHistory ;
if ( updatedData . count &&
historyStorage . count !== null &&
historyStorage . count > 0 ) {
2020-05-18 03:21:58 +02:00
historyStorage . count -= updatedData . count ;
2020-02-06 16:43:07 +01:00
if ( historyStorage . count < 0 ) {
historyStorage . count = 0 ;
}
}
historyStorage . pending = newPending ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_delete' , { peerID , msgs : updatedData.msgs } ) ;
2020-02-06 16:43:07 +01:00
}
2020-10-11 14:51:23 +02:00
const foundDialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
2020-02-06 16:43:07 +01:00
if ( foundDialog ) {
if ( updatedData . unread ) {
foundDialog . unread_count -= updatedData . unread ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_unread' , {
2020-09-18 17:03:26 +02:00
peerID ,
2020-02-06 16:43:07 +01:00
count : foundDialog.unread_count
} ) ;
}
if ( updatedData . msgs [ foundDialog . top_message ] ) {
2020-09-18 17:03:26 +02:00
this . reloadConversation ( peerID ) ;
2020-02-06 16:43:07 +01:00
}
}
2020-05-18 03:21:58 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
break ;
}
case 'updateChannel' : {
2020-06-19 13:49:55 +02:00
const channelID : number = update . channel_id ;
const peerID = - channelID ;
const channel = appChatsManager . getChat ( channelID ) ;
2020-02-06 16:43:07 +01:00
2020-06-19 13:49:55 +02:00
const needDialog = channel . _ == 'channel' && ( ! channel . pFlags . left && ! channel . pFlags . kicked ) ;
const foundDialog = this . getDialogByPeerID ( peerID ) ;
const hasDialog = foundDialog . length > 0 ;
2020-02-06 16:43:07 +01:00
2020-10-28 17:11:57 +01:00
const canViewHistory = channel . _ == 'channel' && ( channel . username || ! channel . pFlags . left && ! channel . pFlags . kicked ) ;
2020-06-19 13:49:55 +02:00
const hasHistory = this . historiesStorage [ peerID ] !== undefined ;
2020-02-06 16:43:07 +01:00
if ( canViewHistory != hasHistory ) {
delete this . historiesStorage [ peerID ] ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_forbidden' , peerID ) ;
2020-02-06 16:43:07 +01:00
}
2020-05-06 03:03:31 +02:00
2020-02-06 16:43:07 +01:00
if ( hasDialog != needDialog ) {
if ( needDialog ) {
this . reloadConversation ( - channelID ) ;
} else {
if ( foundDialog [ 0 ] ) {
2020-06-19 13:49:55 +02:00
this . dialogsStorage . dropDialog ( peerID ) ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'dialog_drop' , { peerID : peerID , dialog : foundDialog [ 0 ] } ) ;
2020-02-06 16:43:07 +01:00
}
}
}
2020-05-06 03:03:31 +02:00
2020-02-06 16:43:07 +01:00
break ;
}
2020-10-11 14:51:23 +02:00
// @ts-ignore
2020-02-06 16:43:07 +01:00
case 'updateChannelReload' : {
2020-10-11 14:51:23 +02:00
// @ts-ignore
2020-06-19 13:49:55 +02:00
const channelID : number = update . channel_id ;
const peerID = - channelID ;
this . dialogsStorage . dropDialog ( peerID ) ;
2020-05-06 03:03:31 +02:00
2020-02-06 16:43:07 +01:00
delete this . historiesStorage [ peerID ] ;
this . reloadConversation ( - channelID ) . then ( ( ) = > {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_reload' , peerID ) ;
2020-02-06 16:43:07 +01:00
} ) ;
2020-05-06 03:03:31 +02:00
2020-02-06 16:43:07 +01:00
break ;
}
case 'updateChannelMessageViews' : {
2020-10-11 14:51:23 +02:00
const views = update . views ;
const mid = appMessagesIDsManager . getFullMessageID ( update . id , update . channel_id ) ;
const message = this . getMessage ( mid ) ;
2020-02-06 16:43:07 +01:00
if ( message && message . views && message . views < views ) {
message . views = views ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'message_views' , { mid , views } ) ;
2020-02-06 16:43:07 +01:00
}
break ;
}
case 'updateServiceNotification' : {
2020-06-13 10:19:39 +02:00
this . log ( 'updateServiceNotification' , update ) ;
2020-10-11 14:51:23 +02:00
const fromID = 777000 ;
const peerID = fromID ;
const messageID = this . tempID -- ;
const message : any = {
2020-02-06 16:43:07 +01:00
_ : 'message' ,
id : messageID ,
2020-10-02 22:33:32 +02:00
from_id : appPeersManager.getOutputPeer ( fromID ) ,
peer_id : appPeersManager.getOutputPeer ( peerID ) ,
2020-02-06 16:43:07 +01:00
pFlags : { unread : true } ,
2020-02-11 16:35:57 +01:00
date : ( update . inbox_date || tsNow ( true ) ) + serverTimeManager . serverTimeOffset ,
2020-02-06 16:43:07 +01:00
message : update.message ,
media : update.media ,
entities : update.entities
} ;
if ( ! appUsersManager . hasUser ( fromID ) ) {
appUsersManager . saveApiUsers ( [ {
_ : 'user' ,
id : fromID ,
pFlags : { verified : true } ,
access_hash : 0 ,
first_name : 'Telegram' ,
phone : '42777'
} ] ) ;
}
this . saveMessages ( [ message ] ) ;
if ( update . inbox_date ) {
this . pendingTopMsgs [ peerID ] = messageID ;
this . handleUpdate ( {
_ : 'updateNewMessage' ,
message : message
2020-10-11 14:51:23 +02:00
} as any ) ;
2020-02-06 16:43:07 +01:00
}
2020-05-18 03:21:58 +02:00
2020-02-06 16:43:07 +01:00
break ;
}
2020-06-05 18:01:06 +02:00
2020-11-25 20:36:18 +01:00
case 'updatePinnedMessages' :
case 'updatePinnedChannelMessages' : {
const channelID = update . _ == 'updatePinnedChannelMessages' ? update.channel_id : undefined ;
const peerID = channelID ? - channelID : appPeersManager.getPeerID ( ( update as Update . updatePinnedMessages ) . peer ) ;
2020-12-08 20:48:44 +01: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 ) {
delete this . searchesStorage [ peerID ] [ 'inputMessagesFilterPinned' ] ;
}
rootScope . broadcast ( 'peer_pinned_messages' , peerID ) ;
2020-11-25 20:36:18 +01:00
break ;
2020-12-08 20:48:44 +01:00
} * /
2020-11-25 20:36:18 +01:00
const messages = channelID ? update . messages . map ( messageID = > appMessagesIDsManager . getFullMessageID ( messageID , channelID ) ) : update . messages ;
const missingMessages = messages . filter ( mid = > ! this . messagesStorage [ mid ] ) ;
const getMissingPromise = missingMessages . length ? Promise . all ( missingMessages . map ( mid = > this . wrapSingleMessage ( mid ) ) ) : Promise . resolve ( ) ;
getMissingPromise . finally ( ( ) = > {
const werePinned = update . pFlags ? . pinned ;
if ( werePinned ) {
for ( const mid of messages ) {
2020-12-08 20:48:44 +01:00
//storage.history.push(mid);
2020-11-25 20:36:18 +01:00
const message = this . messagesStorage [ mid ] ;
message . pFlags . pinned = true ;
}
2020-12-08 20:48:44 +01: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
} * /
//storage.history.sort((a, b) => b - a);
2020-11-25 20:36:18 +01:00
} else {
for ( const mid of messages ) {
2020-12-08 20:48:44 +01:00
//storage.history.findAndSplice(_mid => _mid == mid);
2020-11-25 20:36:18 +01:00
const message = this . messagesStorage [ mid ] ;
delete message . pFlags . pinned ;
}
}
2020-12-08 20:48:44 +01:00
delete this . pinnedMessages [ peerID ] ;
appStateManager . getState ( ) . then ( state = > {
delete state . hiddenPinnedMessages [ peerID ] ;
rootScope . broadcast ( 'peer_pinned_messages' , peerID ) ;
} ) ;
2020-11-25 20:36:18 +01:00
} ) ;
2020-06-05 18:01:06 +02:00
break ;
}
2020-12-01 16:38:36 +01:00
case 'updateNotifySettings' : {
const { peer , notify_settings } = update ;
const peerID = appPeersManager . getPeerID ( ( peer as NotifyPeer . notifyPeer ) . peer ) ;
const dialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
if ( dialog ) {
dialog . notify_settings = notify_settings ;
rootScope . broadcast ( 'dialog_notify_settings' , peerID ) ;
}
/////this.log('updateNotifySettings', peerID, notify_settings);
break ;
}
}
}
public isPeerMuted ( peerID : number ) {
if ( peerID == rootScope . myID ) return false ;
const dialog = this . getDialogByPeerID ( peerID ) [ 0 ] ;
let muted = false ;
if ( dialog && dialog . notify_settings && dialog . notify_settings . mute_until ) {
muted = new Date ( dialog . notify_settings . mute_until * 1000 ) > new Date ( ) ;
}
return muted ;
}
public mutePeer ( peerID : number ) {
let inputPeer = appPeersManager . getInputPeerByID ( peerID ) ;
let inputNotifyPeer : InputNotifyPeer.inputNotifyPeer = {
_ : 'inputNotifyPeer' ,
peer : inputPeer
} ;
let settings : InputPeerNotifySettings = {
_ : 'inputPeerNotifySettings'
} ;
let dialog = appMessagesManager . getDialogByPeerID ( peerID ) [ 0 ] ;
let muted = true ;
if ( dialog && dialog . notify_settings ) {
muted = dialog . notify_settings . mute_until > ( Date . now ( ) / 1000 | 0 ) ;
}
if ( ! muted ) {
settings . mute_until = 2147483647 ;
2020-02-06 16:43:07 +01:00
}
2020-12-01 16:38:36 +01:00
apiManager . invokeApi ( 'account.updateNotifySettings' , {
peer : inputNotifyPeer ,
settings : settings
} ) . then ( bool = > {
if ( bool ) {
this . handleUpdate ( {
_ : 'updateNotifySettings' ,
peer : {
_ : 'notifyPeer' ,
peer : appPeersManager.getOutputPeer ( peerID )
} ,
notify_settings : { // ! WOW, IT WORKS !
. . . settings ,
_ : 'peerNotifySettings' ,
}
} ) ;
}
} ) ;
/ * r e t u r n a p i M a n a g e r . i n v o k e A p i ( ' a c c o u n t . g e t N o t i f y S e t t i n g s ' , {
peer : inputNotifyPeer
} ) . then ( ( settings : any ) = > {
settings . mute_until = 2000000000 ; // 2147483646
return apiManager . invokeApi ( 'account.updateNotifySettings' , {
peer : inputNotifyPeer ,
settings : Object.assign ( settings , {
_ : 'inputPeerNotifySettings'
} )
} ) . then ( res = > {
this . log ( 'mute result:' , res ) ;
} ) ;
} ) ; * /
}
public canWriteToPeer ( peerID : number ) {
const isChannel = appPeersManager . isChannel ( peerID ) ;
const hasRights = isChannel && appChatsManager . hasRights ( - peerID , 'send' ) ;
return ( ! isChannel || hasRights ) && ( peerID < 0 || appUsersManager . canSendToUser ( peerID ) ) ;
2020-02-06 16:43:07 +01:00
}
public finalizePendingMessage ( randomID : number , finalMessage : any ) {
var pendingData = this . pendingByRandomID [ randomID ] ;
2020-06-13 10:19:39 +02:00
// this.log('pdata', randomID, pendingData)
2020-02-06 16:43:07 +01:00
if ( pendingData ) {
var peerID = pendingData [ 0 ] ;
var tempID = pendingData [ 1 ] ;
var historyStorage = this . historiesStorage [ peerID ] ,
2020-04-26 03:45:07 +02:00
message ;
2020-02-06 16:43:07 +01:00
2020-06-13 10:19:39 +02:00
// this.log('pending', randomID, historyStorage.pending)
2020-02-06 16:43:07 +01:00
var pos = historyStorage . pending . indexOf ( tempID ) ;
if ( pos != - 1 ) {
historyStorage . pending . splice ( pos , 1 ) ;
}
if ( message = this . messagesStorage [ tempID ] ) {
delete message . pending ;
delete message . error ;
delete message . random_id ;
delete message . send ;
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_pending' ) ;
2020-02-06 16:43:07 +01:00
}
delete this . messagesStorage [ tempID ] ;
this . finalizePendingMessageCallbacks ( tempID , finalMessage . mid ) ;
return message ;
}
return false
}
public finalizePendingMessageCallbacks ( tempID : number , mid : number ) {
2020-10-13 15:51:11 +02:00
const callbacks = this . tempFinalizeCallbacks [ tempID ] ;
2020-09-20 00:38:00 +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 ] ;
this . log ( ` finalizePendingMessageCallbacks: will invoke ${ name } callback ` ) ;
callback ( mid ) . then ( deferred . resolve , deferred . reject ) ;
}
2020-02-14 17:15:41 +01:00
delete this . tempFinalizeCallbacks [ tempID ] ;
}
2020-12-01 16:38:36 +01:00
// set cached url to media
const message = appMessagesManager . getMessage ( mid ) ;
if ( message . media ) {
if ( message . media . photo ) {
const photo = appPhotosManager . getPhoto ( '' + tempID ) ;
if ( /* photo._ != 'photoEmpty' */ photo ) {
const newPhoto = message . media . photo ;
// костыль
defineNotNumerableProperties ( newPhoto , [ 'downloaded' , 'url' ] ) ;
newPhoto . downloaded = photo . downloaded ;
newPhoto . url = photo . url ;
}
} else if ( message . media . document ) {
const doc = appDocsManager . getDoc ( '' + tempID ) ;
if ( /* doc._ != 'documentEmpty' && */ doc ? . type && doc . type != 'sticker' ) {
const newDoc = message . media . document ;
newDoc . downloaded = doc . downloaded ;
newDoc . url = doc . url ;
}
} else if ( message . media . poll ) {
delete appPollsManager . polls [ tempID ] ;
delete appPollsManager . results [ tempID ] ;
}
}
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'message_sent' , { tempID , mid } ) ;
2020-02-06 16:43:07 +01:00
}
public incrementMaxSeenID ( maxID : number ) {
if ( ! maxID || ! ( ! this . maxSeenID || maxID > this . maxSeenID ) ) {
return false ;
}
2020-09-20 00:38:00 +02:00
this . maxSeenID = maxID ;
AppStorage . set ( { max_seen_msg : maxID } ) ;
2020-02-06 16:43:07 +01:00
2020-02-11 16:35:57 +01:00
apiManager . invokeApi ( 'messages.receivedMessages' , {
2020-02-06 16:43:07 +01:00
max_id : maxID
} ) ;
}
2020-05-10 03:23:21 +02:00
public getHistory ( peerID : number , maxID = 0 , limit : number , backLimit? : number ) {
2020-02-06 16:43:07 +01:00
if ( this . migratedFromTo [ peerID ] ) {
peerID = this . migratedFromTo [ peerID ] ;
}
2020-05-26 17:04:06 +02:00
const historyStorage = this . historiesStorage [ peerID ] ? ? ( this . historiesStorage [ peerID ] = { count : null , history : [ ] , pending : [ ] } ) ;
const unreadOffset = 0 ;
const unreadSkip = false ;
let offset = 0 ;
let offsetNotFound = false ;
let isMigrated = false ;
let reqPeerID = peerID ;
2020-02-06 16:43:07 +01:00
if ( this . migratedToFrom [ peerID ] ) {
isMigrated = true ;
if ( maxID && maxID < appMessagesIDsManager . fullMsgIDModulus ) {
reqPeerID = this . migratedToFrom [ peerID ] ;
}
}
if ( maxID > 0 ) {
offsetNotFound = true ;
2020-05-26 17:04:06 +02:00
for ( ; offset < historyStorage . history . length ; offset ++ ) {
2020-02-06 16:43:07 +01:00
if ( maxID > historyStorage . history [ offset ] ) {
offsetNotFound = false ;
break ;
}
}
}
if ( ! offsetNotFound && (
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
2020-05-26 17:04:06 +02:00
let history = historyStorage . history . slice ( offset , offset + limit ) ;
2020-02-06 16:43:07 +01:00
if ( ! maxID && historyStorage . pending . length ) {
history = historyStorage . pending . slice ( ) . concat ( history ) ;
}
2020-04-14 17:46:31 +02:00
2020-05-13 17:26:40 +02:00
return this . wrapHistoryResult ( {
2020-02-06 16:43:07 +01:00
count : historyStorage.count ,
history : history ,
unreadOffset : unreadOffset ,
unreadSkip : unreadSkip
} ) ;
}
if ( offsetNotFound ) {
offset = 0 ;
}
if ( ( backLimit || unreadSkip || maxID ) && historyStorage . history . indexOf ( maxID ) == - 1 ) {
if ( backLimit ) {
offset = - backLimit ;
limit += backLimit ;
}
2020-10-30 01:23:10 +01:00
return this . requestHistory ( reqPeerID , maxID , limit , offset ) . then ( ( historyResult ) = > {
2020-02-06 16:43:07 +01:00
historyStorage . count = historyResult . count || historyResult . messages . length ;
if ( isMigrated ) {
historyStorage . count ++ ;
}
2020-05-26 17:04:06 +02:00
let history : number [ ] = [ ] ;
2020-02-06 16:43:07 +01:00
historyResult . messages . forEach ( ( message : any ) = > {
history . push ( message . mid ) ;
2020-05-26 17:04:06 +02:00
} ) ;
2020-02-06 16:43:07 +01:00
if ( ! maxID && historyStorage . pending . length ) {
history = historyStorage . pending . slice ( ) . concat ( history ) ;
}
2020-05-13 17:26:40 +02:00
return this . wrapHistoryResult ( {
2020-02-06 16:43:07 +01:00
count : historyStorage.count ,
history : history ,
unreadOffset : unreadOffset ,
unreadSkip : unreadSkip
} ) ;
} ) ;
}
return this . fillHistoryStorage ( peerID , maxID , limit , historyStorage ) . then ( ( ) = > {
offset = 0 ;
if ( maxID > 0 ) {
for ( offset = 0 ; offset < historyStorage . history . length ; offset ++ ) {
if ( maxID > historyStorage . history [ offset ] ) {
break ;
}
}
}
2020-09-01 18:11:29 +02:00
let history = historyStorage . history . slice ( backLimit ? Math . max ( offset - backLimit , 0 ) : offset , offset + limit ) ;
2020-02-06 16:43:07 +01:00
if ( ! maxID && historyStorage . pending . length ) {
history = historyStorage . pending . slice ( ) . concat ( history ) ;
}
2020-05-13 17:26:40 +02:00
return this . wrapHistoryResult ( {
2020-02-06 16:43:07 +01:00
count : historyStorage.count ,
history : history ,
unreadOffset : unreadOffset ,
unreadSkip : unreadSkip
} ) ;
} ) ;
}
public fillHistoryStorage ( peerID : number , maxID : number , fullLimit : number , historyStorage : HistoryStorage ) : Promise < boolean > {
2020-06-13 10:19:39 +02:00
// this.log('fill history storage', peerID, maxID, fullLimit, angular.copy(historyStorage))
2020-05-26 17:04:06 +02:00
const offset = ( this . migratedFromTo [ peerID ] && ! maxID ) ? 1 : 0 ;
2020-02-06 16:43:07 +01:00
return this . requestHistory ( peerID , maxID , fullLimit , offset ) . then ( ( historyResult : any ) = > {
historyStorage . count = historyResult . count || historyResult . messages . length ;
if ( ! maxID && historyResult . messages . length ) {
maxID = historyResult . messages [ 0 ] . mid + 1 ;
}
2020-05-26 17:04:06 +02:00
let offset = 0 ;
2020-02-06 16:43:07 +01:00
if ( maxID > 0 ) {
2020-05-26 17:04:06 +02:00
for ( ; offset < historyStorage . history . length ; offset ++ ) {
2020-02-06 16:43:07 +01:00
if ( maxID > historyStorage . history [ offset ] ) {
break ;
}
}
}
2020-05-26 17:04:06 +02:00
const wasTotalCount = historyStorage . history . length ;
2020-02-06 16:43:07 +01:00
2020-05-26 17:04:06 +02:00
historyStorage . history . splice ( offset , historyStorage . history . length - offset ) ;
2020-02-06 16:43:07 +01:00
historyResult . messages . forEach ( ( message : any ) = > {
if ( this . mergeReplyKeyboard ( historyStorage , message ) ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_reply_markup' , { peerID } ) ;
2020-02-06 16:43:07 +01:00
}
historyStorage . history . push ( message . mid ) ;
} ) ;
2020-05-26 17:04:06 +02:00
const totalCount = historyStorage . history . length ;
2020-02-06 16:43:07 +01:00
fullLimit -= ( totalCount - wasTotalCount ) ;
2020-05-26 17:04:06 +02:00
const migratedNextPeer = this . migratedFromTo [ peerID ] ;
const migratedPrevPeer = this . migratedToFrom [ peerID ]
const isMigrated = migratedNextPeer !== undefined || migratedPrevPeer !== undefined ;
2020-02-06 16:43:07 +01:00
if ( isMigrated ) {
historyStorage . count = Math . max ( historyStorage . count , totalCount ) + 1 ;
}
if ( fullLimit > 0 ) {
maxID = historyStorage . history [ totalCount - 1 ] ;
if ( isMigrated ) {
if ( ! historyResult . messages . length ) {
if ( migratedPrevPeer ) {
maxID = 0 ;
peerID = migratedPrevPeer ;
} else {
historyStorage . count = totalCount ;
return true ;
}
}
return this . fillHistoryStorage ( peerID , maxID , fullLimit , historyStorage ) ;
} else if ( totalCount < historyStorage . count ) {
return this . fillHistoryStorage ( peerID , maxID , fullLimit , historyStorage ) ;
}
}
return true ;
} ) ;
}
2020-05-13 17:26:40 +02:00
public wrapHistoryResult ( result : HistoryResult ) {
2020-05-26 17:04:06 +02:00
if ( result . unreadOffset ) {
for ( let i = result . history . length - 1 ; i >= 0 ; i -- ) {
const message = this . messagesStorage [ result . history [ i ] ] ;
2020-02-06 16:43:07 +01:00
if ( message && ! message . pFlags . out && message . pFlags . unread ) {
result . unreadOffset = i + 1 ;
break ;
}
}
}
2020-04-14 17:46:31 +02:00
return result ;
2020-02-06 16:43:07 +01:00
}
2020-06-13 10:19:39 +02:00
public requestHistory ( peerID : number , maxID : number , limit = 0 , offset = 0 , offsetDate = 0 ) : Promise < any > {
2020-05-26 17:04:06 +02:00
const isChannel = appPeersManager . isChannel ( peerID ) ;
2020-02-06 16:43:07 +01:00
2020-02-08 12:58:22 +01:00
//console.trace('requestHistory', peerID, maxID, limit, offset);
2020-02-06 16:43:07 +01:00
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'history_request' ) ;
2020-04-14 17:46:31 +02:00
2020-02-11 16:35:57 +01:00
return apiManager . invokeApi ( 'messages.getHistory' , {
2020-05-18 03:21:58 +02:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
2020-02-06 16:43:07 +01:00
offset_id : maxID ? appMessagesIDsManager . getMessageLocalID ( maxID ) : 0 ,
2020-06-13 10:19:39 +02:00
offset_date : offsetDate ,
add_offset : offset ,
limit : limit ,
2020-02-06 16:43:07 +01:00
max_id : 0 ,
min_id : 0 ,
hash : 0
2020-02-08 12:58:22 +01:00
} , {
2020-09-18 17:52:21 +02:00
//timeout: APITIMEOUT,
2020-02-06 16:43:07 +01:00
noErrorBox : true
2020-09-28 02:23:00 +02:00
} ) . then ( ( historyResult ) = > {
2020-10-30 01:23:10 +01:00
this . log ( 'requestHistory result:' , peerID , historyResult , maxID , limit , offset ) ;
2020-02-13 16:42:39 +01:00
2020-09-28 02:23:00 +02:00
if ( historyResult . _ == 'messages.messagesNotModified' ) {
return historyResult ;
}
2020-02-06 16:43:07 +01:00
appUsersManager . saveApiUsers ( historyResult . users ) ;
appChatsManager . saveApiChats ( historyResult . chats ) ;
this . saveMessages ( historyResult . messages ) ;
if ( isChannel ) {
2020-09-28 02:23:00 +02:00
apiUpdatesManager . addChannelState ( - peerID , ( historyResult as MessagesMessages . messagesChannelMessages ) . pts ) ;
2020-02-06 16:43:07 +01:00
}
2020-05-26 17:04:06 +02:00
let length = historyResult . messages . length ;
2020-02-08 12:58:22 +01:00
if ( length && historyResult . messages [ length - 1 ] . deleted ) {
2020-02-06 16:43:07 +01:00
historyResult . messages . splice ( length - 1 , 1 ) ;
length -- ;
2020-09-28 02:23:00 +02:00
( historyResult as MessagesMessages . messagesMessagesSlice ) . 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)
2020-05-26 17:04:06 +02:00
const historyStorage = this . historiesStorage [ peerID ] ;
2020-04-28 19:30:54 +02:00
// historyResult.messages: desc sorted
2020-09-28 02:23:00 +02:00
if ( length && ( historyResult . messages [ length - 1 ] as Message . message ) . grouped_id
&& ( historyStorage . history . length + historyResult . messages . length ) < ( historyResult as MessagesMessages . messagesMessagesSlice ) . count ) {
return this . requestHistory ( peerID , ( historyResult . messages [ length - 1 ] as Message . message ) . mid , 10 , 0 ) . then ( ( _historyResult ) = > {
2020-04-28 19:30:54 +02:00
return historyResult ;
} ) ;
}
2020-02-08 12:58:22 +01:00
// don't need the intro now
/ * i f ( p e e r I D < 0 | | ! a p p U s e r s M a n a g e r . i s B o t ( p e e r I D ) | | ( l e n g t h = = l i m i t & & l i m i t < h i s t o r y R e s u l t . c o u n t ) ) {
2020-02-06 16:43:07 +01:00
return historyResult ;
2020-02-08 12:58:22 +01:00
} * /
return historyResult ;
2020-02-06 16:43:07 +01:00
2020-02-08 12:58:22 +01:00
/ * r e t u r n a p p P r o f i l e M a n a g e r . g e t P r o f i l e ( p e e r I D ) . t h e n ( ( u s e r F u l l : a n y ) = > {
2020-02-06 16:43:07 +01:00
var description = userFull . bot_info && userFull . bot_info . description ;
if ( description ) {
var messageID = this . tempID -- ;
var message = {
_ : 'messageService' ,
id : messageID ,
from_id : peerID ,
2020-10-02 22:33:32 +02:00
peer_id : appPeersManager.getOutputPeer ( peerID ) ,
2020-02-06 16:43:07 +01:00
pFlags : { } ,
2020-02-11 16:35:57 +01:00
date : tsNow ( true ) + serverTimeManager . serverTimeOffset ,
2020-02-06 16:43:07 +01:00
action : {
_ : 'messageActionBotIntro' ,
description : description
}
}
this . saveMessages ( [ message ] ) ;
historyResult . messages . push ( message ) ;
if ( historyResult . count ) {
historyResult . count ++ ;
}
}
return historyResult ;
2020-02-08 12:58:22 +01:00
} ) ; * /
2020-02-06 16:43:07 +01:00
} , ( error ) = > {
switch ( error . type ) {
case 'CHANNEL_PRIVATE' :
2020-05-26 17:04:06 +02:00
let channel = appChatsManager . getChat ( - peerID ) ;
2020-02-06 16:43:07 +01:00
channel = { _ : 'channelForbidden' , access_hash : channel.access_hash , title : channel.title } ;
apiUpdatesManager . processUpdateMessage ( {
_ : 'updates' ,
updates : [ {
_ : 'updateChannel' ,
channel_id : - peerID
} ] ,
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 ;
}
2020-09-28 02:23:00 +02:00
return this . fetchSingleMessagesPromise = new Promise ( ( resolve ) = > {
setTimeout ( ( ) = > {
const mids = this . needSingleMessages . slice ( ) ;
this . needSingleMessages . length = 0 ;
const splitted = appMessagesIDsManager . splitMessageIDsByChannels ( mids ) ;
let promises : Promise < void > [ ] = [ ] ;
Object . keys ( splitted . msgIDs ) . forEach ( ( channelID : number | string ) = > {
channelID = + channelID ;
const msgIDs : InputMessage [ ] = splitted . msgIDs [ channelID ] . map ( ( msgID : number ) = > {
return {
_ : 'inputMessageID' ,
id : msgID
} ;
} ) ;
let promise : Promise < MethodDeclMap [ ' channels.getMessages ' ] [ ' res ' ] | MethodDeclMap [ ' messages.getMessages ' ] [ ' res ' ] > ;
if ( channelID > 0 ) {
promise = apiManager . invokeApi ( 'channels.getMessages' , {
channel : appChatsManager.getChannelInput ( channelID ) ,
id : msgIDs
} ) ;
} else {
promise = apiManager . invokeApi ( 'messages.getMessages' , {
id : msgIDs
} ) ;
}
promises . push ( promise . then ( getMessagesResult = > {
if ( getMessagesResult . _ != 'messages.messagesNotModified' ) {
appUsersManager . saveApiUsers ( getMessagesResult . users ) ;
appChatsManager . saveApiChats ( getMessagesResult . chats ) ;
this . saveMessages ( getMessagesResult . messages ) ;
}
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_downloaded' , splitted . mids [ + channelID ] ) ;
2020-09-28 02:23:00 +02:00
} ) ) ;
2020-02-06 16:43:07 +01:00
} ) ;
2020-09-28 02:23:00 +02:00
Promise . all ( promises ) . finally ( ( ) = > {
this . fetchSingleMessagesPromise = null ;
if ( this . needSingleMessages . length ) this . fetchSingleMessages ( ) ;
resolve ( ) ;
} ) ;
} , 0 ) ;
2020-02-06 16:43:07 +01:00
} ) ;
}
2020-09-28 02:23:00 +02:00
public wrapSingleMessage ( msgID : number , overwrite = false ) : Promise < void > {
2020-06-16 22:48:08 +02:00
if ( this . messagesStorage [ msgID ] && ! overwrite ) {
2020-11-15 04:33:47 +01:00
rootScope . broadcast ( 'messages_downloaded' , [ msgID ] ) ;
2020-09-28 02:23:00 +02:00
return Promise . resolve ( ) ;
2020-06-05 18:01:06 +02:00
} else if ( this . needSingleMessages . indexOf ( msgID ) == - 1 ) {
2020-02-06 16:43:07 +01:00
this . needSingleMessages . push ( msgID ) ;
2020-09-28 02:23:00 +02:00
return this . fetchSingleMessages ( ) ;
2020-10-15 00:46:29 +02:00
} else if ( this . fetchSingleMessagesPromise ) {
return this . fetchSingleMessagesPromise ;
2020-06-05 18:01:06 +02:00
}
2020-02-06 16:43:07 +01:00
}
2020-06-06 07:26:18 +02:00
2020-10-28 17:11:57 +01:00
public setTyping ( peerID : number , _action : any ) : Promise < boolean > {
2020-12-01 16:38:36 +01:00
if ( ! rootScope . myID || ! peerID || ! this . canWriteToPeer ( peerID ) ) return Promise . resolve ( false ) ;
2020-06-06 07:26:18 +02:00
2020-10-28 17:11:57 +01:00
const action : SendMessageAction = typeof ( _action ) == 'string' ? { _ : _action } : _action ;
2020-06-06 07:26:18 +02:00
return apiManager . invokeApi ( 'messages.setTyping' , {
2020-10-28 17:11:57 +01:00
peer : appPeersManager.getInputPeerByID ( peerID ) ,
action
2020-06-06 07:26:18 +02:00
} ) as Promise < boolean > ;
}
2020-02-06 16:43:07 +01:00
}
2020-06-19 13:49:55 +02:00
const appMessagesManager = new AppMessagesManager ( ) ;
2020-11-11 18:01:38 +01:00
MOUNT_CLASS_TO && ( MOUNT_CLASS_TO . appMessagesManager = appMessagesManager ) ;
2020-06-19 13:49:55 +02:00
export default appMessagesManager ;