-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit afbc554
Showing
3 changed files
with
379 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// | ||
// GSTwitPicEngine.h | ||
// TwitPic Uploader | ||
// | ||
// Created by Gurpartap Singh on 19/06/10. | ||
// Copyright 2010 Gurpartap Singh. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
#import "OAToken.h" | ||
|
||
#import "ASIHTTPRequest.h" | ||
|
||
|
||
// Define these API credentials as per your applicationss. | ||
|
||
// Get here: http://twitter.com/apps | ||
#define TWITTER_OAUTH_CONSUMER_KEY kTwitterOAuthConsumerKey | ||
#define TWITTER_OAUTH_CONSUMER_SECRET kTwitterOAuthConsumerSecret | ||
|
||
// Get here: http://dev.twitpic.com/apps/ | ||
#define TWITPIC_API_KEY kTwitPicAPIKey | ||
|
||
// TwitPic API Version: http://dev.twitpic.com/docs/ | ||
#define TWITPIC_API_VERSION @"2" | ||
|
||
// Enable one of the JSON Parsing libraries that the project has. | ||
// Disable all to get raw string as response in delegate call to parse yourself. | ||
#define TWITPIC_USE_YAJL 1 | ||
#define TWITPIC_USE_SBJSON 0 | ||
#define TWITPIC_USE_TOUCHJSON 0 | ||
#define TWITPIC_API_FORMAT @"json" | ||
|
||
// Implement XML here if you wish to. | ||
// #define TWITPIC_USE_LIBXML 0 | ||
// #if TWITPIC_USE_LIBXML | ||
// #define TWITPIC_API_FORMAT @"xml" | ||
// #endif | ||
|
||
|
||
@protocol GSTwitPicEngineDelegate | ||
|
||
- (void)twitpicDidFinishUpload:(NSDictionary *)response; | ||
- (void)twitpicDidFailUpload:(NSDictionary *)error; | ||
|
||
@end | ||
|
||
@class ASINetworkQueue; | ||
|
||
@interface GSTwitPicEngine : NSObject <ASIHTTPRequestDelegate, UIWebViewDelegate> { | ||
__weak NSObject <GSTwitPicEngineDelegate> *_delegate; | ||
|
||
OAToken *_accessToken; | ||
|
||
ASINetworkQueue *_queue; | ||
} | ||
|
||
@property (retain) ASINetworkQueue *_queue; | ||
|
||
+ (GSTwitPicEngine *)twitpicEngineWithDelegate:(NSObject *)theDelegate; | ||
- (GSTwitPicEngine *)initWithDelegate:(NSObject *)theDelegate; | ||
|
||
- (void)uploadPicture:(UIImage *)picture; | ||
- (void)uploadPicture:(UIImage *)picture withMessage:(NSString *)message; | ||
|
||
@end | ||
|
||
|
||
@interface GSTwitPicEngine (OAuth) | ||
|
||
- (void)setAccessToken:(OAToken *)token; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
// | ||
// GSTwitPicEngine.m | ||
// TwitPic Uploader | ||
// | ||
// Created by Gurpartap Singh on 19/06/10. | ||
// Copyright 2010 Gurpartap Singh. All rights reserved. | ||
// | ||
|
||
#import "GSTwitPicEngine.h" | ||
|
||
#if TWITPIC_USE_YAJL | ||
#import "NSObject+YAJL.h" | ||
|
||
#elif TWITPIC_USE_SBJSON | ||
#import "JSON.h" | ||
|
||
#elif TWITPIC_USE_TOUCHJSON | ||
#import "CJSONDeserializer.h" | ||
|
||
// #elif TWITPIC_USE_LIBXML | ||
// #include <libxml/xmlreader.h> | ||
#endif | ||
|
||
#import "ASIFormDataRequest.h" | ||
#import "ASINetworkQueue.h" | ||
|
||
#import "OAConsumer.h" | ||
#import "OARequestHeader.h" | ||
|
||
@implementation GSTwitPicEngine | ||
|
||
@synthesize _queue; | ||
|
||
+ (GSTwitPicEngine *)twitpicEngineWithDelegate:(NSObject *)theDelegate { | ||
return [[[self alloc] initWithDelegate:theDelegate] autorelease]; | ||
} | ||
|
||
|
||
- (GSTwitPicEngine *)initWithDelegate:(NSObject *)delegate { | ||
if (self = [super init]) { | ||
_delegate = delegate; | ||
_queue = [[ASINetworkQueue alloc] init]; | ||
[_queue setMaxConcurrentOperationCount:1]; | ||
[_queue setShouldCancelAllRequestsOnFailure:NO]; | ||
[_queue setDelegate:self]; | ||
[_queue setRequestDidFinishSelector:@selector(requestFinished:)]; | ||
[_queue setRequestDidFailSelector:@selector(requestFailed:)]; | ||
// [_queue setQueueDidFinishSelector:@selector(queueFinished:)]; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
|
||
- (void)dealloc { | ||
_delegate = nil; | ||
[_queue release]; | ||
[super dealloc]; | ||
} | ||
|
||
|
||
#pragma mark - | ||
#pragma mark Instance methods | ||
|
||
- (BOOL)_isValidDelegateForSelector:(SEL)selector { | ||
return ((_delegate != nil) && [_delegate respondsToSelector:selector]); | ||
} | ||
|
||
|
||
- (void)uploadPicture:(UIImage *)picture { | ||
[self uploadPicture:picture withMessage:@""]; | ||
} | ||
|
||
|
||
- (void)uploadPicture:(UIImage *)picture withMessage:(NSString *)message { | ||
if ([TWITPIC_API_VERSION isEqualToString:@"1"]) { | ||
// TwitPic OAuth. | ||
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://api.twitpic.com/1/upload.%@", TWITPIC_API_FORMAT]]; | ||
|
||
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; | ||
|
||
[request addPostValue:TWITPIC_API_KEY forKey:@"key"]; | ||
[request addPostValue:TWITTER_OAUTH_CONSUMER_KEY forKey:@"consumer_token"]; | ||
[request addPostValue:TWITTER_OAUTH_CONSUMER_SECRET forKey:@"consumer_secret"]; | ||
[request addPostValue:[_accessToken key] forKey:@"oauth_token"]; | ||
[request addPostValue:[_accessToken secret] forKey:@"oauth_secret"]; | ||
[request addPostValue:message forKey:@"message"]; | ||
[request addData:UIImageJPEGRepresentation(picture, 0.8) forKey:@"media"]; | ||
|
||
request.requestMethod = @"POST"; | ||
|
||
[_queue addOperation:request]; | ||
[_queue go]; | ||
} | ||
else { | ||
// Twitter OAuth Echo. | ||
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://api.twitpic.com/2/upload.%@", TWITPIC_API_FORMAT]]; | ||
|
||
OAConsumer *consumer = [[[OAConsumer alloc] initWithKey:TWITTER_OAUTH_CONSUMER_KEY secret:TWITTER_OAUTH_CONSUMER_SECRET] autorelease]; | ||
|
||
// NSLog(@"consumer: %@", consumer); | ||
|
||
OARequestHeader *requestHeader = [[[OARequestHeader alloc] initWithProvider:@"https://api.twitter.com/1/account/verify_credentials.json" | ||
method:@"GET" | ||
consumer:consumer | ||
token:_accessToken | ||
realm:@"http://api.twitter.com/"] autorelease]; | ||
|
||
NSString *oauthHeaders = [requestHeader generateRequestHeaders]; | ||
|
||
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; | ||
[request setUserInfo:[NSDictionary dictionaryWithObject:message forKey:@"message"]]; | ||
|
||
[request addRequestHeader:@"X-Verify-Credentials-Authorization" value:oauthHeaders]; | ||
[request addRequestHeader:@"X-Auth-Service-Provider" value:@"https://api.twitter.com/1/account/verify_credentials.json"]; | ||
|
||
[request addPostValue:TWITPIC_API_KEY forKey:@"key"]; | ||
[request addPostValue:message forKey:@"message"]; | ||
[request addData:UIImageJPEGRepresentation(picture, 0.8) forKey:@"media"]; | ||
|
||
request.requestMethod = @"POST"; | ||
|
||
// NSLog(@"requestHeaders: %@", [request requestHeaders]); | ||
|
||
[_queue addOperation:request]; | ||
[_queue go]; | ||
} | ||
} | ||
|
||
|
||
#pragma mark - | ||
#pragma mark OAuth | ||
|
||
- (void)setAccessToken:(OAToken *)token { | ||
[_accessToken autorelease]; | ||
_accessToken = [token retain]; | ||
} | ||
|
||
|
||
#pragma mark - | ||
#pragma mark ASIHTTPRequestDelegate methods | ||
|
||
- (void)requestFinished:(ASIHTTPRequest *)request { | ||
// TODO: Pass values as individual parameters to delegate methods instead of wrapping in NSDictionary. | ||
NSMutableDictionary *delegateResponse = [[[NSMutableDictionary alloc] init] autorelease]; | ||
|
||
[delegateResponse setObject:request forKey:@"request"]; | ||
|
||
switch ([request responseStatusCode]) { | ||
case 200: | ||
{ | ||
// Success, but let's parse and see. | ||
// TODO: Error out if parse failed? | ||
// TODO: Need further checks for success. | ||
NSDictionary *response = [[NSDictionary alloc] init]; | ||
NSString *responseString = nil; | ||
responseString = [request responseString]; | ||
|
||
@try { | ||
#if TWITPIC_USE_YAJL | ||
response = [responseString yajl_JSON]; | ||
#elif TWITPIC_USE_SBJSON | ||
response = [responseString JSONValue]; | ||
#elif TWITPIC_USE_TOUCHJSON | ||
NSError *error = nil; | ||
response = [[CJSONDeserializer deserializer] deserialize:responseString error:&error]; | ||
if (error != nil) { | ||
@throw([NSException exceptionWithName:@"TOUCHJSONParsingException" reason:[error localizedFailureReason] userInfo:[error userInfo]]); | ||
} | ||
// TODO: Implemented XML Parsing. | ||
// #elif TWITPIC_USE_LIBXML | ||
#endif | ||
} | ||
@catch (NSException *e) { | ||
NSLog(@"Error while parsing TwitPic response. Does the project really have the parsing library specified? %@.", e); | ||
return; | ||
} | ||
|
||
[delegateResponse setObject:response forKey:@"parsedResponse"]; | ||
|
||
if ([self _isValidDelegateForSelector:@selector(twitpicDidFinishUpload:)]) { | ||
[_delegate twitpicDidFinishUpload:delegateResponse]; | ||
} | ||
|
||
break; | ||
} | ||
case 400: | ||
// Failed. | ||
[delegateResponse setObject:@"Bad request. Missing parameters." forKey:@"errorDescription"]; | ||
|
||
if ([self _isValidDelegateForSelector:@selector(twitpicDidFailUpload:)]) { | ||
[_delegate twitpicDidFailUpload:delegateResponse]; | ||
} | ||
|
||
break; | ||
default: | ||
[delegateResponse setObject:@"Request failed." forKey:@"errorDescription"]; | ||
|
||
if ([self _isValidDelegateForSelector:@selector(twitpicDidFailUpload:)]) { | ||
[_delegate twitpicDidFailUpload:delegateResponse]; | ||
} | ||
|
||
break; | ||
} | ||
} | ||
|
||
|
||
- (void)requestFailed:(ASIHTTPRequest *)request { | ||
NSMutableDictionary *delegateResponse = [[[NSMutableDictionary alloc] init] autorelease]; | ||
|
||
[delegateResponse setObject:request forKey:@"request"]; | ||
|
||
switch ([request responseStatusCode]) { | ||
case 401: | ||
// Twitter.com could be down or slow. Or your request took too long to reach twitter.com authentication verification via twitpic.com. | ||
// TODO: Attempt to try again? | ||
[delegateResponse setObject:@"Timed out verifying authentication token with Twitter.com. This could be a problem with TwitPic servers. Try again later." forKey:@"errorDescription"]; | ||
|
||
break; | ||
default: | ||
[delegateResponse setObject:@"Request failed." forKey:@"errorDescription"]; | ||
break; | ||
} | ||
|
||
if ([self _isValidDelegateForSelector:@selector(twitpicDidFailUpload:)]) { | ||
[_delegate twitpicDidFailUpload:delegateResponse]; | ||
} | ||
} | ||
|
||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
|
||
GSTwitPicEngine | ||
============= | ||
|
||
GSTwitPicEngine provides easy to implement wrapper around the TwitPic.com's OAuth (v1) and OAuth Echo (v2) API for iPhone application projects. | ||
|
||
Requirements | ||
------------ | ||
|
||
* **ASIHTTPRequest** - [http://allseeing-i.com/ASIHTTPRequest/] | ||
* **OAuthConsumer** - [http://github.com/jdg/oauthconsumer] | ||
* **OARequestHeader** - [http://github.com/Gurpartap/OARequestHeader] | ||
* One of these **JSON parsers**: | ||
- yajl & yajl-objc (enabled by default) - [http://github.com/gabriel/yajl-objc] | ||
- TouchJSON | ||
- SBJSON | ||
* MGTwitterEngine or anything of your choice that supplies the **OAToken instance** (from OAuthConsumer). | ||
|
||
Usage | ||
----- | ||
|
||
* Set kTwitterOAuthConsumerKey, kTwitterOAuthConsumerSecret and kTwitPicAPIKey constants to their respective values before GSTwitPicEngine.h is imported. | ||
* See GSTwitPicEngine.h to configure TwitPic API Format (XML or JSON) and to set which JSON Parser to use. | ||
* Add header file: | ||
|
||
#import "GSTwitPicEngine.h" | ||
* Setup retained (@synthesize) instance var/property in the header: | ||
|
||
GSTwitPicEngine *twitpicEngine; | ||
* Implement **GSTwitPicEngineDelegate** protocol for the class. | ||
* Initialize the engine with class or as needed: | ||
|
||
self.twitpicEngine = (GSTwitPicEngine *)[GSTwitPicEngine twitpicEngineWithDelegate:self]; | ||
* Find the authorization token and supply to twitpicEngine with: | ||
|
||
[twitpicEngine setAccessToken:token]; | ||
* Then to upload image and attach a text message along with it (does not post to twitter): | ||
|
||
[twitpicEngine uploadPicture:[UIImage imageNamed:@"mypic.png"] withMessage:@"Hello world!"]; // This message is supplied back in success delegate call in request's userInfo. | ||
* To upload image only: | ||
|
||
[twitpicEngine uploadPicture:uploadImageView.image]; | ||
* Upon end of request, one of the delegate methods is called with appropriate data and information. | ||
|
||
GSTwitPicEngineDelegate | ||
-------------------------------------- | ||
|
||
* GSTwitPicEngineDelegate protocol specifies two delegate methods: | ||
|
||
<pre>- (void)twitpicDidFinishUpload:(NSDictionary *)response { | ||
NSLog(@"TwitPic finished uploading: %@", response); | ||
|
||
// [response objectForKey:@"parsedResponse"] gives an NSDictionary of the response one of the parsing libraries was available. | ||
// Otherwise, use [[response objectForKey:@"request"] objectForKey:@"responseString"] to parse yourself. | ||
|
||
if ([[[response objectForKey:@"request"] userInfo] objectForKey:@"message"] > 0 && [[response objectForKey:@"parsedResponse"] count] > 0) { | ||
// Uncomment to update status upon successful upload, using MGTwitterEngine's instance. | ||
// [twitterEngine sendUpdate:[NSString stringWithFormat:@"%@ %@", [[[response objectForKey:@"request"] userInfo] objectForKey:@"message"], [[response objectForKey:@"parsedResponse"] objectForKey:@"url"]]]; | ||
} | ||
}</pre> | ||
|
||
<pre>- (void)twitpicDidFailUpload:(NSDictionary *)error { | ||
NSLog(@"TwitPic failed to upload: %@", error); | ||
|
||
if ([[error objectForKey:@"request"] responseStatusCode] == 401) { | ||
// UIAlertViewQuick(@"Authentication failed", [error objectForKey:@"errorDescription"], @"OK"); | ||
} | ||
} | ||
</pre> | ||
|
||
[http://allseeing-i.com/ASIHTTPRequest/]: http://allseeing-i.com/ASIHTTPRequest/ | ||
[http://github.com/jdg/oauthconsumer]: http://github.com/jdg/oauthconsumer | ||
[http://github.com/Gurpartap/OARequestHeader]: http://github.com/Gurpartap/OARequestHeader | ||
[http://github.com/gabriel/yajl-objc]: http://github.com/gabriel/yajl-objc |