1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-03 09:57:46 +01:00
Telegram/Telegraph/TGSendMessageSignals.mm
2016-02-25 01:03:51 +01:00

537 lines
26 KiB
Plaintext

#import "TGSendMessageSignals.h"
#import "TGTelegraph.h"
#import "TGTelegramNetworking.h"
#import "TGDatabase.h"
#import "ActionStage.h"
#import "TGStickersSignals.h"
#import "TL/TLMetaScheme.h"
#import "TLRPCmessages_sendMessage_manual.h"
#import "TLRPCmessages_sendMedia_manual.h"
#import "TLUpdates+TG.h"
#import "TGMessage+Telegraph.h"
#import "TLMessage$modernMessage.h"
#import "TLMessage$modernMessageService.h"
#import "TLUpdates$updateShortSentMessage.h"
#import "TGPeerIdAdapter.h"
@implementation TGSendMessageSignals
+ (SSignal *)sendTextMessageWithPeerId:(int64_t)peerId text:(NSString *)text replyToMid:(int32_t)replyToMid
{
SSignal *accessHashSignal = TGPeerIdIsChannel(peerId) ? [[[TGDatabaseInstance() existingChannel:peerId] take:1] map:^NSNumber *(TGConversation *channel)
{
return @(channel.accessHash);
}] : [SSignal single:nil];
SSignal *addToDatabaseSignal = [self _addMessageToDatabaseWithPeerId:peerId replyToMid:replyToMid text:text attachment:nil];
SSignal *(^sendMessage)(TGMessage *, int64_t) = ^SSignal *(TGMessage *message, int64_t accessHash)
{
TLRPCmessages_sendMessage_manual *sendMessage = [[TLRPCmessages_sendMessage_manual alloc] init];
sendMessage.peer = [TGTelegraphInstance createInputPeerForConversation:peerId accessHash:accessHash];
sendMessage.message = message.text;
sendMessage.random_id = message.randomId;
sendMessage.reply_to_msg_id = replyToMid;
sendMessage.flags |= replyToMid != 0 ? (1 << 0) : 0;
return [[SSignal single:message] then:[[[[[TGTelegramNetworking instance] requestSignal:sendMessage] mapToSignal:^SSignal *(TLUpdates *updates)
{
TLMessage *updateMessage = updates.messages.firstObject;
if ([updates isKindOfClass:[TLUpdates$updateShortSentMessage class]])
{
TLUpdates$updateShortSentMessage *sentMessage = (TLUpdates$updateShortSentMessage *)updates;
std::vector<TGDatabaseMessageFlagValue> flags;
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDeliveryState, .value = TGMessageDeliveryStateDelivered});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagMid, .value = sentMessage.n_id});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDate, .value = sentMessage.date});
TGMessage *updatedMessage = [message copy];
updatedMessage.mid = sentMessage.n_id;
updatedMessage.deliveryState = TGMessageDeliveryStateDelivered;
updatedMessage.date = sentMessage.date;
if ([sentMessage.media isKindOfClass:[TLMessageMedia$messageMediaWebPage class]])
{
NSMutableArray *attachments = [[NSMutableArray alloc] initWithArray:updatedMessage.mediaAttachments];
for (id attachment in attachments)
{
if ([attachment isKindOfClass:[TGWebPageMediaAttachment class]])
{
[attachments removeObject:attachment];
break;
}
}
[attachments addObjectsFromArray:[TGMessage parseTelegraphMedia:sentMessage.media]];
updatedMessage.mediaAttachments = attachments;
}
[TGDatabaseInstance() updateMessage:message.mid peerId:0 flags:flags media:updatedMessage.mediaAttachments dispatch:true];
[TGDatabaseInstance() removeTempIds:@[@(message.randomId)]];
[[TGTelegramNetworking instance] updatePts:sentMessage.pts ptsCount:sentMessage.pts_count seq:0];
id resource = [[SGraphObjectNode alloc] initWithObject:[[NSArray alloc] initWithObjects:[[NSNumber alloc] initWithInt:message.mid], updatedMessage, nil]];
[ActionStageInstance() dispatchResource:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messagesChanged", (long long)peerId] resource:resource];
return [SSignal single:updatedMessage];
}
else if (updateMessage != nil)
{
int32_t date = 0;
if ([updateMessage isKindOfClass:[TLMessage$modernMessage class]])
date = ((TLMessage$message *)updateMessage).date;
else if ([updateMessage isKindOfClass:[TLMessage$modernMessageService class]])
date = ((TLMessage$modernMessageService *)updateMessage).date;
std::vector<TGDatabaseMessageFlagValue> flags;
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDeliveryState, .value = TGMessageDeliveryStateDelivered});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagMid, .value = updateMessage.n_id});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDate, .value = date});
TGMessage *updatedMessage = [[TGMessage alloc] initWithTelegraphMessageDesc:updateMessage];
[TGDatabaseInstance() updateMessage:message.mid peerId:0 flags:flags media:updatedMessage.mediaAttachments dispatch:true];
[TGDatabaseInstance() removeTempIds:@[@(message.randomId)]];
id resource = [[SGraphObjectNode alloc] initWithObject:[[NSArray alloc] initWithObjects:[[NSNumber alloc] initWithInt:message.mid], updatedMessage, nil]];
[ActionStageInstance() dispatchResource:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messagesChanged", (long long)peerId] resource:resource];
[[TGTelegramNetworking instance] addUpdates:updates];
return [SSignal single:updatedMessage];
}
else
return [SSignal fail:nil];
}] take:1] catch:^SSignal *(__unused id error)
{
TGMessage *updatedMessage = [message copy];
updatedMessage.deliveryState = TGMessageDeliveryStateFailed;
return [SSignal single:updatedMessage];
}]];
};
return [addToDatabaseSignal mapToSignal:^SSignal *(TGMessage *message)
{
return [accessHashSignal mapToSignal:^SSignal *(NSNumber *accessHash)
{
return sendMessage(message, accessHash.int64Value);
}];
}];
}
+ (SSignal *)_addMessageToDatabaseWithPeerId:(int64_t)peerId replyToMid:(int32_t)replyToMid text:(NSString *)text attachment:(TGMediaAttachment *)attachment
{
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
{
TGMessage *message = [[TGMessage alloc] init];
message.outgoing = true;
message.unread = true;
message.fromUid = TGTelegraphInstance.clientUserId;
message.toUid = peerId;
message.deliveryState = TGMessageDeliveryStatePending;
int64_t randomId = 0;
arc4random_buf(&randomId, 8);
message.randomId = randomId;
if (text != nil)
message.text = text;
NSMutableArray *attachments = [[NSMutableArray alloc] init];
TGMessage *replyMessage = nil;
if (replyToMid != 0)
replyMessage = [TGDatabaseInstance() loadMessageWithMid:replyToMid peerId:peerId];
if (replyMessage != nil)
{
TGReplyMessageMediaAttachment *replyMedia = [[TGReplyMessageMediaAttachment alloc] init];
replyMedia.replyMessageId = replyMessage.mid;
replyMedia.replyMessage = replyMessage;
[attachments addObject:replyMedia];
}
if (attachment != nil)
[attachments addObject:attachment];
message.mediaAttachments = attachments;
message.mid = [[[TGDatabaseInstance() generateLocalMids:1] firstObject] intValue];
message.date = (int)[[TGTelegramNetworking instance] approximateRemoteTime];
[TGDatabaseInstance() addMessagesToConversation:@[message] conversationId:peerId updateConversation:nil dispatch:true countUnread:false];
[ActionStageInstance() dispatchResource:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messages", (long long)peerId] resource:[[SGraphObjectNode alloc] initWithObject:@[message]]];
[subscriber putNext:message];
[subscriber putCompletion];
return nil;
}];
}
+ (SSignal *)_sendMediaWithMessage:(TGMessage *)message replyToMid:(int32_t)replyToMid mediaProducer:(TLInputMedia *(^)(void))mediaProducer
{
int64_t peerId = message.toUid;
SSignal *accessHashSignal = TGPeerIdIsChannel(peerId) ? [[[TGDatabaseInstance() existingChannel:peerId] take:1] map:^NSNumber *(TGConversation *channel)
{
return @(channel.accessHash);
}] : [SSignal single:nil];
return [accessHashSignal mapToSignal:^SSignal *(NSNumber *accessHash)
{
TLRPCmessages_sendMedia_manual *sendMedia = [[TLRPCmessages_sendMedia_manual alloc] init];
sendMedia.peer = [TGTelegraphInstance createInputPeerForConversation:message.toUid accessHash:accessHash.int64Value];
sendMedia.media = mediaProducer();
sendMedia.random_id = message.randomId;
sendMedia.reply_to_msg_id = replyToMid;
sendMedia.flags |= replyToMid != 0 ? (1 << 0) : 0;
if (TGPeerIdIsChannel(message.toUid)) {
}
return [[SSignal single:message] then:[[[[[TGTelegramNetworking instance] requestSignal:sendMedia] mapToSignal:^SSignal *(TLUpdates *updates)
{
TLMessage *updateMessage = updates.messages.firstObject;
if (updateMessage != nil)
{
int32_t date = 0;
if ([updateMessage isKindOfClass:[TLMessage$modernMessage class]])
date = ((TLMessage$message *)updateMessage).date;
else if ([updateMessage isKindOfClass:[TLMessage$modernMessageService class]])
date = ((TLMessage$modernMessageService *)updateMessage).date;
std::vector<TGDatabaseMessageFlagValue> flags;
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDeliveryState, .value = TGMessageDeliveryStateDelivered});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagMid, .value = updateMessage.n_id});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDate, .value = date});
TGMessage *updatedMessage = [[TGMessage alloc] initWithTelegraphMessageDesc:updateMessage];
[TGDatabaseInstance() updateMessage:message.mid peerId:0 flags:flags media:updatedMessage.mediaAttachments dispatch:true];
[TGDatabaseInstance() removeTempIds:@[@(message.randomId)]];
id resource = [[SGraphObjectNode alloc] initWithObject:[[NSArray alloc] initWithObjects:[[NSNumber alloc] initWithInt:message.mid], updatedMessage, nil]];
[ActionStageInstance() dispatchResource:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messagesChanged", (long long)message.toUid] resource:resource];
[[TGTelegramNetworking instance] addUpdates:updates];
return [SSignal single:updatedMessage];
}
else
return [SSignal fail:nil];
}] take:1] catch:^SSignal *(__unused id error)
{
TGMessage *updatedMessage = [message copy];
updatedMessage.deliveryState = TGMessageDeliveryStateFailed;
return [SSignal single:updatedMessage];
}]];
}];
}
+ (SSignal *)_sendMediaWithPeerId:(int64_t)peerId replyToMid:(int32_t)replyToMid attachment:(TGMediaAttachment *)attachment mediaProducer:(TLInputMedia *(^)(void))mediaProducer
{
return [[self _addMessageToDatabaseWithPeerId:peerId replyToMid:replyToMid text:nil attachment:attachment] mapToSignal:^SSignal *(TGMessage *message)
{
return [self _sendMediaWithMessage:message replyToMid:replyToMid mediaProducer:mediaProducer];
}];
}
+ (SSignal *)sendLocationWithPeerId:(int64_t)peerId replyToMid:(int32_t)replyToMid locationAttachment:(TGLocationMediaAttachment *)locationAttachment
{
return [self _sendMediaWithPeerId:peerId replyToMid:replyToMid attachment:locationAttachment mediaProducer:^TLInputMedia *
{
TLInputGeoPoint$inputGeoPoint *geoPoint = [[TLInputGeoPoint$inputGeoPoint alloc] init];
geoPoint.lat = locationAttachment.latitude;
geoPoint.n_long = locationAttachment.longitude;
TLInputMedia *media = nil;
if (locationAttachment.venue != nil)
{
TGVenueAttachment *venue = locationAttachment.venue;
TLInputMedia$inputMediaVenue *inputVenue = [[TLInputMedia$inputMediaVenue alloc] init];
inputVenue.geo_point = geoPoint;
inputVenue.title = venue.title;
inputVenue.address = venue.address;
inputVenue.provider = venue.provider;
inputVenue.venue_id = venue.venueId;
media = inputVenue;
}
else
{
TLInputMedia$inputMediaGeoPoint *inputGeoPoint = [[TLInputMedia$inputMediaGeoPoint alloc] init];
inputGeoPoint.geo_point = geoPoint;
media = inputGeoPoint;
}
return media;
}];
}
+ (SSignal *)sendRemoteDocumentWithPeerId:(int64_t)peerId replyToMid:(int32_t)replyToMid documentAttachment:(TGDocumentMediaAttachment *)documentAttachment
{
bool isSticker = false;
for (id attribute in documentAttachment.attributes)
{
if ([attribute isKindOfClass:[TGDocumentAttributeSticker class]])
{
isSticker = true;
break;
}
}
if (isSticker)
{
[[SQueue concurrentDefaultQueue] dispatch:^{
[TGStickersSignals addUseCountForDocumentId:documentAttachment.documentId];
}];
}
return [self _sendMediaWithPeerId:peerId replyToMid:replyToMid attachment:documentAttachment mediaProducer:^TLInputMedia *
{
TLInputMedia$inputMediaDocument *remoteDocument = [[TLInputMedia$inputMediaDocument alloc] init];
TLInputDocument$inputDocument *inputDocument = [[TLInputDocument$inputDocument alloc] init];
inputDocument.n_id = documentAttachment.documentId;
inputDocument.access_hash = documentAttachment.accessHash;
remoteDocument.n_id = inputDocument;
return remoteDocument;
}];
}
+ (SSignal *)forwardMessageWithMid:(int32_t)mid peerId:(int64_t)peerId
{
SSignal *addToDatabaseSignal = [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
{
TGMessage *forwardedMessage = [TGDatabaseInstance() loadMessageWithMid:mid peerId:peerId];
int32_t forwardMid = forwardedMessage.mid;
bool keepForwarded = true;
NSMutableArray *attachments = [[NSMutableArray alloc] init];
for (TGMediaAttachment *attachment in forwardedMessage.mediaAttachments)
{
if ([attachment isKindOfClass:[TGForwardedMessageMediaAttachment class]])
{
TGForwardedMessageMediaAttachment *forwardedMessageAttachment = (TGForwardedMessageMediaAttachment *)attachment;
forwardedMessage.fromUid = forwardedMessageAttachment.forwardPeerId;
forwardedMessage.date = forwardedMessageAttachment.forwardDate;
if (forwardedMessageAttachment.forwardMid != 0)
forwardMid = forwardedMessageAttachment.forwardMid;
}
else if (![attachment isKindOfClass:[TGReplyMessageMediaAttachment class]])
{
[attachments addObject:attachment];
}
}
TGForwardedMessageMediaAttachment *forwardAttachment = nil;
if (keepForwarded)
{
forwardAttachment = [[TGForwardedMessageMediaAttachment alloc] init];
forwardAttachment.forwardPeerId = (int32_t)forwardedMessage.fromUid;
forwardAttachment.forwardDate = (int32_t)forwardedMessage.date;
forwardAttachment.forwardMid = forwardMid;
}
if (forwardAttachment != nil)
[attachments addObject:forwardAttachment];
TGMessage *message = [forwardedMessage copy];
if (message.contentProperties != nil)
{
NSMutableDictionary *contentProperties = [[NSMutableDictionary alloc] initWithDictionary:message.contentProperties];
[contentProperties removeObjectForKey:@"contentsRead"];
message.contentProperties = contentProperties;
}
message.outgoing = true;
message.unread = true;
message.fromUid = TGTelegraphInstance.clientUserId;
message.toUid = peerId;
message.deliveryState = TGMessageDeliveryStatePending;
int64_t randomId = 0;
arc4random_buf(&randomId, 8);
message.randomId = randomId;
message.mediaAttachments = attachments;
message.mid = [[[TGDatabaseInstance() generateLocalMids:1] firstObject] intValue];
message.date = (int)[[TGTelegramNetworking instance] approximateRemoteTime];
[TGDatabaseInstance() addMessagesToConversation:@[message] conversationId:peerId updateConversation:nil dispatch:true countUnread:false];
[ActionStageInstance() dispatchResource:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messages", (long long)peerId] resource:[[SGraphObjectNode alloc] initWithObject:@[message]]];
[subscriber putNext:message];
[subscriber putCompletion];
return nil;
}];
SSignal *(^sendMessage)(TGMessage *) = ^SSignal *(TGMessage *message)
{
TLRPCmessages_forwardMessages$messages_forwardMessages *forwardMessages = [[TLRPCmessages_forwardMessages$messages_forwardMessages alloc] init];
forwardMessages.to_peer = [TGTelegraphInstance createInputPeerForConversation:peerId accessHash:0];
forwardMessages.from_peer = [[TLInputPeer$inputPeerEmpty alloc] init];
forwardMessages.n_id = @[@(mid)];
forwardMessages.random_id = @[@(message.randomId)];
return [[SSignal single:message] then:[[[[[TGTelegramNetworking instance] requestSignal:forwardMessages] mapToSignal:^SSignal *(TLUpdates *updates)
{
TLMessage *updateMessage = updates.messages.firstObject;
if (updateMessage != nil)
{
int32_t date = 0;
if ([updateMessage isKindOfClass:[TLMessage$modernMessage class]])
date = ((TLMessage$message *)updateMessage).date;
else if ([updateMessage isKindOfClass:[TLMessage$modernMessageService class]])
date = ((TLMessage$modernMessageService *)updateMessage).date;
std::vector<TGDatabaseMessageFlagValue> flags;
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDeliveryState, .value = TGMessageDeliveryStateDelivered});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagMid, .value = updateMessage.n_id});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDate, .value = date});
TGMessage *updatedMessage = [[TGMessage alloc] initWithTelegraphMessageDesc:updateMessage];
[TGDatabaseInstance() updateMessage:message.mid peerId:0 flags:flags media:updatedMessage.mediaAttachments dispatch:true];
[TGDatabaseInstance() removeTempIds:@[@(message.randomId)]];
id resource = [[SGraphObjectNode alloc] initWithObject:[[NSArray alloc] initWithObjects:[[NSNumber alloc] initWithInt:message.mid], updatedMessage, nil]];
[ActionStageInstance() dispatchResource:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messagesChanged", (long long)peerId] resource:resource];
[[TGTelegramNetworking instance] addUpdates:updates];
return [SSignal single:updatedMessage];
}
else
return [SSignal fail:nil];
}] take:1] catch:^SSignal *(__unused id error)
{
TGMessage *updatedMessage = [message copy];
updatedMessage.deliveryState = TGMessageDeliveryStateFailed;
return [SSignal single:updatedMessage];
}]];
};
return [addToDatabaseSignal mapToSignal:^SSignal *(TGMessage *message)
{
return sendMessage(message);
}];
}
+ (SSignal *)forwardMessageWithMessageIds:(NSArray *)messageIds peerId:(int64_t)peerId accessHash:(int64_t)accessHash fromPeerId:(int64_t)fromPeerId fromPeerAccessHash:(int64_t)fromPeerAccessHash
{
SSignal *(^sendMessage)() = ^SSignal *()
{
TLRPCmessages_forwardMessages$messages_forwardMessages *forwardMessages = [[TLRPCmessages_forwardMessages$messages_forwardMessages alloc] init];
forwardMessages.to_peer = [TGTelegraphInstance createInputPeerForConversation:peerId accessHash:accessHash];
forwardMessages.from_peer = [TGTelegraphInstance createInputPeerForConversation:fromPeerId accessHash:fromPeerAccessHash];
if (TGPeerIdIsChannel(peerId)) {
TGConversation *conversation = [TGDatabaseInstance() loadConversationWithId:peerId];
if (conversation.isChannelGroup) {
} else {
forwardMessages.flags |= 16;
}
}
NSMutableArray *randomIds = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < messageIds.count; i++) {
int64_t randomId = 0;
arc4random_buf(&randomId, 8);
[randomIds addObject:@(randomId)];
}
forwardMessages.n_id = messageIds;
forwardMessages.random_id = randomIds;
return [[[[[TGTelegramNetworking instance] requestSignal:forwardMessages] mapToSignal:^SSignal *(TLUpdates *updates)
{
[[TGTelegramNetworking instance] addUpdates:updates];
/*TLMessage *updateMessage = updates.messages.firstObject;
if (updateMessage != nil)
{
int32_t date = 0;
if ([updateMessage isKindOfClass:[TLMessage$modernMessage class]])
date = ((TLMessage$message *)updateMessage).date;
else if ([updateMessage isKindOfClass:[TLMessage$modernMessageService class]])
date = ((TLMessage$modernMessageService *)updateMessage).date;
std::vector<TGDatabaseMessageFlagValue> flags;
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDeliveryState, .value = TGMessageDeliveryStateDelivered});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagMid, .value = updateMessage.n_id});
flags.push_back((TGDatabaseMessageFlagValue){.flag = TGDatabaseMessageFlagDate, .value = date});
TGMessage *updatedMessage = [[TGMessage alloc] initWithTelegraphMessageDesc:updateMessage];
[TGDatabaseInstance() updateMessage:message.mid peerId:0 flags:flags media:updatedMessage.mediaAttachments dispatch:true];
[TGDatabaseInstance() removeTempIds:@[@(message.randomId)]];
id resource = [[SGraphObjectNode alloc] initWithObject:[[NSArray alloc] initWithObjects:[[NSNumber alloc] initWithInt:message.mid], updatedMessage, nil]];
[ActionStageInstance() dispatchResource:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messagesChanged", (long long)peerId] resource:resource];
[[TGTelegramNetworking instance] addUpdates:updates];
return [SSignal single:updatedMessage];
}
else
return [SSignal fail:nil];*/
return [SSignal complete];
}] take:1] catch:^SSignal *(__unused id error)
{
return [SSignal fail:nil];
}];
};
return sendMessage();
}
+ (SSignal *)forwardMessagesWithMessageIds:(NSArray *)messageIds toPeerIds:(NSArray *)peerIds fromPeerId:(int64_t)fromPeerId fromPeerAccessHash:(int64_t)fromPeerAccessHash {
NSMutableArray *signals = [[NSMutableArray alloc] init];
for (NSNumber *nPeerId in peerIds) {
int64_t accessHash = 0;
if (TGPeerIdIsChannel([nPeerId longLongValue])) {
accessHash = ((TGConversation *)[TGDatabaseInstance() loadChannels:@[nPeerId]][nPeerId]).accessHash;
}
SSignal *signal = [self forwardMessageWithMessageIds:messageIds peerId:[nPeerId longLongValue] accessHash:accessHash fromPeerId:fromPeerId fromPeerAccessHash:fromPeerAccessHash];
[signals addObject:signal];
}
return [SSignal combineSignals:signals];
}
+ (SSignal *)broadcastMessageWithText:(NSString *)text toPeerIds:(NSArray *)peerIds {
NSMutableArray *signals = [[NSMutableArray alloc] init];
for (NSNumber *nPeerId in peerIds) {
SSignal *signal = [[self sendTextMessageWithPeerId:[nPeerId longLongValue] text:text replyToMid:0] catch:^SSignal *(__unused id error) {
return [SSignal complete];
}];
[signals addObject:signal];
}
return [SSignal combineSignals:signals];
}
@end