Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question - Sending attachments through IMCore #109

Open
sabogalc opened this issue Mar 17, 2021 · 4 comments
Open

Question - Sending attachments through IMCore #109

sabogalc opened this issue Mar 17, 2021 · 4 comments
Labels
question Further information is requested

Comments

@sabogalc
Copy link

I was reading here and saw that the a limitation of sending messages through IMCore was that there was no way to send attachments. I asked Eric from MyMessage about this, and he pointed me to this page. Would it be possible to have SMServer fully integrate with IMCore? Or would ChatKit still be needed for certain functions?

@itsjunetime itsjunetime added the question Further information is requested label Mar 18, 2021
@itsjunetime
Copy link
Owner

Yeah, we should be able to fully integrate with IMCore; I'd have to do quite a bit of testing to ensure that we didn't lose any functionality in the process. However, I'm not quite sure why that would be necessary. It would be somewhat nice to depend on less frameworks, and it would make the code more portable if/when I decide to port SMServer to Mac, but I don't know if those small benefits are enough to merit the time/energy that would be needed to port everything over. What are your thoughts?

@sabogalc
Copy link
Author

Unfortunately, I don't know enough about the differences in the frameworks to give a substantial answer. However, I do know that SMServer works, and it works very well. I also know what it's like to work on something for months and then have that silent "Ohh😬" moment when you realize that a redesign or reworking is possible/would be better. The benefits of depending solely on IMCore instead of ChatKit as I see them are

  1. The code works "closer to the metal" and will increase performance

  2. SMServer will be extremely future proof.
    For example, Remote Messages was not updated past iOS 9 due to changes in ChatKit (screenshot and link below), and while it is ~ possible ~ for Apple to rewrite the core functionality of IMCore, I personally think that it's extremely unlikely (for the time being anyway. Apple is a company that always surprises me, and sometimes that isn't a compliment).
    Remote messages 10
    That screenshot is edited/cropped from here in order to fit both the original question and the developer's response in one screenshot.

  3. More features
    Things like viewing handwritten messages, digital touch messages, and message extensions would (maybe) be possible if the tweak were to only run on IMCore. I'm not sure if remotely sending them would be possible, however. This would also open the door for things like in-line replies and mentions, and any other iMessage features from the future.

  4. SMServer can be ported to macOS.
    Granted, the SIP and AMFI will most likely need to be disabled since Apple only allows access to AppleScript by default, but assuming that IMCore is the only framework used, this should do away with bugs in AirMessage and BlueBubbles caused by macOS updates, such as not being able to create new conversations on Big Sur. In macOS Big Sur, Apple removed that ability from the AppleScript API. Can they do that? Sure! But can they remove it from IMCore?

  5. SMServer will serve as a great framework for other apps (though it already is)
    I'm pretty sure the situation with Beeper right now is that they have their iMessage server running on macOS but not on iOS. This would both solve that problem and make it easier for them to run on iOS 8 - 14 like they would like to.

  6. (This one's a bit of a stretch, so I'll make this my last one) SMServer will [maybe] be able to work on lower iOS versions.
    Realistically, I think it would be able to reach as low as iOS 10, since that is where all the substantial updates with tapbacks and screen effects were added. Assuming that SMServer doesn't hook into springboard or require any post iOS 11 jailbreak kernels and such anyways. However, with proper porting and such, SMServer (and MyMessage for that matter) could work as low as iOS 5/6.

But now, the drawbacks. You said that you're not sure if the benefits merit the time and energy required for a rewrite/port, and I agree. You're one person working on this tweak and it's a lot for you to undertake. In an ideal situation, a team of jailbreak and iMessage forwarding devs teams up to do this rewrite together, and people like me who are enthusiastic about the app either learn more programming to help as well or we donate to the project. But as it stands now, you'd have to do this mostly on your own, so here are a few cons.

  1. (Complete) Rewrites are a pain
    So you've finished writing your program, but something is a bit off. Did one of your while loops not execute as planned maybe? Well, that's no problem, just see what you did wrong and fix it up. But did you use an older version of your programming language or one that isn't compatible with the hardware that you intended to run it on? Well, now things suddenly get much less fun. This is especially troublesome when the program already performs its intended function (and performs it well at that).

  2. You're doing this alone
    Of course, you've already gotten SMServer to the great spot it's in today on your own, and no matter how a rewrite would be done, it would be lots of time-consuming work and testing.

  3. SMServer already works
    And if it ain't broke, don't fix it

  4. Everything would have to be updated
    All the read me's and API's and documentation and most (or all) of libsmserver. You might even have to change the current versioning like Apple did from 10.15 to 11.0

  5. All the behind-the-scenes stuff that I don't know about

That's about all I have right now, I may edit this comment to add or remove things, or just make new comments. Let me know what you think.

@sabogalc
Copy link
Author

@tneotia
Copy link

tneotia commented Feb 24, 2023

Sending attachments using IMCore uses the following process (on macOS):

  1. Copy attachment into ~/Library/Messages/Attachments directory
  2. Create an NSURL of this saved file path
  3. Create an IMFileTransfer:
+(IMFileTransfer *) prepareFileTransferForAttachment:(NSURL *) originalPath filename:(NSString *) filename {
    // Creates the initial guid for the file transfer (cannot use for sending)
    NSString *transferInitGuid = [[IMFileTransferCenter sharedInstance] guidForNewOutgoingTransferWithLocalURL:originalPath useLegacyGuid:YES];

    // Creates the initial transfer object
    IMFileTransfer *newTransfer = [[IMFileTransferCenter sharedInstance] transferForGUID:transferInitGuid];
    // Get location of where attachments should be placed
    NSString *persistentPath = [[IMDPersistentAttachmentController sharedInstance] _persistentPathForTransfer:newTransfer filename:filename highQuality:TRUE chatGUID:nil storeAtExternalPath:TRUE];

    if (persistentPath) {
        NSError *folder_creation_error;
        NSError *file_move_error;
        NSURL *persistentURL = [NSURL fileURLWithPath:persistentPath];

        // Create the attachment location
        [[NSFileManager defaultManager] createDirectoryAtURL:[persistentURL URLByDeletingLastPathComponent] withIntermediateDirectories:TRUE attributes:nil error:&folder_creation_error];
        // Handle error and exit
        if (folder_creation_error) {
            return nil;
        }

        // Copy the file to the attachment location
        [[NSFileManager defaultManager] copyItemAtURL:originalPath toURL:persistentURL error:&file_move_error];
        // Handle error and exit
        if (file_move_error) {
            return nil;
        }

        // We updated the transfer location
        [[IMFileTransferCenter sharedInstance] retargetTransfer:[newTransfer guid] toPath:persistentPath];
        // Update the local url inside of the transfer
        newTransfer.localURL = persistentURL;
    }

    // Register the transfer (The file must be in correct location before this)
    // *Warning* Can fail but gives only warning in console that failed
    [[IMFileTransferCenter sharedInstance] registerTransferWithDaemon:[newTransfer guid]];
    return newTransfer;
}
  1. Create NSAttributedString for sending:
        NSMutableAttributedString *attachmentStr = [[NSMutableAttributedString alloc] initWithString: @"\ufffc"];
        [attachmentStr addAttributes:@{
            @"__kIMBaseWritingDirectionAttributeName": @"-1",
            @"__kIMFileTransferGUIDAttributeName": fileTransfer.guid,
            @"__kIMFilenameAttributeName": [fileUrl lastPathComponent],
            @"__kIMMessagePartAttributeName": @0,
        } range:NSMakeRange(0, 1)];

"\ufffc" is an object replacement character which iMessage uses to denote an attachment.

  1. Create the IMMessage with the attributed string and the file transfer GUID, and send

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants