terminal-notifier 1.7.2 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.markdown +1 -1
  3. data/lib/terminal-notifier.rb +5 -4
  4. data/vendor/terminal-notifier +0 -0
  5. metadata +6 -44
  6. data/vendor/terminal-notifier/LICENSE.md +0 -9
  7. data/vendor/terminal-notifier/README.markdown +0 -301
  8. data/vendor/terminal-notifier/Ruby/Gemfile +0 -2
  9. data/vendor/terminal-notifier/Ruby/Gemfile.lock +0 -23
  10. data/vendor/terminal-notifier/Ruby/LICENSE +0 -24
  11. data/vendor/terminal-notifier/Ruby/README.markdown +0 -48
  12. data/vendor/terminal-notifier/Ruby/Rakefile +0 -48
  13. data/vendor/terminal-notifier/Ruby/bin/terminal-notifier +0 -13
  14. data/vendor/terminal-notifier/Ruby/lib/terminal-notifier.rb +0 -92
  15. data/vendor/terminal-notifier/Ruby/spec/terminal-notifier_spec.rb +0 -79
  16. data/vendor/terminal-notifier/Ruby/terminal-notifier.gemspec +0 -26
  17. data/vendor/terminal-notifier/Terminal Notifier.xcodeproj/project.pbxproj +0 -315
  18. data/vendor/terminal-notifier/Terminal Notifier.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  19. data/vendor/terminal-notifier/Terminal Notifier.xcodeproj/project.xcworkspace/xcshareddata/Terminal Notifier.xccheckout +0 -41
  20. data/vendor/terminal-notifier/Terminal Notifier.xcodeproj/xcshareddata/xcschemes/Terminal Notifier.xcscheme +0 -140
  21. data/vendor/terminal-notifier/Terminal Notifier/AppDelegate.h +0 -4
  22. data/vendor/terminal-notifier/Terminal Notifier/AppDelegate.m +0 -594
  23. data/vendor/terminal-notifier/Terminal Notifier/Terminal Notifier-Info.plist +0 -43
  24. data/vendor/terminal-notifier/Terminal Notifier/Terminal Notifier-Prefix.pch +0 -7
  25. data/vendor/terminal-notifier/Terminal Notifier/en.lproj/Credits.rtf +0 -29
  26. data/vendor/terminal-notifier/Terminal Notifier/en.lproj/InfoPlist.strings +0 -2
  27. data/vendor/terminal-notifier/Terminal Notifier/en.lproj/MainMenu.xib +0 -3387
  28. data/vendor/terminal-notifier/Terminal Notifier/main.m +0 -6
  29. data/vendor/terminal-notifier/Terminal.icns +0 -0
  30. data/vendor/terminal-notifier/assets/Example_1.png +0 -0
  31. data/vendor/terminal-notifier/assets/Example_2.png +0 -0
  32. data/vendor/terminal-notifier/assets/Example_3.png +0 -0
  33. data/vendor/terminal-notifier/assets/Example_4.png +0 -0
  34. data/vendor/terminal-notifier/assets/Example_5.png +0 -0
  35. data/vendor/terminal-notifier/assets/System_prefs.png +0 -0
  36. data/vendor/terminal-notifier/terminal-notifier.app/Contents/Info.plist +0 -63
  37. data/vendor/terminal-notifier/terminal-notifier.app/Contents/MacOS/terminal-notifier +0 -0
  38. data/vendor/terminal-notifier/terminal-notifier.app/Contents/PkgInfo +0 -1
  39. data/vendor/terminal-notifier/terminal-notifier.app/Contents/Resources/Terminal.icns +0 -0
  40. data/vendor/terminal-notifier/terminal-notifier.app/Contents/Resources/en.lproj/Credits.rtf +0 -29
  41. data/vendor/terminal-notifier/terminal-notifier.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  42. data/vendor/terminal-notifier/terminal-notifier.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Workspace
