Permalink
Browse files

First pass at implementing the search API.

  • Loading branch information...
1 parent ff9733a commit d92366b01135ec2e359e27f5b109ac5ff8a0fe22 Craig Hockenberry committed Jan 20, 2009
View
@@ -21,6 +21,9 @@
NSString *_clientURL;
NSString *_clientSourceToken;
NSString *_APIDomain;
+#if YAJL_AVAILABLE
+ NSString *_searchDomain;
+#endif
BOOL _secureConnection;
BOOL _clearsCookies;
}
@@ -41,6 +44,10 @@
- (void)setClientName:(NSString *)name version:(NSString *)version URL:(NSString *)url token:(NSString *)token;
- (NSString *)APIDomain;
- (void)setAPIDomain:(NSString *)domain;
+#if YAJL_AVAILABLE
+- (NSString *)searchDomain;
+- (void)setSearchDomain:(NSString *)domain;
+#endif
- (BOOL)usesSecureConnection; // YES = uses HTTPS, default is YES
- (void)setUsesSecureConnection:(BOOL)flag;
- (BOOL)clearsCookies; // YES = deletes twitter.com cookies when setting username/password, default is NO (see README.txt)
@@ -117,4 +124,24 @@
- (NSString *)sendDirectMessage:(NSString *)message to:(NSString *)username;
- (NSString *)deleteDirectMessage:(int)updateID; // this user must be the RECIPIENT
+#if YAJL_AVAILABLE
+
+// Search
+- (NSString *)getSearchResultsForQuery:(NSString *)query;
+- (NSString *)getTrends;
+
+/*
+lang: restricts tweets to the given language, given by an ISO 639-1 code. Ex: http://search.twitter.com/search.atom?lang=en&q=devo
+
+rpp: the number of tweets to return per page, up to a max of 100. Ex: http://search.twitter.com/search.atom?lang=en&q=devo&rpp=15
+
+page: the page number (starting at 1) to return, up to a max of roughly 1500 results (based on rpp * page)
+
+since_id: returns tweets with status ids greater than the given id.
+
+geocode: returns tweets by users located within a given radius of the given latitude/longitude, where the user's location is taken from their Twitter profile. The parameter value is specified by "latitide,longitude,radius", where radius units must be specified as either "mi" (miles) or "km" (kilometers). Ex: http://search.twitter.com/search.atom?geocode=40.757929%2C-73.985506%2C25km. Note that you cannot use the near operator via the API to geocode arbitrary locations; however you can use this geocode parameter to search near geocodes directly.
+*/
+
+#endif
+
@end
View
@@ -20,6 +20,7 @@
#import "MGTwitterMessagesYAJLParser.h"
#import "MGTwitterUsersYAJLParser.h"
#import "MGTwitterMiscYAJLParser.h"
+ #import "MGTwitterSearchYAJLParser.h"
#else
#define API_FORMAT @"xml"
@@ -37,6 +38,9 @@
#endif
#define TWITTER_DOMAIN @"twitter.com"
+#if YAJL_AVAILABLE
+ #define TWITTER_SEARCH_DOMAIN @"search.twitter.com"
+#endif
#define HTTP_POST_METHOD @"POST"
#define MAX_MESSAGE_LENGTH 140 // Twitter recommends tweets of max 140 chars
#define MAX_LOCATION_LENGTH 31
@@ -98,6 +102,10 @@ - (MGTwitterEngine *)initWithDelegate:(NSObject *)newDelegate
_clientURL = [DEFAULT_CLIENT_URL retain];
_clientSourceToken = [DEFAULT_CLIENT_TOKEN retain];
_APIDomain = [TWITTER_DOMAIN retain];
+#if YAJL_AVAILABLE
+ _searchDomain = [TWITTER_SEARCH_DOMAIN retain];
+#endif
+
_secureConnection = YES;
_clearsCookies = NO;
}
@@ -120,6 +128,9 @@ - (void)dealloc
[_clientURL release];
[_clientSourceToken release];
[_APIDomain release];
+#if YAJL_AVAILABLE
+ [_searchDomain release];
+#endif
[super dealloc];
}
@@ -234,6 +245,27 @@ - (void)setAPIDomain:(NSString *)domain
}
+#if YAJL_AVAILABLE
+
+- (NSString *)searchDomain
+{
+ return [[_searchDomain retain] autorelease];
+}
+
+
+- (void)setSearchDomain:(NSString *)domain
+{
+ [_searchDomain release];
+ if (!domain || [domain length] == 0) {
+ _searchDomain = [TWITTER_SEARCH_DOMAIN retain];
+ } else {
+ _searchDomain = [domain retain];
+ }
+}
+
+#endif
+
+
- (BOOL)usesSecureConnection
{
return _secureConnection;
@@ -409,15 +441,35 @@ - (NSString *)_sendRequestWithMethod:(NSString *)method
fullPath = [self _queryStringWithBase:fullPath parameters:params prefixed:YES];
}
+ NSString *domain = nil;
+ NSString *connectionType = nil;
+ if (requestType == MGTwitterSearchRequest)
+ {
+ domain = _searchDomain;
+ connectionType = @"http";
+ }
+ else
+ {
+ domain = _APIDomain;
+ if (_secureConnection)
+ {
+ connectionType = @"https";
+ }
+ else
+ {
+ connectionType = @"http";
+ }
+ }
+
#if SET_AUTHORIZATION_IN_HEADER
NSString *urlString = [NSString stringWithFormat:@"%@://%@/%@",
- (_secureConnection) ? @"https" : @"http",
- _APIDomain, fullPath];
+ connectionType,
+ domain, fullPath];
#else
NSString *urlString = [NSString stringWithFormat:@"%@://%@:%@@%@/%@",
- (_secureConnection) ? @"https" : @"http",
+ connectionType,
[self _encodeString:_username], [self _encodeString:_password],
- _APIDomain, fullPath];
+ domain, fullPath];
#endif
NSURL *finalURL = [NSURL URLWithString:urlString];
@@ -526,7 +578,12 @@ - (void)_parseDataForConnection:(MGTwitterHTTPURLConnection *)connection
connectionIdentifier:identifier requestType:requestType
responseType:responseType URL:URL];
break;
- default:
+ case MGTwitterSearchResults:
+ [MGTwitterSearchYAJLParser parserWithJSON:jsonData delegate:self
+ connectionIdentifier:identifier requestType:requestType
+ responseType:responseType URL:URL];
+ break;
+ default:
break;
}
}
@@ -636,6 +693,12 @@ - (void)parsingSucceededForRequest:(NSString *)identifier
if ([self _isValidDelegateForSelector:@selector(miscInfoReceived:forRequest:)])
[_delegate miscInfoReceived:parsedObjects forRequest:identifier];
break;
+#if YAJL_AVAILABLE
+ case MGTwitterSearchResults:
+ if ([self _isValidDelegateForSelector:@selector(searchResultsReceived:forRequest:)])
+ [_delegate searchResultsReceived:parsedObjects forRequest:identifier];
+ break;
+#endif
default:
break;
}
@@ -1410,5 +1473,27 @@ - (NSString *)deleteDirectMessage:(int)updateID
responseType:MGTwitterGeneric];
}
+#if YAJL_AVAILABLE
+
+#pragma mark Search
+
+- (NSString *)getSearchResultsForQuery:(NSString *)query
+{
+ NSString *path = [NSString stringWithFormat:@"search.%@", API_FORMAT];
+
+ NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:1];
+ [params setObject:query forKey:@"q"];
+
+ return [self _sendRequestWithMethod:nil path:path queryParameters:params body:nil
+ requestType:MGTwitterSearchRequest
+ responseType:MGTwitterSearchResults];
+}
+
+- (NSString *)getTrends
+{
+ return nil;
+}
+
+#endif
@end
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 440E60680F257C1300EF8874 /* MGTwitterSearchYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 440E60660F257C1300EF8874 /* MGTwitterSearchYAJLParser.m */; };
44AE00810F214F26004F5AE3 /* libyajl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 44AE00800F214F26004F5AE3 /* libyajl.dylib */; };
44AEFFF10F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44AEFFE80F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.m */; };
44AEFFF20F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44AEFFEA0F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.m */; };
@@ -43,6 +44,8 @@
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
32CA4F630368D1EE00C91783 /* MGTwitterEngine_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterEngine_Prefix.pch; sourceTree = "<group>"; };
+ 440E60660F257C1300EF8874 /* MGTwitterSearchYAJLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterSearchYAJLParser.m; sourceTree = "<group>"; };
+ 440E60670F257C1300EF8874 /* MGTwitterSearchYAJLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterSearchYAJLParser.h; sourceTree = "<group>"; };
44AE00800F214F26004F5AE3 /* libyajl.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libyajl.dylib; path = "yajl/build/yajl-0.4.0/lib/libyajl.dylib"; sourceTree = "<group>"; };
44AEFFE70F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterMessagesYAJLParser.h; sourceTree = "<group>"; };
44AEFFE80F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterMessagesYAJLParser.m; sourceTree = "<group>"; };
@@ -202,6 +205,8 @@
44AEFFE80F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.m */,
44AEFFE90F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.h */,
44AEFFEA0F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.m */,
+ 440E60670F257C1300EF8874 /* MGTwitterSearchYAJLParser.h */,
+ 440E60660F257C1300EF8874 /* MGTwitterSearchYAJLParser.m */,
);
name = "Twitter YAJL Parsers";
sourceTree = "<group>";
@@ -355,6 +360,7 @@
44AEFFF30F2141AB004F5AE3 /* MGTwitterStatusesYAJLParser.m in Sources */,
44AEFFF40F2141AB004F5AE3 /* MGTwitterUsersYAJLParser.m in Sources */,
44AEFFF50F2141AB004F5AE3 /* MGTwitterYAJLParser.m in Sources */,
+ 440E60680F257C1300EF8874 /* MGTwitterSearchYAJLParser.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -17,6 +17,9 @@
- (void)directMessagesReceived:(NSArray *)messages forRequest:(NSString *)identifier;
- (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)identifier;
- (void)miscInfoReceived:(NSArray *)miscInfo forRequest:(NSString *)identifier;
+#if YAJL_AVAILABLE
+- (void)searchResultsReceived:(NSArray *)searchResults forRequest:(NSString *)identifier;
+#endif
#if TARGET_OS_IPHONE
- (void)imageReceived:(UIImage *)image forRequest:(NSString *)identifier;
View
@@ -17,6 +17,7 @@ typedef enum _MGTwitterRequestType {
MGTwitterStatusSend = 5, // sending a new status
MGTwitterDirectMessageSend = 6, // sending a new direct message
MGTwitterImageRequest = 7, // requesting an image
+ MGTwitterSearchRequest = 9, // a search request
} MGTwitterRequestType;
typedef enum _MGTwitterResponseType {
@@ -29,6 +30,7 @@ typedef enum _MGTwitterResponseType {
MGTwitterGeneric = 6, // a generic response not requiring parsing
MGTwitterMiscellaneous = 8, // a miscellaneous response of key-value pairs
MGTwitterImage = 7, // an image
+ MGTwitterSearchResults = 9, // search results
} MGTwitterResponseType;
// This key is added to each tweet or direct message returned,
@@ -0,0 +1,20 @@
+//
+// MGTwitterSearchYAJLParser.h
+// MGTwitterEngine
+//
+// Created by Matt Gemmell on 11/02/2008.
+// Copyright 2008 Instinctive Code.
+//
+
+#import "MGTwitterEngineGlobalHeader.h"
+
+#import "MGTwitterYAJLParser.h"
+
+@interface MGTwitterSearchYAJLParser : MGTwitterYAJLParser {
+
+ BOOL haveStartedArray;
+ NSMutableDictionary *_results;
+ NSMutableDictionary *_status;
+}
+
+@end
View
@@ -0,0 +1,102 @@
+//
+// MGTwitterSearchYAJLParser.m
+// MGTwitterEngine
+//
+// Created by Matt Gemmell on 11/02/2008.
+// Copyright 2008 Instinctive Code.
+//
+
+#import "MGTwitterSearchYAJLParser.h"
+
+#define DEBUG_PARSING 1
+
+@implementation MGTwitterSearchYAJLParser
+
+- (void)addValue:(id)value forKey:(NSString *)key
+{
+ if (_results)
+ {
+ [_results setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"search: results: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
+ }
+ else if (_status)
+ {
+ [_status setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"search: status: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
+ }
+}
+
+- (void)startDictionaryWithKey:(NSString *)key
+{
+#if DEBUG_PARSING
+ NSLog(@"search: dictionary start = %@", key);
+#endif
+
+ if (haveStartedArray)
+ {
+ if (! _results)
+ {
+ _results = [[NSMutableDictionary alloc] initWithCapacity:0];
+ }
+ }
+ else
+ {
+ if (! _status)
+ {
+ _status = [[NSMutableDictionary alloc] initWithCapacity:0];
+ }
+ }
+}
+
+- (void)endDictionary
+{
+ if (haveStartedArray)
+ {
+ if (_results)
+ {
+ [_results setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE];
+
+ [parsedObjects addObject:_results];
+ [_results release];
+ _results = nil;
+ }
+ }
+ else
+ {
+ if (_status)
+ {
+ [_status setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE];
+
+ [parsedObjects addObject:_status];
+ [_status release];
+ _status = nil;
+ }
+ }
+
+#if DEBUG_PARSING
+ NSLog(@"search: dictionary end");
+#endif
+}
+
+- (void)startArrayWithKey:(NSString *)key
+{
+#if DEBUG_PARSING
+ NSLog(@"search: array start = %@", key);
+#endif
+ haveStartedArray = YES;
+}
+
+- (void)endArray
+{
+#if DEBUG_PARSING
+ NSLog(@"search: array end");
+#endif
+ haveStartedArray = NO;
+}
+
+
+@end
Oops, something went wrong.

0 comments on commit d92366b

Please sign in to comment.