2018-11-13 12:29:15 -08:00
|
|
|
//
|
|
|
|
|
// MBIMSendMessageOperation.m
|
|
|
|
|
// kordophoned
|
|
|
|
|
//
|
|
|
|
|
// Created by James Magahern on 11/13/18.
|
|
|
|
|
// Copyright © 2018 James Magahern. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#import "MBIMSendMessageOperation.h"
|
|
|
|
|
|
2019-12-16 17:29:53 -08:00
|
|
|
#import "IMCore_ClassDump.h"
|
2024-01-02 18:14:31 -08:00
|
|
|
#import "IMMessageItem+Encoded.h"
|
2026-04-01 15:29:37 -07:00
|
|
|
#import "MBIMErrorResponse.h"
|
2018-11-13 12:29:15 -08:00
|
|
|
|
|
|
|
|
@implementation MBIMSendMessageOperation
|
|
|
|
|
|
|
|
|
|
+ (void)load { [super load]; }
|
|
|
|
|
|
|
|
|
|
+ (NSString *)endpointName
|
|
|
|
|
{
|
|
|
|
|
return @"sendMessage";
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 17:22:28 -07:00
|
|
|
- (nullable IMChat *)_existingSingleChatForHandle:(IMHandle *)handle registry:(IMChatRegistry *)registry
|
|
|
|
|
{
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatWithHandle:allowAlternativeService:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatWithHandle:allowAlternativeService:");
|
|
|
|
|
return [registry existingChatWithHandle:handle allowAlternativeService:NO];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatWithHandle:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatWithHandle:");
|
|
|
|
|
return [registry existingChatWithHandle:handle];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatForIMHandle:allowRetargeting:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatForIMHandle:allowRetargeting:");
|
|
|
|
|
return [registry existingChatForIMHandle:handle allowRetargeting:NO];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatForIMHandle:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatForIMHandle:");
|
|
|
|
|
return [registry existingChatForIMHandle:handle];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MBIMLogError(@"IMChatRegistry does not support any known single-handle existing chat lookup selector.");
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable IMChat *)_createSingleChatForHandle:(IMHandle *)handle registry:(IMChatRegistry *)registry
|
|
|
|
|
{
|
|
|
|
|
if ([registry respondsToSelector:@selector(chatWithHandle:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry chatWithHandle:");
|
|
|
|
|
return [registry chatWithHandle:handle];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(chatForIMHandle:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry chatForIMHandle:");
|
|
|
|
|
return [registry chatForIMHandle:handle];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MBIMLogError(@"IMChatRegistry does not support any known single-handle chat creation selector.");
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable IMChat *)_existingGroupChatForHandles:(NSArray<IMHandle *> *)handles registry:(IMChatRegistry *)registry
|
|
|
|
|
{
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatWithHandles:allowAlternativeService:groupID:displayName:joinedChatsOnly:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatWithHandles:allowAlternativeService:groupID:displayName:joinedChatsOnly:");
|
|
|
|
|
return [registry existingChatWithHandles:handles
|
|
|
|
|
allowAlternativeService:NO
|
|
|
|
|
groupID:nil
|
|
|
|
|
displayName:nil
|
|
|
|
|
joinedChatsOnly:YES];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatWithHandles:allowAlternativeService:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatWithHandles:allowAlternativeService:");
|
|
|
|
|
return [registry existingChatWithHandles:handles allowAlternativeService:NO];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatWithHandles:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatWithHandles:");
|
|
|
|
|
return [registry existingChatWithHandles:handles];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatForIMHandles:allowRetargeting:groupID:displayName:joinedChatsOnly:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatForIMHandles:allowRetargeting:groupID:displayName:joinedChatsOnly:");
|
|
|
|
|
return [registry existingChatForIMHandles:handles
|
|
|
|
|
allowRetargeting:NO
|
|
|
|
|
groupID:nil
|
|
|
|
|
displayName:nil
|
|
|
|
|
joinedChatsOnly:YES];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatForIMHandles:allowRetargeting:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatForIMHandles:allowRetargeting:");
|
|
|
|
|
return [registry existingChatForIMHandles:handles allowRetargeting:NO];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(existingChatForIMHandles:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry existingChatForIMHandles:");
|
|
|
|
|
return [registry existingChatForIMHandles:handles];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MBIMLogError(@"IMChatRegistry does not support any known multi-handle existing chat lookup selector.");
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable IMChat *)_createGroupChatForHandles:(NSArray<IMHandle *> *)handles registry:(IMChatRegistry *)registry
|
|
|
|
|
{
|
|
|
|
|
if ([registry respondsToSelector:@selector(chatWithHandles:displayName:joinedChatsOnly:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry chatWithHandles:displayName:joinedChatsOnly:");
|
|
|
|
|
return [registry chatWithHandles:handles displayName:nil joinedChatsOnly:YES];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(chatWithHandles:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry chatWithHandles:");
|
|
|
|
|
return [registry chatWithHandles:handles];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(chatForIMHandles:displayName:joinedChatsOnly:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry chatForIMHandles:displayName:joinedChatsOnly:");
|
|
|
|
|
return [registry chatForIMHandles:handles displayName:nil joinedChatsOnly:YES];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([registry respondsToSelector:@selector(chatForIMHandles:)]) {
|
|
|
|
|
MBIMLogInfo(@"Using IMChatRegistry chatForIMHandles:");
|
|
|
|
|
return [registry chatForIMHandles:handles];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MBIMLogError(@"IMChatRegistry does not support any known multi-handle chat creation selector.");
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 15:29:37 -07:00
|
|
|
- (nullable IMChat *)_chatForHandleIDs:(NSArray<NSString *> *)handleIDs registry:(IMChatRegistry *)registry
|
2018-11-13 12:29:15 -08:00
|
|
|
{
|
2026-04-01 17:16:58 -07:00
|
|
|
MBIMLogInfo(@"Resolving send target for handles: %@", handleIDs);
|
|
|
|
|
|
2026-04-01 15:29:37 -07:00
|
|
|
IMAccount *iMessageAccount = [[IMAccountController sharedInstance] bestAccountForService:[IMServiceImpl iMessageService]];
|
|
|
|
|
if (!iMessageAccount) {
|
|
|
|
|
MBIMLogError(@"Unable to find an iMessage account for message send.");
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSMutableArray<IMHandle *> *handles = [NSMutableArray arrayWithCapacity:[handleIDs count]];
|
|
|
|
|
for (NSString *handleID in handleIDs) {
|
|
|
|
|
IMHandle *handle = [iMessageAccount imHandleWithID:handleID];
|
|
|
|
|
if (!handle) {
|
|
|
|
|
MBIMLogError(@"Couldn't resolve IMHandle for id %@", handleID);
|
|
|
|
|
return nil;
|
2019-01-16 14:17:31 -08:00
|
|
|
}
|
2026-04-01 15:29:37 -07:00
|
|
|
|
|
|
|
|
[handles addObject:handle];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([handles count] == 1) {
|
|
|
|
|
IMHandle *handle = [handles firstObject];
|
2026-04-01 17:22:28 -07:00
|
|
|
IMChat *chat = [self _existingSingleChatForHandle:handle registry:registry];
|
2018-11-21 15:51:51 -07:00
|
|
|
if (!chat) {
|
2026-04-01 17:22:28 -07:00
|
|
|
chat = [self _createSingleChatForHandle:handle registry:registry];
|
2026-04-01 15:29:37 -07:00
|
|
|
}
|
|
|
|
|
|
2026-04-01 17:16:58 -07:00
|
|
|
if (chat) {
|
|
|
|
|
MBIMLogInfo(@"Resolved send target %@ to chat %@", [handle ID], [chat guid] ?: @"<unknown>");
|
|
|
|
|
} else {
|
|
|
|
|
MBIMLogError(@"Unable to locate or create chat for handle %@", [handle ID]);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 15:29:37 -07:00
|
|
|
return chat;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 17:22:28 -07:00
|
|
|
IMChat *chat = [self _existingGroupChatForHandles:handles registry:registry];
|
2026-04-01 15:29:37 -07:00
|
|
|
if (!chat) {
|
2026-04-01 17:22:28 -07:00
|
|
|
chat = [self _createGroupChatForHandles:handles registry:registry];
|
2026-04-01 15:29:37 -07:00
|
|
|
}
|
|
|
|
|
|
2026-04-01 17:16:58 -07:00
|
|
|
if (chat) {
|
|
|
|
|
MBIMLogInfo(@"Resolved handles %@ to chat %@", handleIDs, [chat guid] ?: @"<unknown>");
|
|
|
|
|
} else {
|
|
|
|
|
MBIMLogError(@"Unable to locate or create chat for handles %@", handleIDs);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 15:29:37 -07:00
|
|
|
return chat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable NSDictionary *)_sendMessage:(NSString *)messageBody toChat:(IMChat *)chat attachmentGUIDs:(NSArray<NSString *> *)guids includeConversationGUID:(BOOL)includeConversationGUID
|
|
|
|
|
{
|
|
|
|
|
if (!chat) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 17:16:58 -07:00
|
|
|
NSString *chatGUID = [chat guid];
|
|
|
|
|
if (!chatGUID) {
|
|
|
|
|
chatGUID = [[[IMChatRegistry sharedInstance] allGUIDsForChat:chat] firstObject];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MBIMLogInfo(@"Preparing sendMessage for chat %@ (bodyLength=%lu attachmentCount=%lu)", chatGUID ?: @"<unknown>", (unsigned long)[messageBody length], (unsigned long)[guids count]);
|
|
|
|
|
|
2026-04-01 15:29:37 -07:00
|
|
|
IMAccount *sendingAccount = [chat account];
|
|
|
|
|
if (!sendingAccount) {
|
|
|
|
|
sendingAccount = [[IMAccountController sharedInstance] bestAccountForService:[IMServiceImpl iMessageService]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IMHandle *senderHandle = [sendingAccount loginIMHandle];
|
|
|
|
|
if (!senderHandle) {
|
|
|
|
|
MBIMLogError(@"Unable to determine sender handle for message send.");
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSAttributedString *replyAttrString = [[NSAttributedString alloc] initWithString:messageBody];
|
|
|
|
|
NSAttributedString *attrStringWithFileTransfers = IMCreateSuperFormatStringWithAppendedFileTransfers(replyAttrString, guids);
|
|
|
|
|
|
|
|
|
|
IMMessage *reply = [IMMessage fromMeIMHandle:senderHandle
|
|
|
|
|
withText:attrStringWithFileTransfers
|
|
|
|
|
fileTransferGUIDs:guids
|
|
|
|
|
flags:(kIMMessageFinished | kIMMessageIsFromMe)];
|
|
|
|
|
|
|
|
|
|
for (NSString *guid in [reply fileTransferGUIDs]) {
|
|
|
|
|
[[IMFileTransferCenter sharedInstance] assignTransfer:guid toMessage:reply account:sendingAccount];
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 17:16:58 -07:00
|
|
|
NSDictionary *replyRepresentation = [reply mbim_dictionaryRepresentation];
|
|
|
|
|
if (![replyRepresentation isKindOfClass:[NSDictionary class]]) {
|
|
|
|
|
MBIMLogError(@"Unable to encode sent message for chat %@", chatGUID ?: @"<unknown>");
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSMutableDictionary *result = [replyRepresentation mutableCopy];
|
2026-04-01 15:29:37 -07:00
|
|
|
if (includeConversationGUID) {
|
2026-04-01 17:16:58 -07:00
|
|
|
NSString *conversationGUID = chatGUID;
|
2026-04-01 15:29:37 -07:00
|
|
|
if (!conversationGUID) {
|
|
|
|
|
conversationGUID = [[[IMChatRegistry sharedInstance] allGUIDsForChat:chat] firstObject];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (conversationGUID) {
|
|
|
|
|
result[@"conversationGUID"] = conversationGUID;
|
2018-11-21 15:51:51 -07:00
|
|
|
}
|
2026-04-01 15:29:37 -07:00
|
|
|
}
|
|
|
|
|
|
2026-04-01 17:16:58 -07:00
|
|
|
MBIMLogInfo(@"Dispatching IMCore send for chat %@", chatGUID ?: @"<unknown>");
|
2026-04-01 15:29:37 -07:00
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
|
[chat sendMessage:reply];
|
2018-11-21 15:51:51 -07:00
|
|
|
});
|
2026-04-01 15:29:37 -07:00
|
|
|
|
2018-11-21 15:51:51 -07:00
|
|
|
return result;
|
2018-11-13 12:29:15 -08:00
|
|
|
}
|
|
|
|
|
|
2024-10-02 17:18:44 -07:00
|
|
|
#if 0
|
|
|
|
|
- (NSDictionary *)adjustMessageSummaryInfoForSending:(NSDictionary *)messageSummaryInfo
|
|
|
|
|
{
|
|
|
|
|
NSMutableDictionary *adjustedInfo = [messageSummaryInfo mutableCopy];
|
|
|
|
|
if (!adjustedInfo) {
|
|
|
|
|
adjustedInfo = [NSMutableDictionary dictionary];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([fullText length] > 50) {
|
|
|
|
|
summary = [[summary substringToIndex:[summary rangeOfComposedCharacterSequenceAtIndex:kMaxSummaryLength].location] stringByAppendingString:@"…"];
|
|
|
|
|
adjustedInfo[IMMessageSummaryInfoSummary] = summary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
adjustedInfo[IMMessageSummaryInfoTapbackRepresentationKey] = @"Loved";
|
|
|
|
|
|
|
|
|
|
return adjustedInfo;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-11-13 12:29:15 -08:00
|
|
|
- (void)main
|
|
|
|
|
{
|
2026-04-01 15:29:37 -07:00
|
|
|
__block NSObject<HTTPResponse> *response = [[HTTPErrorResponse alloc] initWithErrorCode:500];
|
2018-11-13 12:29:15 -08:00
|
|
|
|
2018-11-16 01:30:38 -08:00
|
|
|
NSError *error = nil;
|
|
|
|
|
NSDictionary *args = [NSJSONSerialization JSONObjectWithData:self.requestBodyData options:0 error:&error];
|
|
|
|
|
if (error || args.count == 0) {
|
2026-04-01 17:16:58 -07:00
|
|
|
MBIMLogError(@"Unable to parse sendMessage request body: %@", error);
|
2018-11-16 01:30:38 -08:00
|
|
|
self.serverCompletionBlock(response);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-11-13 12:29:15 -08:00
|
|
|
|
|
|
|
|
NSString *guid = [args objectForKey:@"guid"];
|
|
|
|
|
NSString *messageBody = [args objectForKey:@"body"];
|
2026-04-01 15:29:37 -07:00
|
|
|
NSArray *rawHandleIDs = [args objectForKey:@"handleIDs"];
|
|
|
|
|
BOOL hasGUID = [guid isKindOfClass:[NSString class]] && [guid length] > 0;
|
|
|
|
|
BOOL hasHandleIDs = [rawHandleIDs isKindOfClass:[NSArray class]] && [rawHandleIDs count] > 0;
|
|
|
|
|
|
|
|
|
|
if (![messageBody isKindOfClass:[NSString class]] || (!hasGUID && !hasHandleIDs) || (hasGUID && hasHandleIDs)) {
|
|
|
|
|
response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"sendMessage requires body and exactly one of guid or handleIDs."];
|
2018-11-16 01:30:38 -08:00
|
|
|
self.serverCompletionBlock(response);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-11-13 12:29:15 -08:00
|
|
|
|
2026-04-01 15:29:37 -07:00
|
|
|
NSMutableArray<NSString *> *handleIDs = [NSMutableArray array];
|
|
|
|
|
if (hasHandleIDs) {
|
|
|
|
|
for (id handleID in rawHandleIDs) {
|
|
|
|
|
if ([handleID isKindOfClass:[NSString class]] && [handleID length] > 0) {
|
|
|
|
|
[handleIDs addObject:handleID];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleIDs = [[[NSOrderedSet orderedSetWithArray:handleIDs] array] mutableCopy];
|
|
|
|
|
if ([handleIDs count] == 0) {
|
|
|
|
|
response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"No valid handle IDs provided."];
|
|
|
|
|
self.serverCompletionBlock(response);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-01-16 14:17:31 -08:00
|
|
|
}
|
2026-04-01 15:29:37 -07:00
|
|
|
|
|
|
|
|
NSArray *rawTransferGUIDs = [args objectForKey:@"fileTransferGUIDs"];
|
|
|
|
|
NSMutableArray<NSString *> *transferGUIDs = [NSMutableArray array];
|
|
|
|
|
if ([rawTransferGUIDs isKindOfClass:[NSArray class]]) {
|
|
|
|
|
for (id transferGUID in rawTransferGUIDs) {
|
|
|
|
|
if ([transferGUID isKindOfClass:[NSString class]] && [transferGUID length] > 0) {
|
|
|
|
|
[transferGUIDs addObject:transferGUID];
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-13 12:29:15 -08:00
|
|
|
}
|
2026-04-01 15:29:37 -07:00
|
|
|
|
2026-04-01 17:16:58 -07:00
|
|
|
MBIMLogInfo(@"sendMessage request received. guid=%@ handleIDs=%@ bodyLength=%lu attachmentGUIDs=%@", hasGUID ? guid : @"<none>", handleIDs, (unsigned long)[messageBody length], transferGUIDs);
|
|
|
|
|
|
|
|
|
|
@try {
|
|
|
|
|
dispatch_sync([[self class] sharedIMAccessQueue], ^{
|
|
|
|
|
IMChatRegistry *registry = [IMChatRegistry sharedInstance];
|
|
|
|
|
IMChat *chat = nil;
|
|
|
|
|
BOOL includeConversationGUID = NO;
|
|
|
|
|
|
|
|
|
|
if (hasGUID) {
|
|
|
|
|
MBIMLogInfo(@"sendMessage targeting existing conversation %@", guid);
|
|
|
|
|
chat = [registry existingChatWithGUID:guid];
|
|
|
|
|
if (!chat) {
|
|
|
|
|
MBIMLogError(@"Chat does not exist for guid %@", guid);
|
|
|
|
|
response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"Chat does not exist for the provided guid."];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
MBIMLogInfo(@"sendMessage targeting handles %@", handleIDs);
|
|
|
|
|
chat = [self _chatForHandleIDs:handleIDs registry:registry];
|
|
|
|
|
includeConversationGUID = YES;
|
|
|
|
|
if (!chat) {
|
|
|
|
|
response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"Unable to create or locate a chat for the provided handles."];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-01 15:29:37 -07:00
|
|
|
|
2026-04-01 17:16:58 -07:00
|
|
|
NSString *resolvedChatGUID = [chat guid];
|
|
|
|
|
if (!resolvedChatGUID) {
|
|
|
|
|
resolvedChatGUID = [[[IMChatRegistry sharedInstance] allGUIDsForChat:chat] firstObject];
|
2026-04-01 15:29:37 -07:00
|
|
|
}
|
2026-04-01 17:16:58 -07:00
|
|
|
MBIMLogInfo(@"sendMessage resolved target chat %@", resolvedChatGUID ?: @"<unknown>");
|
|
|
|
|
|
|
|
|
|
NSDictionary *result = [self _sendMessage:messageBody
|
|
|
|
|
toChat:chat
|
|
|
|
|
attachmentGUIDs:transferGUIDs
|
|
|
|
|
includeConversationGUID:includeConversationGUID];
|
|
|
|
|
if (!result) {
|
|
|
|
|
MBIMLogError(@"sendMessage failed before a response payload could be encoded for chat %@", resolvedChatGUID ?: @"<unknown>");
|
|
|
|
|
response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"Unable to construct sent message response."];
|
2026-04-01 15:29:37 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 17:16:58 -07:00
|
|
|
NSObject<HTTPResponse> *jsonResponse = [MBIMJSONDataResponse responseWithJSONObject:result];
|
|
|
|
|
if (jsonResponse) {
|
|
|
|
|
response = jsonResponse;
|
|
|
|
|
} else {
|
|
|
|
|
MBIMLogError(@"Unable to encode sendMessage JSON response for chat %@", resolvedChatGUID ?: @"<unknown>");
|
|
|
|
|
response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"Unable to encode sendMessage response."];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} @catch (NSException *exception) {
|
|
|
|
|
MBIMLogError(@"Unhandled exception during sendMessage. name=%@ reason=%@ userInfo=%@", exception.name, exception.reason, exception.userInfo);
|
|
|
|
|
response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"Unhandled exception while sending message. Check server logs."];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (response == nil) {
|
|
|
|
|
MBIMLogError(@"sendMessage completed without producing a response. guid=%@ handleIDs=%@", hasGUID ? guid : @"<none>", handleIDs);
|
|
|
|
|
response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"sendMessage did not produce a response. Check server logs."];
|
|
|
|
|
}
|
2018-11-13 12:29:15 -08:00
|
|
|
|
|
|
|
|
self.serverCompletionBlock(response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|