imessage-ts
Version:
TypeScript library for interacting with iMessage on macOS - send messages, monitor chats, and automate responses
122 lines • 5.77 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageSender = void 0;
const child_process_1 = require("child_process");
const util_1 = require("util");
const types_1 = require("../types");
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const os_1 = __importDefault(require("os"));
const execAsync = (0, util_1.promisify)(child_process_1.exec);
/**
* Service to send messages via iMessage using AppleScript
*/
class MessageSender {
/**
* Send a message to a recipient or group
*/
async sendMessage(options) {
const { text, to, subject, attachments, service = types_1.MessageService.IMESSAGE } = options;
if (!text && (!attachments || attachments.length === 0)) {
throw new Error('Message must have text or attachments');
}
if (!to || (Array.isArray(to) && to.length === 0)) {
throw new Error('Recipient(s) required');
}
// Validate attachment files exist
if (attachments && attachments.length > 0) {
for (const attachment of attachments) {
if (!await fs_extra_1.default.pathExists(attachment)) {
throw new Error(`Attachment file not found: ${attachment}`);
}
}
}
const recipients = Array.isArray(to) ? to : [to];
try {
// Build the AppleScript - using a simpler approach
let script = `tell application "Messages"\n`;
// Get the service ID first
const serviceType = service === types_1.MessageService.SMS ? 'SMS' : 'iMessage';
script += ` set targetService to id of 1st service whose service type = ${serviceType}\n`;
// For each recipient
for (const recipient of recipients) {
// Create the buddy reference
script += ` set theBuddy to buddy "${escapeAppleScriptString(recipient)}" of service id targetService\n`;
// If we have both text and attachments
if (text && attachments && attachments.length > 0 && service === types_1.MessageService.IMESSAGE) {
// Send text first
script += ` send "${escapeAppleScriptString(text)}" to theBuddy\n`;
// Then send each attachment separately with a delay
for (const attachment of attachments) {
script += ` delay 1\n`; // Small delay to ensure messages are sent in order
script += ` set theAttachment to POSIX file "${escapeAppleScriptString(attachment)}"\n`;
script += ` send theAttachment to theBuddy\n`;
}
}
else if (text) {
// Just text message
script += ` send "${escapeAppleScriptString(text)}" to theBuddy\n`;
}
else if (attachments && attachments.length > 0 && service === types_1.MessageService.IMESSAGE) {
// Just attachments
for (const attachment of attachments) {
script += ` set theAttachment to POSIX file "${escapeAppleScriptString(attachment)}"\n`;
script += ` send theAttachment to theBuddy\n`;
}
}
if (attachments && attachments.length > 0 && service === types_1.MessageService.SMS) {
console.warn('Warning: SMS service has limited attachment support. Some attachments may not send properly.');
}
}
script += `end tell\n`;
// Debug: Log the script
console.log('Generated AppleScript:');
console.log(script);
// Write script to a temporary file to avoid shell escaping issues
const tempFile = path_1.default.join(os_1.default.tmpdir(), `imessage-script-${Date.now()}.scpt`);
await fs_extra_1.default.writeFile(tempFile, script);
try {
// Execute the AppleScript from the temp file
await execAsync(`osascript "${tempFile}"`);
}
finally {
// Clean up temp file
await fs_extra_1.default.remove(tempFile).catch(() => { }); // Ignore errors on cleanup
}
}
catch (error) {
throw new Error(`Failed to send message: ${error.message}`);
}
}
/**
* Check if iMessage is available
*/
async isAvailable() {
try {
await execAsync('osascript -e \'tell application "Messages" to return name\'');
return true;
}
catch (error) {
return false;
}
}
}
exports.MessageSender = MessageSender;
/**
* Escape special characters in AppleScript strings
*/
function escapeAppleScriptString(str) {
// In AppleScript, escape quotes by doubling them
// Also handle Unicode quotes and other special characters
return str
.replace(/\\/g, '\\\\') // Escape backslashes first
.replace(/"/g, '""') // Escape quotes by doubling them (AppleScript style)
.replace(/'/g, "'") // Replace curly apostrophe with straight apostrophe
.replace(/'/g, "'") // Replace other curly apostrophe with straight apostrophe
.replace(/"/g, '""') // Replace left curly quote with escaped straight quote
.replace(/"/g, '""'); // Replace right curly quote with escaped straight quote
}
//# sourceMappingURL=message-sender.js.map