adium 2389:9b5721fa5865: Using an unpublished (but provided by p...

commits at adium.im commits at adium.im
Fri May 29 03:57:49 UTC 2009


details:	http://hg.adium.im/adium/rev/9b5721fa5865
revision:	2389:9b5721fa5865
author:		Zachary West <zacw at adium.im>
date:		Thu May 28 23:57:35 2009 -0400

Using an unpublished (but provided by pic.im) API, provide the pic.im server with information about tweets we send.

The AIChat for the timeline (or whatever future chat gets implemented for "groups"/search) stores the pic.im's reference string. When the send goes out, if the tweet contains the image address, its meta data is posted to the pic.im server.

This has no error checking: it either succeeds or fails. Some future error checking might be needed, but I'm not sure what we could do besides retry the same request, which might very well fail again too.

diffs (239 lines):

diff -r b454802ac946 -r 9b5721fa5865 Adium.xcodeproj/project.pbxproj
--- a/Adium.xcodeproj/project.pbxproj	Thu May 28 20:55:15 2009 -0400
+++ b/Adium.xcodeproj/project.pbxproj	Thu May 28 23:57:35 2009 -0400
@@ -143,6 +143,7 @@
 		11879DF80F6FFC0B00CACFB1 /* OAuthConsumer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 11879DF70F6FFC0B00CACFB1 /* OAuthConsumer.framework */; };
 		11879E0A0F6FFC1000CACFB1 /* OAuthConsumer.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 11879DF70F6FFC0B00CACFB1 /* OAuthConsumer.framework */; };
 		11945F400F7935A2002A54B3 /* Ignore.png in Resources */ = {isa = PBXBuildFile; fileRef = 11945F3F0F7935A2002A54B3 /* Ignore.png */; };
+		1197F6710FCF8D180032F19B /* AITwitterStatusFollowup.m in Sources */ = {isa = PBXBuildFile; fileRef = 1197F6700FCF8D180032F19B /* AITwitterStatusFollowup.m */; };
 		11A2F10A0FC8FC1A00C3F05C /* AIMessageAlertsAdvancedPreferences.nib in Resources */ = {isa = PBXBuildFile; fileRef = 11A2F1090FC8FC1A00C3F05C /* AIMessageAlertsAdvancedPreferences.nib */; };
 		11A2F1220FC8FC9D00C3F05C /* AIMessageAlertsAdvancedPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 11A2F1210FC8FC9D00C3F05C /* AIMessageAlertsAdvancedPreferences.m */; };
 		11AA10130FCE0969003908B6 /* AIProgressDataUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = 11AA10110FCE0969003908B6 /* AIProgressDataUploader.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1882,6 +1883,8 @@
 		11879C0A0F6FF4C400CACFB1 /* AITwitterAccountOAuthSetup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AITwitterAccountOAuthSetup.m; path = "Plugins/Twitter Plugin/AITwitterAccountOAuthSetup.m"; sourceTree = "<group>"; };
 		11879DF70F6FFC0B00CACFB1 /* OAuthConsumer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OAuthConsumer.framework; path = Frameworks/OAuthConsumer.framework; sourceTree = "<group>"; };
 		11945F3F0F7935A2002A54B3 /* Ignore.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Ignore.png; path = "Frameworks/Adium Framework/Resources/Ignore.png"; sourceTree = "<group>"; };
+		1197F66F0FCF8D180032F19B /* AITwitterStatusFollowup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AITwitterStatusFollowup.h; path = "Plugins/Twitter Plugin/AITwitterStatusFollowup.h"; sourceTree = "<group>"; };
+		1197F6700FCF8D180032F19B /* AITwitterStatusFollowup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AITwitterStatusFollowup.m; path = "Plugins/Twitter Plugin/AITwitterStatusFollowup.m"; sourceTree = "<group>"; };
 		11A2F1090FC8FC1A00C3F05C /* AIMessageAlertsAdvancedPreferences.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = AIMessageAlertsAdvancedPreferences.nib; path = Resources/AIMessageAlertsAdvancedPreferences.nib; sourceTree = "<group>"; };
 		11A2F1200FC8FC9D00C3F05C /* AIMessageAlertsAdvancedPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIMessageAlertsAdvancedPreferences.h; path = Source/AIMessageAlertsAdvancedPreferences.h; sourceTree = "<group>"; };
 		11A2F1210FC8FC9D00C3F05C /* AIMessageAlertsAdvancedPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIMessageAlertsAdvancedPreferences.m; path = Source/AIMessageAlertsAdvancedPreferences.m; sourceTree = "<group>"; };
@@ -4942,6 +4945,8 @@
 			children = (
 				11F739590F58D4DC00B3285B /* MGTwitterEngine */,
 				113891850F6B6B0300A7D7DC /* Laconica */,
