Skip to content
Browse files

[FEATURE] Growl rate limiting.

  • Loading branch information...
1 parent aeb4e0c commit 210dd16354f105434ef394bb452126b586c90511 @nullobject nullobject committed
Showing with 69 additions and 30 deletions.
  1. +8 −1 GrowlNotifier.h
  2. +61 −29 GrowlNotifier.m
View
9 GrowlNotifier.h
@@ -10,10 +10,17 @@
#import <Growl/Growl.h>
#import "Notifier.h"
+#define GROWL_FRAMEWORK_FILE_NAME @"Growl.framework"
#define NOISE_NOTIFICATION @"Noise Notification"
-@interface GrowlNotifier : Notifier <GrowlApplicationBridgeDelegate> {
+// Growl rate limiting.
+#define GROWLS_PER_PERIOD 5
+#define PERIOD 5 // seconds
+@interface GrowlNotifier : Notifier <GrowlApplicationBridgeDelegate> {
+@private
+ double growlAllowance;
+ NSDate *lastGrowl;
}
@end
View
90 GrowlNotifier.m
@@ -9,43 +9,41 @@
#import "GrowlNotifier.h"
#import "Message.h"
-#define GROWL_FRAMEWORK_FILE_NAME @"Growl.framework"
+
+@interface GrowlNotifier (Private)
+
+- (void)initGrowl;
+- (void)growlMessage:(Message *)message;
+
+@end
+
@implementation GrowlNotifier
- (id)init {
if (self = [super init]) {
- NSString *privateFrameworksPath = [[NSBundle bundleForClass:[GrowlNotifier class]] privateFrameworksPath];
- NSString *growlBundlePath = [privateFrameworksPath stringByAppendingPathComponent:GROWL_FRAMEWORK_FILE_NAME];
- NSBundle *growlBundle = [NSBundle bundleWithPath:growlBundlePath];
-
- if (growlBundle) {
- if ([growlBundle load]) {
- if ([GrowlApplicationBridge respondsToSelector:@selector(frameworkInfoDictionary)]) {
- [GrowlApplicationBridge setGrowlDelegate:self];
-
- NSDictionary *infoDictionary = [GrowlApplicationBridge frameworkInfoDictionary];
- NSLog(@"Using %@ %@", GROWL_FRAMEWORK_FILE_NAME, [infoDictionary objectForKey:(NSString *)kCFBundleVersionKey]);
- } else {
- NSLog(@"Using a version of %@ older than 1.1", GROWL_FRAMEWORK_FILE_NAME);
- }
- }
- } else {
- NSLog(@"Could not load %@, GrowlNotifier disabled", GROWL_FRAMEWORK_FILE_NAME);
- }
+ growlAllowance = GROWLS_PER_PERIOD;
+ [self initGrowl];
}
-
return self;
}
- (void)notify:(Message *)message {
- [GrowlApplicationBridge notifyWithTitle:message.title
- description:message.content
- notificationName:@"Noise Notification"
- iconData:nil
- priority:message.priority
- isSticky:message.sticky
- clickContext:nil];
+ double timeSinceLastNotify = [lastGrowl timeIntervalSinceNow];
+ growlAllowance += timeSinceLastNotify * (GROWLS_PER_PERIOD / PERIOD);
+ lastGrowl = [NSDate date];
+
+ if (growlAllowance > GROWLS_PER_PERIOD) {
+ growlAllowance = GROWLS_PER_PERIOD; // throttle
+ }
+
+ if (growlAllowance <= 0) {
+ NSLog(@"Rate limit exceeded, discarding message");
+ } else {
+ [self growlMessage:message];
+ }
+
+ growlAllowance -= 1.0;
}
#pragma mark -
@@ -62,13 +60,47 @@ - (NSImage *)applicationIconForGrowl {
- (NSDictionary *)registrationDictionaryForGrowl {
NSArray *allowedNotifications = [NSArray arrayWithObject:NOISE_NOTIFICATION];
NSArray *defaultNotifications = [NSArray arrayWithObject:NOISE_NOTIFICATION];
-
+
NSDictionary *ticket = [NSDictionary dictionaryWithObjectsAndKeys:
allowedNotifications, GROWL_NOTIFICATIONS_ALL,
defaultNotifications, GROWL_NOTIFICATIONS_DEFAULT,
nil];
-
+
return ticket;
}
+#pragma mark -
+#pragma mark Private methods
+
+- (void)initGrowl {
+ NSString *privateFrameworksPath = [[NSBundle bundleForClass:[GrowlNotifier class]] privateFrameworksPath];
+ NSString *growlBundlePath = [privateFrameworksPath stringByAppendingPathComponent:GROWL_FRAMEWORK_FILE_NAME];
+ NSBundle *growlBundle = [NSBundle bundleWithPath:growlBundlePath];
+
+ if (growlBundle) {
+ if ([growlBundle load]) {
+ if ([GrowlApplicationBridge respondsToSelector:@selector(frameworkInfoDictionary)]) {
+ [GrowlApplicationBridge setGrowlDelegate:self];
+
+ NSDictionary *infoDictionary = [GrowlApplicationBridge frameworkInfoDictionary];
+ NSLog(@"Using %@ %@", GROWL_FRAMEWORK_FILE_NAME, [infoDictionary objectForKey:(NSString *)kCFBundleVersionKey]);
+ } else {
+ NSLog(@"Using a version of %@ older than 1.1", GROWL_FRAMEWORK_FILE_NAME);
+ }
+ }
+ } else {
+ NSLog(@"Could not load %@, GrowlNotifier disabled", GROWL_FRAMEWORK_FILE_NAME);
+ }
+}
+
+- (void)growlMessage:(Message *)message {
+ [GrowlApplicationBridge notifyWithTitle:message.title
+ description:message.content
+ notificationName:@"Noise Notification"
+ iconData:nil
+ priority:message.priority
+ isSticky:message.sticky
+ clickContext:nil];
+}
+
@end

0 comments on commit 210dd16

Please sign in to comment.
Something went wrong with that request. Please try again.