macos_notify.swift

 1#!/usr/bin/swift
 2import Cocoa
 3
 4// Compilation: swiftc macos_notify.swift -o macos_notify
 5// Usage: ./macos_notify <title> <body> <logoPath> [subtitle] [identifier] [soundName] [contentImagePath]
 6// Or: ./macos_notify --remove [identifier]
 7
 8let args = ProcessInfo.processInfo.arguments
 9
10if args.contains("--remove") {
11    let center = NSUserNotificationCenter.default
12    if args.count > 2 {
13        let identifier = args[2]
14        center.removeDeliveredNotification(withIdentifier: identifier)
15    } else {
16        center.removeAllDeliveredNotifications()
17    }
18    exit(0)
19}
20
21guard args.count >= 4 else {
22    print("Usage: \(args[0]) <title> <body> <logoPath> [subtitle] [identifier] [soundName] [contentImagePath]")
23    print("       \(args[0]) --remove [identifier]")
24    exit(1)
25}
26
27let title = args[1]
28let body = args[2]
29let logoPath = args[3]
30let subtitle = args.count > 4 ? args[4] : ""
31let identifier = args.count > 5 ? args[5] : nil
32let soundName = args.count > 6 ? args[6] : NSUserNotificationDefaultSoundName
33let contentImagePath = args.count > 7 ? args[7] : ""
34
35class NotificationDelegate: NSObject, NSUserNotificationCenterDelegate {
36    func userNotificationCenter(_ center: NSUserNotificationCenter, shouldPresent notification: NSUserNotification) -> Bool {
37        return true
38    }
39}
40
41let notification = NSUserNotification()
42notification.title = title
43notification.informativeText = body
44notification.subtitle = subtitle
45notification.soundName = soundName
46
47if let identifier = identifier {
48    notification.identifier = identifier
49}
50
51func loadImage(from path: String) -> NSImage? {
52    if path.isEmpty { return nil }
53    let expandedPath = (path as NSString).expandingTildeInPath
54    return NSImage(contentsOfFile: expandedPath)
55}
56
57if let img = loadImage(from: logoPath) {
58    // _identityImage is a private key that allows showing an image on the left of the notification.
59    notification.setValue(img, forKey: "_identityImage")
60}
61
62if let contentImg = loadImage(from: contentImagePath) {
63    notification.contentImage = contentImg
64}
65
66let delegate = NotificationDelegate()
67NSUserNotificationCenter.default.delegate = delegate
68NSUserNotificationCenter.default.deliver(notification)
69
70// Wait for the notification to be delivered to the system.
71RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))