+				1197F66F0FCF8D180032F19B /* AITwitterStatusFollowup.h */,
+				1197F6700FCF8D180032F19B /* AITwitterStatusFollowup.m */,
 				1109634B0F61C1D00064CA0E /* AITwitterReplyWindow.nib */,
 				110966180F61D3E70064CA0E /* AITwitterReplyWindowController.h */,
 				110966190F61D3E70064CA0E /* AITwitterReplyWindowController.m */,
@@ -10469,6 +10474,7 @@
 				11BE289A0FCC7C13000E6A10 /* AIPicImImageUploader.m in Sources */,
 				11BE28DF0FCC7D2B000E6A10 /* AIImageUploaderPlugin.m in Sources */,
 				11BE29680FCCA9E3000E6A10 /* AIImageUploaderWindowController.m in Sources */,
+				1197F6710FCF8D180032F19B /* AITwitterStatusFollowup.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff -r b454802ac946 -r 9b5721fa5865 Plugins/Image Uploading Plugin/AIPicImImageUploader.m
--- a/Plugins/Image Uploading Plugin/AIPicImImageUploader.m	Thu May 28 20:55:15 2009 -0400
+++ b/Plugins/Image Uploading Plugin/AIPicImImageUploader.m	Thu May 28 23:57:35 2009 -0400
@@ -8,6 +8,7 @@
 
 #import "AIPicImImageUploader.h"
 
+#import <Adium/AIChat.h>
 #import <Adium/AIInterfaceControllerProtocol.h>
 #import <AIUtilities/AIStringAdditions.h>
 #import <AIUtilities/AIProgressDataUploader.h>
@@ -190,6 +191,10 @@
 		[uploader errorWithMessage:[status objectForKey:@"message"] forChat:chat];
 	} else if ([[status objectForKey:@"result"] isCaseInsensitivelyEqualToString:@"ok"]) {
 		[uploader uploadedURL:[[trim objectForKey:@"url"] objectForKey:@"value"] forChat:chat];
+		
+		NSMutableDictionary *dict = [chat valueForProperty:@"PicImReferences"] ?: [NSMutableDictionary dictionary];
+		[dict setObject:[[trim objectForKey:@"reference"] objectForKey:@"value"] forKey:[[trim objectForKey:@"url"] objectForKey:@"value"]];
+		[chat setValue:dict forProperty:@"PicImReferences" notify:NotifyNever];
 	} else {
 		[uploader errorWithMessage:AILocalizedString(@"Unable to upload", nil) forChat:chat];
 	}
diff -r b454802ac946 -r 9b5721fa5865 Plugins/Twitter Plugin/AITwitterAccount.h
--- a/Plugins/Twitter Plugin/AITwitterAccount.h	Thu May 28 20:55:15 2009 -0400
+++ b/Plugins/Twitter Plugin/AITwitterAccount.h	Thu May 28 23:57:35 2009 -0400
@@ -107,6 +107,8 @@
 #define TWITTER_PREFERENCE_REPLIES_LAST_ID		@"Replies Last ID"
 #define TWITTER_PREFERENCE_GROUP_UPDATES		@"Twitter Preferences"
 
+#define AITwitterNotificationPostedStatus		@"AITwitterNotificationPostedStatus"
+
 // Status Updates
 #define TWITTER_STATUS_ID					@"id"
 #define TWITTER_STATUS_REPLY_UID			@"in_reply_to_screen_name"
diff -r b454802ac946 -r 9b5721fa5865 Plugins/Twitter Plugin/AITwitterAccount.m
--- a/Plugins/Twitter Plugin/AITwitterAccount.m	Thu May 28 20:55:15 2009 -0400
+++ b/Plugins/Twitter Plugin/AITwitterAccount.m	Thu May 28 23:57:35 2009 -0400
@@ -2032,18 +2032,20 @@
 		if (updateAfterSend) {
 			[self periodicUpdate];
 		}
-		
-		if ([[self preferenceForKey:TWITTER_PREFERENCE_UPDATE_GLOBAL group:TWITTER_PREFERENCE_GROUP_UPDATES] boolValue]) {
-			for(NSDictionary *update in statuses) {
-				NSString *text = [[update objectForKey:TWITTER_STATUS_TEXT] stringByUnescapingFromXMLWithEntities:nil];
 				
-				if(![text hasPrefix:@"@"] ||
-				   [[self preferenceForKey:TWITTER_PREFERENCE_UPDATE_GLOBAL_REPLIES group:TWITTER_PREFERENCE_GROUP_UPDATES] boolValue]) {
-					AIStatus *availableStatus = [AIStatus statusOfType:AIAvailableStatusType];
-					
-					availableStatus.statusMessage = [NSAttributedString stringWithString:text];
-					[adium.statusController setActiveStatusState:availableStatus];
-				}
+		for(NSDictionary *update in statuses) {
+			[[NSNotificationCenter defaultCenter] postNotificationName:AITwitterNotificationPostedStatus
+																object:update
+															  userInfo:[NSDictionary dictionaryWithObjectsAndKeys:self.timelineChat, @"AIChat", nil]];
+			
+			NSString *text = [[update objectForKey:TWITTER_STATUS_TEXT] stringByUnescapingFromXMLWithEntities:nil];
+			
+			if([[self preferenceForKey:TWITTER_PREFERENCE_UPDATE_GLOBAL group:TWITTER_PREFERENCE_GROUP_UPDATES] boolValue] &&
+			   (![text hasPrefix:@"@"] || [[self preferenceForKey:TWITTER_PREFERENCE_UPDATE_GLOBAL_REPLIES group:TWITTER_PREFERENCE_GROUP_UPDATES] boolValue])) {
+				AIStatus *availableStatus = [AIStatus statusOfType:AIAvailableStatusType];
+				
+				availableStatus.statusMessage = [NSAttributedString stringWithString:text];
+				[adium.statusController setActiveStatusState:availableStatus];
 			}
 		}
 	} else if ([self requestTypeForRequestID:identifier] == AITwitterFavoriteYes ||
diff -r b454802ac946 -r 9b5721fa5865 Plugins/Twitter Plugin/AITwitterStatusFollowup.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Twitter Plugin/AITwitterStatusFollowup.h	Thu May 28 23:57:35 2009 -0400
@@ -0,0 +1,13 @@
+//
+//  AITwitterStatusFollowup.h
+//  Adium
+//
+//  Created by Zachary West on 2009-05-28.
+//  Copyright 2009 Adium. All rights reserved.
+//
+
+ at interface AITwitterStatusFollowup : AIPlugin {
+	
+}
+
+ at end
diff -r b454802ac946 -r 9b5721fa5865 Plugins/Twitter Plugin/AITwitterStatusFollowup.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Twitter Plugin/AITwitterStatusFollowup.m	Thu May 28 23:57:35 2009 -0400
@@ -0,0 +1,101 @@
+//
+//  AITwitterStatusFollowup.m
+//  Adium
+//
+//  Created by Zachary West on 2009-05-28.
+//  Copyright 2009 Adium. All rights reserved.
+//
+
+#import "AITwitterStatusFollowup.h"
+#import "AITwitterAccount.h"
+#import <Adium/AIChat.h>
+#import <Adium/AIAccount.h>
+#import <AIUtilities/AIStringAdditions.h>
+
+ at interface AITwitterStatusFollowup()
+- (void)twitterStatusPosted:(NSNotification *)notification;
+- (void)linkTweetID:(NSString *)tweetID
+			  tweet:(NSString *)tweetText
+		   username:(NSString *)username
+			network:(NSString *)network
+		  reference:(NSString *)reference;
+ at end
+
+ at implementation AITwitterStatusFollowup
+- (void)installPlugin
+{
+	[[NSNotificationCenter defaultCenter] addObserver:self
+											 selector:@selector(twitterStatusPosted:)
+												 name:AITwitterNotificationPostedStatus
+											   object:nil];
+}
+
+- (void)uninstallPlugin
+{
+	[[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)twitterStatusPosted:(NSNotification *)notification
+{
+	NSDictionary	*update = notification.object;
+	AIChat			*chat = [[notification userInfo] objectForKey:@"AIChat"];
+	NSString		*updateText = [update objectForKey:TWITTER_STATUS_TEXT];
+	NSDictionary	*references = [chat valueForProperty:@"PicImReferences"];
+	
+	// Don't link direct messages.
+	if ([updateText hasPrefix:@"d "]) {
+		return;
+	}
+	
+	for (NSString *purl in references) {
+		if ([updateText rangeOfString:purl options:NSCaseInsensitiveSearch].location != NSNotFound) {
+			AIAccount *account = chat.account;
+			NSString *network = nil;
+			
+			// Valid network type is either "twitter" or "identica"
+			if ([account.host isEqualToString:@"twitter.com"]) {
+				network = @"twitter";
+			} else if ([account.host isEqualToString:@"identi.ca"]) {
+				network = @"identica";
+			}
+			
+			// A random laconica network, or something.
+			if (!network)
+				continue;
+			
+			// Perform the link.
+			[self linkTweetID:[update objectForKey:TWITTER_STATUS_ID] 
+						tweet:updateText
+					 username:account.UID
+					  network:network
+					reference:[references objectForKey:purl]];
+		}
+	}
+}
+
+- (void)linkTweetID:(NSString *)tweetID
+			  tweet:(NSString *)tweetText
+		   username:(NSString *)username
+			network:(NSString *)network
+		  reference:(NSString *)reference
+{
+	NSMutableString *url = [NSMutableString string];
+	
+	[url appendString:@"http://api.tr.im/api/picim_tweet.xml?api_key=zghQN6sv5y0FkLPNlQAopm7qDQz6ItO33ENU21OBsy3dL1Kl"];
+	
+	[url appendFormat:@"&reference=%@", reference];
+	[url appendFormat:@"&tweet=%@", [tweetText stringByAddingPercentEscapesForAllCharacters]];
+	[url appendFormat:@"&tweet_id=%@", tweetID];
+	[url appendFormat:@"&username=%@", username];
+	[url appendFormat:@"&network=%@", network];
+	
+	NSURLConnection *connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]
+																delegate:self];
+	
+	// We don't implement any delegate methods, because if this fails we don't bother retrying.
+	if (!connection) {
+		AILogWithSignature(@"Immediate fail when trying to link tweet to %@", reference);
+	}
+}
+
+ at end
diff -r b454802ac946 -r 9b5721fa5865 Source/AICoreComponentLoader.m
--- a/Source/AICoreComponentLoader.m	Thu May 28 20:55:15 2009 -0400
+++ b/Source/AICoreComponentLoader.m	Thu May 28 23:57:35 2009 -0400
@@ -161,6 +161,7 @@
 		@"AWBonjourPlugin",
 		@"CBPurpleServicePlugin",
 		@"AIImageUploaderPlugin",
+		@"AITwitterStatusFollowup",
 		nil
 	];
 	//Load each component




More information about the commits mailing list