-
Notifications
You must be signed in to change notification settings - Fork 1
/
betterdisplaycli.swift
97 lines (84 loc) · 3.68 KB
/
betterdisplaycli.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//
// betterdisplaycli
//
// Created by @waydabber
//
// Usage:
// 1. compile by entering: `swiftc betterdisplaycli.swift`
// 2. make sure BetterDisplay 2.2.x and newer is running and is configured to accept CLI/notification requests (default)
// 3. run `./betterdisplaycli` for help
//
import Foundation
var arguments = CommandLine.arguments
var commands: [String] = []
var parameters: [String: String?] = [:]
if arguments.count <= 1 {
arguments = ["help"]
} else {
arguments.removeFirst()
}
for argument in arguments {
if argument.hasPrefix("-") {
let argumentParts = argument.components(separatedBy: "=")
parameters[argumentParts[0].trimmingCharacters(in: CharacterSet(charactersIn: "-"))] = argumentParts.count > 1 ? argumentParts[1] : nil
} else {
commands.append(argument)
}
}
await BetterDisplayNotificationIntegration().sendRequest(commands: commands, parameters: parameters)
exit(EXIT_FAILURE)
class BetterDisplayNotificationIntegration {
let integrationNotificationRequestName = "com.betterdisplay.BetterDisplay.request"
let integrationNotificationResponseName = "com.betterdisplay.BetterDisplay.response"
var integrationNotificationRequestData: IntegrationNotificationRequestData?
struct IntegrationNotificationRequestData: Codable {
var uuid: String?
var commands: [String] = []
var parameters: [String: String?] = [:]
}
struct IntegrationNotificationResponseData: Codable {
var uuid: String?
var result: Bool?
var payload: String?
}
func sendRequest(commands: [String], parameters: [String: String?]) async {
DistributedNotificationCenter.default.addObserver(self, selector: #selector(self.processResponse), name: .init(self.integrationNotificationResponseName), object: nil)
self.integrationNotificationRequestData = IntegrationNotificationRequestData(uuid: UUID().uuidString, commands: commands, parameters: parameters)
do {
let encodedIntegrationNotificationRequestData = try JSONEncoder().encode(self.integrationNotificationRequestData)
if let encodedIntegrationNotificationRequestDataString = String(data: encodedIntegrationNotificationRequestData, encoding: .utf8) {
DistributedNotificationCenter.default().postNotificationName(.init(self.integrationNotificationRequestName), object: encodedIntegrationNotificationRequestDataString, userInfo: nil, deliverImmediately: true)
do {
try await Task.sleep(nanoseconds: UInt64(15 * 1_000_000_000))
} catch {}
fputs("Failed. Request timed out. BetterDisplay might not be running or is not configured to accept notifications.\n", stderr)
exit(EXIT_FAILURE)
}
} catch {}
fputs("Failed. Unable to send notification due to an error.\n", stderr)
exit(EXIT_FAILURE)
}
@objc func processResponse(notification: NSNotification) {
guard let notificationString = notification.object as? String else {
return
}
do {
let integrationNotificationResponseData = try JSONDecoder().decode(IntegrationNotificationResponseData.self, from: Data(notificationString.utf8))
if integrationNotificationResponseData.uuid != self.integrationNotificationRequestData?.uuid {
return
}
if integrationNotificationResponseData.result == false {
fputs("Failed.\(integrationNotificationResponseData.payload != nil ? " \(integrationNotificationResponseData.payload ?? "")" : "")\n", stderr)
exit(EXIT_FAILURE)
} else {
if let payload = integrationNotificationResponseData.payload {
print(payload)
}
exit(EXIT_SUCCESS)
}
} catch {
fputs("Failed. Unable to process response due to an error.\n", stderr)
exit(EXIT_FAILURE)
}
}
}