Skip to content

Commit

Permalink
Migrate Rhea to Bitly's v4 API per https://dev.bitly.com/v4_documenta…
Browse files Browse the repository at this point in the history
…tion.html#section/Migrating-from-V3.

v3 API is being deprecated 3/1/20.
  • Loading branch information
timonus committed Feb 29, 2020
1 parent 67f699b commit 8786ff9
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 22 deletions.
20 changes: 15 additions & 5 deletions Rhea/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppl
clientIdentifier:[[self class] _bitlyClientIdentifier]
clientSecret:[[self class] _bitlyClientSecret]
redirectURL:[NSURL URLWithString:kRHEABitlyRedirectURLString]
completion:^(NSString * _Nullable accessToken) {
completion:^(NSString *accessToken, NSString *groupIdentifier) {
NSString *message = nil;
if (accessToken) {
if (accessToken && groupIdentifier) {
message = @"Logged in to Bitly!";
[SAMKeychain setPassword:accessToken forService:kRHEABitlyAccountKey account:kRHEABitlyAccountKey];
[SAMKeychain setPassword:[NSString stringWithFormat:@"%@ %@", groupIdentifier, accessToken] forService:kRHEABitlyAccountKey account:kRHEABitlyAccountKey];
} else {
message = @"Unable to log into Bitly";
}
Expand Down Expand Up @@ -607,9 +607,19 @@ - (void)shortenURL:(NSURL *const)url
[alert runModal];
}
};
if ([SAMKeychain passwordForService:kRHEABitlyAccountKey account:kRHEABitlyAccountKey] != nil) {
[RHEABitlyClient shortenURL:url accessToken:[SAMKeychain passwordForService:kRHEABitlyAccountKey account:kRHEABitlyAccountKey] completion:completion];
NSString *const credentials = [SAMKeychain passwordForService:kRHEABitlyAccountKey account:kRHEABitlyAccountKey];
NSArray<NSString *> *const components = [credentials componentsSeparatedByString:@" "];
if (components.count == 2) {
NSString *const groupIdentifier = components.firstObject;
NSString *const accessToken = components.lastObject;
[RHEABitlyClient shortenURL:url
groupIdentifier:groupIdentifier
accessToken:accessToken
completion:completion];
} else {
if (credentials) {
[SAMKeychain deletePasswordForService:kRHEABitlyAccountKey account:kRHEABitlyAccountKey];
}
NSAlert *const alert = [[NSAlert alloc] init];
alert.messageText = @"Bitly account needed";
alert.informativeText = @"You must log in to a Bitly account to shorten links.";
Expand Down
7 changes: 5 additions & 2 deletions Rhea/RHEABitlyClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ NS_ASSUME_NONNULL_BEGIN
clientIdentifier:(NSString *const)clientIdentifier
clientSecret:(NSString *const)clientSecret
redirectURL:(NSURL *const)redirectURL
completion:(void (^)(NSString *_Nullable accessToken))completion;
completion:(void (^)(NSString *_Nullable accessToken, NSString *_Nullable groupIdentifier))completion;

// Shortening
+ (void)shortenURL:(NSURL *const)url accessToken:(NSString *const)accessToken completion:(void (^)(NSURL *_Nullable shortenedURL))completion;
+ (void)shortenURL:(NSURL *const)url
groupIdentifier:(NSString *const)groupIdentifier
accessToken:(NSString *const)accessToken
completion:(void (^)(NSURL *_Nullable shortenedURL))completion;

@end

Expand Down
58 changes: 43 additions & 15 deletions Rhea/RHEABitlyClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ + (void)authenticateWithCode:(NSString *const)code
clientIdentifier:(NSString *const)clientIdentifier
clientSecret:(NSString *const)clientSecret
redirectURL:(NSURL *const)redirectURL
completion:(void (^)(NSString *accessToken))completion
completion:(void (^)(NSString *accessToken, NSString *groupIdentifier))completion
{
NSMutableURLRequest *const request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api-ssl.bitly.com/oauth/access_token"]];
request.HTTPMethod = @"POST";
Expand All @@ -63,29 +63,57 @@ + (void)authenticateWithCode:(NSString *const)code
}
}
}
dispatch_async(dispatch_get_main_queue(), ^{
completion(accessToken);
});
if (accessToken) {

// TODO: Make Rhea Bitly group-aware.
// Right now we implicitly always select the first group.

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api-ssl.bitly.com/v4/groups"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0];
[request setValue:[NSString stringWithFormat:@"Bearer %@", accessToken] forHTTPHeaderField:@"Authorization"];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *groupIdentifier = nil;
if (data.length > 0) {
id resultObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if ([resultObject isKindOfClass:[NSDictionary class]] && [resultObject[@"groups"] isKindOfClass:[NSArray class]] && [resultObject[@"groups"] count] > 0) {
groupIdentifier = [[resultObject[@"groups"] firstObject] objectForKey:@"guid"];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
completion(accessToken, groupIdentifier);
});
}] resume];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil, nil);
});
}
}] resume];
}

+ (void)shortenURL:(NSURL *const)url accessToken:(NSString *const)accessToken completion:(void (^)(NSURL *_Nullable shortenedURL))completion
+ (void)shortenURL:(NSURL *const)url
groupIdentifier:(NSString *const)groupIdentifier
accessToken:(NSString *const)accessToken
completion:(void (^)(NSURL *_Nullable shortenedURL))completion
{
NSURLComponents *const components = [[NSURLComponents alloc] initWithString:@"https://api-ssl.bitly.com/v3/shorten"];
components.queryItems = @[
[NSURLQueryItem queryItemWithName:@"access_token" value:accessToken],
[NSURLQueryItem queryItemWithName:@"longUrl" value:url.absoluteString]
];
[[[NSURLSession sharedSession] dataTaskWithURL:components.URL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *urlString = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api-ssl.bitly.com/v4/shorten"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0];
[request setValue:[NSString stringWithFormat:@"Bearer %@", accessToken] forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:[NSJSONSerialization dataWithJSONObject:@{
@"group_guid": groupIdentifier,
@"long_url": url.absoluteString
} options:0 error:nil]];
[request setHTTPMethod:@"POST"];

[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSURL *result = nil;
if (data.length > 0) {
id resultObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if ([resultObject isKindOfClass:[NSDictionary class]] && [resultObject[@"data"] isKindOfClass:[NSDictionary class]]) {
urlString = [resultObject[@"data"][@"url"] stringByReplacingOccurrencesOfString:@"http://" withString:@"https://"];
if ([resultObject isKindOfClass:[NSDictionary class]] && [resultObject[@"link"] isKindOfClass:[NSString class]]) {
result = [NSURL URLWithString:[resultObject[@"link"] stringByReplacingOccurrencesOfString:@"http://" withString:@"https://"]];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
completion([NSURL URLWithString:urlString]);
completion(result);
});
}] resume];
}
Expand Down

0 comments on commit 8786ff9

Please sign in to comment.