Changeset - 26e5289cefeb
[Not reviewed]
0 3 0
Sarang Bharadwaj - 13 years ago 2012-05-31 16:49:20
sarang.bh@gmail.com
Fetching the user's friends - initial code
3 files changed with 63 insertions and 5 deletions:
0 comments (0 inline, 0 general)
backends/twitter/TwitterResponseParser.cpp
Show inline comments
 
@@ -25,38 +25,57 @@ Status getStatus(const Swift::ParserElement::ref &element, const std::string xml
 
		LOG4CXX_ERROR(logger, "Not a status element!")
 
		return status;
 
	}
 

	
 
	status.setCreationTime( std::string( element->getChild(TwitterReponseTypes::created_at, xmlns)->getText() ) );
 
	status.setID( std::string( element->getChild(TwitterReponseTypes::id, xmlns)->getText() ) );
 
	status.setTweet( std::string( element->getChild(TwitterReponseTypes::text, xmlns)->getText() ) );
 
	status.setTruncated( std::string( element->getChild(TwitterReponseTypes::truncated, xmlns)->getText() )=="true" );
 
	status.setReplyToStatusID( std::string( element->getChild(TwitterReponseTypes::in_reply_to_status_id, xmlns)->getText() ) );
 
	status.setReplyToUserID( std::string( element->getChild(TwitterReponseTypes::in_reply_to_user_id, xmlns)->getText() ) );
 
	status.setReplyToScreenName( std::string( element->getChild(TwitterReponseTypes::in_reply_to_screen_name, xmlns)->getText() ) );
 
	status.setUserData( getUser(element->getChild(TwitterReponseTypes::user, xmlns), xmlns) );
 
	status.setRetweetCount( atoi( element->getChild(TwitterReponseTypes::retweet_count, xmlns)->getText().c_str() ) );
 
	status.setFavorited( std::string( element->getChild(TwitterReponseTypes::favorited, xmlns)->getText() )=="true" );
 
	status.setRetweeted( std::string( element->getChild(TwitterReponseTypes::retweeted, xmlns)->getText() )=="true" );
 
	return status;
 
}
 

	
 
std::vector<Status> getTimeline(std::string &xml)
 
{
 
	std::vector<Status> statuses;
 
	Swift::ParserElement::ref rootElement = Swift::StringTreeParser::parse(xml);
 
	
 
	if(rootElement->getName() != "statuses") {
 
		LOG4CXX_ERROR(logger, "XML doesnt correspond to timline")
 
		LOG4CXX_ERROR(logger, "XML doesn't correspond to timeline")
 
		return statuses;
 
	}
 

	
 
	const std::string xmlns = rootElement->getNamespace();
 
	const std::vector<Swift::ParserElement::ref> children = rootElement->getChildren(TwitterReponseTypes::status, xmlns);
 
//	const std::vector<Swift::ParserElement::ref>::iterator it;
 

	
 
	for(int i = 0; i <  children.size() ; i++) {
 
		const Swift::ParserElement::ref status = children[i];
 
		statuses.push_back(getStatus(status, xmlns));
 
	}
 
	return statuses;
 
}
 

	
 
std::vector<std::string> getIDs(std::string &xml)
 
{
 
	std::vector<std::string> IDs;
 
	Swift::ParserElement::ref rootElement = Swift::StringTreeParser::parse(xml);
 

	
 
	if(rootElement->getName() != TwitterReponseTypes::id_list) {
 
		LOG4CXX_ERROR(logger, "XML doesn't correspond to id_list");
 
		return IDs;
 
	}
 

	
 
	const std::string xmlns = rootElement->getNamespace();
 
	const std::vector<Swift::ParserElement::ref> ids = rootElement->getChild(TwitterReponseTypes::ids, xmlns)->getChildren(TwitterReponseTypes::id, xmlns);
 
	
 
	for(int i=0 ; i<ids.size() ; i++) {
 
		IDs.push_back(std::string( ids[i]->getText() ));
 
	}
 
	return IDs;
 
}
backends/twitter/TwitterResponseParser.h
Show inline comments
 
#ifndef TWITTERRESPOSNSEPARSER_H
 
#define TWITTERRESPOSNSEPARSER_H
 

	
 
#include "Swiften/Parser/StringTreeParser.h"
 
#include <iostream>
 
#include <vector>
 

	
 
namespace TwitterReponseTypes
 
{
 
	const std::string id = "id";
 
	const std::string id_list = "id_list";
 
	const std::string ids = "ids";
 
	const std::string name = "name";
 
	const std::string screen_name = "screen_name";
 
	const std::string statuses_count = "statuses_count";
 
	const std::string created_at = "created_at";
 
	const std::string text = "text";
 
	const std::string truncated = "truncated";
 
	const std::string in_reply_to_status_id = "in_reply_to_user_id";
 
	const std::string in_reply_to_user_id = "in_reply_to_user_id";
 
	const std::string in_reply_to_screen_name = "in_reply_to_screen_name";
 
	const std::string retweet_count = "retweet_count";
 
	const std::string favorited = "favorited";
 
	const std::string retweeted = "retweeted";
 
	const std::string user = "user";
 
	const std::string status = "status";
 
};
 

	
 
//Class holding user data
 
class User
 
{
 
	std::string ID;
 
	std::string name;
 
	std::string screen_name;
 
	unsigned int statuses_count;
 

	
 
@@ -72,27 +74,28 @@ class Status
 
	std::string getTweet() {return text;}
 
	bool isTruncated() {return truncated;}
 
	std::string getReplyToStatusID() {return in_reply_to_status_id;}
 
	std::string getReplyToUserID() {return in_reply_to_user_id;}
 
	std::string getReplyToScreenName() {return in_reply_to_screen_name;}
 
	User getUserData() {return user;}
 
	unsigned int getRetweetCount() {return retweet_count;}
 
	bool isFavorited() {return favorited;}
 
	bool isRetweeted() {return retweeted;}
 
	
 
	void setCreationTime(std::string _created) {created_at = _created;}
 
	void setID(std::string _id) {ID = _id;}
 
	void setTweet(std::string _text) {text = _text;}
 
	void setTruncated(bool val) {truncated = val;}
 
	void setReplyToStatusID(std::string _id) {in_reply_to_status_id = _id;}
 
	void setReplyToUserID(std::string _id) {in_reply_to_user_id = _id;}
 
	void setReplyToScreenName(std::string _name) {in_reply_to_screen_name = _name;}
 
	void setUserData(User u) {user = u;}
 
	void setRetweetCount(unsigned int rc) {retweet_count = rc;}
 
	void setFavorited(bool val) {favorited = val;}
 
	void setRetweeted(bool val) {retweeted = val;}
 
};
 

	
 
std::vector<Status> getTimeline(std::string &xml);
 
std::vector<std::string> getIDs(std::string &xml);
 
Status getStatus(const Swift::ParserElement::ref &element, const std::string xmlns);
 
User getUser(const Swift::ParserElement::ref &element, const std::string xmlns);
 
#endif
backends/twitter/main.cpp
Show inline comments
 
@@ -145,159 +145,195 @@ class TwitterPlugin : public NetworkPlugin {
 
				}
 
				handleMessage(user, "twitter-account", std::string("Please visit the following link and authorize this application: ") + authUrl);
 
				handleMessage(user, "twitter-account", std::string("Please reply with the PIN provided by twitter. Prefix the pin with 'pin:'. Ex. 'pin: 1234'"));
 
				connectionState[user] = WAITING_FOR_PIN;	
 
			} else {
 
				LOG4CXX_INFO(logger, user << " is already registerd. Using the stored oauth key and secret")
 
				LOG4CXX_INFO(logger, key << " " << secret)
 

	
 
				sessions[user]->getOAuth().setOAuthTokenKey( key );
 
				sessions[user]->getOAuth().setOAuthTokenSecret( secret );
 
				connectionState[user] = CONNECTED;
 
			}
 
		}
 
		
 
		// User logging out
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			delete sessions[user];
 
			sessions[user] = NULL;
 
			connectionState[user] = DISCONNECTED;
 
		}
 

	
 
		void handlePINExchange(const std::string &user, std::string &data) {
 
			sessions[user]->getOAuth().setOAuthPin( data );
 
			if (sessions[user]->oAuthAccessToken() == false) {
 
				LOG4CXX_ERROR(logger, "Error while exchanging PIN with AcessToken!")
 
				LOG4CXX_ERROR(logger, "Error while exchanging PIN for Access Token!")
 
				handleLogoutRequest(user, "");
 
				return;
 
			}
 
			
 
			std::string OAuthAccessTokenKey, OAuthAccessTokenSecret;
 
			sessions[user]->getOAuth().getOAuthTokenKey( OAuthAccessTokenKey );
 
			sessions[user]->getOAuth().getOAuthTokenSecret( OAuthAccessTokenSecret );
 

	
 
			UserInfo info;
 
			if(storagebackend->getUser(user, info) == false) {
 
				LOG4CXX_ERROR(logger, "Didn't find entry for " << user << " in the database!")
 
				handleLogoutRequest(user, "");
 
				return;
 
			}
 

	
 
			storagebackend->updateUserSetting((long)info.id, OAUTH_KEY, OAuthAccessTokenKey);	
 
			storagebackend->updateUserSetting((long)info.id, OAUTH_SECRET, OAuthAccessTokenSecret);	
 

	
 
			connectionState[user] = CONNECTED;
 
			LOG4CXX_INFO(logger, "Sent PIN " << data << " and obtained access token");
 
			LOG4CXX_INFO(logger, "Sent PIN " << data << " and obtained Access Token");
 
		}
 

	
 
		void printHelpMessage(const std::string &user) {
 
			std::string helpMsg = "";
 
			helpMsg = helpMsg
 
				    + "\nHELP\n"
 
					+ "status:<your status> - Update your status\n"
 
					+ "#status:<your status> - Update your status\n"
 
					+ "#timeline - Retrieve your timeline\n"
 
					+ "@<username>:<message> - Send a directed message to the user <username>\n"
 
					+ "#help - print this help message\n";
 

	
 
			handleMessage(user, "twitter-account", helpMsg);
 
		}
 

	
 
		void handleDirectMessage(const std::string &user, std::string &username, std::string &data) {
 
			if(sessions[user]->directMessageSend(username, data, false) == false) {
 
				LOG4CXX_ERROR(logger, "Error while sending directed message to user " << username );
 
				return;
 
			}
 

	
 
			LOG4CXX_INFO(logger, "Sending " << data << " to " << username)
 

	
 
			std::string replyMsg;
 
			sessions[user]->getLastWebResponse( replyMsg );
 
			LOG4CXX_INFO(logger, replyMsg);
 
		}
 

	
 
		void handleStatusUpdate(const std::string &user, std::string &data) {
 
			if(connectionState[user] != CONNECTED) {
 
				LOG4CXX_ERROR(logger, "Trying to update status for " << user << " when not connected!");
 
				return;
 
			}
 

	
 
			std::string replyMsg; 
 
			if( sessions[user]->statusUpdate( data ) ) {
 
				replyMsg = "";
 
				while(replyMsg.length() == 0) {
 
					sessions[user]->getLastWebResponse( replyMsg );
 
				}
 
				LOG4CXX_INFO(logger, "twitCurl:statusUpdate web response: " << replyMsg );
 
			} else {
 
				sessions[user]->getLastCurlError( replyMsg );
 
				LOG4CXX_INFO(logger, "twitCurl::statusUpdate error: " << replyMsg );
 
			}
 
			LOG4CXX_INFO(logger, "Updated status for " << user << ": " << data);
 
		}
 

	
 
		void fetchTimeline(const std::string &user) {
 
			if(connectionState[user] != CONNECTED) {
 
				LOG4CXX_ERROR(logger, "Trying to update status for " << user << " when not connected!");
 
				LOG4CXX_ERROR(logger, "Trying to fetch timeline for " << user << " when not connected!");
 
				return;
 
			}
 
			
 
			std::string replyMsg = ""; 
 
			if( sessions[user]->timelineHomeGet()) {
 
				
 
				while(replyMsg.length() == 0) {
 
					sessions[user]->getLastWebResponse( replyMsg );
 
				}
 

	
 
				LOG4CXX_INFO(logger, "twitCurl::timeline web response: " << replyMsg.length() << " " << replyMsg << "\n" );
 
				
 
				std::vector<Status> tweets = getTimeline(replyMsg);
 
				std::string timeline = "\n";
 
				for(int i=0 ; i<tweets.size() ; i++) {
 
					timeline += tweets[i].getTweet() + "\n";
 
				}
 

	
 
				handleMessage(user, "twitter-account", timeline);
 

	
 
			} else {
 
				sessions[user]->getLastCurlError( replyMsg );
 
				LOG4CXX_INFO(logger, "twitCurl::timeline error: " << replyMsg );
 
			}
 
		}
 

	
 
		void fetchFriends(const std::string &user) {
 
			if(connectionState[user] != CONNECTED) {
 
				LOG4CXX_ERROR(logger, "Trying to fetch friends of " << user << " when not connected!");
 
				return;
 
			}
 
			
 
			std::string replyMsg = ""; 
 
			if( sessions[user]->friendsIdsGet(sessions[user]->getTwitterUsername())) {
 
				
 
				while(replyMsg.length() == 0) {
 
					sessions[user]->getLastWebResponse( replyMsg );
 
				}
 

	
 
				LOG4CXX_INFO(logger, "twitCurl::friendsIdsGet web response: " << replyMsg.length() << " " << replyMsg << "\n" );
 

	
 
				std::vector<std::string> IDs = getIDs( replyMsg );
 
				for(int i=0 ; i<IDs.size() ; i++) {
 
					LOG4CXX_INFO(logger, "ID #" << i+1 << ": " << IDs[i]);
 
				}
 
				
 
				/*std::vector<Status> tweets = getTimeline(replyMsg);
 
				std::string timeline = "\n";
 
				for(int i=0 ; i<tweets.size() ; i++) {
 
					timeline += tweets[i].getTweet() + "\n";
 
				}
 

	
 
				handleMessage(user, "twitter-account", timeline);*/
 

	
 
			} else {
 
				sessions[user]->getLastCurlError( replyMsg );
 
				LOG4CXX_INFO(logger, "twitCurl::friendsIdsGet error: " << replyMsg );
 
			}
 
			
 
		}
 

	
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") {
 
			LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
 
			if(legacyName == "twitter-account") {
 
				std::string cmd = message.substr(0, message.find(':'));
 
				std::string data = message.substr(message.find(':') + 1);
 
				
 
				handleMessage(user, "twitter-account", cmd + " " + data);
 

	
 
				if(cmd == "#pin") handlePINExchange(user, data);
 
				else if(cmd == "#help") printHelpMessage(user);
 
				else if(cmd[0] == '@') {std::string username = cmd.substr(1); handleDirectMessage(user, username, data);}
 
				else if(cmd == "#status") handleStatusUpdate(user, data);
 
				else if(cmd == "#timeline") fetchTimeline(user);
 
				else if(cmd == "#friends") fetchFriends(user);
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 
			LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
 
			handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
 
		}
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 

	
 
		}
 

	
 
	private:
 
		enum status {NEW, WAITING_FOR_PIN, CONNECTED, DISCONNECTED};
 
		Config *config;
 
		//UserDB *db;
 
		std::string consumerKey;
 
		std::string consumerSecret;
 
		//std::set<std::string> registeredUsers;
 
		std::map<std::string, twitCurl*> sessions;
 
		std::map<std::string, status> connectionState;
 
		std::string OAUTH_KEY;
 
		std::string OAUTH_SECRET;
 
};
0 comments (0 inline, 0 general)