3
- version = "1.0">
4
- <FileRef
5
- location = "self:Terminal Notifier.xcodeproj">
6
- </FileRef>
7
- </Workspace>
@@ -1,41 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>IDESourceControlProjectFavoriteDictionaryKey</key>
6
- <false/>
7
- <key>IDESourceControlProjectIdentifier</key>
8
- <string>A55309C1-2ABD-460A-B080-5A322DCAF4B5</string>
9
- <key>IDESourceControlProjectName</key>
10
- <string>Terminal Notifier</string>
11
- <key>IDESourceControlProjectOriginsDictionary</key>
12
- <dict>
13
- <key>9F67DD19109869B0F5A85172DA9B0D3E8F7EF383</key>
14
- <string>github.com:alloy/terminal-notifier.git</string>
15
- </dict>
16
- <key>IDESourceControlProjectPath</key>
17
- <string>Terminal Notifier.xcodeproj</string>
18
- <key>IDESourceControlProjectRelativeInstallPathDictionary</key>
19
- <dict>
20
- <key>9F67DD19109869B0F5A85172DA9B0D3E8F7EF383</key>
21
- <string>../..</string>
22
- </dict>
23
- <key>IDESourceControlProjectURL</key>
24
- <string>github.com:alloy/terminal-notifier.git</string>
25
- <key>IDESourceControlProjectVersion</key>
26
- <integer>111</integer>
27
- <key>IDESourceControlProjectWCCIdentifier</key>
28
- <string>9F67DD19109869B0F5A85172DA9B0D3E8F7EF383</string>
29
- <key>IDESourceControlProjectWCConfigurations</key>
30
- <array>
31
- <dict>
32
- <key>IDESourceControlRepositoryExtensionIdentifierKey</key>
33
- <string>public.vcs.git</string>
34
- <key>IDESourceControlWCCIdentifierKey</key>
35
- <string>9F67DD19109869B0F5A85172DA9B0D3E8F7EF383</string>
36
- <key>IDESourceControlWCCName</key>
37
- <string>terminal-notifier</string>
38
- </dict>
39
- </array>
40
- </dict>
41
- </plist>
@@ -1,140 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Scheme
3
- LastUpgradeVersion = "0440"
4
- version = "1.3">
5
- <BuildAction
6
- parallelizeBuildables = "YES"
7
- buildImplicitDependencies = "YES">
8
- <BuildActionEntries>
9
- <BuildActionEntry
10
- buildForTesting = "YES"
11
- buildForRunning = "YES"
12
- buildForProfiling = "YES"
13
- buildForArchiving = "YES"
14
- buildForAnalyzing = "YES">
15
- <BuildableReference
16
- BuildableIdentifier = "primary"
17
- BlueprintIdentifier = "5199791315B1F92B003AFC57"
18
- BuildableName = "terminal-notifier.app"
19
- BlueprintName = "terminal-notifier"
20
- ReferencedContainer = "container:Terminal Notifier.xcodeproj">
21
- </BuildableReference>
22
- </BuildActionEntry>
23
- </BuildActionEntries>
24
- </BuildAction>
25
- <TestAction
26
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
27
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
28
- shouldUseLaunchSchemeArgsEnv = "YES"
29
- buildConfiguration = "Debug">
30
- <Testables>
31
- </Testables>
32
- <MacroExpansion>
33
- <BuildableReference
34
- BuildableIdentifier = "primary"
35
- BlueprintIdentifier = "5199791315B1F92B003AFC57"
36
- BuildableName = "terminal-notifier.app"
37
- BlueprintName = "terminal-notifier"
38
- ReferencedContainer = "container:Terminal Notifier.xcodeproj">
39
- </BuildableReference>
40
- </MacroExpansion>
41
- </TestAction>
42
- <LaunchAction
43
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
44
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
45
- launchStyle = "0"
46
- useCustomWorkingDirectory = "NO"
47
- buildConfiguration = "Release"
48
- ignoresPersistentStateOnLaunch = "NO"
49
- debugDocumentVersioning = "NO"
50
- allowLocationSimulation = "YES">
51
- <BuildableProductRunnable>
52
- <BuildableReference
53
- BuildableIdentifier = "primary"
54
- BlueprintIdentifier = "5199791315B1F92B003AFC57"
55
- BuildableName = "terminal-notifier.app"
56
- BlueprintName = "terminal-notifier"
57
- ReferencedContainer = "container:Terminal Notifier.xcodeproj">
58
- </BuildableReference>
59
- </BuildableProductRunnable>
60
- <CommandLineArguments>
61
- <CommandLineArgument
62
- argument = "-group abcde"
63
- isEnabled = "NO">
64
- </CommandLineArgument>
65
- <CommandLineArgument
66
- argument = "-help"
67
- isEnabled = "NO">
68
- </CommandLineArgument>
69
- <CommandLineArgument
70
- argument = "-sound default"
71
- isEnabled = "NO">
72
- </CommandLineArgument>
73
- <CommandLineArgument
74
- argument = "-list ALL"
75
- isEnabled = "NO">
76
- </CommandLineArgument>
77
- <CommandLineArgument
78
- argument = "-list abcde"
79
- isEnabled = "NO">
80
- </CommandLineArgument>
81
- <CommandLineArgument
82
- argument = "-remove abcde"
83
- isEnabled = "NO">
84
- </CommandLineArgument>
85
- <CommandLineArgument
86
- argument = "-open &apos;http://google.com/search?q=http status codes&apos;"
87
- isEnabled = "YES">
88
- </CommandLineArgument>
89
- <CommandLineArgument
90
- argument = "-execute &apos;say &quot;OMG&quot;&apos;"
91
- isEnabled = "NO">
92
- </CommandLineArgument>
93
- <CommandLineArgument
94
- argument = "-execute &apos;ls -l&apos;"
95
- isEnabled = "NO">
96
- </CommandLineArgument>
97
- <CommandLineArgument
98
- argument = "-title Kicker"
99
- isEnabled = "NO">
100
- </CommandLineArgument>
101
- <CommandLineArgument
102
- argument = "-message &apos;Execute: rake spec&apos;"
103
- isEnabled = "NO">
104
- </CommandLineArgument>
105
- <CommandLineArgument
106
- argument = "-activate com.apple.Safari"
107
- isEnabled = "NO">
108
- </CommandLineArgument>
109
- <CommandLineArgument
110
- argument = "-sender com.apple.Safari"
111
- isEnabled = "NO">
112
- </CommandLineArgument>
113
- </CommandLineArguments>
114
- <AdditionalOptions>
115
- </AdditionalOptions>
116
- </LaunchAction>
117
- <ProfileAction
118
- shouldUseLaunchSchemeArgsEnv = "YES"
119
- savedToolIdentifier = ""
120
- useCustomWorkingDirectory = "NO"
121
- buildConfiguration = "Release"
122
- debugDocumentVersioning = "YES">
123
- <BuildableProductRunnable>
124
- <BuildableReference
125
- BuildableIdentifier = "primary"
126
- BlueprintIdentifier = "5199791315B1F92B003AFC57"
127
- BuildableName = "terminal-notifier.app"
128
- BlueprintName = "terminal-notifier"
129
- ReferencedContainer = "container:Terminal Notifier.xcodeproj">
130
- </BuildableReference>
131
- </BuildableProductRunnable>
132
- </ProfileAction>
133
- <AnalyzeAction
134
- buildConfiguration = "Debug">
135
- </AnalyzeAction>
136
- <ArchiveAction
137
- buildConfiguration = "Release"
138
- revealArchiveInOrganizer = "YES">
139
- </ArchiveAction>
140
- </Scheme>
@@ -1,4 +0,0 @@
1
- #import <Cocoa/Cocoa.h>
2
-
3
- @interface AppDelegate : NSObject <NSApplicationDelegate, NSUserNotificationCenterDelegate>
4
- @end
@@ -1,594 +0,0 @@
1
- #import "AppDelegate.h"
2
- #import <ScriptingBridge/ScriptingBridge.h>
3
- #import <objc/runtime.h>
4
-
5
- NSString * const TerminalNotifierBundleID = @"nl.superalloy.oss.terminal-notifier";
6
- NSString * const NotificationCenterUIBundleID = @"com.apple.notificationcenterui";
7
-
8
- // Set OS Params
9
- #define NSAppKitVersionNumber10_8 1187
10
- #define NSAppKitVersionNumber10_9 1265
11
-
12
- #define contains(str1, str2) ([str1 rangeOfString: str2 ].location != NSNotFound)
13
-
14
- NSString *_fakeBundleIdentifier = nil;
15
- NSUserNotification *currentNotification = nil;
16
-
17
- @implementation NSBundle (FakeBundleIdentifier)
18
-
19
- // Overriding bundleIdentifier works, but overriding NSUserNotificationAlertStyle does not work.
20
-
21
- - (NSString *)__bundleIdentifier;
22
- {
23
- if (self == [NSBundle mainBundle]) {
24
- return _fakeBundleIdentifier ? _fakeBundleIdentifier : TerminalNotifierBundleID;
25
- } else {
26
- return [self __bundleIdentifier];
27
- }
28
- }
29
-
30
- @end
31
-
32
- static BOOL
33
- InstallFakeBundleIdentifierHook()
34
- {
35
- Class class = objc_getClass("NSBundle");
36
- if (class) {
37
- method_exchangeImplementations(class_getInstanceMethod(class, @selector(bundleIdentifier)),
38
- class_getInstanceMethod(class, @selector(__bundleIdentifier)));
39
- return YES;
40
- }
41
- return NO;
42
- }
43
-
44
- static BOOL
45
- isMavericks()
46
- {
47
- if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_8) {
48
- /* On a 10.8 - 10.8.x system */
49
- return NO;
50
- } else {
51
- /* 10.9 or later system */
52
- return YES;
53
- }
54
- }
55
-
56
- @implementation NSUserDefaults (SubscriptAndUnescape)
57
- - (id)objectForKeyedSubscript:(id)key;
58
- {
59
- id obj = [self objectForKey:key];
60
- if ([obj isKindOfClass:[NSString class]] && [(NSString *)obj hasPrefix:@"\\"]) {
61
- obj = [(NSString *)obj substringFromIndex:1];
62
- }
63
- return obj;
64
- }
65
- @end
66
-
67
-
68
- @implementation AppDelegate
69
-
70
- +(void)initializeUserDefaults
71
- {
72
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
73
-
74
- // initialize the dictionary with default values depending on OS level
75
- NSDictionary *appDefaults;
76
-
77
- if (isMavericks()) {
78
- //10.9
79
- appDefaults = @{@"sender": @"com.apple.Terminal"};
80
- } else {
81
- //10.8
82
- appDefaults = @{@"": @"message"};
83
- }
84
-
85
- // and set them appropriately
86
- [defaults registerDefaults:appDefaults];
87
- }
88
-
89
- - (void)printHelpBanner;
90
- {
91
- const char *appName = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleExecutable"] UTF8String];
92
- const char *appVersion = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] UTF8String];
93
- printf("%s (%s) is a command-line tool to send OS X User Notifications.\n" \
94
- "\n" \
95
- "Usage: %s -[message|list|remove] [VALUE|ID|ID] [options]\n" \
96
- "\n" \
97
- " Either of these is required (unless message data is piped to the tool):\n" \
98
- "\n" \
99
- " -help Display this help banner.\n" \
100
- " -message VALUE The notification message.\n" \
101
- " -remove ID Removes a notification with the specified ‘group’ ID.\n" \
102
- " -list ID If the specified ‘group’ ID exists show when it was delivered,\n" \
103
- " or use ‘ALL’ as ID to see all notifications.\n" \
104
- " The output is a tab-separated list.\n"
105
- "\n" \
106
- " Reply type notification:\n" \
107
- "\n" \
108
- " -reply VALUE The notification will be displayed as a reply type alert, VALUE used as placeholder.\n" \
109
- "\n" \
110
- " Actions type notification:\n" \
111
- "\n" \
112
- " -actions VALUE1,VALUE2.\n" \
113
- " The notification actions avalaible.\n" \
114
- " When you provide more than one value, a dropdown will be displayed.\n" \
115
- " You can customize this dropdown label with the next option.\n" \
116
- " -dropdownLabel VALUE\n" \
117
- " The notification actions dropdown title (only when multiples actions are provided).\n" \
118
- " Notification style must be set to Alert.\n" \
119
- "\n" \
120
- " Optional:\n" \
121
- "\n" \
122
- " -title VALUE The notification title. Defaults to ‘Terminal’.\n" \
123
- " -subtitle VALUE The notification subtitle.\n" \
124
- " -closeLabel VALUE The notification close button label.\n" \
125
- " -sound NAME The name of a sound to play when the notification appears. The names are listed\n" \
126
- " in Sound Preferences. Use 'default' for the default notification sound.\n" \
127
- " -group ID A string which identifies the group the notifications belong to.\n" \
128
- " Old notifications with the same ID will be removed.\n" \
129
- " -activate ID The bundle identifier of the application to activate when the user clicks the notification.\n" \
130
- " -sender ID The bundle identifier of the application that should be shown as the sender, including its icon.\n" \
131
- " -appIcon URL The URL of a image to display instead of the application icon (Mavericks+ only)\n" \
132
- " -contentImage URL The URL of a image to display attached to the notification (Mavericks+ only)\n" \
133
- " -open URL The URL of a resource to open when the user clicks the notification.\n" \
134
- " -execute COMMAND A shell command to perform when the user clicks the notification.\n" \
135
- " -timeout NUMBER Close the notification after NUMBER seconds.\n" \
136
- " -json Output event or value to stdout as JSON \n" \
137
- "\n" \
138
- "When the user activates a notification, the results are logged to the system logs.\n" \
139
- "Use Console.app to view these logs.\n" \
140
- "\n" \
141
- "Note that in some circumstances the first character of a message has to be escaped in order to be recognized.\n" \
142
- "An example of this is when using an open bracket, which has to be escaped like so: ‘\\[’.\n" \
143
- "\n" \
144
- "For more information see https://github.com/julienXX/terminal-notifier.\n",
145
- appName, appVersion, appName);
146
- }
147
-
148
- - (void)applicationDidFinishLaunching:(NSNotification *)notification;
149
- {
150
- NSUserNotification *userNotification = notification.userInfo[NSApplicationLaunchUserNotificationKey];
151
- if (userNotification) {
152
- [self userActivatedNotification:userNotification];
153
-
154
- } else {
155
- if ([[[NSProcessInfo processInfo] arguments] indexOfObject:@"-help"] != NSNotFound) {
156
- [self printHelpBanner];
157
- exit(0);
158
- }
159
-
160
- NSArray *runningProcesses = [[[NSWorkspace sharedWorkspace] runningApplications] valueForKey:@"bundleIdentifier"];
161
- if ([runningProcesses indexOfObject:NotificationCenterUIBundleID] == NSNotFound) {
162
- NSLog(@"[!] Unable to post a notification for the current user (%@), as it has no running NotificationCenter instance.", NSUserName());
163
- exit(1);
164
- }
165
-
166
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
167
-
168
- NSString *subtitle = defaults[@"subtitle"];
169
- NSString *message = defaults[@"message"];
170
- NSString *remove = defaults[@"remove"];
171
- NSString *list = defaults[@"list"];
172
- NSString *sound = defaults[@"sound"];
173
-
174
- // If there is no message and data is piped to the application, use that
175
- // instead.
176
- if (message == nil && !isatty(STDIN_FILENO)) {
177
- NSData *inputData = [NSData dataWithData:[[NSFileHandle fileHandleWithStandardInput] readDataToEndOfFile]];
178
- message = [[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding];
179
- }
180
-
181
- if (message == nil && remove == nil && list == nil) {
182
- [self printHelpBanner];
183
- exit(1);
184
- }
185
-
186
- if (list) {
187
- [self listNotificationWithGroupID:list];
188
- exit(0);
189
- }
190
-
191
- // Install the fake bundle ID hook so we can fake the sender. This also
192
- // needs to be done to be able to remove a message.
193
- if (defaults[@"sender"]) {
194
- @autoreleasepool {
195
- if (InstallFakeBundleIdentifierHook()) {
196
- _fakeBundleIdentifier = defaults[@"sender"];
197
- }
198
- }
199
- }
200
-
201
- if (remove) {
202
- [self removeNotificationWithGroupID:remove];
203
- if (message == nil) exit(0);
204
- }
205
-
206
- if (message) {
207
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
208
- if (defaults[@"activate"]) options[@"bundleID"] = defaults[@"activate"];
209
- if (defaults[@"group"]) options[@"groupID"] = defaults[@"group"];
210
- if (defaults[@"execute"]) options[@"command"] = defaults[@"execute"];
211
- if (defaults[@"appIcon"]) options[@"appIcon"] = defaults[@"appIcon"];
212
- if (defaults[@"contentImage"]) options[@"contentImage"] = defaults[@"contentImage"];
213
- if (defaults[@"closeLabel"]) options[@"closeLabel"] = defaults[@"closeLabel"];
214
- if (defaults[@"dropdownLabel"]) options[@"dropdownLabel"] = defaults[@"dropdownLabel"];
215
- if (defaults[@"actions"]) options[@"actions"] = defaults[@"actions"];
216
-
217
- if([[[NSProcessInfo processInfo] arguments] containsObject:@"-reply"] == true) {
218
- options[@"reply"] = @"Reply";
219
- if (defaults[@"reply"]) options[@"reply"] = defaults[@"reply"];
220
- }
221
-
222
- options[@"output"] = @"outputEvent";
223
- if([[[NSProcessInfo processInfo] arguments] containsObject:@"-json"] == true) {
224
- options[@"output"] = @"json";
225
- }
226
-
227
- options[@"uuid"] = [NSString stringWithFormat:@"%ld", self.hash];
228
- options[@"timeout"] = defaults[@"timeout"] ? defaults[@"timeout"] : @"0";
229
-
230
- if (options[@"reply"] || defaults[@"timeout"] || defaults[@"actions"]) options[@"waitForResponse"] = @YES;
231
-
232
- if (defaults[@"open"]) {
233
- /*
234
- * it may be better to use stringByAddingPercentEncodingWithAllowedCharacters instead of stringByAddingPercentEscapesUsingEncoding,
235
- * but stringByAddingPercentEncodingWithAllowedCharacters is only available on OS X 10.9 or higher.
236
- */
237
- NSString *encodedURL = [defaults[@"open"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
238
- NSURL *url = [NSURL URLWithString:defaults[@"open"]];
239
- NSString *fragment = [url fragment];
240
- if (fragment) {
241
- options[@"open"] = [self decodeFragmentInURL:encodedURL fragment:fragment];
242
- } else {
243
- options[@"open"] = encodedURL;
244
- }
245
- }
246
-
247
- options[@"uuid"] = [NSString stringWithFormat:@"%ld", self.hash];
248
-
249
- [self deliverNotificationWithTitle:defaults[@"title"] ?: @"Terminal"
250
- subtitle:subtitle
251
- message:message
252
- options:options
253
- sound:sound];
254
- }
255
- }
256
- }
257
-
258
- - (NSImage*)getImageFromURL:(NSString *) url;
259
- {
260
- NSURL *imageURL = [NSURL URLWithString:url];
261
- if([[imageURL scheme] length] == 0){
262
- // Prefix 'file://' if no scheme
263
- imageURL = [NSURL fileURLWithPath:url];
264
- }
265
- return [[NSImage alloc] initWithContentsOfURL:imageURL];
266
- }
267
-
268
- /**
269
- * Decode fragment identifier
270
- *
271
- * @see http://tools.ietf.org/html/rfc3986#section-2.1
272
- * @see http://en.wikipedia.org/wiki/URI_scheme
273
- */
274
- - (NSString*)decodeFragmentInURL:(NSString *) encodedURL fragment:(NSString *) framgent
275
- {
276
- NSString *beforeStr = [@"%23" stringByAppendingString:framgent];
277
- NSString *afterStr = [@"#" stringByAppendingString:framgent];
278
- NSString *decodedURL = [encodedURL stringByReplacingOccurrencesOfString:beforeStr withString:afterStr];
279
- return decodedURL;
280
- }
281
-
282
- - (void)deliverNotificationWithTitle:(NSString *)title
283
- subtitle:(NSString *)subtitle
284
- message:(NSString *)message
285
- options:(NSDictionary *)options
286
- sound:(NSString *)sound;
287
- {
288
- // First remove earlier notification with the same group ID.
289
- if (options[@"groupID"]) [self removeNotificationWithGroupID:options[@"groupID"]];
290
-
291
- NSUserNotification *userNotification = [NSUserNotification new];
292
- userNotification.title = title;
293
- userNotification.subtitle = subtitle;
294
- userNotification.informativeText = message;
295
- userNotification.userInfo = options;
296
-
297
- if(isMavericks()){
298
- // Mavericks options
299
- if(options[@"appIcon"]){
300
- // replacement app icon
301
- [userNotification setValue:[self getImageFromURL:options[@"appIcon"]] forKey:@"_identityImage"];
302
- [userNotification setValue:@(false) forKey:@"_identityImageHasBorder"];
303
- }
304
- if(options[@"contentImage"]){
305
- // content image
306
- userNotification.contentImage = [self getImageFromURL:options[@"contentImage"]];
307
- }
308
- // Actions
309
- if (options[@"actions"]){
310
- [userNotification setValue:@YES forKey:@"_showsButtons"];
311
- NSArray *myActions = [options[@"actions"] componentsSeparatedByString:@","];
312
- if (myActions.count > 1) {
313
- [userNotification setValue:@YES forKey:@"_alwaysShowAlternateActionMenu"];
314
- [userNotification setValue:myActions forKey:@"_alternateActionButtonTitles"];
315
-
316
- //Main Actions Title
317
- if(options[@"dropdownLabel"]){
318
- userNotification.actionButtonTitle = options[@"dropdownLabel"];
319
- userNotification.hasActionButton = true;
320
- }
321
- }else{
322
- userNotification.actionButtonTitle = options[@"actions"];
323
- }
324
- }else if (options[@"reply"]) {
325
- [userNotification setValue:@YES forKey:@"_showsButtons"];
326
- userNotification.hasReplyButton = 1;
327
- userNotification.responsePlaceholder = options[@"reply"];
328
- }
329
-
330
- // Close button
331
- if(options[@"closeLabel"]){
332
- userNotification.otherButtonTitle = options[@"closeLabel"];
333
- }
334
- }
335
-
336
- if (sound != nil) {
337
- userNotification.soundName = [sound isEqualToString: @"default"] ? NSUserNotificationDefaultSoundName : sound;
338
- }
339
-
340
- NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
341
- center.delegate = self;
342
- [center deliverNotification:userNotification];
343
- }
344
-
345
- - (void)removeNotificationWithGroupID:(NSString *)groupID;
346
- {
347
- NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
348
- for (NSUserNotification *userNotification in center.deliveredNotifications) {
349
- if ([@"ALL" isEqualToString:groupID] || [userNotification.userInfo[@"groupID"] isEqualToString:groupID]) {
350
- [center removeDeliveredNotification:userNotification];
351
- }
352
- }
353
- }
354
-
355
- - (void)userActivatedNotification:(NSUserNotification *)userNotification;
356
- {
357
- [[NSUserNotificationCenter defaultUserNotificationCenter] removeDeliveredNotification:userNotification];
358
-
359
- NSString *groupID = userNotification.userInfo[@"groupID"];
360
- NSString *bundleID = userNotification.userInfo[@"bundleID"];
361
- NSString *command = userNotification.userInfo[@"command"];
362
- NSString *open = userNotification.userInfo[@"open"];
363
-
364
- if (bundleID) [self activateAppWithBundleID:bundleID];
365
- if (command) [self executeShellCommand:command];
366
- if (open) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:open]];
367
- }
368
-
369
- - (BOOL)activateAppWithBundleID:(NSString *)bundleID;
370
- {
371
- id app = [SBApplication applicationWithBundleIdentifier:bundleID];
372
- if (app) {
373
- [app activate];
374
- return YES;
375
-
376
- } else {
377
- NSLog(@"Unable to find an application with the specified bundle indentifier.");
378
- return NO;
379
- }
380
- }
381
-
382
- - (BOOL)executeShellCommand:(NSString *)command;
383
- {
384
- NSPipe *pipe = [NSPipe pipe];
385
- NSFileHandle *fileHandle = [pipe fileHandleForReading];
386
-
387
- NSTask *task = [NSTask new];
388
- task.launchPath = @"/bin/sh";
389
- task.arguments = @[@"-c", command];
390
- task.standardOutput = pipe;
391
- task.standardError = pipe;
392
- [task launch];
393
-
394
- NSData *data = nil;
395
- NSMutableData *accumulatedData = [NSMutableData data];
396
- while ((data = [fileHandle availableData]) && [data length]) {
397
- [accumulatedData appendData:data];
398
- }
399
-
400
- [task waitUntilExit];
401
- NSLog(@"command output:\n%@", [[NSString alloc] initWithData:accumulatedData encoding:NSUTF8StringEncoding]);
402
- return [task terminationStatus] == 0;
403
- }
404
-
405
- - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
406
- shouldPresentNotification:(NSUserNotification *)notification;
407
- {
408
- return YES;
409
- }
410
-
411
- // Once the notification is delivered we can exit. (Only if no actions or reply)
412
- - (void)userNotificationCenter:(NSUserNotificationCenter *)center
413
- didDeliverNotification:(NSUserNotification *)userNotification;
414
- {
415
- if (!userNotification.userInfo[@"waitForResponse"]) exit(0);
416
-
417
- currentNotification = userNotification;
418
-
419
- dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
420
- ^{
421
- __block BOOL notificationStillPresent;
422
- do {
423
- @autoreleasepool {
424
- notificationStillPresent = NO;
425
- for (NSUserNotification *nox in [[NSUserNotificationCenter defaultUserNotificationCenter] deliveredNotifications]) {
426
- if ([nox.userInfo[@"uuid"] isEqualToString:[NSString stringWithFormat:@"%ld", self.hash] ]) notificationStillPresent = YES;
427
- }
428
- if (notificationStillPresent) [NSThread sleepForTimeInterval:0.20f];
429
- }
430
- } while (notificationStillPresent);
431
-
432
- dispatch_async(dispatch_get_main_queue(), ^{
433
- NSDictionary *udict = @{@"activationType" : @"closed", @"activationValue" : userNotification.otherButtonTitle};
434
- [self Quit:udict notification:userNotification];
435
- exit(0);
436
- });
437
- });
438
-
439
- if ([userNotification.userInfo[@"timeout"] integerValue] > 0){
440
- dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
441
- ^{
442
- [NSThread sleepForTimeInterval:[userNotification.userInfo[@"timeout"] integerValue]];
443
- [center removeDeliveredNotification:currentNotification];
444
- [center removeDeliveredNotification:userNotification];
445
- NSDictionary *udict = @{@"activationType" : @"timeout"};
446
- [self Quit:udict notification:userNotification];
447
- exit(0);
448
- });
449
- }
450
- }
451
-
452
- - (void)userNotificationCenter:(NSUserNotificationCenter *)center
453
- didActivateNotification:(NSUserNotification *)notification {
454
-
455
- if ([notification.userInfo[@"uuid"] isNotEqualTo:[NSString stringWithFormat:@"%ld", self.hash] ]) {
456
- return;
457
- };
458
-
459
- unsigned long long additionalActionIndex = ULLONG_MAX;
460
-
461
- NSString* ActionsClicked = @"";
462
- switch (notification.activationType) {
463
-
464
- case NSUserNotificationActivationTypeAdditionalActionClicked:
465
- case NSUserNotificationActivationTypeActionButtonClicked:
466
- if ([[(NSObject*)notification valueForKey:@"_alternateActionButtonTitles"] count] > 1 ){
467
- NSNumber *alternateActionIndex = [(NSObject*)notification valueForKey:@"_alternateActionIndex"];
468
- additionalActionIndex = [alternateActionIndex unsignedLongLongValue];
469
- ActionsClicked = [(NSObject*)notification valueForKey:@"_alternateActionButtonTitles"][additionalActionIndex];
470
-
471
- NSDictionary *udict = @{@"activationType" : @"actionClicked", @"activationValue" : ActionsClicked, @"activationValueIndex" :[NSString stringWithFormat:@"%llu", additionalActionIndex]};
472
- [self Quit:udict notification:notification];
473
- }else{
474
- NSDictionary *udict = @{@"activationType" : @"actionClicked", @"activationValue" : notification.actionButtonTitle};
475
- [self Quit:udict notification:notification];
476
- }
477
- break;
478
-
479
- case NSUserNotificationActivationTypeContentsClicked:
480
- [self userActivatedNotification:notification];
481
- [self Quit:@{@"activationType" : @"contentsClicked"} notification:notification];
482
- break;
483
-
484
- case NSUserNotificationActivationTypeReplied:
485
- [self Quit:@{@"activationType" : @"replied",@"activationValue":notification.response.string} notification:notification];
486
- break;
487
- case NSUserNotificationActivationTypeNone:
488
- default:
489
- [self Quit:@{@"activationType" : @"none"} notification:notification];
490
- break;
491
- }
492
-
493
- [center removeDeliveredNotification:notification];
494
- [center removeDeliveredNotification:currentNotification];
495
- exit(0);
496
- }
497
-
498
- - (BOOL)Quit:(NSDictionary *)udict notification:(NSUserNotification *)notification;
499
- {
500
- if ([notification.userInfo[@"output"] isEqualToString:@"outputEvent"]) {
501
- if ([udict[@"activationType"] isEqualToString:@"closed"]) {
502
- if ([udict[@"activationValue"] isEqualToString:@""]) {
503
- printf("%s", "@CLOSED" );
504
- }else{
505
- printf("%s", [udict[@"activationValue"] UTF8String] );
506
- }
507
- } else if ([udict[@"activationType"] isEqualToString:@"timeout"]) {
508
- printf("%s", "@TIMEOUT" );
509
- } else if ([udict[@"activationType"] isEqualToString:@"contentsClicked"]) {
510
- printf("%s", "@CONTENTCLICKED" );
511
- } else{
512
- if ([udict[@"activationValue"] isEqualToString:@""]) {
513
- printf("%s", "@ACTIONCLICKED" );
514
- }else{
515
- printf("%s", [udict[@"activationValue"] UTF8String] );
516
- }
517
- }
518
-
519
- return 1;
520
- }
521
-
522
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
523
- dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss Z";
524
-
525
- // Dictionary with several key/value pairs and the above array of arrays
526
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
527
- [dict addEntriesFromDictionary:udict];
528
- [dict setValue:[dateFormatter stringFromDate:notification.actualDeliveryDate] forKey:@"deliveredAt"];
529
- [dict setValue:[dateFormatter stringFromDate:[NSDate new]] forKey:@"activationAt"];
530
-
531
- NSError *error = nil;
532
- NSData *json;
533
-
534
- // Dictionary convertable to JSON ?
535
- if ([NSJSONSerialization isValidJSONObject:dict])
536
- {
537
- // Serialize the dictionary
538
- json = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
539
-
540
- // If no errors, let's view the JSON
541
- if (json != nil && error == nil)
542
- {
543
- NSString *jsonString = [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding];
544
- printf("%s", [jsonString cStringUsingEncoding:NSUTF8StringEncoding]);
545
- }
546
- }
547
-
548
- return 1;
549
- }
550
-
551
- - (void)listNotificationWithGroupID:(NSString *)listGroupID;
552
- {
553
- NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
554
-
555
- NSMutableArray *lines = [NSMutableArray array];
556
- for (NSUserNotification *userNotification in center.deliveredNotifications) {
557
- NSString *deliveredgroupID = userNotification.userInfo[@"groupID"];
558
- NSString *title = userNotification.title;
559
- NSString *subtitle = userNotification.subtitle;
560
- NSString *message = userNotification.informativeText;
561
- NSString *deliveredAt = [userNotification.actualDeliveryDate description];
562
-
563
- if ([@"ALL" isEqualToString:listGroupID] || [deliveredgroupID isEqualToString:listGroupID]) {
564
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
565
- [dict setValue:deliveredgroupID forKey:@"GroupID"];
566
- [dict setValue:title forKey:@"Title"];
567
- [dict setValue:subtitle forKey:@"subtitle"];
568
- [dict setValue:message forKey:@"message"];
569
- [dict setValue:deliveredAt forKey:@"deliveredAt"];
570
- [lines addObject:dict];
571
- }
572
- }
573
-
574
- if (lines.count > 0) {
575
- NSData *json;
576
- NSError *error = nil;
577
- // Dictionary convertable to JSON ?
578
- if ([NSJSONSerialization isValidJSONObject:lines])
579
- {
580
- // Serialize the dictionary
581
- json = [NSJSONSerialization dataWithJSONObject:lines options:NSJSONWritingPrettyPrinted error:&error];
582
-
583
- // If no errors, let's view the JSON
584
- if (json != nil && error == nil)
585
- {
586
- NSString *jsonString = [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding];
587
- printf("%s", [jsonString cStringUsingEncoding:NSUTF8StringEncoding]);
588
- }
589
- }
590
-
591
- }
592
- }
593
-
594
- @end