Skip to content

Commit

Permalink
Upload image for Pushover also
Browse files Browse the repository at this point in the history
  • Loading branch information
vkedwardli committed Aug 7, 2022
1 parent de4dd1a commit 956f12b
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 40 deletions.
14 changes: 13 additions & 1 deletion Preferences/NSPCustomizeAppsController.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ - (void)setAppDefaults:(NSString *)appID {
XEq(_service, PUSHER_SERVICE_PUSHER_RECEIVER)) {
defaultDict[@"includeIcon"] = _defaultIncludeIcon;
}
if (_isCustomService || XEq(_service, PUSHER_SERVICE_PUSHER_RECEIVER)) {
if (_isCustomService || XEq(_service, PUSHER_SERVICE_PUSHER_RECEIVER) || XEq(_service, PUSHER_SERVICE_PUSHOVER)) {
defaultDict[@"includeImage"] = _defaultIncludeImage;
defaultDict[@"imageMaxWidth"] = _defaultImageMaxWidth;
defaultDict[@"imageMaxHeight"] = _defaultImageMaxHeight;
Expand Down Expand Up @@ -163,6 +163,18 @@ - (void)viewWillAppear:(BOOL)animated {
_defaultSounds =
[(prefs[[self.specifier propertyForKey:@"defaultSoundsKey"]]
?: @[]) copy];
_defaultIncludeImage =
[(prefs[[self.specifier propertyForKey:@"defaultIncludeImageKey"]]
?: @YES) copy];
_defaultImageMaxWidth =
[(prefs[[self.specifier propertyForKey:@"defaultImageMaxWidthKey"]]
?: @(PUSHER_DEFAULT_MAX_WIDTH)) copy];
_defaultImageMaxHeight =
[(prefs[[self.specifier propertyForKey:@"defaultImageMaxHeightKey"]]
?: @(PUSHER_DEFAULT_MAX_HEIGHT)) copy];
_defaultImageShrinkFactor =
[(prefs[[self.specifier propertyForKey:@"defaultImageShrinkFactorKey"]]
?: @(PUSHER_DEFAULT_SHRINK_FACTOR)) copy];
}
if (XEq(_service, PUSHER_SERVICE_IFTTT)) {
_defaultEventName =
Expand Down
83 changes: 82 additions & 1 deletion Preferences/NSPSharedSpecifiers.m
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,94 @@ + (NSArray *)pushover:(NSString *)appID {

[devices setProperty:@(isCustomApp) forKey:@"isCustomApp"];
[sounds setProperty:@(isCustomApp) forKey:@"isCustomApp"];

PSSpecifier *includeImage = [PSSpecifier
preferenceSpecifierNamed:@"Include Image"
target:self
set:@selector(setPreferenceValue:
forBuiltInServiceSpecifier:)
get:@selector(readBuiltInServicePreferenceValue:)
detail:nil
cell:PSSwitchCell
edit:nil];
[includeImage setProperty:NSPPreferencePushoverIncludeImageKey
forKey:@"key"];
[includeImage setProperty:@YES forKey:@"enabled"];
[includeImage setProperty:@YES forKey:@"default"];
[includeImage setProperty:@(isCustomApp) forKey:@"isCustomApp"];
[includeImage setProperty:NSPPreferencePushoverCustomAppsKey
forKey:@"customAppsKey"];
[includeImage setProperty:@"includeImage" forKey:@"customAppsPrefsKey"];

PSSpecifier *imageMaxWidth = [PSSpecifier
preferenceSpecifierNamed:@"Maximum Image Width (pixels)"
target:self
set:@selector(setPreferenceValue:
forBuiltInServiceSpecifier:)
get:@selector(readBuiltInServicePreferenceValue:)
detail:nil
cell:PSEditTextCell
edit:nil];
[imageMaxWidth setProperty:NSPPreferencePushoverImageMaxWidthKey
forKey:@"key"];
[imageMaxWidth setProperty:@YES forKey:@"enabled"];
[imageMaxWidth setProperty:@YES forKey:@"isDecimalPad"];
[imageMaxWidth setProperty:@(PUSHER_DEFAULT_MAX_WIDTH) forKey:@"default"];
[imageMaxWidth setProperty:@(isCustomApp) forKey:@"isCustomApp"];
[imageMaxWidth setProperty:NSPPreferencePushoverCustomAppsKey
forKey:@"customAppsKey"];
[imageMaxWidth setProperty:@"imageMaxWidth" forKey:@"customAppsPrefsKey"];

PSSpecifier *imageMaxHeight = [PSSpecifier
preferenceSpecifierNamed:@"Maximum Image Height (pixels)"
target:self
set:@selector(setPreferenceValue:
forBuiltInServiceSpecifier:)
get:@selector(readBuiltInServicePreferenceValue:)
detail:nil
cell:PSEditTextCell
edit:nil];
[imageMaxHeight setProperty:NSPPreferencePushoverImageMaxHeightKey
forKey:@"key"];
[imageMaxHeight setProperty:@YES forKey:@"enabled"];
[imageMaxHeight setProperty:@YES forKey:@"isDecimalPad"];
[imageMaxHeight setProperty:@(PUSHER_DEFAULT_MAX_HEIGHT) forKey:@"default"];
[imageMaxHeight setProperty:@(isCustomApp) forKey:@"isCustomApp"];
[imageMaxHeight setProperty:NSPPreferencePushoverCustomAppsKey
forKey:@"customAppsKey"];
[imageMaxHeight setProperty:@"imageMaxHeight" forKey:@"customAppsPrefsKey"];

PSSpecifier *imageShrinkFactor = [PSSpecifier
preferenceSpecifierNamed:@"Image Shrink Factor Upon Retry"
target:self
set:@selector(setPreferenceValue:
forBuiltInServiceSpecifier:)
get:@selector(readBuiltInServicePreferenceValue:)
detail:nil
cell:PSEditTextCell
edit:nil];
[imageShrinkFactor setProperty:NSPPreferencePushoverImageShrinkFactorKey
forKey:@"key"];
[imageShrinkFactor setProperty:@YES forKey:@"enabled"];
[imageShrinkFactor setProperty:@YES forKey:@"isDecimalPad"];
[imageShrinkFactor setProperty:@(PUSHER_DEFAULT_SHRINK_FACTOR)
forKey:@"default"];
[imageShrinkFactor setProperty:@(isCustomApp) forKey:@"isCustomApp"];
[imageShrinkFactor setProperty:NSPPreferencePushoverCustomAppsKey
forKey:@"customAppsKey"];
[imageShrinkFactor setProperty:@"imageShrinkFactor"
forKey:@"customAppsPrefsKey"];

if (isCustomApp) {
[devices setProperty:appID forKey:@"customAppIDKey"];
[sounds setProperty:appID forKey:@"customAppIDKey"];
[includeImage setProperty:appID forKey:@"customAppID"];
[imageMaxWidth setProperty:appID forKey:@"customAppID"];
[imageMaxHeight setProperty:appID forKey:@"customAppID"];
[imageShrinkFactor setProperty:appID forKey:@"customAppID"];
}

return @[ devices, sounds ];
return @[ devices, sounds, includeImage, imageMaxWidth, imageMaxHeight, imageShrinkFactor ];
}

+ (NSArray *)pushbullet:(NSString *)appID {
Expand Down
162 changes: 124 additions & 38 deletions Tweak.xm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@
format:(int)format;
@end

@interface UIImage (Alpha)
- (BOOL)hasAlpha;
@end

@implementation UIImage (Alpha)
// Returns true if the image has an alpha layer
- (BOOL)hasAlpha {
CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage);
return (alpha == kCGImageAlphaFirst ||
alpha == kCGImageAlphaLast ||
alpha == kCGImageAlphaPremultipliedFirst ||
alpha == kCGImageAlphaPremultipliedLast);
}
@end

static BOOL pusherEnabled = NO;
static int pusherWhenToPush = PUSHER_WHEN_TO_PUSH_EITHER;
static NSArray *pusherSNS = nil;
Expand Down Expand Up @@ -75,6 +90,9 @@ static NSString *stringForObject(id object, NSString *prefix,
stringForObject(dict[key], XStr(@"%@\t", prefix), dontTruncate));
}
str = XStr(@"%@\n%@}", str, prefix);
} else if ([object isKindOfClass:NSData.class]) {
NSData *data = (NSData *) object;
str = XStr(@"%@%@", prefix, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
} else {
if (!dontTruncate && [object isKindOfClass:NSString.class] &&
((NSString *)object).length > PUSHER_LOG_MAX_STRING_LENGTH) {
Expand Down Expand Up @@ -307,7 +325,7 @@ static NSString *base64RepresentationForImage(UIImage *image) {
static UIImage *shrinkImage(UIImage *image, CGFloat factor) {
CGSize newSize =
CGSizeMake(image.size.width / factor, image.size.height / factor);
UIGraphicsBeginImageContext(newSize);
UIGraphicsBeginImageContextWithOptions(newSize, !image.hasAlpha, 1.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Expand Down Expand Up @@ -508,6 +526,20 @@ static void pusherPrefsChanged() {
NSString *curateDataKey = XStr(@"%@CurateData", service);
servicePrefs[@"curateData"] = prefs[curateDataKey] ?: @YES;
}

if (XEq(service, PUSHER_SERVICE_PUSHOVER)) {
NSString *includeImageKey = XStr(@"%@IncludeImage", service);
servicePrefs[@"includeImage"] = prefs[includeImageKey] ?: @YES;

NSString *imageMaxWidthKey = XStr(@"%@ImageMaxWidth", service);
servicePrefs[@"imageMaxWidth"] = prefs[imageMaxWidthKey] ?: @(PUSHER_DEFAULT_MAX_WIDTH);

NSString *imageMaxHeightKey = XStr(@"%@ImageMaxHeight", service);
servicePrefs[@"imageMaxHeight"] = prefs[imageMaxHeightKey] ?: @(PUSHER_DEFAULT_MAX_HEIGHT);

NSString *imageShrinkFactorKey = XStr(@"%@ImageShrinkFactor", service);
servicePrefs[@"imageShrinkFactor"] = prefs[imageShrinkFactorKey] ?: @(PUSHER_DEFAULT_SHRINK_FACTOR);
}

if (XEq(service, PUSHER_SERVICE_PUSHER_RECEIVER)) {
NSString *includeIconKey = XStr(@"%@IncludeIcon", service);
Expand Down Expand Up @@ -1037,19 +1069,7 @@ static NSString *prefsSayNo(BBServer *server, BBBulletin *bulletin) {
for (NSDictionary *device in dictionary[@"devices"]) {
[deviceIDs addObject:device[@"id"]];
}
if (XEq(service, PUSHER_SERVICE_PUSHOVER)) {
NSString *combinedDevices = [deviceIDs componentsJoinedByString:@","];
NSMutableDictionary *pushoverInfoDict = [@{
@"title" : dictionary[@"title"],
@"message" : dictionary[@"message"],
@"device" : combinedDevices
} mutableCopy];
NSString *firstSoundID = [dictionary[@"sounds"] firstObject];
if (firstSoundID) {
pushoverInfoDict[@"sound"] = firstSoundID;
}
return pushoverInfoDict;
} else if (XEq(service, PUSHER_SERVICE_PUSHBULLET)) {
if (XEq(service, PUSHER_SERVICE_PUSHBULLET)) {
// should always only be one, but just in case
NSString *firstDevice = [deviceIDs firstObject];
NSMutableDictionary *pushbulletInfoDict = [@{
Expand Down Expand Up @@ -1133,8 +1153,16 @@ static NSString *prefsSayNo(BBServer *server, BBBulletin *bulletin) {
}
}
}

if (XEq(service, PUSHER_SERVICE_IFTTT)) {
if (XEq(service, PUSHER_SERVICE_PUSHOVER)) {
NSString *combinedDevices = [deviceIDs componentsJoinedByString:@","];
data[@"device"] = combinedDevices;
data[@"title"] = dictionary[@"title"];
NSString *firstSoundID = [dictionary[@"sounds"] firstObject];
if (firstSoundID) {
data[@"sound"] = firstSoundID;
}
return data;
} else if (XEq(service, PUSHER_SERVICE_IFTTT)) {
if (dictionary[@"curateData"] &&
((NSNumber *)dictionary[@"curateData"]).boolValue) {
return @{
Expand Down Expand Up @@ -1224,10 +1252,12 @@ static NSString *prefsSayNo(BBServer *server, BBBulletin *bulletin) {
}

//! XEq(service, PUSHER_SERVICE_PUSHER_RECEIVER) &&
if (infoDictForRequest[@"image"] &&
[infoDictForRequest[@"image"] isKindOfClass:UIImage.class]) {
infoDictForRequest[@"image"] =
base64RepresentationForImage(infoDictForRequest[@"image"]);
if (!XEq(service, PUSHER_SERVICE_PUSHOVER)) {
if (infoDictForRequest[@"image"] &&
[infoDictForRequest[@"image"] isKindOfClass:UIImage.class]) {
infoDictForRequest[@"image"] =
base64RepresentationForImage(infoDictForRequest[@"image"]);
}
}

if (XEq(method, @"GET")) {
Expand Down Expand Up @@ -1282,26 +1312,82 @@ static NSString *prefsSayNo(BBServer *server, BBBulletin *bulletin) {
}

if (XEq(method, @"POST")) {
// replace image strings with shorter string
NSMutableDictionary *infoDictForLog = [infoDictForRequest mutableCopy];
for (NSString *prop in PUSHER_LOG_IMAGE_DATA_PROPERTIES) {
if (infoDictForLog[prop]) {
infoDictForLog[prop] = PUSHER_LOG_IMAGE_DATA_REPLACEMENT;
if (XEq(service, PUSHER_SERVICE_PUSHOVER)) {
NSString *boundary = @"---BoundaryPUSHOVER";
NSString *contentType = XStr(@"multipart/form-data; boundary=%@",boundary);
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
NSMutableData *body = [NSMutableData data];

NSDictionary *stringOnlyInfoDictForRequest = [infoDictForRequest dictionaryWithValuesForKeys:@[@"user", @"token", @"message", @"title", @"device"]];
[stringOnlyInfoDictForRequest enumerateKeysAndObjectsUsingBlock: ^(NSString *key, NSString *object, BOOL *stop) {
[body appendData:[XStr(@"--%@\r\n",boundary) dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[XStr(@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key) dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[XStr(@"%@\r\n",object) dataUsingEncoding:NSUTF8StringEncoding]];
}];
NSMutableData *bodyForLog = [body mutableCopy];

if (infoDictForRequest[@"image"] && [infoDictForRequest[@"image"] isKindOfClass:UIImage.class]) {

UIImage* image = (UIImage*)infoDictForRequest[@"image"];

for( NSData* data in @[
[XStr(@"--%@\r\n",boundary) dataUsingEncoding:NSUTF8StringEncoding],
[XStr(@"Content-Disposition: form-data; name=\"attachment\"; filename=\"file.%@\"\r\n", image.hasAlpha ? @"png" : @"jpg") dataUsingEncoding:NSUTF8StringEncoding],
[XStr(@"Content-Type: image/%@\r\n\r\n", image.hasAlpha ? @"png" : @"jpeg") dataUsingEncoding:NSUTF8StringEncoding]
] ){
[body appendData:data];
[bodyForLog appendData:data];
}


if ( image.hasAlpha ) {
[body appendData:UIImagePNGRepresentation(image)];
}else{
[body appendData:UIImageJPEGRepresentation(image, 1.0)];
}
[bodyForLog appendData:[PUSHER_LOG_IMAGE_DATA_REPLACEMENT dataUsingEncoding:NSUTF8StringEncoding]];


for( NSData* data in @[
[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
] ){
[body appendData:data];
[bodyForLog appendData:data];
}
}

for( NSData* data in @[
[XStr(@"--%@--\r\n", boundary) dataUsingEncoding:NSUTF8StringEncoding]
] ){
[body appendData:data];
[bodyForLog appendData:data];
}

[request setHTTPBody:body];
addToLogIfEnabled(service, bulletin, @"Request Body", bodyForLog);

} else {
// replace image strings with shorter string
NSMutableDictionary *infoDictForLog = [infoDictForRequest mutableCopy];
for (NSString *prop in PUSHER_LOG_IMAGE_DATA_PROPERTIES) {
if (infoDictForLog[prop]) {
infoDictForLog[prop] = PUSHER_LOG_IMAGE_DATA_REPLACEMENT;
}
}
addToLogIfEnabled(service, bulletin, @"Request Body Dictionary",
infoDictForLog);

[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

NSData *requestData =
[NSJSONSerialization dataWithJSONObject:infoDictForRequest
options:NSJSONWritingPrettyPrinted
error:nil];
[request setValue:XStr(@"%d", (int)requestData.length)
forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:requestData];
}
addToLogIfEnabled(service, bulletin, @"Request Body Dictionary",
infoDictForLog);

[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

NSData *requestData =
[NSJSONSerialization dataWithJSONObject:infoDictForRequest
options:NSJSONWritingPrettyPrinted
error:nil];
[request setValue:XStr(@"%d", (int)requestData.length)
forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:requestData];
}

// use async way to connect network
Expand Down
4 changes: 4 additions & 0 deletions global.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ typedef enum {
#define NSPPreferencePushoverSoundsKey @"PushoverSounds"
#define NSPPreferencePushoverBLPrefix @"PushoverBL-"
#define NSPPreferencePushoverCustomAppsKey @"PushoverCustomApps"
#define NSPPreferencePushoverIncludeImageKey @"PushoverIncludeImage"
#define NSPPreferencePushoverImageMaxWidthKey @"PushoverImageMaxWidth"
#define NSPPreferencePushoverImageMaxHeightKey @"PushoverImageMaxHeight"
#define NSPPreferencePushoverImageShrinkFactorKey @"PushoverImageShrinkFactor"

// All keys MUST HAVE the prefix equal to the name of the service
#define PUSHER_SERVICE_PUSHBULLET @"Pushbullet"
Expand Down

0 comments on commit 956f12b

Please sign in to comment.