feat(imessage): ✨ improve iMessage service detection and error handling
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
b104ee1b12
commit
5290e1de2f
1 changed files with 47 additions and 1 deletions
|
|
@ -88,9 +88,23 @@ class SendService {
|
|||
.replacingOccurrences(of: "\\", with: "\\\\")
|
||||
.replacingOccurrences(of: "\"", with: "\\\"")
|
||||
|
||||
// Resolve the iMessage service by iterating with a per-service `try`.
|
||||
// A plain `1st service whose service type = iMessage` throws (-1728)
|
||||
// when any stale service errors on `service type`, and it would also
|
||||
// pick a *disabled* service. Require an enabled iMessage service; if
|
||||
// none, fail with a clear reason instead of a cryptic delivery error.
|
||||
let script = """
|
||||
tell application "Messages"
|
||||
set targetService to 1st service whose service type = iMessage
|
||||
set targetService to missing value
|
||||
repeat with s in services
|
||||
try
|
||||
if (service type of s) is iMessage and (enabled of s) then
|
||||
set targetService to s
|
||||
exit repeat
|
||||
end if
|
||||
end try
|
||||
end repeat
|
||||
if targetService is missing value then error "no enabled iMessage service"
|
||||
set targetBuddy to buddy "\(sanitizedBuddy)" of targetService
|
||||
send "\(sanitizedBody)" to targetBuddy
|
||||
end tell
|
||||
|
|
@ -143,6 +157,17 @@ class SendService {
|
|||
return (false, nil, errorMessage)
|
||||
}
|
||||
|
||||
// osascript exiting 0 only means Messages accepted the command — NOT
|
||||
// that the message transmitted. Verify against chat.db: a disabled
|
||||
// iMessage service still creates a message row, but with error != 0
|
||||
// (e.g. error 33). Never report success the ground truth contradicts.
|
||||
Thread.sleep(forTimeInterval: 4)
|
||||
if let sendError = Self.chatDBSendError(buddyId: buddyId), sendError != 0 {
|
||||
osLog.error("send: chat.db reports error=\(sendError, privacy: .public) for \(logPrefix, privacy: .public) — NOT delivered")
|
||||
activityLog.error("iMessage send failed to \(logPrefix)...: Messages error \(sendError)")
|
||||
return (false, nil, "Messages reported error \(sendError) — not delivered (iMessage service may be disabled)")
|
||||
}
|
||||
|
||||
dailySendCount += 1
|
||||
hourlySendCount += 1
|
||||
|
||||
|
|
@ -192,6 +217,27 @@ class SendService {
|
|||
}
|
||||
}
|
||||
|
||||
/// Most-recent outbound `message.error` for `buddyId` from chat.db, or nil
|
||||
/// if no row is found. A non-zero value means Messages failed the send
|
||||
/// even when `osascript` exited 0 (e.g. disabled iMessage service → 33).
|
||||
nonisolated static func chatDBSendError(buddyId: String) -> Int? {
|
||||
guard let dbQueue = iMessageReader.shared.getDatabaseQueue() else { return nil }
|
||||
let suffix = String(buddyId.suffix(7))
|
||||
let value: Int? = (try? dbQueue.read { db -> Int? in
|
||||
guard let row = try Row.fetchOne(db, sql: """
|
||||
SELECT m.error AS err
|
||||
FROM message m
|
||||
JOIN handle h ON h.ROWID = m.handle_id
|
||||
WHERE m.is_from_me = 1 AND h.id LIKE ?
|
||||
ORDER BY m.date DESC
|
||||
LIMIT 1
|
||||
""", arguments: ["%\(suffix)"])
|
||||
else { return nil }
|
||||
return (row["err"] as? Int64).map(Int.init)
|
||||
}) ?? nil
|
||||
return value
|
||||
}
|
||||
|
||||
func getRateLimitStatus() -> (dailyRemaining: Int, hourlyRemaining: Int) {
|
||||
resetCountersIfNeeded()
|
||||
return (max(0, maxDailyMessages - dailySendCount), max(0, maxHourlyMessages - hourlySendCount))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue