Added code to fetch avatars

This commit is contained in:
Sarang Bharadwaj 2012-07-19 19:11:48 +05:30
parent dcdaeff7f2
commit bdb8aed78f
10 changed files with 271 additions and 33 deletions

View file

@ -3,10 +3,17 @@ DEFINE_LOGGER(logger, "CreateFriendRequest")
void CreateFriendRequest::run()
{
LOG4CXX_INFO(logger, user << ": Sending follow request for " << frnd)
LOG4CXX_INFO(logger, user << " - Sending follow request for " << frnd)
replyMsg = "";
success = twitObj->friendshipCreate(frnd, false);
if(success) twitObj->getLastWebResponse(replyMsg);
if(success) {
twitObj->getLastWebResponse(replyMsg);
LOG4CXX_INFO(logger, user << replyMsg)
friendInfo = getUser(replyMsg);
if(friendInfo.getScreenName() == "") LOG4CXX_INFO(logger, user << " - Was unable to fetch user info for " << frnd);
}
}
void CreateFriendRequest::finalize()
@ -15,15 +22,14 @@ void CreateFriendRequest::finalize()
std::string error;
twitObj->getLastCurlError(error);
LOG4CXX_ERROR(logger, user << " - Curl error: " << error)
callBack(user, frnd, error);
callBack(user, friendInfo, error);
} else {
std::string error;
error = getErrorMessage(replyMsg);
if(error.length()) {
LOG4CXX_ERROR(logger, user << " - " << error)
//LOG4CXX_ERROR(logger, user << " " << replyMsg)
}
else LOG4CXX_INFO(logger, user << ": Now following " << frnd)
callBack(user, frnd, error);
callBack(user, friendInfo, error);
}
}

View file

@ -8,6 +8,7 @@
#include <string>
#include <boost/function.hpp>
#include <iostream>
#include <vector>
using namespace Transport;
@ -17,13 +18,13 @@ class CreateFriendRequest : public Thread
std::string user;
std::string frnd;
std::string replyMsg;
boost::function< void (std::string&, std::string&, std::string&) > callBack;
boost::function< void (std::string&, User&, std::string&) > callBack;
User friendInfo;
bool success;
public:
CreateFriendRequest(twitCurl *obj, const std::string &_user, const std::string & _frnd,
boost::function< void (std::string&, std::string&, std::string&) > cb) {
boost::function< void (std::string&, User&, std::string&) > cb) {
twitObj = obj->clone();
user = _user;
frnd = _frnd;

View file

@ -5,7 +5,15 @@ void DestroyFriendRequest::run()
{
replyMsg = "";
success = twitObj->friendshipDestroy(frnd, false);
if(success) twitObj->getLastWebResponse(replyMsg);
if(success) {
twitObj->getLastWebResponse(replyMsg);
LOG4CXX_INFO(logger, user << replyMsg)
friendInfo = getUser(replyMsg);
if(friendInfo.getScreenName() == "") LOG4CXX_INFO(logger, user << " - Was unable to fetch user info for " << frnd);
}
}
void DestroyFriendRequest::finalize()
@ -14,11 +22,11 @@ void DestroyFriendRequest::finalize()
std::string error;
twitObj->getLastCurlError(error);
LOG4CXX_ERROR(logger, user << " Curl error: " << error)
callBack(user, frnd, error);
callBack(user, friendInfo, error);
} else {
std::string error;
error = getErrorMessage(replyMsg);
if(error.length()) LOG4CXX_ERROR(logger, user << " - " << error)
callBack(user, frnd, error);
callBack(user, friendInfo, error);
}
}

View file

@ -8,6 +8,7 @@
#include <string>
#include <boost/function.hpp>
#include <iostream>
#include <vector>
using namespace Transport;
@ -17,12 +18,13 @@ class DestroyFriendRequest : public Thread
std::string user;
std::string frnd;
std::string replyMsg;
boost::function< void (std::string&, std::string&, std::string&) > callBack;
boost::function< void (std::string&, User&, std::string&) > callBack;
User friendInfo;
bool success;
public:
DestroyFriendRequest(twitCurl *obj, const std::string &_user, const std::string & _frnd,
boost::function< void (std::string&, std::string&, std::string&) > cb) {
boost::function< void (std::string&, User&, std::string&) > cb) {
twitObj = obj->clone();
user = _user;
frnd = _frnd;

View file

@ -0,0 +1,63 @@
#include "ProfileImageRequest.h"
DEFINE_LOGGER(logger, "ProfileImageRequest")
int ProfileImageRequest::curlCallback(char* data, size_t size, size_t nmemb, ProfileImageRequest* obj)
{
int writtenSize = 0;
if(obj && data) {
obj->callbackdata.append(data, size*nmemb);
writtenSize = (int)(size*nmemb);
}
return writtenSize;
}
bool ProfileImageRequest::fetchImage()
{
LOG4CXX_INFO(logger, user << " - Fetching profile image");
curl_easy_setopt(curlhandle, CURLOPT_CUSTOMREQUEST, NULL);
curl_easy_setopt(curlhandle, CURLOPT_ENCODING, "");
img = "";
callbackdata = "";
memset(curl_errorbuffer, 0, 1024);
curl_easy_setopt(curlhandle, CURLOPT_ERRORBUFFER, curl_errorbuffer);
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, curlCallback);
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, this);
/* Set http request and url */
curl_easy_setopt(curlhandle, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curlhandle, CURLOPT_URL, url.c_str());
/* Send http request and return status*/
return (CURLE_OK == curl_easy_perform(curlhandle));
}
void ProfileImageRequest::run()
{
if(curlhandle == NULL) {
error = "Failed to init CURL!";
success = false;
return;
}
success = fetchImage();
if(!success) error.assign(curl_errorbuffer);
}
void ProfileImageRequest::finalize()
{
if(!success) {
LOG4CXX_ERROR(logger, user << " - " << error)
img = "";
callBack(user, buddy, img, reqID, error);
} else {
//std::string error = getErrorMessage(replyMsg);
//if(error.length()) LOG4CXX_ERROR(logger, user << " - " << error)
LOG4CXX_INFO(logger, user << " - " << callbackdata);
img = callbackdata;
callBack(user, buddy, img, reqID, error);
}
}

View file

@ -0,0 +1,89 @@
#ifndef PROFILEIMAGE_H
#define PROFILEIMAGE_H
#include "../ThreadPool.h"
#include "../libtwitcurl/curl/curl.h"
#include "../TwitterResponseParser.h"
#include "transport/logging.h"
#include "transport/config.h"
#include <string>
#include <boost/signals.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <sstream>
using namespace Transport;
using namespace boost::program_options;
class ProfileImageRequest : public Thread
{
std::string user;
std::string buddy;
std::string url;
std::string img;
unsigned int reqID;
boost::function< void (std::string&, std::string&, std::string&, int, std::string&) > callBack;
bool success;
CURL *curlhandle;
std::string error;
std::string callbackdata;
char curl_errorbuffer[1024];
bool fetchImage();
static int curlCallback( char* data, size_t size, size_t nmemb, ProfileImageRequest *obj);
public:
ProfileImageRequest(Config *config, const std::string &_user, const std::string &_buddy, const std::string &_url, unsigned int _reqID,
boost::function< void (std::string&, std::string&, std::string&, int, std::string&) > cb) {
curlhandle = curl_easy_init();
curl_easy_setopt(curlhandle, CURLOPT_PROXY, NULL);
curl_easy_setopt(curlhandle, CURLOPT_PROXYUSERPWD, NULL);
curl_easy_setopt(curlhandle, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
/************ Set proxy if available *****************************************/
if(CONFIG_HAS_KEY(config,"proxy.server")) {
std::string ip = CONFIG_STRING(config,"proxy.server");
std::ostringstream out;
out << CONFIG_INT(config,"proxy.port");
std::string port = out.str();
std::string puser = CONFIG_STRING(config,"proxy.user");
std::string ppasswd = CONFIG_STRING(config,"proxy.password");
if(ip != "localhost" && port != "0") {
/* Set proxy details in cURL */
std::string proxyIpPort = ip + ":" + port;
curl_easy_setopt(curlhandle, CURLOPT_PROXY, proxyIpPort.c_str());
/* Prepare username and password for proxy server */
if(puser.length() && ppasswd.length()) {
std::string proxyUserPass = puser + ":" + ppasswd;
curl_easy_setopt(curlhandle, CURLOPT_PROXYUSERPWD, proxyUserPass.c_str());
}
}
}
/*****************************************************************************/
user = _user;
buddy = _buddy;
url = _url;
reqID = _reqID;
callBack = cb;
}
~ProfileImageRequest() {
if(curlhandle) {
curl_easy_cleanup(curlhandle);
curlhandle = NULL;
}
}
void run();
void finalize();
};
#endif

View file

@ -9,6 +9,7 @@
#include "Requests/CreateFriendRequest.h"
#include "Requests/DestroyFriendRequest.h"
#include "Requests/RetweetRequest.h"
#include "Requests/ProfileImageRequest.h"
DEFINE_LOGGER(logger, "Twitter Backend");
@ -139,7 +140,6 @@ void TwitterPlugin::handleLoginRequest(const std::string &user, const std::strin
void TwitterPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName)
{
if(onlineUsers.count(user)) {
clearRoster(user);
delete sessions[user];
sessions[user] = NULL;
connectionState[user] = DISCONNECTED;
@ -291,6 +291,20 @@ void TwitterPlugin::handleBuddyRemovedRequest(const std::string &user, const std
boost::bind(&TwitterPlugin::deleteFriendResponse, this, _1, _2, _3)));
}
void TwitterPlugin::handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id)
{
LOG4CXX_INFO(logger, user << " - VCardRequest for " << legacyName << ", " << imgURL[legacyName])
if(connectionState[user] != CONNECTED) {
LOG4CXX_ERROR(logger, user << " is not connected to twitter!")
return;
}
if(getTwitterMode(user) != SINGLECONTACT && buddies[user].count(legacyName) && imgURL[legacyName].length()) {
LOG4CXX_INFO(logger, user << " - Initiating VCard request for " << legacyName);
tp->runAsThread(new ProfileImageRequest(config, user, legacyName, imgURL[legacyName], id,
boost::bind(&TwitterPlugin::profileImageResponse, this, _1, _2, _3, _4, _5)));
}
}
void TwitterPlugin::pollForTweets()
{
@ -510,7 +524,7 @@ void TwitterPlugin::clearRoster(const std::string user)
if(buddies[user].size() == 0) return;
std::set<std::string>::iterator it = buddies[user].begin();
while(it != buddies[user].end()) {
handleBuddyChanged(user, *it, *it, std::vector<std::string>(), pbnetwork::STATUS_NONE);
//handleBuddyChanged(user, *it, *it, std::vector<std::string>(), pbnetwork::STATUS_NONE);
handleBuddyRemoved(user, *it);
it++;
}
@ -524,10 +538,10 @@ void TwitterPlugin::populateRoster(std::string &user, std::vector<User> &friends
for(int i=0 ; i<friends.size() ; i++) {
if(twitterMode[user] == MULTIPLECONTACT)
handleBuddyChanged(user, friends[i].getScreenName(), friends[i].getScreenName(), std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
else if(twitterMode[user] == CHATROOM) {
else if(twitterMode[user] == CHATROOM)
handleParticipantChanged(user, friends[i].getScreenName(), adminChatRoom, 0, pbnetwork::STATUS_ONLINE);
buddies[user].insert(friends[i].getScreenName());
}
buddies[user].insert(friends[i].getScreenName());
imgURL[friends[i].getScreenName()] = friends[i].getProfileImgURL();
}
} else handleMessage(user, twitterMode[user] == CHATROOM ? adminChatRoom : adminLegacyName,
std::string("Error populating roster - ") + errMsg, twitterMode[user] == CHATROOM ? adminNickName : "");
@ -629,7 +643,7 @@ void TwitterPlugin::directMessageResponse(std::string &user, std::string &userna
}
}
void TwitterPlugin::createFriendResponse(std::string &user, std::string &frnd, std::string &errMsg)
void TwitterPlugin::createFriendResponse(std::string &user, User &frnd, std::string &errMsg)
{
if(errMsg.length()) {
handleMessage(user, twitterMode[user] == CHATROOM ? adminChatRoom : adminLegacyName,
@ -638,20 +652,22 @@ void TwitterPlugin::createFriendResponse(std::string &user, std::string &frnd, s
}
handleMessage(user, twitterMode[user] == CHATROOM ? adminChatRoom : adminLegacyName,
std::string("You are now following ") + frnd, twitterMode[user] == CHATROOM ? adminNickName : "");
std::string("You are now following ") + frnd.getScreenName(), twitterMode[user] == CHATROOM ? adminNickName : "");
//buddies[user].insert(frnd);
buddies[user].insert(frnd.getScreenName());
imgURL[frnd.getScreenName()] = frnd.getProfileImgURL();
LOG4CXX_INFO(logger, user << " - " << frnd.getScreenName() << ", " << imgURL[frnd.getScreenName()])
//handleBuddyChanged(user, frnd, frnd, std::vector<std::string>(), pbnetwork::STATUS_NONE);
if(twitterMode[user] == MULTIPLECONTACT) {
handleBuddyChanged(user, frnd, frnd, std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
handleBuddyChanged(user, frnd.getScreenName(), frnd.getScreenName(), std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
} else if(twitterMode[user] == CHATROOM) {
buddies[user].insert(frnd);
handleParticipantChanged(user, frnd, adminChatRoom, 0, pbnetwork::STATUS_ONLINE);
//buddies[user].insert(frnd);
handleParticipantChanged(user, frnd.getScreenName(), adminChatRoom, 0, pbnetwork::STATUS_ONLINE);
}
}
void TwitterPlugin::deleteFriendResponse(std::string &user, std::string &frnd, std::string &errMsg)
void TwitterPlugin::deleteFriendResponse(std::string &user, User &frnd, std::string &errMsg)
{
if(errMsg.length()) {
handleMessage(user, twitterMode[user] == CHATROOM ? adminChatRoom : adminLegacyName,
@ -660,16 +676,21 @@ void TwitterPlugin::deleteFriendResponse(std::string &user, std::string &frnd, s
}
handleMessage(user, twitterMode[user] == CHATROOM ? adminChatRoom : adminLegacyName,
std::string("You are not following ") + frnd + " anymore", twitterMode[user] == CHATROOM ? adminNickName : "");
std::string("You are not following ") + frnd.getScreenName() + " anymore", twitterMode[user] == CHATROOM ? adminNickName : "");
if (twitterMode[user] == CHATROOM) {
handleParticipantChanged(user, frnd, adminLegacyName, 0, pbnetwork::STATUS_NONE);
buddies[user].erase(frnd);
handleParticipantChanged(user, frnd.getScreenName(), adminLegacyName, 0, pbnetwork::STATUS_NONE);
//buddies[user].erase(frnd);
}
//buddies[user].erase(frnd);
LOG4CXX_INFO(logger, user << " - " << frnd.getScreenName() << ", " << imgURL[frnd.getScreenName()])
buddies[user].erase(frnd.getScreenName());
imgURL[frnd.getScreenName()] = "";
//handleBuddyRemoved(user, frnd);
if(twitterMode[user] == MULTIPLECONTACT) {
handleBuddyRemoved(user, frnd);
handleBuddyRemoved(user, frnd.getScreenName());
}
}
@ -684,3 +705,14 @@ void TwitterPlugin::RetweetResponse(std::string &user, std::string &errMsg)
"Retweet successful", twitterMode[user] == CHATROOM ? adminNickName : "");
}
}
void TwitterPlugin::profileImageResponse(std::string &user, std::string &buddy, std::string &img, unsigned int reqID, std::string &errMsg)
{
if(errMsg.length()) {
handleMessage(user, twitterMode[user] == CHATROOM ? adminChatRoom : adminLegacyName,
errMsg, twitterMode[user] == CHATROOM ? adminNickName : "");
} else {
LOG4CXX_INFO(logger, user << " - Sending VCard for " << buddy)
handleVCard(user, reqID, buddy, buddy, "", img);
}
}

View file

@ -77,6 +77,8 @@ class TwitterPlugin : public NetworkPlugin {
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups);
void handleVCardRequest(const std::string &/*user*/, const std::string &/*legacyName*/, unsigned int /*id*/);
void pollForTweets();
void pollForDirectMessages();
@ -112,9 +114,10 @@ class TwitterPlugin : public NetworkPlugin {
void displayFriendlist(std::string &user, std::vector<User> &friends, std::string &errMsg);
void displayTweets(std::string &user, std::string &userRequested, std::vector<Status> &tweets , std::string &errMsg);
void directMessageResponse(std::string &user, std::string &username, std::vector<DirectMessage> &messages, std::string &errMsg);
void createFriendResponse(std::string &user, std::string &frnd, std::string &errMsg);
void deleteFriendResponse(std::string &user, std::string &frnd, std::string &errMsg);
void createFriendResponse(std::string &user, User &frnd, std::string &errMsg);
void deleteFriendResponse(std::string &user, User &frnd, std::string &errMsg);
void RetweetResponse(std::string &user, std::string &errMsg);
void profileImageResponse(std::string &user, std::string &buddy, std::string &img, unsigned int reqID, std::string &errMsg);
/***********************************************************************************/
private:
@ -143,6 +146,7 @@ class TwitterPlugin : public NetworkPlugin {
std::set<std::string> onlineUsers;
std::map<std::string,std::string> nickName;
std::map<std::string, std::set<std::string> > buddies;
std::map<std::string, std::string> imgURL;
std::map<std::string, mode> twitterMode;
};

View file

@ -1,8 +1,16 @@
#include "TwitterResponseParser.h"
#include "transport/logging.h"
#include <cctype>
DEFINE_LOGGER(logger, "TwitterResponseParser")
static std::string tolowercase(std::string inp)
{
std::string out = inp;
for(int i=0 ; i<out.size() ; i++) out[i] = tolower(out[i]);
return out;
}
User getUser(const Swift::ParserElement::ref &element, const std::string xmlns)
{
User user;
@ -14,8 +22,9 @@ User getUser(const Swift::ParserElement::ref &element, const std::string xmlns)
}
user.setUserID( std::string( element->getChild(TwitterReponseTypes::id, xmlns)->getText() ) );
user.setScreenName( std::string( element->getChild(TwitterReponseTypes::screen_name, xmlns)->getText() ) );
user.setScreenName( tolowercase( std::string( element->getChild(TwitterReponseTypes::screen_name, xmlns)->getText() ) ) );
user.setUserName( std::string( element->getChild(TwitterReponseTypes::name, xmlns)->getText() ) );
user.setProfileImgURL( std::string( element->getChild(TwitterReponseTypes::profile_image_url, xmlns)->getText() ) );
user.setNumberOfTweets( atoi(element->getChild(TwitterReponseTypes::statuses_count, xmlns)->getText().c_str()) );
return user;
}
@ -137,6 +146,25 @@ std::vector<User> getUsers(std::string &xml)
return users;
}
User getUser(std::string &xml)
{
User user;
Swift::ParserElement::ref rootElement = Swift::StringTreeParser::parse(xml);
if(rootElement == NULL) {
LOG4CXX_ERROR(logger, "Error while parsing XML")
return user;
}
if(rootElement->getName() != TwitterReponseTypes::user) {
LOG4CXX_ERROR(logger, "XML doesn't correspond to user object")
return user;
}
const std::string xmlns = rootElement->getNamespace();
return user = getUser(rootElement, xmlns);
}
std::vector<std::string> getIDs(std::string &xml)
{
std::vector<std::string> IDs;

View file

@ -34,6 +34,7 @@ namespace TwitterReponseTypes
const std::string recipient_screen_name = "recipient_screen_name";
const std::string sender = "sender";
const std::string recipient = "recipient";
const std::string profile_image_url = "profile_image_url";
};
//Class holding user data
@ -42,6 +43,7 @@ class User
std::string ID;
std::string name;
std::string screen_name;
std::string profile_image_url;
unsigned int statuses_count;
public:
@ -50,12 +52,14 @@ class User
std::string getUserID() {return ID;}
std::string getUserName() {return name;}
std::string getScreenName() {return screen_name;}
std::string getProfileImgURL() {return profile_image_url;}
unsigned int getNumberOfTweets() {return statuses_count;}
void setUserID(std::string _id) {ID = _id;}
void setUserName(std::string _name) {name = _name;}
void setScreenName(std::string _screen) {screen_name = _screen;}
void setProfileImgURL(std::string _url) {profile_image_url = _url;}
void setNumberOfTweets(unsigned int sc) {statuses_count = sc;}
};
@ -145,6 +149,7 @@ std::vector<Status> getTimeline(std::string &xml);
std::vector<DirectMessage> getDirectMessages(std::string &xml);
std::vector<std::string> getIDs(std::string &xml);
std::vector<User> getUsers(std::string &xml);
User getUser(std::string &xml);
std::string getErrorMessage(std::string &xml);
Status getStatus(const Swift::ParserElement::ref &element, const std::string xmlns);