summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwatcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb>2012-01-19 12:21:27 +0000
committerwatcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb>2012-01-19 12:21:27 +0000
commite94c705bb01c662d934c0096480bc9a732d0e1ec (patch)
treea07c6aa2174cf87d62ecfccdde8dbfa56185d78f
parent9b2d93c613db59b7d47327899a0850d370d6ea5e (diff)
FacebookRM: Version bump
Version 0.0.7.0 + Support for group chats (EXPERIMENTAL!) - enable it in options ! Fixed loading contact list ! Fixed potential freeze. Total downloads: (None or statistics not available yet) Version 0.0.6.1a Reuploaded. Total downloads: (None or statistics not available yet) Version 0.0.6.1 + Returned option to close chat windows (on website) + New option to map non-standard statuses to Invisible (insetad of Online) + New option to load contacts, which have "On the Phone" status ! Fixed changing chat visibility ! Very long messages are no longer received duplicitely ! Changes and fixes related to multiuser messages and messages from people, which are not in server-list Total downloads: (None or statistics not available yet) git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@261 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb
-rw-r--r--FacebookRM/build.h2
-rw-r--r--FacebookRM/chat.cpp328
-rw-r--r--FacebookRM/client.h9
-rw-r--r--FacebookRM/common.h2
-rw-r--r--FacebookRM/communication.cpp205
-rw-r--r--FacebookRM/connection.cpp10
-rw-r--r--FacebookRM/constants.h15
-rw-r--r--FacebookRM/contacts.cpp55
-rw-r--r--FacebookRM/db.h6
-rw-r--r--FacebookRM/dialogs.cpp17
-rw-r--r--FacebookRM/entities.h35
-rw-r--r--FacebookRM/facebook.rc46
-rw-r--r--FacebookRM/facebook.vcproj20
-rw-r--r--FacebookRM/facebook_10.sln3
-rw-r--r--FacebookRM/facebook_10.vcxproj18
-rw-r--r--FacebookRM/facebook_10.vcxproj.filters3
-rw-r--r--FacebookRM/icons/addFriend.icobin0 -> 2550 bytes
-rw-r--r--FacebookRM/icons/removeFriend.icobin0 -> 2550 bytes
-rw-r--r--FacebookRM/json.cpp248
-rw-r--r--FacebookRM/json.h1
-rw-r--r--FacebookRM/messages.cpp35
-rw-r--r--FacebookRM/process.cpp108
-rw-r--r--FacebookRM/proto.cpp117
-rw-r--r--FacebookRM/proto.h23
-rw-r--r--FacebookRM/resource.h21
-rw-r--r--FacebookRM/theme.cpp48
-rw-r--r--FacebookRM/theme.h2
-rw-r--r--FacebookRM/utils.cpp18
-rw-r--r--FacebookRM/utils.h1
29 files changed, 1113 insertions, 283 deletions
diff --git a/FacebookRM/build.h b/FacebookRM/build.h
index 81c7985..e409157 100644
--- a/FacebookRM/build.h
+++ b/FacebookRM/build.h
@@ -1 +1 @@
-#define __BUILD 1874
+#define __BUILD 2068
diff --git a/FacebookRM/chat.cpp b/FacebookRM/chat.cpp
new file mode 100644
index 0000000..8e0e007
--- /dev/null
+++ b/FacebookRM/chat.cpp
@@ -0,0 +1,328 @@
+/*
+
+Facebook plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011 Robert Pösel
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+
+void FacebookProto::UpdateChat(const char *chat_id, const char *id, const char *name, const char *message)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = mir_a2t(chat_id);
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.ptszText = mir_a2t_cp(message,CP_UTF8);
+ gce.time = ::time(NULL);
+ gce.dwFlags = GC_TCHAR;
+ gcd.iType = GC_EVENT_MESSAGE;
+ gce.bIsMe = !strcmp(id,facy.self_.user_id.c_str());
+ gce.dwFlags |= GCEF_ADDTOLOG;
+
+ gce.ptszNick = mir_a2t_cp(name,CP_UTF8);
+ gce.ptszUID = mir_a2t(id);
+
+ CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce));
+
+ mir_free(const_cast<TCHAR*>(gce.ptszUID));
+ mir_free(const_cast<TCHAR*>(gce.ptszNick));
+ mir_free(const_cast<TCHAR*>(gce.ptszText));
+ mir_free(const_cast<TCHAR*>(gcd.ptszID));
+
+
+ // Close chat window, if set
+ ForkThread( &FacebookProto::MessagingWorker, this, new send_messaging(chat_id, FACEBOOK_SEND_MESSAGE ) );
+}
+
+int FacebookProto::OnChatOutgoing(WPARAM wParam,LPARAM lParam)
+{
+ GCHOOK *hook = reinterpret_cast<GCHOOK*>(lParam);
+ char *text;
+ char *id;
+
+ if (strcmp(hook->pDest->pszModule,m_szModuleName))
+ return 0;
+
+ switch(hook->pDest->iType)
+ {
+ case GC_USER_MESSAGE:
+ {
+ text = mir_t2a_cp(hook->ptszText,CP_UTF8);
+ std::string msg = text;
+
+ id = mir_t2a_cp(hook->pDest->ptszID,CP_UTF8);
+ std::string chat_id = id;
+
+ mir_free(text);
+ mir_free(id);
+
+ if (isOnline()) {
+ LOG("**Chat - Outgoing message: %s", text);
+ ForkThread(&FacebookProto::SendChatMsgWorker, this, new send_chat(chat_id, msg) );
+ }
+
+ break;
+ }
+
+ case GC_USER_LEAVE:
+ case GC_SESSION_TERMINATE:
+ {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void FacebookProto::AddChatContact(const char *chat_id, const char *id, const char *name)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = mir_a2t(chat_id);
+ gcd.iType = GC_EVENT_JOIN;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR | GCEF_ADDTOLOG;
+ gce.ptszNick = mir_a2t_cp(name, CP_UTF8);
+ gce.ptszUID = mir_a2t(id);
+ gce.time = ::time(NULL);
+ gce.bIsMe = !strcmp(id, facy.self_.user_id.c_str());
+
+/* if (gce.bIsMe)
+ gce.ptszStatus = _T("Admin");
+ else*/
+ gce.ptszStatus = _T("Normal");
+
+ CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce));
+
+ mir_free(const_cast<TCHAR*>(gce.ptszNick));
+ mir_free(const_cast<TCHAR*>(gce.ptszUID));
+ mir_free(const_cast<TCHAR*>(gcd.ptszID));
+}
+
+
+void FacebookProto::RemoveChatContact(const char *chat_id, const char *id)
+{
+ // We dont want to remove our self-contact from chat. Ever.
+ if (!strcmp(id, facy.self_.user_id.c_str()))
+ return;
+
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = mir_a2t(chat_id);
+ gcd.iType = GC_EVENT_PART;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR | GCEF_ADDTOLOG;
+ //gce.ptszNick = mir_a2t_cp(name, CP_UTF8);
+ gce.ptszUID = mir_a2t(id);
+ gce.ptszNick = gce.ptszUID;
+ gce.time = ::time(NULL);
+ gce.bIsMe = false;//!strcmp(id, facy.self_.user_id.c_str());
+
+ CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce));
+
+ mir_free(const_cast<TCHAR*>(gcd.ptszID));
+ mir_free(const_cast<TCHAR*>(gce.ptszNick));
+ mir_free(const_cast<TCHAR*>(gce.ptszUID));
+}
+
+char *FacebookProto::GetChatUsers(const char *chat_id)
+{
+ GC_INFO gci = {0};
+ gci.Flags = USERS;
+ gci.pszModule = m_szModuleName;
+ gci.pszID = mir_a2t(chat_id);
+ CallService(MS_GC_GETINFO, 0, (LPARAM)(GC_INFO *) &gci);
+
+ LOG("**Chat - Users in chat %s: %s", chat_id, gci.pszUsers);
+
+ mir_free(gci.pszID);
+
+ // mir_free(gci.pszUsers);
+ return gci.pszUsers;
+}
+
+bool FacebookProto::IsChatContact(const char *chat_id, const char *id)
+{
+ char *users = GetChatUsers(chat_id);
+ bool found = false;
+
+ if (users != NULL && strstr(users, id) != NULL)
+ found = true;
+
+ mir_free(users);
+ return found;
+}
+
+void FacebookProto::AddChat(const char *id, const char *name)
+{
+ GCSESSION gcw = {sizeof(gcw)};
+
+ // Create the group chat session
+ gcw.dwFlags = GC_TCHAR;
+ gcw.iType = GCW_CHATROOM;
+ gcw.pszModule = m_szModuleName;
+ gcw.ptszName = mir_a2t_cp(name, CP_UTF8);
+ gcw.ptszID = mir_a2t(id);
+ CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw);
+
+ mir_free(const_cast<TCHAR*>(gcw.ptszName));
+ mir_free(const_cast<TCHAR*>(gcw.ptszID));
+
+ // Send setting events
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = mir_a2t(id);
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR;
+
+ // Create a user statuses
+ gcd.iType = GC_EVENT_ADDGROUP;
+ gce.ptszStatus = _T("Admin");
+ CallServiceSync( MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce) );
+ gce.ptszStatus = _T("Normal");
+ CallServiceSync( MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce) );
+
+ // Finish initialization
+ gcd.iType = GC_EVENT_CONTROL;
+ gce.time = ::time(NULL);
+ gce.pDest = &gcd;
+
+ // Add self contact
+ AddChatContact(id, facy.self_.user_id.c_str(), facy.self_.real_name.c_str());
+ CallServiceSync(MS_GC_EVENT,SESSION_INITDONE,reinterpret_cast<LPARAM>(&gce));
+ CallServiceSync(MS_GC_EVENT,SESSION_ONLINE, reinterpret_cast<LPARAM>(&gce));
+
+ mir_free(const_cast<TCHAR*>(gcd.ptszID));
+}
+
+
+int FacebookProto::OnJoinChat(WPARAM,LPARAM suppress)
+{
+/* GCSESSION gcw = {sizeof(gcw)};
+
+ // Create the group chat session
+ gcw.dwFlags = GC_TCHAR;
+ gcw.iType = GCW_CHATROOM;
+ gcw.pszModule = m_szModuleName;
+ gcw.ptszName = m_tszUserName;
+ gcw.ptszID = m_tszUserName;
+ CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw);
+
+ if(m_iStatus != ID_STATUS_ONLINE)
+ return 0;
+
+ // Create a group
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR;
+
+ gcd.iType = GC_EVENT_ADDGROUP;
+
+ gce.ptszStatus = _T("Admin");
+ CallServiceSync( MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce) );
+
+ gce.ptszStatus = _T("Normal");
+ CallServiceSync( MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce) );
+
+ SetTopic("Omegle is a great way of meeting new friends!");
+
+ // Note: Initialization will finish up in SetChatStatus, called separately
+ if(!suppress)
+ SetChatStatus(m_iStatus);
+*/
+ return 0;
+}
+
+/*void FacebookProto::SetTopic(const char *topic)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_TOPIC;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR;
+ gce.time = ::time(NULL);
+
+ std::string top = Translate(topic);
+ gce.ptszText = mir_a2t(top.c_str());
+ CallServiceSync(MS_GC_EVENT,0, reinterpret_cast<LPARAM>(&gce));
+}
+*/
+int FacebookProto::OnLeaveChat(WPARAM,LPARAM)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = NULL;
+ gcd.iType = GC_EVENT_CONTROL;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.dwFlags = GC_TCHAR;
+ gce.time = ::time(NULL);
+ gce.pDest = &gcd;
+
+ CallServiceSync(MS_GC_EVENT,SESSION_OFFLINE, reinterpret_cast<LPARAM>(&gce));
+ CallServiceSync(MS_GC_EVENT,SESSION_TERMINATE,reinterpret_cast<LPARAM>(&gce));
+
+ return 0;
+}
+/*
+void FacebookProto::SetChatStatus(int status)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_CONTROL;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.dwFlags = GC_TCHAR;
+ gce.time = ::time(NULL);
+ gce.pDest = &gcd;
+
+ if(status == ID_STATUS_ONLINE)
+ {
+ // Add self contact
+ AddChatContact(facy.nick_.c_str());
+
+ CallServiceSync(MS_GC_EVENT,SESSION_INITDONE,reinterpret_cast<LPARAM>(&gce));
+ CallServiceSync(MS_GC_EVENT,SESSION_ONLINE, reinterpret_cast<LPARAM>(&gce));
+ }
+ else
+ {
+ CallServiceSync(MS_GC_EVENT,SESSION_OFFLINE,reinterpret_cast<LPARAM>(&gce));
+ }
+}
+/*
+void FacebookProto::ClearChat()
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_CONTROL;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.dwFlags = GC_TCHAR;
+ gce.pDest = &gcd;
+
+ CallServiceSync(MS_GC_EVENT,WINDOW_CLEARLOG,reinterpret_cast<LPARAM>(&gce));
+}
+*/ \ No newline at end of file
diff --git a/FacebookRM/client.h b/FacebookRM/client.h
index 39b3c17..cff5c09 100644
--- a/FacebookRM/client.h
+++ b/FacebookRM/client.h
@@ -44,9 +44,7 @@ public:
chat_sequence_num_ = chat_channel_host_ = chat_channel_partition_ = chat_channel_jslogger_ = \
logout_hash_ = "";
- msgid_ = error_count_ = last_feeds_update_ = \
- last_notification_time_ = /*last_message_time_ =*/ \
- last_grpmessage_time_ = /*last_close_chat_time_ =*/ 0;
+ msgid_ = error_count_ = last_feeds_update_ = last_notification_time_ = 0;
invisible_ = is_typing_ = false;
@@ -83,9 +81,6 @@ public:
bool is_typing_;
time_t last_feeds_update_;
unsigned __int64 last_notification_time_;
- //unsigned __int64 last_message_time_;
- time_t last_grpmessage_time_;
- //time_t last_close_chat_time_;
int msgid_;
////////////////////////////////////////////////////////////
@@ -150,9 +145,9 @@ public:
HANDLE send_message_lock_;
bool buddy_list( );
+ bool facepiles( );
bool load_friends( );
bool feeds( );
- void delete_friends( );
////////////////////////////////////////////////////////////
diff --git a/FacebookRM/common.h b/FacebookRM/common.h
index c544d13..ce4e572 100644
--- a/FacebookRM/common.h
+++ b/FacebookRM/common.h
@@ -108,4 +108,4 @@ class FacebookProto;
extern HINSTANCE g_hInstance;
extern std::string g_strUserAgent;
-extern DWORD g_mirandaVersion;
+extern DWORD g_mirandaVersion; \ No newline at end of file
diff --git a/FacebookRM/communication.cpp b/FacebookRM/communication.cpp
index 174c084..3b8da48 100644
--- a/FacebookRM/communication.cpp
+++ b/FacebookRM/communication.cpp
@@ -224,15 +224,17 @@ DWORD facebook_client::choose_security_level( int request_type )
// case FACEBOOK_REQUEST_LOGOUT:
// case FACEBOOK_REQUEST_HOME:
// case FACEBOOK_REQUEST_BUDDY_LIST:
+// case FACEBOOK_REQUEST_FACEPILES:
// case FACEBOOK_REQUEST_LOAD_FRIENDS:
// case FACEBOOK_REQUEST_DELETE_FRIEND:
+// case FACEBOOK_REQUEST_ADD_FRIEND:
// case FACEBOOK_REQUEST_FEEDS:
// case FACEBOOK_REQUEST_NOTIFICATIONS:
// case FACEBOOK_REQUEST_RECONNECT:
// case FACEBOOK_REQUEST_STATUS_SET:
// case FACEBOOK_REQUEST_MESSAGE_SEND:
// case FACEBOOK_REQUEST_MESSAGES_RECEIVE:
-// case FACEBOOK_REQUEST_SETTINGS:
+// case FACEBOOK_REQUEST_VISIBILITY:
// case FACEBOOK_REQUEST_TABS:
// case FACEBOOK_REQUEST_ASYNC:
// case FACEBOOK_REQUEST_ASYNC_GET:
@@ -249,14 +251,16 @@ int facebook_client::choose_method( int request_type )
case FACEBOOK_REQUEST_LOGIN:
case FACEBOOK_REQUEST_SETUP_MACHINE:
case FACEBOOK_REQUEST_BUDDY_LIST:
+ case FACEBOOK_REQUEST_FACEPILES:
case FACEBOOK_REQUEST_STATUS_SET:
case FACEBOOK_REQUEST_MESSAGE_SEND:
- case FACEBOOK_REQUEST_SETTINGS:
+ case FACEBOOK_REQUEST_VISIBILITY:
case FACEBOOK_REQUEST_TABS:
case FACEBOOK_REQUEST_ASYNC:
case FACEBOOK_REQUEST_TYPING_SEND:
case FACEBOOK_REQUEST_LOGOUT:
case FACEBOOK_REQUEST_DELETE_FRIEND:
+ case FACEBOOK_REQUEST_ADD_FRIEND:
return REQUEST_POST;
// case FACEBOOK_REQUEST_HOME:
@@ -287,16 +291,18 @@ std::string facebook_client::choose_proto( int request_type )
// case FACEBOOK_REQUEST_NOTIFICATIONS:
// case FACEBOOK_REQUEST_RECONNECT:
// case FACEBOOK_REQUEST_BUDDY_LIST:
+// case FACEBOOK_REQUEST_FACEPILES:
// case FACEBOOK_REQUEST_LOAD_FRIENDS:
// case FACEBOOK_REQUEST_STATUS_SET:
// case FACEBOOK_REQUEST_MESSAGE_SEND:
// case FACEBOOK_REQUEST_MESSAGES_RECEIVE:
-// case FACEBOOK_REQUEST_SETTINGS:
+// case FACEBOOK_REQUEST_VISIBILITY:
// case FACEBOOK_REQUEST_TABS:
// case FACEBOOK_REQUEST_ASYNC:
// case FACEBOOK_REQUEST_ASYNC_GET:
// case FACEBOOK_REQUEST_TYPING_SEND:
// case FACEBOOK_REQUEST_DELETE_FRIEND:
+// case FACEBOOK_REQUEST_ADD_FRIEND:
default:
return HTTP_PROTO_REGULAR;
@@ -327,19 +333,21 @@ std::string facebook_client::choose_server( int request_type, std::string* data
// case FACEBOOK_REQUEST_LOGOUT:
// case FACEBOOK_REQUEST_HOME:
// case FACEBOOK_REQUEST_BUDDY_LIST:
+// case FACEBOOK_REQUEST_FACEPILES:
// case FACEBOOK_REQUEST_LOAD_FRIENDS:
// case FACEBOOK_REQUEST_FEEDS:
// case FACEBOOK_REQUEST_NOTIFICATIONS:
// case FACEBOOK_REQUEST_RECONNECT:
// case FACEBOOK_REQUEST_STATUS_SET:
// case FACEBOOK_REQUEST_MESSAGE_SEND:
-// case FACEBOOK_REQUEST_SETTINGS:
+// case FACEBOOK_REQUEST_VISIBILITY:
// case FACEBOOK_REQUEST_TABS:
// case FACEBOOK_REQUEST_ASYNC:
// case FACEBOOK_REQUEST_ASYNC_GET:
// case FACEBOOK_REQUEST_TYPING_SEND:
// case FACEBOOK_REQUEST_SETUP_MACHINE:
// case FACEBOOK_REQUEST_DELETE_FRIEND:
+// case FACEBOOK_REQUEST_ADD_FRIEND:
default:
return FACEBOOK_SERVER_REGULAR;
}
@@ -359,11 +367,14 @@ std::string facebook_client::choose_action( int request_type, std::string* data
return "/logout.php";
case FACEBOOK_REQUEST_HOME:
- return "/home.php";
+ return "/home.php?_fb_noscript=1";
case FACEBOOK_REQUEST_BUDDY_LIST:
return "/ajax/chat/buddy_list.php?__a=1";
+ case FACEBOOK_REQUEST_FACEPILES:
+ return "/ajax/groups/chat/update_facepiles.php?__a=1";
+
case FACEBOOK_REQUEST_LOAD_FRIENDS:
{
std::string action = "/ajax/chat/user_info_all.php?__a=1&viewer=%s";
@@ -376,6 +387,11 @@ std::string facebook_client::choose_action( int request_type, std::string* data
return "/ajax/profile/removefriend.php?__a=1";
}
+ case FACEBOOK_REQUEST_ADD_FRIEND:
+ {
+ return "/ajax/add_friend/action.php?__a=1";
+ }
+
case FACEBOOK_REQUEST_FEEDS:
{
std::string action = "/ajax/intent.php?filter=";
@@ -426,8 +442,8 @@ std::string facebook_client::choose_action( int request_type, std::string* data
return action;
}
- case FACEBOOK_REQUEST_SETTINGS:
- return "/ajax/chat/settings.php?__a=1";
+ case FACEBOOK_REQUEST_VISIBILITY:
+ return "/ajax/chat/visibility.php?__a=1";
case FACEBOOK_REQUEST_TABS:
return "/ajax/chat/tabs.php?__a=1";
@@ -446,7 +462,7 @@ std::string facebook_client::choose_action( int request_type, std::string* data
return "/ajax/messaging/typ.php?__a=1";
default:
- return "/";
+ return "/?_fb_noscript=1";
}
}
@@ -465,15 +481,17 @@ NETLIBHTTPHEADER* facebook_client::get_request_headers( int request_type, int* h
case FACEBOOK_REQUEST_LOGIN:
case FACEBOOK_REQUEST_SETUP_MACHINE:
case FACEBOOK_REQUEST_BUDDY_LIST:
+ case FACEBOOK_REQUEST_FACEPILES:
case FACEBOOK_REQUEST_LOAD_FRIENDS:
case FACEBOOK_REQUEST_STATUS_SET:
case FACEBOOK_REQUEST_MESSAGE_SEND:
- case FACEBOOK_REQUEST_SETTINGS:
+ case FACEBOOK_REQUEST_VISIBILITY:
case FACEBOOK_REQUEST_TABS:
case FACEBOOK_REQUEST_ASYNC:
case FACEBOOK_REQUEST_ASYNC_GET:
case FACEBOOK_REQUEST_TYPING_SEND:
case FACEBOOK_REQUEST_DELETE_FRIEND:
+ case FACEBOOK_REQUEST_ADD_FRIEND:
*headers_count = 5;
break;
@@ -494,15 +512,17 @@ NETLIBHTTPHEADER* facebook_client::get_request_headers( int request_type, int* h
case FACEBOOK_REQUEST_LOGIN:
case FACEBOOK_REQUEST_SETUP_MACHINE:
case FACEBOOK_REQUEST_BUDDY_LIST:
+ case FACEBOOK_REQUEST_FACEPILES:
case FACEBOOK_REQUEST_LOAD_FRIENDS:
case FACEBOOK_REQUEST_STATUS_SET:
case FACEBOOK_REQUEST_MESSAGE_SEND:
- case FACEBOOK_REQUEST_SETTINGS:
+ case FACEBOOK_REQUEST_VISIBILITY:
case FACEBOOK_REQUEST_TABS:
case FACEBOOK_REQUEST_ASYNC:
case FACEBOOK_REQUEST_ASYNC_GET:
case FACEBOOK_REQUEST_TYPING_SEND:
case FACEBOOK_REQUEST_DELETE_FRIEND:
+ case FACEBOOK_REQUEST_ADD_FRIEND:
headers[4].szName = "Content-Type";
headers[4].szValue = "application/x-www-form-urlencoded; charset=utf-8";
@@ -574,7 +594,7 @@ void facebook_client::store_headers( http::response* resp, NETLIBHTTPHEADER* hea
}
else
{ // TODO RM: (un)comment
- parent->Log("----- Got header '%s': %s", header_name.c_str(), header_value.c_str() );
+ //parent->Log("----- Got header '%s': %s", header_name.c_str(), header_value.c_str() );
resp->headers[header_name] = header_value;
}
}
@@ -768,13 +788,13 @@ bool facebook_client::home( )
// Get real_name
this->self_.real_name = utils::text::remove_html( utils::text::special_expressions_decode( utils::text::source_get_value( &resp.data, 2, " id=\"navAccountName\">", "</a" ) ) );
DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,FACEBOOK_KEY_NAME,this->self_.real_name.c_str());
- DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,"Nick",this->self_.real_name.c_str());
+ DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,FACEBOOK_KEY_NICK,this->self_.real_name.c_str());
parent->Log(" Got self real name: %s", this->self_.real_name.c_str());
} else if ( resp.data.find("id=\"pageNav\"") != std::string::npos ) {
// Get real_name
this->self_.real_name = utils::text::remove_html( utils::text::special_expressions_decode( utils::text::source_get_value( &resp.data, 3, " class=\"headerTinymanName\"", ">", "</a" ) ) );
DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,FACEBOOK_KEY_NAME,this->self_.real_name.c_str());
- DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,"Nick",this->self_.real_name.c_str());
+ DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,FACEBOOK_KEY_NICK,this->self_.real_name.c_str());
parent->Log(" Got self real name: %s", this->self_.real_name.c_str());
} else {
client_notify(TranslateT("Something happened to Facebook. Maybe there was some major update so you should wait for an update."));
@@ -791,11 +811,11 @@ bool facebook_client::home( )
parent->CheckAvatarChange(NULL, this->self_.image_url);
// Get post_form_id
- this->post_form_id_ = utils::text::source_get_value( &resp.data, 2, "post_form_id:\"", "\"" );
+ this->post_form_id_ = utils::text::source_get_value( &resp.data, 3, "name=\"post_form_id\"", "value=\"", "\"" );
parent->Log(" Got self post form id: %s", this->post_form_id_.c_str());
// Get dtsg
- this->dtsg_ = utils::text::source_get_value( &resp.data, 2, "fb_dtsg:\"", "\"" );
+ this->dtsg_ = utils::text::source_get_value( &resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\"" );
parent->Log(" Got self dtsg: %s", this->dtsg_.c_str());
// Get logout hash
@@ -836,35 +856,28 @@ bool facebook_client::home( )
ForkThread( &FacebookProto::ProcessNotifications, this->parent, NULL );
}
- // TODO RM: if enabled groupchats support
- // Get group chats
-/* std::string chat_ids = utils::text::source_get_value( &resp.data, 2, "HomeNavController.initGroupCounts([","]" );
- if ( chat_ids.length() )
- {
+ // TODO RM: if enabled groupchats support
- // split by comma to ids, find names in source, inicialize groups in contactlist
- // maybe check which groupchats user wants
- // add to list? start worker for parse and add contacts to groupchat
- // add "," to end for better parsing
- chat_ids += ",";
- std::string::size_type oldpos = 0, pos = 0;
-
- while ( ( pos = chat_ids.find(",", oldpos) ) != std::string::npos )
- {
- std::string id = chat_ids.substr(oldpos, pos-oldpos);
- std::string name = utils::text::trim(
- utils::text::special_expressions_decode(
- utils::text::remove_html(
- utils::text::edit_html(
- utils::text::source_get_value( &resp.data, 5, "HomeNavController.initGroupCounts", "home.php?sk=group_", id.c_str(), "input title=\\\"", "\\\" " ) ) ) ) );
-
- parent->Log(" Got groupchat id: %s, name: %s", id.c_str(), name.c_str());
- oldpos = pos+1;
-
- parent->AddChat(id.c_str(), name.c_str());
- }
- }*/
+ if (DBGetContactSettingByte(NULL, parent->m_szModuleName, FACEBOOK_KEY_ENABLE_GROUPCHATS, DEFAULT_ENABLE_GROUPCHATS)) {
+ // Get group chats
+ std::string favorites = utils::text::source_get_value( &resp.data, 2, "<div id=\"leftCol\"", "<div id=\"contentCol\"" );
+
+ std::string::size_type pos = 0;
+ while ((pos = favorites.find("href=\"/groups/",pos)) != std::string::npos) {
+ pos += 14;
+ std::string item = favorites.substr(pos, favorites.find("</a>", pos) - pos);
+ std::string id = item.substr(0, item.find("/"));
+
+ if (!id.empty()) {
+ std::string name = utils::text::source_get_value( &item, 3, "class=\"linkWrap", ">", "</div>" );
+ name = utils::text::special_expressions_decode(utils::text::slashu_to_utf8( name ) );
+ parent->Log(" Got new group chat: %s (id: %s)", name.c_str(), id.c_str());
+ if (!name.empty())
+ parent->AddChat(id.c_str(), name.c_str());
+ }
+ }
+ }
return handle_success( "home" );
@@ -891,7 +904,7 @@ bool facebook_client::chat_state( bool online )
data += "&post_form_id_source=AsyncRequest";
data += "&fb_dtsg=" + this->dtsg_;
data += "&lsd=";
- http::response resp = flap( FACEBOOK_REQUEST_SETTINGS, &data );
+ http::response resp = flap( FACEBOOK_REQUEST_VISIBILITY, &data );
return handle_success( "chat_state" );
}
@@ -942,16 +955,16 @@ bool facebook_client::buddy_list( )
handle_entry( "buddy_list" );
// Prepare update data
- std::string data = "user=" + this->self_.user_id + "&force_render=true&fetch_mobile=true&post_form_id=" + this->post_form_id_ + "&fb_dtsg=" + this->dtsg_ + "&lsd=&post_form_id_source=AsyncRequest&__user=" + this->self_.user_id;
+ std::string data = "user=" + this->self_.user_id + "&fetch_mobile=true&post_form_id=" + this->post_form_id_ + "&fb_dtsg=" + this->dtsg_ + "&lsd=&post_form_id_source=AsyncRequest&__user=" + this->self_.user_id;
{
ScopedLock s(buddies_lock_);
int counter = 0;
- for (List::Item< facebook_user >* i = buddies.begin(); i != NULL; i = i->next )
+ for (List::Item< facebook_user >* i = buddies.begin(); i != NULL; i = i->next, counter++ )
{
data += "&available_user_info_ids[";
- data += counter++;
+ data += utils::conversion::to_string(&counter, UTILS_CONV_UNSIGNED_NUMBER);
data += "]=";
data += i->data->user_id;
}
@@ -966,12 +979,11 @@ bool facebook_client::buddy_list( )
switch ( resp.code )
{
case HTTP_CODE_OK:
- if ( resp.data.find( "\"listChanged\":true" ) != std::string::npos )
- {
- std::string* response_data = new std::string( resp.data );
- ForkThread( &FacebookProto::ProcessBuddyList, this->parent, ( void* )response_data );
- }
+ {
+ std::string* response_data = new std::string( resp.data );
+ ForkThread( &FacebookProto::ProcessBuddyList, this->parent, ( void* )response_data );
return handle_success( "buddy_list" );
+ }
case HTTP_CODE_FAKE_ERROR:
case HTTP_CODE_FAKE_DISCONNECTED:
@@ -980,6 +992,51 @@ bool facebook_client::buddy_list( )
}
}
+bool facebook_client::facepiles( )
+{
+ handle_entry( "facepiles" );
+
+ int count = (int)CallServiceSync(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)parent->m_szModuleName);
+ for ( int i = 0; i < count; i++ ) {
+ GC_INFO gci = {0};
+ gci.Flags = BYINDEX | TYPE | ID;
+ gci.iItem = i;
+ gci.pszModule = parent->m_szModuleName;
+ if ( !CallServiceSync( MS_GC_GETINFO, 0, (LPARAM)&gci ) && gci.iType == GCW_CHATROOM ) {
+ char *id = mir_t2a(gci.pszID);
+
+ // Prepare data
+ std::string data = "id=";
+ data += id;
+ data += "&post_form_id=" + this->post_form_id_ + "&fb_dtsg=" + this->dtsg_ + "&lsd=&post_form_id_source=AsyncRequest&__user=" + this->self_.user_id + "&phstamp=0";
+
+ // Get facepiles
+ http::response resp = flap( FACEBOOK_REQUEST_FACEPILES, &data );
+
+ // Process result data
+ validate_response(&resp);
+
+ std::string chat_id = id;
+ mir_free(id);
+
+ switch ( resp.code )
+ {
+ case HTTP_CODE_OK:
+ ForkThread( &FacebookProto::ProcessFacepiles, this->parent, new send_chat(chat_id, resp.data) );
+ break;
+
+ case HTTP_CODE_FAKE_ERROR:
+ case HTTP_CODE_FAKE_DISCONNECTED:
+ default:
+ return handle_error( "facepiles" );
+ }
+
+ }
+ }
+
+ return handle_success( "facepiles" );
+}
+
bool facebook_client::load_friends( )
{
handle_entry( "load_friends" );
@@ -1037,42 +1094,6 @@ bool facebook_client::feeds( )
}
}
-void facebook_client::delete_friends( )
-{
- handle_entry( "delete_friends" );
-
- // Check and update old contacts
- for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
- hContact;
- hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0) )
- {
- if(!parent->IsMyContact(hContact))
- continue;
-
- if( !DBGetContactSettingByte(hContact,parent->m_szModuleName,FACEBOOK_KEY_DELETE_NEXT,0) ) {
- DBVARIANT dbv;
- if( !DBGetContactSettingString(hContact,parent->m_szModuleName,FACEBOOK_KEY_ID,&dbv) ) {
- std::string* id = new std::string(dbv.pszVal);
- DBFreeVariant(&dbv);
-
- if( !DBGetContactSettingString(hContact,parent->m_szModuleName,FACEBOOK_KEY_NAME,&dbv) ) {
-
- TCHAR* szTitle = mir_a2t_cp(dbv.pszVal, CP_UTF8);
- parent->NotifyEvent(szTitle, TranslateT("Contact was deleted."), hContact, FACEBOOK_EVENT_CLIENT, NULL);
- mir_free( szTitle );
- DBFreeVariant(&dbv);
-
- CallService(MS_DB_CONTACT_DELETE,(WPARAM)hContact,0);
-
- ForkThread( &FacebookProto::DeleteContactFromServer, this->parent, ( void* )id );
- }
- }
- }
- }
-
- handle_success( "delete_friends" );
-}
-
bool facebook_client::channel( )
{
handle_entry( "channel" );
@@ -1131,6 +1152,12 @@ bool facebook_client::channel( )
case HTTP_CODE_FAKE_DISCONNECTED:
case HTTP_CODE_FAKE_ERROR:
default:
+ // Testing workaround for channel change
+ if (!this->chat_channel_jslogger_.empty())
+ this->chat_channel_jslogger_ = "_";
+ else
+ this->chat_channel_jslogger_.clear();
+
return handle_error( "channel" );
}
}
@@ -1191,7 +1218,8 @@ bool facebook_client::send_message( std::string message_recipient, std::string m
case 1356003: // Contact is offline
{
HANDLE hContact = parent->ContactIDToHContact( message_recipient );
- DBWriteContactSettingWord(hContact,parent->m_szModuleName,"Status",ID_STATUS_OFFLINE);
+ if (hContact != NULL)
+ DBWriteContactSettingWord(hContact,parent->m_szModuleName,"Status",ID_STATUS_OFFLINE);
return false;
} break;
@@ -1225,6 +1253,7 @@ bool facebook_client::send_message( std::string message_recipient, std::string m
case HTTP_CODE_FAKE_DISCONNECTED:
default:
*error_text = Translate("Timeout when sending message.");
+
handle_error( "send_message" );
return false;
}
diff --git a/FacebookRM/connection.cpp b/FacebookRM/connection.cpp
index b546e79..d871ee1 100644
--- a/FacebookRM/connection.cpp
+++ b/FacebookRM/connection.cpp
@@ -55,6 +55,8 @@ void FacebookProto::ChangeStatus(void*)
ProtoBroadcastAck(m_szModuleName, 0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
+ OnLeaveChat(NULL, NULL);
+
SetAllContactStatuses( ID_STATUS_OFFLINE );
ToggleStatusMenuItems(false);
@@ -83,7 +85,6 @@ void FacebookProto::ChangeStatus(void*)
facy.home();
facy.reconnect();
- facy.delete_friends();
facy.load_friends();
setDword( "LogonTS", (DWORD)time(NULL) );
@@ -118,6 +119,7 @@ void FacebookProto::ChangeStatus(void*)
facy.chat_state( m_iDesiredStatus != ID_STATUS_INVISIBLE );
facy.buddy_list( );
+ facy.facepiles( );
m_iStatus = facy.self_.status_id = m_iDesiredStatus;
ProtoBroadcastAck(m_szModuleName, 0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
@@ -179,10 +181,14 @@ void FacebookProto::UpdateLoop(void *)
for ( int i = -1; !isOffline(); i = ++i % 6 )
{
- if ( i != -1 )
+ if ( i != -1 ) {
if ( !facy.invisible_ )
if ( !facy.buddy_list( ) )
break;
+ if ( getByte( FACEBOOK_KEY_ENABLE_GROUPCHATS, DEFAULT_ENABLE_GROUPCHATS) )
+ if ( !facy.facepiles( ) )
+ break;
+ }
if ( i == 2 && getByte( FACEBOOK_KEY_EVENT_FEEDS_ENABLE, DEFAULT_EVENT_FEEDS_ENABLE ) )
if ( !facy.feeds( ) )
break;
diff --git a/FacebookRM/constants.h b/FacebookRM/constants.h
index 7c5171c..a9a7844 100644
--- a/FacebookRM/constants.h
+++ b/FacebookRM/constants.h
@@ -29,13 +29,13 @@ Last change on : $Date$
// Version management
#include "build.h"
-#define __VERSION_DWORD PLUGIN_MAKE_VERSION(0, 0, 6, 0)
+#define __VERSION_DWORD PLUGIN_MAKE_VERSION(0, 0, 7, 0)
#define __PRODUCT_DWORD PLUGIN_MAKE_VERSION(0, 9, 14, 0)
-#define __VERSION_STRING "0.0.6.0"
+#define __VERSION_STRING "0.0.7.0"
#define __PRODUCT_STRING "0.9.14.0"
-#define __VERSION_VS_FILE 0,0,6,0
+#define __VERSION_VS_FILE 0,0,7,0
#define __VERSION_VS_PROD 0,9,14,0
-#define __VERSION_VS_FILE_STRING "0, 0, 6, 0"
+#define __VERSION_VS_FILE_STRING "0, 0, 7, 0"
#define __VERSION_VS_PROD_STRING "0, 9, 14, 0"
// Product management
@@ -77,6 +77,9 @@ Last change on : $Date$
#define DEFAULT_BIG_AVATARS 0
#define DEFAULT_DISCONNECT_CHAT 0
#define DEFAULT_PARSE_MESSAGES 0
+#define DEFAULT_MAP_STATUSES 0
+#define DEFAULT_LOAD_MOBILE 0
+#define DEFAULT_ENABLE_GROUPCHATS 0
#define DEFAULT_EVENT_NOTIFICATIONS_ENABLE 1
#define DEFAULT_EVENT_FEEDS_ENABLE 1
@@ -101,6 +104,8 @@ Last change on : $Date$
#define FACEBOOK_REQUEST_BUDDY_LIST 120 // getting regular updates (friends online, ...)
#define FACEBOOK_REQUEST_LOAD_FRIENDS 121 // getting list of all friends
#define FACEBOOK_REQUEST_DELETE_FRIEND 122 // deleting friends
+#define FACEBOOK_REQUEST_ADD_FRIEND 123 // adding friends
+#define FACEBOOK_REQUEST_FACEPILES 124 // getting list of contacts in chat
#define FACEBOOK_REQUEST_FEEDS 125 // getting feeds
#define FACEBOOK_REQUEST_NOTIFICATIONS 126 // getting notifications
#define FACEBOOK_REQUEST_RECONNECT 130 // getting __sequence_num__ and __channel_id__
@@ -108,7 +113,7 @@ Last change on : $Date$
#define FACEBOOK_REQUEST_MESSAGE_SEND 300 // sending message
#define FACEBOOK_REQUEST_MESSAGES_RECEIVE 301 // receiving messages
#define FACEBOOK_REQUEST_TYPING_SEND 304 // sending typing notification
-#define FACEBOOK_REQUEST_SETTINGS 305 // setting chat visibility
+#define FACEBOOK_REQUEST_VISIBILITY 305 // setting chat visibility
#define FACEBOOK_REQUEST_TABS 306 // closing message window, setting chat visibility
#define FACEBOOK_REQUEST_ASYNC 307 // marking messages read and getting other things
#define FACEBOOK_REQUEST_ASYNC_GET 308 // GET version of async request
diff --git a/FacebookRM/contacts.cpp b/FacebookRM/contacts.cpp
index de01800..1f0a007 100644
--- a/FacebookRM/contacts.cpp
+++ b/FacebookRM/contacts.cpp
@@ -68,7 +68,7 @@ HANDLE FacebookProto::ContactIDToHContact(std::string user_id)
return 0;
}
-HANDLE FacebookProto::AddToContactList(facebook_user* fbu, bool dont_check)
+HANDLE FacebookProto::AddToContactList(facebook_user* fbu, bool dont_check, const char *new_name)
{
HANDLE hContact;
@@ -98,7 +98,13 @@ HANDLE FacebookProto::AddToContactList(facebook_user* fbu, bool dont_check)
DBWriteContactSettingTString(hContact,"CList","Group",dbv.ptszVal);
DBFreeVariant(&dbv);
}
-
+
+ if (strlen(new_name) > 0) {
+ DBWriteContactSettingUTF8String(hContact, m_szModuleName, FACEBOOK_KEY_NAME, new_name);
+ DBWriteContactSettingUTF8String(hContact, m_szModuleName, FACEBOOK_KEY_NICK, new_name);
+ DBWriteContactSettingByte(hContact, m_szModuleName, FACEBOOK_KEY_CONTACT_TYPE, 1); // We suppose he is not on server list
+ }
+
if (getByte(FACEBOOK_KEY_DISABLE_STATUS_NOTIFY, 0))
CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, (LPARAM)IGNOREEVENT_USERONLINE);
@@ -154,10 +160,46 @@ void FacebookProto::DeleteContactFromServer(void *data)
if (resp.code != HTTP_CODE_OK) {
facy.handle_error( "DeleteContactFromServer" );
}
+
+ NotifyEvent(TranslateT("Deleting contact"), TranslateT("Contact was sucessfully removed from server."), NULL, FACEBOOK_EVENT_OTHER, NULL);
+
+ delete data;
+}
+
+void FacebookProto::AddContactToServer(void *data)
+{
+ facy.handle_entry( "AddContactToServer" );
+
+ if ( data == NULL )
+ return;
+
+ std::string *id = (std::string*)data;
+ std::string query = "action=add_friend&how_found=profile_button&ref_param=ts&outgoing_id=&unwanted=&logging_location=&no_flyout_on_click=false&ego_log_data=&post_form_id_source=AsyncRequest&lsd=&fb_dtsg=";
+ query += facy.dtsg_;
+ query += "&post_form_id=";
+ query += facy.post_form_id_;
+ query += "&to_friend=";
+ query += *id;
+ query += "&__user=";
+ query += facy.self_.user_id;
+
+ // Get unread inbox threads
+ http::response resp = facy.flap( FACEBOOK_REQUEST_ADD_FRIEND, &query );
+
+ // Process result data
+ facy.validate_response(&resp);
+
+ if (resp.code != HTTP_CODE_OK || resp.data.find("\"success\":true") == std::string::npos) {
+ facy.handle_error( "AddContactToServer" );
+ }
+// RM TODO: better notify...
+ NotifyEvent(TranslateT("Adding contact"), TranslateT("Request for friendship was sent successfully."), NULL, FACEBOOK_EVENT_OTHER, NULL);
+
delete data;
}
+
HANDLE FacebookProto::GetAwayMsg(HANDLE hContact)
{
return 0; // Status messages are disabled
@@ -169,7 +211,7 @@ int FacebookProto::OnContactDeleted(WPARAM wparam,LPARAM)
if (IsMyContact(hContact))
{
- if (!DBGetContactSettingByte(hContact,m_szModuleName,FACEBOOK_KEY_DELETE_NEXT,0)) {
+// if (!DBGetContactSettingByte(hContact,m_szModuleName,FACEBOOK_KEY_DELETE_NEXT,0)) {
if (MessageBox( 0, TranslateT("Do you want to delete this contact also from server list?"), m_tszUserName, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2 ) == IDYES) {
DBVARIANT dbv;
if( !DBGetContactSettingString(hContact,m_szModuleName,FACEBOOK_KEY_ID,&dbv) )
@@ -179,16 +221,17 @@ int FacebookProto::OnContactDeleted(WPARAM wparam,LPARAM)
ForkThread( &FacebookProto::DeleteContactFromServer, this, ( void* )id );
DBFreeVariant(&dbv);
} else {
- facebook_user fbu;
+/* facebook_user fbu;
fbu.user_id = dbv.pszVal;
hContact = AddToContactList(&fbu);
DBWriteContactSettingByte(hContact,m_szModuleName,FACEBOOK_KEY_DELETE_NEXT,1);
- facy.client_notify(TranslateT("Contact will be deleted at next login."));
+ facy.client_notify(TranslateT("Contact will be deleted at next login."));*/
+ NotifyEvent(TranslateT("Deleting contact"), TranslateT("Contact wasn't deleted, because you are not connected."), NULL, FACEBOOK_EVENT_OTHER, NULL);
}
}
}
- }
+// }
ScopedLock s(facy.buddies_lock_);
diff --git a/FacebookRM/db.h b/FacebookRM/db.h
index 8278889..4c8afcf 100644
--- a/FacebookRM/db.h
+++ b/FacebookRM/db.h
@@ -46,12 +46,13 @@ Last change on : $Date: 2011-01-08 11:10:34 +0100 (so, 08 1 2011) $
#define FACEBOOK_KEY_LOGIN "Email"
#define FACEBOOK_KEY_ID "ID"
#define FACEBOOK_KEY_NAME "RealName"
+#define FACEBOOK_KEY_NICK "Nick"
#define FACEBOOK_KEY_PASS "Password"
#define FACEBOOK_KEY_UPD_NAMES "UpdateNames"
#define FACEBOOK_KEY_DEVICE_ID "DeviceID"
#define FACEBOOK_KEY_AV_URL "AvatarURL"
#define FACEBOOK_KEY_DELETED "Deleted"
-#define FACEBOOK_KEY_DELETE_NEXT "DeleteNext"
+#define FACEBOOK_KEY_CONTACT_TYPE "ContactType"
#define FACEBOOK_KEY_DEF_GROUP "DefaultGroup"
#define FACEBOOK_KEY_FORCE_HTTPS "ForceHTTPS"
@@ -64,6 +65,9 @@ Last change on : $Date: 2011-01-08 11:10:34 +0100 (so, 08 1 2011) $
#define FACEBOOK_KEY_PARSE_MESSAGES "ParseUnreadMessages"
#define FACEBOOK_KEY_BIG_AVATARS "UseBigAvatars"
#define FACEBOOK_KEY_DISCONNECT_CHAT "DisconnectChatEnable"
+#define FACEBOOK_KEY_MAP_STATUSES "MapStatuses"
+#define FACEBOOK_KEY_LOAD_MOBILE "LoadMobile"
+#define FACEBOOK_KEY_ENABLE_GROUPCHATS "GroupchatsEnable"
#define FACEBOOK_KEY_POLL_RATE "PollRate" // [HIDDEN]
#define FACEBOOK_KEY_TIMEOUTS_LIMIT "TimeoutsLimit" // [HIDDEN]
diff --git a/FacebookRM/dialogs.cpp b/FacebookRM/dialogs.cpp
index aa58ff3..309bbad 100644
--- a/FacebookRM/dialogs.cpp
+++ b/FacebookRM/dialogs.cpp
@@ -227,15 +227,19 @@ INT_PTR CALLBACK FBOptionsProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM l
DBFreeVariant(&dbv);
}
- LoadDBCheckState(proto, hwnd, IDC_SECURE, FACEBOOK_KEY_FORCE_HTTPS, DEFAULT_FORCE_HTTPS);
+ LoadDBCheckState(proto, hwnd, IDC_SECURE, FACEBOOK_KEY_FORCE_HTTPS, DEFAULT_FORCE_HTTPS);
LoadDBCheckState(proto, hwnd, IDC_SECURE_CHANNEL, FACEBOOK_KEY_FORCE_HTTPS_CHANNEL, DEFAULT_FORCE_HTTPS_CHANNEL);
LoadDBCheckState(proto, hwnd, IDC_SET_IGNORE_STATUS, FACEBOOK_KEY_DISABLE_STATUS_NOTIFY, DEFAULT_DISABLE_STATUS_NOTIFY);
LoadDBCheckState(proto, hwnd, IDC_BIGGER_AVATARS, FACEBOOK_KEY_BIG_AVATARS, DEFAULT_BIG_AVATARS);
LoadDBCheckState(proto, hwnd, IDC_DISCONNECT_CHAT, FACEBOOK_KEY_DISCONNECT_CHAT, DEFAULT_DISCONNECT_CHAT);
- LoadDBCheckState(proto, hwnd, IDC_PARSE_UNREAD, FACEBOOK_KEY_PARSE_MESSAGES, DEFAULT_PARSE_MESSAGES);
+ LoadDBCheckState(proto, hwnd, IDC_PARSE_UNREAD, FACEBOOK_KEY_PARSE_MESSAGES, DEFAULT_PARSE_MESSAGES);
LoadDBCheckState(proto, hwnd, IDC_CLOSE_WINDOWS, FACEBOOK_KEY_CLOSE_WINDOWS_ENABLE, DEFAULT_CLOSE_WINDOWS_ENABLE);
LoadDBCheckState(proto, hwnd, IDC_SET_STATUS, FACEBOOK_KEY_SET_MIRANDA_STATUS, DEFAULT_SET_MIRANDA_STATUS);
- LoadDBCheckState(proto, hwnd, IDC_LOGGING, FACEBOOK_KEY_LOGGING_ENABLE, DEFAULT_LOGGING_ENABLE);
+ LoadDBCheckState(proto, hwnd, IDC_LOGGING, FACEBOOK_KEY_LOGGING_ENABLE, DEFAULT_LOGGING_ENABLE);
+ LoadDBCheckState(proto, hwnd, IDC_MAP_STATUSES, FACEBOOK_KEY_MAP_STATUSES, DEFAULT_MAP_STATUSES);
+ LoadDBCheckState(proto, hwnd, IDC_LOAD_MOBILE, FACEBOOK_KEY_LOAD_MOBILE, DEFAULT_LOAD_MOBILE);
+ LoadDBCheckState(proto, hwnd, IDC_GROUPCHATS, FACEBOOK_KEY_ENABLE_GROUPCHATS, DEFAULT_ENABLE_GROUPCHATS);
+
EnableWindow(GetDlgItem(hwnd, IDC_SECURE_CHANNEL), IsDlgButtonChecked(hwnd, IDC_SECURE));
@@ -287,12 +291,15 @@ INT_PTR CALLBACK FBOptionsProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM l
StoreDBCheckState(proto, hwnd, IDC_SECURE, FACEBOOK_KEY_FORCE_HTTPS);
StoreDBCheckState(proto, hwnd, IDC_CLOSE_WINDOWS, FACEBOOK_KEY_CLOSE_WINDOWS_ENABLE);
- StoreDBCheckState(proto, hwnd, IDC_LOGGING, FACEBOOK_KEY_LOGGING_ENABLE);
+ StoreDBCheckState(proto, hwnd, IDC_LOGGING, FACEBOOK_KEY_LOGGING_ENABLE);
StoreDBCheckState(proto, hwnd, IDC_SECURE_CHANNEL, FACEBOOK_KEY_FORCE_HTTPS_CHANNEL);
StoreDBCheckState(proto, hwnd, IDC_SET_IGNORE_STATUS, FACEBOOK_KEY_DISABLE_STATUS_NOTIFY);
StoreDBCheckState(proto, hwnd, IDC_BIGGER_AVATARS, FACEBOOK_KEY_BIG_AVATARS);
StoreDBCheckState(proto, hwnd, IDC_DISCONNECT_CHAT, FACEBOOK_KEY_DISCONNECT_CHAT);
StoreDBCheckState(proto, hwnd, IDC_PARSE_UNREAD, FACEBOOK_KEY_PARSE_MESSAGES);
+ StoreDBCheckState(proto, hwnd, IDC_MAP_STATUSES, FACEBOOK_KEY_MAP_STATUSES);
+ StoreDBCheckState(proto, hwnd, IDC_LOAD_MOBILE, FACEBOOK_KEY_LOAD_MOBILE);
+ StoreDBCheckState(proto, hwnd, IDC_GROUPCHATS, FACEBOOK_KEY_ENABLE_GROUPCHATS);
BOOL setStatus = IsDlgButtonChecked(hwnd, IDC_SET_STATUS);
BOOL setStatusOld = DBGetContactSettingByte(NULL, proto->m_szModuleName, FACEBOOK_KEY_SET_MIRANDA_STATUS, DEFAULT_SET_MIRANDA_STATUS);
@@ -406,8 +413,6 @@ INT_PTR CALLBACK FBEventsProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
{
if ( reinterpret_cast<NMHDR*>(lparam)->code == PSN_APPLY )
{
- DBWriteContactSettingByte(NULL, proto->m_szModuleName, FACEBOOK_KEY_FEED_TYPE, SendDlgItemMessage(hwnd, IDC_FEEDS_TYPE, CB_GETCURSEL, 0, 0));
-
StoreDBCheckState(proto, hwnd, IDC_SYSTRAY_NOTIFY, FACEBOOK_KEY_SYSTRAY_NOTIFY);
StoreDBCheckState(proto, hwnd, IDC_NOTIFICATIONS_ENABLE, FACEBOOK_KEY_EVENT_NOTIFICATIONS_ENABLE);
diff --git a/FacebookRM/entities.h b/FacebookRM/entities.h
index 432af9f..c09c20d 100644
--- a/FacebookRM/entities.h
+++ b/FacebookRM/entities.h
@@ -63,11 +63,12 @@ struct facebook_message
{
std::string user_id;
std::string message_text;
+ std::string sender_name;
time_t time;
facebook_message( )
{
- this->user_id = this->message_text = "";
+ this->user_id = this->message_text = this->sender_name = "";
this->time = 0;
}
@@ -75,6 +76,7 @@ struct facebook_message
{
this->user_id = msg.user_id;
this->message_text = msg.message_text;
+ this->sender_name = msg.sender_name;
this->time = msg.time;
}
};
@@ -103,3 +105,34 @@ struct facebook_newsfeed
this->user_id = this->title = this->text = this->link = "";
}
};
+
+
+struct send_chat
+{
+ send_chat(const std::string &chat_id,const std::string &msg) : chat_id(chat_id), msg(msg) {}
+ std::string chat_id;
+ std::string msg;
+};
+
+
+struct send_direct
+{
+ send_direct(HANDLE hContact,const std::string &msg, HANDLE msgid) : hContact(hContact), msg(msg), msgid(msgid) {}
+ HANDLE hContact;
+ std::string msg;
+ HANDLE msgid;
+};
+
+struct send_typing
+{
+ send_typing(HANDLE hContact,const int status) : hContact(hContact), status(status) {}
+ HANDLE hContact;
+ int status;
+};
+
+struct send_messaging
+{
+ send_messaging(const std::string &user_id, const int type) : user_id(user_id), type(type) {}
+ std::string user_id;
+ int type;
+};
diff --git a/FacebookRM/facebook.rc b/FacebookRM/facebook.rc
index 6516e4a..be34e49 100644
--- a/FacebookRM/facebook.rc
+++ b/FacebookRM/facebook.rc
@@ -55,6 +55,8 @@ END
// remains consistent on all systems.
IDI_FACEBOOK ICON "icons/facebook.ico"
IDI_MIND ICON "icons/mind.ico"
+IDI_ADDFRIEND ICON "icons/addFriend.ico"
+IDI_REMOVEFRIEND ICON "icons/removeFriend.ico"
/////////////////////////////////////////////////////////////////////////////
//
@@ -91,30 +93,38 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- GROUPBOX "User Details",IDC_STATIC,50,7,224,58
- LTEXT "E-mail:",IDC_STATIC,59,19,60,8
- EDITTEXT IDC_UN,123,17,144,13,ES_AUTOHSCROLL
- LTEXT "Password:",IDC_STATIC,59,34,60,8
- EDITTEXT IDC_PW,123,32,144,13,ES_PASSWORD | ES_AUTOHSCROLL
+ GROUPBOX "User Details",IDC_STATIC,50,7,224,52
+ LTEXT "E-mail:",IDC_STATIC,59,17,60,8
+ EDITTEXT IDC_UN,123,15,144,13,ES_AUTOHSCROLL
+ LTEXT "Password:",IDC_STATIC,59,30,60,8
+ EDITTEXT IDC_PW,123,28,144,13,ES_PASSWORD | ES_AUTOHSCROLL
CONTROL "Create a new Facebook account",IDC_NEWACCOUNTLINK,
- "Hyperlink",WS_TABSTOP,123,50,144,10
- LTEXT "Default group:",IDC_STATIC,59,84,60,8
- EDITTEXT IDC_GROUP,123,84,144,13,ES_AUTOHSCROLL
+ "Hyperlink",WS_TABSTOP,123,44,144,10
+ LTEXT "Default group:",IDC_STATIC,59,75,60,8
+ EDITTEXT IDC_GROUP,123,75,144,13,ES_AUTOHSCROLL
CONTROL "Automatically set 'Ignore status change' flag",IDC_SET_IGNORE_STATUS,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,100,208,10
- GROUPBOX "Contacts Settings",IDC_STATIC,50,71,224,57
- CONTROL "Use bigger avatars",IDC_BIGGER_AVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,113,208,10
- GROUPBOX "Advanced Settings",IDC_STATIC,50,135,224,98
- CONTROL "Force secure (HTTPS) connection",IDC_SECURE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,159,208,10
- CONTROL "Post Miranda statuses to Wall",IDC_SET_STATUS,"Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,59,188,208,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,90,208,10
+ GROUPBOX "Contacts Settings",IDC_STATIC,50,62,224,64
+ CONTROL "Use bigger avatars",IDC_BIGGER_AVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,101,208,10
+ GROUPBOX "Advanced Settings",IDC_STATIC,50,128,224,117
+ CONTROL "Force secure (HTTPS) connection",IDC_SECURE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,149,208,10
+ CONTROL "Post Miranda statuses to Wall",IDC_SET_STATUS,"Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,59,172,208,10
CONTROL "Enable logging for debugging purposes",IDC_LOGGING,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,146,208,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,138,208,10
CONTROL "Use secure connection also for channel requests",IDC_SECURE_CHANNEL,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,69,172,198,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,69,160,198,10
CONTROL "Also disconnect chat when going to offline",IDC_DISCONNECT_CHAT,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,202,208,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,184,208,10
CONTROL "Get unread messages on login (EXPERIMENTAL)",IDC_PARSE_UNREAD,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,215,208,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,220,208,10
+ CONTROL "Automatically close chat windows (on website)",IDC_CLOSE_WINDOWS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,196,208,10
+ CONTROL "Map non-standard statuses to Invisible (instead of Online)",IDC_MAP_STATUSES,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,208,208,10
+ CONTROL "Load contacts with 'On the Mobile' status",IDC_LOAD_MOBILE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,112,208,10
+ CONTROL "Enable groupchats support (EXPERIMENTAL)",IDC_GROUPCHATS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,232,208,10
END
IDD_OPTIONS_EVENTS DIALOGEX 0, 0, 305, 217
diff --git a/FacebookRM/facebook.vcproj b/FacebookRM/facebook.vcproj
index c467ae1..4d3aebe 100644
--- a/FacebookRM/facebook.vcproj
+++ b/FacebookRM/facebook.vcproj
@@ -47,7 +47,7 @@
Name="VCCLCompilerTool"
Optimization="0"
WholeProgramOptimization="false"
- AdditionalIncludeDirectories="../../include;../ExternalAPI"
+ AdditionalIncludeDirectories="../../include;."
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FACEBOOK_EXPORTS;_CRT_SECURE_NO_WARNINGS;NOMINMAX"
MinimalRebuild="false"
RuntimeLibrary="3"
@@ -133,7 +133,7 @@
Name="VCCLCompilerTool"
Optimization="0"
WholeProgramOptimization="false"
- AdditionalIncludeDirectories="../../include;../ExternalAPI"
+ AdditionalIncludeDirectories="../../include;."
PreprocessorDefinitions="_DEBUG;_WINDOWS;_USRDLL;FACEBOOK_EXPORTS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN64"
RuntimeLibrary="3"
EnableFunctionLevelLinking="false"
@@ -217,7 +217,7 @@
Optimization="1"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="2"
- AdditionalIncludeDirectories="../../include;../ExternalAPI"
+ AdditionalIncludeDirectories="../../include;."
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FACEBOOK_EXPORTS;_CRT_SECURE_NO_WARNINGS;NOMINMAX"
StringPooling="true"
RuntimeLibrary="2"
@@ -303,7 +303,7 @@
Optimization="1"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="2"
- AdditionalIncludeDirectories="../../include;../ExternalAPI"
+ AdditionalIncludeDirectories="../../include;."
PreprocessorDefinitions="NDEBUG;_WINDOWS;_USRDLL;FACEBOOK_EXPORTS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN64"
StringPooling="true"
RuntimeLibrary="2"
@@ -373,6 +373,10 @@
>
</File>
<File
+ RelativePath=".\chat.cpp"
+ >
+ </File>
+ <File
RelativePath=".\communication.cpp"
>
</File>
@@ -565,6 +569,10 @@
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
+ RelativePath=".\icons\addFriend.ico"
+ >
+ </File>
+ <File
RelativePath=".\icons\facebook.ico"
>
</File>
@@ -577,6 +585,10 @@
>
</File>
<File
+ RelativePath=".\icons\removeFriend.ico"
+ >
+ </File>
+ <File
RelativePath=".\resource.h"
>
</File>
diff --git a/FacebookRM/facebook_10.sln b/FacebookRM/facebook_10.sln
index fc98ae0..e473e17 100644
--- a/FacebookRM/facebook_10.sln
+++ b/FacebookRM/facebook_10.sln
@@ -1,5 +1,6 @@
+
Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual C++ Express 2010
+# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "facebook", "facebook_10.vcxproj", "{DADE9455-DC28-465A-9604-2CA28052B9FB}"
EndProject
Global
diff --git a/FacebookRM/facebook_10.vcxproj b/FacebookRM/facebook_10.vcxproj
index 5f2ad60..0f98c4a 100644
--- a/FacebookRM/facebook_10.vcxproj
+++ b/FacebookRM/facebook_10.vcxproj
@@ -73,10 +73,8 @@
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">$(SolutionDir)\$(Configuration) $(Platform)/Plugins\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">$(SolutionDir)\$(Configuration) $(Platform)/Obj/$(ProjectName)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">true</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" />
@@ -109,11 +107,11 @@
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_UNICODE;UNICODE;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
+ <MapFileName>$(TargetDir)$(TargetName).map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
@@ -123,6 +121,7 @@
</LinkTimeCodeGeneration>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">
@@ -146,10 +145,8 @@
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_UNICODE;UNICODE;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
- <OutputFile>Build\$(Platform) $(Configuration)\plugins\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(TargetDir)$(TargetName).map</MapFileName>
@@ -162,6 +159,7 @@
</LinkTimeCodeGeneration>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<TargetMachine>MachineX64</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
@@ -188,18 +186,20 @@
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../../include/msapi/</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>$(TargetDir)$(TargetName).map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>uuid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
@@ -223,14 +223,13 @@
<PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Strict</FloatingPointModel>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../../include/msapi/</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -241,10 +240,13 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<TargetMachine>MachineX64</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalDependencies>uuid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="avatars.cpp" />
+ <ClCompile Include="chat.cpp" />
<ClCompile Include="communication.cpp" />
<ClCompile Include="connection.cpp" />
<ClCompile Include="contacts.cpp" />
diff --git a/FacebookRM/facebook_10.vcxproj.filters b/FacebookRM/facebook_10.vcxproj.filters
index 462a553..b3b2a03 100644
--- a/FacebookRM/facebook_10.vcxproj.filters
+++ b/FacebookRM/facebook_10.vcxproj.filters
@@ -63,6 +63,9 @@
<ClCompile Include="utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="chat.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="JSON_CAJUN\elements.h">
diff --git a/FacebookRM/icons/addFriend.ico b/FacebookRM/icons/addFriend.ico
new file mode 100644
index 0000000..d8879d1
--- /dev/null
+++ b/FacebookRM/icons/addFriend.ico
Binary files differ
diff --git a/FacebookRM/icons/removeFriend.ico b/FacebookRM/icons/removeFriend.ico
new file mode 100644
index 0000000..9639a9c
--- /dev/null
+++ b/FacebookRM/icons/removeFriend.ico
Binary files differ
diff --git a/FacebookRM/json.cpp b/FacebookRM/json.cpp
index 1c57f00..bd69c75 100644
--- a/FacebookRM/json.cpp
+++ b/FacebookRM/json.cpp
@@ -62,8 +62,32 @@ int facebook_json_parser::parse_buddy_list( void* data, List::List< facebook_use
i->data->status_id = ID_STATUS_OFFLINE;
}
- const Object& nowAvailableList = objRoot["payload"]["buddy_list"]["nowAvailableList"];
+ // Find mobile friends
+ if (DBGetContactSettingByte(NULL,proto->m_szModuleName,FACEBOOK_KEY_LOAD_MOBILE, DEFAULT_LOAD_MOBILE)) {
+ const Array& mobileFriends = objRoot["payload"]["buddy_list"]["mobile_friends"];
+
+ for ( Array::const_iterator buddy( mobileFriends.Begin() ); buddy != mobileFriends.End(); ++buddy) {
+ const Number& member = *buddy;
+ char was_id[32];
+ lltoa( member.Value(), was_id, 10 );
+
+ std::string id = was_id;
+ if (!id.empty()) {
+ current = buddy_list->find( id );
+
+ if ( current == NULL) {
+ buddy_list->insert( std::make_pair( id, new facebook_user( ) ) );
+ current = buddy_list->find( id );
+ current->user_id = id;
+ }
+
+ current->status_id = ID_STATUS_ONTHEPHONE;
+ }
+ }
+ }
+ const Object& nowAvailableList = objRoot["payload"]["buddy_list"]["nowAvailableList"];
+ // Find now awailable contacts
for (Object::const_iterator itAvailable(nowAvailableList.Begin());
itAvailable != nowAvailableList.End(); ++itAvailable)
{
@@ -78,13 +102,13 @@ int facebook_json_parser::parse_buddy_list( void* data, List::List< facebook_use
buddy_list->insert( std::make_pair( member.name, new facebook_user( ) ) );
current = buddy_list->find( member.name );
current->user_id = current->real_name = member.name;
- }
+ }
current->status_id = (idle ? ID_STATUS_OFFLINE : ID_STATUS_ONLINE);
}
const Object& userInfosList = objRoot["payload"]["buddy_list"]["userInfos"];
-
+ // Get aditional informations about contacts (if available)
for (Object::const_iterator itUserInfo(userInfosList.Begin());
itUserInfo != userInfosList.End(); ++itUserInfo)
{
@@ -121,6 +145,83 @@ int facebook_json_parser::parse_buddy_list( void* data, List::List< facebook_use
return EXIT_SUCCESS;
}
+int facebook_json_parser::parse_facepiles( void* data, std::map< std::string, std::string > *facepiles )
+{
+ using namespace json;
+
+ try
+ {
+ std::string buddyData = static_cast< std::string* >( data )->substr( 9 );
+ std::istringstream sDocument( buddyData );
+ Object objDocument;
+ Reader::Read(objDocument, sDocument);
+ std::map< std::string, std::string >::iterator it;
+
+ const Object& objRoot = objDocument;
+/* const Array& infos = objRoot["payload"]["facepile_click_info"];
+
+ for ( Array::const_iterator info( infos.Begin() );
+ info != infos.End(); ++info)
+ {
+ const Object& objMember = *info;
+
+ if (objMember.Find("uid") != objMember.End()) {
+ const Number& id = objMember["uid"];
+ char was_id[32];
+ lltoa( id.Value(), was_id, 10 );
+
+ const String& name = objMember["name"];
+ std::string user_name = utils::text::slashu_to_utf8(
+ utils::text::special_expressions_decode( name.Value() ) );
+
+ it = facepiles->find( std::string( was_id ) );
+ if ( it == facepiles->end() ) {
+ facepiles->insert( std::make_pair( was_id, user_name ) );
+ }
+ }
+ } */
+
+ // Contacts in chat are getting by parsing html response. Don't know if it will work also for many people in chat room.
+ const String& response_html = objRoot["payload"]["response_html"];
+ std::string contacts = utils::text::slashu_to_utf8( utils::text::special_expressions_decode( response_html.Value( ) ) );
+
+ std::string::size_type pos = 0;
+ while ((pos = contacts.find("<li", pos)) != std::string::npos) {
+ std::string row = contacts.substr(pos, contacts.find("</li>") - pos);
+
+ std::string status = utils::text::source_get_value2( &row, "chat", "\" " ); // "Online" or "Idle"
+ std::string name = utils::text::source_get_value( &row, 2, "title=\"", "\"" );
+ std::string id = utils::text::source_get_value( &row, 3, "href=\"", "/profile.php?id=", "\"" );
+ if (id.empty())
+ id = utils::text::source_get_value( &row, 3, "href=\"", "facebook.com/", "\"" );
+
+ it = facepiles->find( id );
+ if ( it == facepiles->end() ) {
+ facepiles->insert( std::make_pair( id, name ) );
+ }
+
+ pos++;
+ }
+
+ }
+ catch (Reader::ParseException& e)
+ {
+ proto->Log( "!!!!! Caught json::ParseException: %s", e.what() );
+ proto->Log( " Line/offset: %d/%d", e.m_locTokenBegin.m_nLine + 1, e.m_locTokenBegin.m_nLineOffset + 1 );
+ }
+ catch (const Exception& e)
+ {
+ proto->Log( "!!!!! Caught json::Exception: %s", e.what() );
+ }
+ catch (const std::exception& e)
+ {
+ proto->Log( "!!!!! Caught std::exception: %s", e.what() );
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
int facebook_json_parser::parse_friends( void* data, std::map< std::string, facebook_user* >* friends )
{
using namespace json;
@@ -256,7 +357,7 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
const String& type = objMember["type"];
- if ( type.Value( ) == "msg" ) // chat message
+ if ( type.Value( ) == "msg" || type.Value() == "offline_msg" ) // direct message
{
const Number& from = objMember["from"];
char was_id[32];
@@ -264,20 +365,22 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
const Object& messageContent = objMember["msg"];
const String& text = messageContent["text"];
+ //"tab_type":"friend", objMember["tab_type"]
//const Number& time_sent = messageContent["time"];
-
// proto->Log("????? Checking time %15.2f > %15.2f", time_sent.Value(), proto->facy.last_message_time_);
- if (last_msg != text.Value())
-/* if (time_sent.Value() > proto->facy.last_message_time_
- || (time_sent.Value() < 0 && proto->facy.last_message_time_ >= 0)) // Check agains duplicit messages*/
- {
+ if ((messageContent.Find("truncated") != messageContent.End())
+ && (((const Number &)messageContent["truncated"]).Value() == 1)) {
+ // If we got truncated message, we can ignore it, because we should get it again as "messaging" type
+ std::string msg = "????? We got truncated message so we ignore it\n";
+ msg += utils::text::special_expressions_decode(utils::text::slashu_to_utf8(text.Value()));
+ proto->Log(msg.c_str());
+ } else if (last_msg != text.Value()) {
last_msg = text.Value();
- //proto->facy.last_message_time_ = time_sent.Value();
facebook_message* message = new facebook_message( );
- message->message_text= utils::text::special_expressions_decode(
+ message->message_text = utils::text::special_expressions_decode(
utils::text::slashu_to_utf8( text.Value( ) ) );
message->time = ::time( NULL );
message->user_id = was_id;
@@ -289,7 +392,7 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
proto->Log(msg.c_str());
}
}
- else if ( type.Value( ) == "messaging" ) // inbox message
+ else if ( type.Value( ) == "messaging" ) // inbox message (multiuser or direct)
{
const String& type = objMember["event"];
@@ -299,32 +402,69 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
const Number& from = messageContent["sender_fbid"];
char was_id[32];
lltoa( from.Value(), was_id, 10 );
+
+
+ // Ignore if message is from self user
+ if (was_id == proto->facy.self_.user_id)
+ continue;
+
const String& text = messageContent["body"];
+ //std::string tid = ((const String&)messageContent["tid"]).Value();
+
+ const String& sender_name = messageContent["sender_name"];
- // TODO RM: include sender name
- // const String& name = messageContent["sender_name"];
+ std::string row = ((const String &)objMember["thread_row"]).Value();
//const Number& time_sent = messageContent["timestamp"];
//proto->Log("????? Checking time %15.2f > %15.2f", time_sent.Value(), proto->facy.last_message_time_);
- if (last_msg != text.Value())
-/* if (time_sent.Value() > proto->facy.last_message_time_
- || (time_sent.Value() < 0 && proto->facy.last_message_time_ >= 0)) // Check agains duplicit messages*/
- {
+ if (last_msg != text.Value()) {
last_msg = text.Value();
- //proto->facy.last_message_time_ = time_sent.Value();
facebook_message* message = new facebook_message( );
- message->message_text= utils::text::special_expressions_decode(
+ message->message_text = utils::text::special_expressions_decode(
utils::text::slashu_to_utf8( text.Value( ) ) );
- message->time = ::time( NULL );
+ message->sender_name = utils::text::special_expressions_decode(
+ utils::text::slashu_to_utf8( sender_name.Value( ) ) );
+
+ message->time = ::time( NULL );
+ message->user_id = was_id; // TODO: Check if we have contact with this ID in friendlist and then do something different?
- message->user_id = was_id;
+ if (row.find("uiSplitPic",0) != std::string::npos) {
+ // This is multiuser message
+
+ std::string authors = utils::text::special_expressions_decode(
+ utils::text::slashu_to_utf8( row ) );
+ authors = utils::text::source_get_value(&authors, 2, "<strong class=\"authors\">", "<");
- messages->push_back( message );
+ const String& to_id = messageContent["tid"];
+
+ std::string popup_text = message->sender_name;
+ popup_text += ": ";
+ popup_text += message->message_text;
+
+ std::string title = Translate("Multichat");
+ title += ": ";
+ title += authors;
+
+ std::string url = "/?action=read&sk=inbox&page&query&tid=";
+ url += to_id.Value();
+
+ proto->Log(" Got multichat message");
+
+ TCHAR* szTitle = mir_a2t_cp(title.c_str(), CP_UTF8);
+ TCHAR* szText = mir_a2t_cp(popup_text.c_str(), CP_UTF8);
+ TCHAR* szUrl = mir_a2t_cp(url.c_str(), CP_UTF8);
+ proto->NotifyEvent(szTitle,szText,NULL,FACEBOOK_EVENT_OTHER, szUrl);
+ mir_free(szTitle);
+ mir_free(szText);
+
+ } else {
+ messages->push_back( message );
+ }
} else {
std::string msg = "????? Got duplicit inbox message?\n";
msg += utils::text::special_expressions_decode(utils::text::slashu_to_utf8(text.Value()));
@@ -334,13 +474,10 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
}
else if ( type.Value( ) == "group_msg" ) // chat message
{
- if ( (::time(NULL) - proto->facy.last_grpmessage_time_) < 15 ) // TODO RM: remove dont notify more than once every 15 secs
+ if (!DBGetContactSettingByte(NULL,proto->m_szModuleName,FACEBOOK_KEY_ENABLE_GROUPCHATS, DEFAULT_ENABLE_GROUPCHATS))
continue;
-
- proto->facy.last_grpmessage_time_ = ::time(NULL);
-
+
const String& from_name = objMember["from_name"];
- const String& group_name = objMember["to_name"];
const Number& to = objMember["to"];
char group_id[32];
@@ -350,6 +487,32 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
char was_id[32];
lltoa( from.Value(), was_id, 10 );
+ const Object& messageContent = objMember["msg"];
+ const String& text = messageContent["text"];
+
+ std::string msg = utils::text::special_expressions_decode(
+ utils::text::slashu_to_utf8( text.Value( ) ) );
+
+ std::string name = utils::text::special_expressions_decode(
+ utils::text::slashu_to_utf8( from_name.Value( ) ) );
+
+ // Add contact into chat, if isn't there already
+ if (!proto->IsChatContact(group_id, was_id))
+ proto->AddChatContact(group_id, was_id, name.c_str());
+
+ // Add message into chat
+ proto->UpdateChat(group_id, was_id, name.c_str(), msg.c_str());
+ }
+ else if ( type.Value( ) == "thread_msg" ) // multiuser message
+ {
+ const String& from_name = objMember["from_name"];
+ const String& to_name = objMember["to_name"]["__html"];
+ const String& to_id = objMember["to"];
+
+ const Number& from = objMember["from"];
+ char was_id[32];
+ lltoa( from.Value(), was_id, 10 );
+
// Ignore if message is from self user
if (was_id == proto->facy.self_.user_id)
continue;
@@ -357,24 +520,25 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
const Object& messageContent = objMember["msg"];
const String& text = messageContent["text"];
- std::string popup_text = utils::text::remove_html(
- utils::text::special_expressions_decode(
- utils::text::slashu_to_utf8( from_name.Value( ) ) ) );
+
+ last_msg = text.Value();
+
+
+ std::string popup_text = utils::text::special_expressions_decode(
+ utils::text::slashu_to_utf8( from_name.Value( ) ) );
popup_text += ": ";
- popup_text += utils::text::remove_html(
- utils::text::special_expressions_decode(
- utils::text::slashu_to_utf8( text.Value( ) ) ) );
+ popup_text += utils::text::special_expressions_decode(
+ utils::text::slashu_to_utf8( text.Value( ) ) );
- std::string title = Translate("Groupchat");
+ std::string title = Translate("Multichat");
title += ": ";
- title += utils::text::remove_html(
- utils::text::special_expressions_decode(
- utils::text::slashu_to_utf8( group_name.Value( ) ) ) );
-
- std::string url = "/home.php?sk=group_";
- url += group_id;
+ title += utils::text::special_expressions_decode(
+ utils::text::slashu_to_utf8( to_name.Value( ) ) );
+
+ std::string url = "/?action=read&sk=inbox&page&query&tid=";
+ url += to_id.Value();
- proto->Log(" Got groupchat message");
+ proto->Log(" Got multichat message");
TCHAR* szTitle = mir_a2t_cp(title.c_str(), CP_UTF8);
TCHAR* szText = mir_a2t_cp(popup_text.c_str(), CP_UTF8);
diff --git a/FacebookRM/json.h b/FacebookRM/json.h
index 19105b3..6227c78 100644
--- a/FacebookRM/json.h
+++ b/FacebookRM/json.h
@@ -36,6 +36,7 @@ class facebook_json_parser
public:
FacebookProto* proto;
int parse_buddy_list( void*, List::List< facebook_user >* );
+ int parse_facepiles( void*, std::map< std::string, std::string >* );
int parse_friends( void*, std::map< std::string, facebook_user* >* );
int parse_notifications( void*, std::vector< facebook_notification* >* );
int parse_messages( void*, std::vector< facebook_message* >*, std::vector< facebook_notification* >* );
diff --git a/FacebookRM/messages.cpp b/FacebookRM/messages.cpp
index 7091e77..7578550 100644
--- a/FacebookRM/messages.cpp
+++ b/FacebookRM/messages.cpp
@@ -27,28 +27,6 @@ Last change on : $Date: 2011-02-07 18:19:39 +0100 (po, 07 2 2011) $
#include "common.h"
-struct send_direct
-{
- send_direct(HANDLE hContact,const std::string &msg, HANDLE msgid) : hContact(hContact), msg(msg), msgid(msgid) {}
- HANDLE hContact;
- std::string msg;
- HANDLE msgid;
-};
-
-struct send_typing
-{
- send_typing(HANDLE hContact,const int status) : hContact(hContact), status(status) {}
- HANDLE hContact;
- int status;
-};
-
-struct send_messaging
-{
- send_messaging(const std::string &user_id, const int type) : user_id(user_id), type(type) {}
- std::string user_id;
- int type;
-};
-
int FacebookProto::RecvMsg(HANDLE hContact, PROTORECVEVENT *pre)
{
DBVARIANT dbv;
@@ -102,6 +80,19 @@ void FacebookProto::SendMsgWorker(void *p)
delete data;
}
+void FacebookProto::SendChatMsgWorker(void *p)
+{
+ if(p == NULL)
+ return;
+
+ send_chat *data = static_cast<send_chat*>(p);
+ std::string err_message = "";
+
+ facy.send_message(data->chat_id, data->msg, &err_message, false );
+
+ delete data;
+}
+
int FacebookProto::SendMsg(HANDLE hContact, int flags, const char *msg)
{
// TODO: msg comes as Unicode (retyped wchar_t*), why should we convert it as ANSI to UTF-8? o_O
diff --git a/FacebookRM/process.cpp b/FacebookRM/process.cpp
index e6c965c..48430df 100644
--- a/FacebookRM/process.cpp
+++ b/FacebookRM/process.cpp
@@ -70,14 +70,32 @@ void FacebookProto::ProcessBuddyList( void* data )
if (!fbu->handle) { // just been added
fbu->handle = AddToContactList(fbu);
- DBWriteContactSettingUTF8String(fbu->handle,m_szModuleName,FACEBOOK_KEY_NAME,fbu->real_name.c_str());
- DBWriteContactSettingUTF8String(fbu->handle,m_szModuleName,"Nick",fbu->real_name.c_str());
+ if (!fbu->real_name.empty()) {
+ DBWriteContactSettingUTF8String(fbu->handle,m_szModuleName,FACEBOOK_KEY_NAME,fbu->real_name.c_str());
+ DBWriteContactSettingUTF8String(fbu->handle,m_szModuleName,FACEBOOK_KEY_NICK,fbu->real_name.c_str());
+ }
+ }
+
+ if (DBGetContactSettingWord(fbu->handle,m_szModuleName,"Status", 0) != fbu->status_id ) {
+ DBWriteContactSettingWord(fbu->handle,m_szModuleName,"Status", fbu->status_id );
}
- if (DBGetContactSettingWord(fbu->handle,m_szModuleName,"Status", 0) != ID_STATUS_ONLINE) {
- DBWriteContactSettingWord(fbu->handle,m_szModuleName,"Status", ID_STATUS_ONLINE );
+ if (DBGetContactSettingByte(fbu->handle,m_szModuleName,FACEBOOK_KEY_CONTACT_TYPE, 0)) {
+ DBDeleteContactSetting(fbu->handle,m_szModuleName,FACEBOOK_KEY_CONTACT_TYPE); // Set type "on server-list" contact
}
+ // Wasn't contact removed from "server-list" someday?
+ if ( DBGetContactSettingDword(fbu->handle, m_szModuleName, FACEBOOK_KEY_DELETED, 0) ) {
+ DBDeleteContactSetting(fbu->handle, m_szModuleName, FACEBOOK_KEY_DELETED);
+
+ std::string url = FACEBOOK_URL_PROFILE + fbu->user_id;
+
+ TCHAR* szTitle = mir_a2t_cp(fbu->real_name.c_str(), CP_UTF8);
+ TCHAR* szUrl = mir_a2t_cp(url.c_str(), CP_UTF8);
+ NotifyEvent(szTitle, TranslateT("Contact is back on server-list."), fbu->handle, FACEBOOK_EVENT_OTHER, szUrl);
+ mir_free( szTitle );
+ // mir_free( szUrl ); // url is free'd in popup procedure
+ }
// Check avatar change
CheckAvatarChange(fbu->handle, fbu->image_url);
@@ -96,6 +114,66 @@ exit:
delete resp;
}
+void FacebookProto::ProcessFacepiles( void* data )
+{
+ if ( data == NULL )
+ return;
+
+ send_chat *resp = static_cast<send_chat*>(data);
+
+ if ( isOffline() )
+ goto exit;
+
+ LOG("***** Starting processing facepiles");
+
+ CODE_BLOCK_TRY
+
+ std::map< std::string, std::string > facepiles;
+
+ facebook_json_parser* p = new facebook_json_parser( this );
+ p->parse_facepiles( &(resp->msg), &facepiles );
+ delete p;
+
+ std::map< std::string, std::string >::iterator iter;
+
+ char *chat_users = this->GetChatUsers(resp->chat_id.c_str());
+ std::string users = chat_users;
+ mir_free(chat_users);
+
+ std::vector<std::string> users_list;
+ utils::text::explode(users, " ", &users_list);
+
+ for( std::vector<std::string>::size_type i=0; i<users_list.size( ); i++) {
+ iter = facepiles.find( users_list[i] );
+ if (iter == facepiles.end()) {
+ // Contact is now offline, remove him from chat
+ this->RemoveChatContact(resp->chat_id.c_str(), users_list[i].c_str());
+ LOG(" Now offline facepile (%s): [%s]", resp->chat_id.c_str(), users_list[i].c_str());
+ } else {
+ facepiles.erase(iter);
+ }
+ }
+
+ for ( iter = facepiles.begin( ); iter != facepiles.end(); ++iter )
+ {
+ // These contacts are newly online, add them...
+ this->AddChatContact(resp->chat_id.c_str(), iter->first.c_str(), iter->second.c_str());
+ LOG(" Now online facepile (%s): [%s] %s", resp->chat_id.c_str(), iter->first.c_str(), iter->second.c_str());
+ }
+
+ LOG("***** Facepiles processed");
+
+ CODE_BLOCK_CATCH
+
+ LOG("***** Error processing facepiles: %s", e.what());
+
+ CODE_BLOCK_END
+
+exit:
+ delete resp;
+}
+
+
void FacebookProto::ProcessFriendList( void* data )
{
if ( data == NULL )
@@ -151,7 +229,11 @@ void FacebookProto::ProcessFriendList( void* data )
if ( update_required )
{
DBWriteContactSettingUTF8String(hContact, m_szModuleName, FACEBOOK_KEY_NAME, fbu->real_name.c_str());
- DBWriteContactSettingUTF8String(hContact, m_szModuleName, "Nick", fbu->real_name.c_str());
+ DBWriteContactSettingUTF8String(hContact, m_szModuleName, FACEBOOK_KEY_NICK, fbu->real_name.c_str());
+ }
+
+ if (DBGetContactSettingByte(fbu->handle,m_szModuleName,FACEBOOK_KEY_CONTACT_TYPE, 0)) {
+ DBDeleteContactSetting(fbu->handle,m_szModuleName,FACEBOOK_KEY_CONTACT_TYPE); // Has type "on server-list" contact
}
// Wasn't contact removed from "server-list" someday?
@@ -162,7 +244,7 @@ void FacebookProto::ProcessFriendList( void* data )
TCHAR* szTitle = mir_a2t_cp(fbu->real_name.c_str(), CP_UTF8);
TCHAR* szUrl = mir_a2t_cp(url.c_str(), CP_UTF8);
- NotifyEvent(szTitle, TranslateT("Contact is back on server-list."), hContact, FACEBOOK_EVENT_CLIENT, szUrl);
+ NotifyEvent(szTitle, TranslateT("Contact is back on server-list."), hContact, FACEBOOK_EVENT_OTHER, szUrl);
mir_free( szTitle );
// mir_free( szUrl ); // url is free'd in popup procedure
}
@@ -176,7 +258,9 @@ void FacebookProto::ProcessFriendList( void* data )
// Contact was removed from "server-list", notify it
// Wasnt we already been notified about this contact?
- if ( !DBGetContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_DELETED, 0) ) {
+ if ( !DBGetContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_DELETED, 0)
+ && !DBGetContactSettingByte(hContact, m_szModuleName, FACEBOOK_KEY_CONTACT_TYPE, 0) ) { // And is this contact "on-server" contact?
+
DBWriteContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_DELETED, ::time(NULL));
std::string contactname = id;
@@ -189,7 +273,7 @@ void FacebookProto::ProcessFriendList( void* data )
TCHAR* szTitle = mir_a2t_cp(contactname.c_str(), CP_UTF8);
TCHAR* szUrl = mir_a2t_cp(url.c_str(), CP_UTF8);
- NotifyEvent(szTitle, TranslateT("Contact is no longer on server-list."), hContact, FACEBOOK_EVENT_CLIENT, szUrl);
+ NotifyEvent(szTitle, TranslateT("Contact is no longer on server-list."), hContact, FACEBOOK_EVENT_OTHER, szUrl);
mir_free( szTitle );
// mir_free( szUrl ); // url is free'd in popup procedure
}
@@ -206,7 +290,7 @@ void FacebookProto::ProcessFriendList( void* data )
DBWriteContactSettingByte(hContact, m_szModuleName, "Gender", fbu->gender );
DBWriteContactSettingUTF8String(hContact, m_szModuleName, FACEBOOK_KEY_NAME, fbu->real_name.c_str());
- DBWriteContactSettingUTF8String(hContact, m_szModuleName, "Nick", fbu->real_name.c_str());
+ DBWriteContactSettingUTF8String(hContact, m_szModuleName, FACEBOOK_KEY_NICK, fbu->real_name.c_str());
DBWriteContactSettingString(hContact, m_szModuleName, FACEBOOK_KEY_AV_URL, fbu->image_url.c_str());
// DBWriteContactSettingWord(hContact, m_szModuleName, "Status", ID_STATUS_OFFLINE );
}
@@ -266,7 +350,7 @@ void FacebookProto::ProcessUnreadMessages( void* )
std::string user_id = utils::text::source_get_value( &messageslist, 2, "single_thread_id\":", "," );
if (user_id.empty()) {
- LOG(" !! !! Thread id is empty - this is groupchat message."); // todo remove as this is not such 'error'
+ LOG(" !! !! Thread id is empty - this is groupchat message."); // TODO: remove as this is not such 'error'
continue;
}
@@ -336,8 +420,8 @@ void FacebookProto::ProcessMessages( void* data )
facebook_user fbu;
fbu.user_id = messages[i]->user_id;
- HANDLE hContact = AddToContactList(&fbu);
-
+ HANDLE hContact = AddToContactList(&fbu, false, messages[i]->sender_name.c_str());
+
PROTORECVEVENT recv = {0};
CCSDATA ccs = {0};
diff --git a/FacebookRM/proto.cpp b/FacebookRM/proto.cpp
index 5a88c40..f54ceee 100644
--- a/FacebookRM/proto.cpp
+++ b/FacebookRM/proto.cpp
@@ -51,14 +51,16 @@ FacebookProto::FacebookProto(const char* proto_name,const TCHAR* username)
CreateProtoService(m_szModuleName, PS_GETAVATARCAPS, &FacebookProto::GetAvatarCaps, this);
// TODO RM: group chats
-/* CreateProtoService(m_szModuleName,PS_JOINCHAT, &FacebookProto::OnJoinChat, this);
- CreateProtoService(m_szModuleName,PS_LEAVECHAT,&FacebookProto::OnLeaveChat,this);*/
+ CreateProtoService(m_szModuleName, PS_JOINCHAT, &FacebookProto::OnJoinChat, this);
+ CreateProtoService(m_szModuleName, PS_LEAVECHAT, &FacebookProto::OnLeaveChat, this);
+
if(g_mirandaVersion < PLUGIN_MAKE_VERSION(0, 10, 0, 2))
{
HookProtoEvent(ME_DB_CONTACT_DELETED, &FacebookProto::OnContactDeleted, this);
}
- HookProtoEvent(ME_CLIST_PREBUILDSTATUSMENU, &FacebookProto::OnBuildStatusMenu, this);
- HookProtoEvent(ME_OPT_INITIALISE, &FacebookProto::OnOptionsInit, this);
+ HookProtoEvent(ME_CLIST_PREBUILDSTATUSMENU, &FacebookProto::OnBuildStatusMenu, this);
+ HookProtoEvent(ME_OPT_INITIALISE, &FacebookProto::OnOptionsInit, this);
+ HookProtoEvent(ME_GC_EVENT, &FacebookProto::OnChatOutgoing, this);
// Create standard network connection
TCHAR descr[512];
@@ -127,7 +129,7 @@ DWORD_PTR FacebookProto::GetCaps( int type, HANDLE hContact )
else
return PF1_IM | PF1_MODEMSGRECV;
case PFLAGNUM_2:
- return PF2_ONLINE | PF2_INVISIBLE; // | PF2_IDLE | PF2_SHORTAWAY;
+ return PF2_ONLINE | PF2_INVISIBLE | PF2_ONTHEPHONE; // | PF2_IDLE | PF2_SHORTAWAY;
case PFLAGNUM_3:
if ( getByte( FACEBOOK_KEY_SET_MIRANDA_STATUS, 0 ) )
return PF2_ONLINE; // | PF2_SHORTAWAY;
@@ -135,6 +137,8 @@ DWORD_PTR FacebookProto::GetCaps( int type, HANDLE hContact )
return 0;
case PFLAGNUM_4:
return PF4_FORCEAUTH | PF4_NOCUSTOMAUTH /*| PF4_SUPPORTIDLE*/ | PF4_IMSENDUTF | PF4_AVATARS | PF4_SUPPORTTYPING | PF4_NOAUTHDENYREASON | PF4_IMSENDOFFLINE;
+ case PFLAGNUM_5:
+ return PF2_ONTHEPHONE;
case PFLAG_MAXLENOFMESSAGE:
return FACEBOOK_MESSAGE_LIMIT;
case PFLAG_UNIQUEIDTEXT:
@@ -166,7 +170,7 @@ int FacebookProto::SetStatus( int new_status )
switch ( new_status )
{
case ID_STATUS_INVISIBLE:
- case ID_STATUS_OFFLINE:
+ case ID_STATUS_OFFLINE:
m_iDesiredStatus = new_status;
break;
@@ -176,6 +180,11 @@ int FacebookProto::SetStatus( int new_status )
break;
default:
+ m_iDesiredStatus = ID_STATUS_INVISIBLE;
+ if (DBGetContactSettingByte(NULL,m_szModuleName,FACEBOOK_KEY_MAP_STATUSES, DEFAULT_MAP_STATUSES))
+ break;
+ case ID_STATUS_ONLINE:
+ case ID_STATUS_FREECHAT:
m_iDesiredStatus = ID_STATUS_ONLINE;
break;
}
@@ -289,16 +298,14 @@ int FacebookProto::SvcCreateAccMgrUI(WPARAM wParam,LPARAM lParam)
int FacebookProto::OnModulesLoaded(WPARAM wParam,LPARAM lParam)
{
-/*
- // RM TODO: group chats
// Register group chat
GCREGISTER gcr = {sizeof(gcr)};
- gcr.dwFlags = GC_ACKMSG;
+ //gcr.dwFlags = GC_ACKMSG;
gcr.pszModule = m_szModuleName;
gcr.pszModuleDispName = m_szModuleName;
gcr.iMaxText = FACEBOOK_MESSAGE_LIMIT;
CallService(MS_GC_REGISTER,0,reinterpret_cast<LPARAM>(&gcr));
-*/
+
return 0;
}
@@ -311,8 +318,11 @@ int FacebookProto::OnPreShutdown(WPARAM wParam,LPARAM lParam)
int FacebookProto::OnPrebuildContactMenu(WPARAM wParam,LPARAM lParam)
{
HANDLE hContact = reinterpret_cast<HANDLE>(wParam);
- if(IsMyContact(hContact, true))
- ShowContactMenus(true);
+ if(IsMyContact(hContact/*, true*/)) {
+ bool hide = (DBGetContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_DELETED, 0)
+ || DBGetContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_CONTACT_TYPE, 0) );
+ ShowContactMenus(true, hide);
+ }
return 0;
}
@@ -385,7 +395,7 @@ int FacebookProto::OnBuildStatusMenu(WPARAM wParam,LPARAM lParam)
mi.flags = CMIF_ICONFROMICOLIB | CMIF_CHILDPOPUP;
mi.pszName = LPGEN("Visit Profile");
mi.icolibItem = GetIconHandle("homepage");
- // TODO RM: remember and properly free in destructor
+ // TODO RM: remember and properly free in destructor?
/*m_hStatusMind = */reinterpret_cast<HGENMENU>( CallService(
MS_CLIST_ADDPROTOMENUITEM,0,reinterpret_cast<LPARAM>(&mi)) );
@@ -415,27 +425,78 @@ int FacebookProto::VisitProfile(WPARAM wParam,LPARAM lParam)
{
CallService(MS_UTILS_OPENURL,1,reinterpret_cast<LPARAM>(dbv.pszVal));
DBFreeVariant(&dbv);
- }/* else {
- // TODO RM: remove this
- std::string key, url;
- if (DBGetContactSettingByte(hContact,m_szModuleName,"ChatRoom",0) == 0)
- { // usual contact
- key = FACEBOOK_KEY_ID;
- url = FACEBOOK_URL_PROFILE;
+ }
+
+ return 0;
+}
+
+int FacebookProto::RemoveFriend(WPARAM wParam,LPARAM lParam)
+{
+ if (wParam == NULL)
+ { // self contact
+ // CallService(MS_UTILS_OPENURL,1,reinterpret_cast<LPARAM>(FACEBOOK_URL_PROFILE));
+ return 0;
+ }
+
+ if (isOffline())
+ return 0;
+
+ if (MessageBox( 0, TranslateT("Are you sure?"), TranslateT("Delete contact from server list"), MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2 ) != IDYES)
+ return 0;
+
+ HANDLE hContact = reinterpret_cast<HANDLE>(wParam);
+
+ DBVARIANT dbv;
+ if( !DBGetContactSettingString(hContact,m_szModuleName,FACEBOOK_KEY_ID,&dbv) )
+ {
+ if (!isOffline()) {
+ std::string* id = new std::string(dbv.pszVal);
+ ForkThread( &FacebookProto::DeleteContactFromServer, this, ( void* )id );
+ DBFreeVariant(&dbv);
+
+ if ( !DBGetContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_DELETED, 0) )
+ DBWriteContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_DELETED, ::time(NULL));
} else {
- key = "ChatRoomID";
- url = FACEBOOK_URL_GROUP;
+/* facebook_user fbu;
+ fbu.user_id = dbv.pszVal;
+ hContact = AddToContactList(&fbu);
+
+ DBWriteContactSettingByte(hContact,m_szModuleName,FACEBOOK_KEY_DELETE_NEXT,1);
+ facy.client_notify(TranslateT("Contact will be deleted at next login."));*/
+ NotifyEvent(TranslateT("Deleting contact"), TranslateT("Contact wasn't deleted, because you are not connected."), NULL, FACEBOOK_EVENT_OTHER, NULL);
}
+ }
- if ( !DBGetContactSettingString(hContact,m_szModuleName,key.c_str(),&dbv) )
- {
- url += dbv.pszVal;
- DBWriteContactSettingString(hContact,m_szModuleName,"Homepage",url.c_str());
+ return 0;
+}
- CallService(MS_UTILS_OPENURL,1,reinterpret_cast<LPARAM>(url.c_str()));
+int FacebookProto::AddFriend(WPARAM wParam,LPARAM lParam)
+{
+ if (wParam == NULL)
+ { // self contact
+// CallService(MS_UTILS_OPENURL,1,reinterpret_cast<LPARAM>(FACEBOOK_URL_PROFILE));
+ return 0;
+ }
+
+ HANDLE hContact = reinterpret_cast<HANDLE>(wParam);
+
+ DBVARIANT dbv;
+ if( !DBGetContactSettingString(hContact,m_szModuleName,FACEBOOK_KEY_ID,&dbv) )
+ {
+ if (!isOffline()) {
+ std::string* id = new std::string(dbv.pszVal);
+ ForkThread( &FacebookProto::AddContactToServer, this, ( void* )id );
DBFreeVariant(&dbv);
+ } else {
+/* facebook_user fbu;
+ fbu.user_id = dbv.pszVal;
+ hContact = AddToContactList(&fbu);
+
+ DBWriteContactSettingByte(hContact,m_szModuleName,FACEBOOK_KEY_DELETE_NEXT,1);
+ facy.client_notify(TranslateT("Contact will be deleted at next login."));*/
+ NotifyEvent(TranslateT("Adding contact"), TranslateT("Contact wasn't added, because you are not connected."), NULL, FACEBOOK_EVENT_OTHER, NULL);
}
- }*/
+ }
return 0;
}
diff --git a/FacebookRM/proto.h b/FacebookRM/proto.h
index 7c70a56..b6fd3d8 100644
--- a/FacebookRM/proto.h
+++ b/FacebookRM/proto.h
@@ -124,6 +124,8 @@ public:
int __cdecl GetAvatarInfo(WPARAM, LPARAM );
int __cdecl GetAvatarCaps(WPARAM, LPARAM );
int __cdecl VisitProfile(WPARAM, LPARAM );
+ int __cdecl RemoveFriend(WPARAM, LPARAM );
+ int __cdecl AddFriend(WPARAM, LPARAM );
// Events
int __cdecl OnModulesLoaded(WPARAM, LPARAM);
@@ -134,9 +136,9 @@ public:
int __cdecl OnPreShutdown(WPARAM,LPARAM);
int __cdecl OnPrebuildContactMenu(WPARAM,LPARAM);
// TODO RM: Chat handling
- /* int __cdecl OnChatOutgoing(WPARAM,LPARAM);
+ int __cdecl OnChatOutgoing(WPARAM,LPARAM);
int __cdecl OnJoinChat(WPARAM,LPARAM);
- int __cdecl OnLeaveChat(WPARAM,LPARAM);*/
+ int __cdecl OnLeaveChat(WPARAM,LPARAM);
// Loops
bool NegotiateConnection();
@@ -146,6 +148,7 @@ public:
// Processing threads
void __cdecl ProcessBuddyList(void*);
+ void __cdecl ProcessFacepiles(void*);
void __cdecl ProcessFriendList(void*);
void __cdecl ProcessMessages(void*);
void __cdecl ProcessUnreadMessages(void*);
@@ -159,22 +162,26 @@ public:
void __cdecl SetAwayMsgWorker(void*);
void __cdecl UpdateAvatarWorker(void*);
void __cdecl SendMsgWorker(void*);
+ void __cdecl SendChatMsgWorker(void*);
void __cdecl SendTypingWorker(void*);
void __cdecl MessagingWorker(void*);
void __cdecl DeleteContactFromServer(void*);
+ void __cdecl AddContactToServer(void*);
// Contacts handling
bool IsMyContact(HANDLE, bool include_chat = false);
HANDLE ContactIDToHContact(std::string);
- HANDLE AddToContactList(facebook_user*, bool dont_check = false);
+ HANDLE AddToContactList(facebook_user*, bool dont_check = false, const char *new_name = "");
void SetAllContactStatuses(int);
// TODO RM: Chats handling
- /*void AddChat(const char *id,const char *name);
- void UpdateChat(const facebook_user &update);
- void AddChatContact(const char *name,const char *nick=0);
- void DeleteChatContact(const char *name);
- void SetChatStatus(int);*/
+ void AddChat(const char *id, const char *name);
+ void UpdateChat(const char *chat_id, const char *id, const char *name, const char *message);
+ bool IsChatContact(const char *chat_id, const char *id);
+ void AddChatContact(const char *chat_id, const char *id, const char *name);
+ void RemoveChatContact(const char *chat_id, const char *id);
+ void SetChatStatus(const char *chat_id, int status);
+ char *GetChatUsers(const char *chat_id);
// Connection client
facebook_client facy; // TODO: Refactor to "client" and make dynamic
diff --git a/FacebookRM/resource.h b/FacebookRM/resource.h
index a9254bf..50a0638 100644
--- a/FacebookRM/resource.h
+++ b/FacebookRM/resource.h
@@ -4,6 +4,8 @@
//
#define IDI_FACEBOOK 101
#define IDI_MIND 102
+#define IDI_ADDFRIEND 103
+#define IDI_REMOVEFRIEND 104
#define IDD_FACEBOOKACCOUNT 111
#define IDD_MIND 112
#define IDD_OPTIONS 113
@@ -11,27 +13,23 @@
#define IDC_UN 1001
#define IDC_PW 1002
#define IDC_NEWACCOUNTLINK 1003
-#define IDC_NAME 1011
#define IDC_MINDMSG 1012
#define IDC_CHARACTERS 1013
#define IDC_GROUP 1021
-#define IDC_AGENT 1022
-#define IDC_POLLRATE 1023
#define IDC_SECURE 1024
-#define IDC_CLOSE_WINDOWS 1025
-#define IDC_IGNORE_STATUS 1025
#define IDC_SET_IGNORE_STATUS 1025
-#define IDC_SECURE2 1026
#define IDC_SECURE_CHANNEL 1026
#define IDC_LOGGING 1027
-#define IDC_COOKIES 1028
-#define IDC_CLOSE_WINDOWS2 1028
#define IDC_DISCONNECT_CHAT 1028
-#define IDC_LOGGING2 1029
-#define IDC_UNREAD_MESSAGES 1029
#define IDC_PARSE_UNREAD 1029
-#define IDC_SET_IGNORE_STATUS2 1030
#define IDC_BIGGER_AVATARS 1030
+#define IDC_CLOSE_CHAT 1031
+#define IDC_CLOSE_WINDOWS 1031
+#define IDC_MAP_STATUSES 1032
+#define IDC_BIGGER_AVATARS2 1033
+#define IDC_LOAD_MOBILE 1033
+#define IDC_PARSE_UNREAD2 1034
+#define IDC_GROUPCHATS 1034
#define IDC_NOTIFICATIONS_ENABLE 1041
#define IDC_FEEDS_ENABLE 1042
#define IDC_OTHER_ENABLE 1043
@@ -59,7 +57,6 @@
#define IDC_SYSTRAY_NOTIFY 1098
#define IDC_PREVIEW 1099
#define IDC_SET_STATUS 1126
-#define IDC_FEEDS_TYPE 1201
#define IDC_FEED_TYPE 1201
// Next default values for new objects
diff --git a/FacebookRM/theme.cpp b/FacebookRM/theme.cpp
index 30f4513..6e919ae 100644
--- a/FacebookRM/theme.cpp
+++ b/FacebookRM/theme.cpp
@@ -32,16 +32,18 @@ extern OBJLIST<FacebookProto> g_Instances;
struct
{
const char* name;
- const char* descr;
+ char* descr;
int defIconID;
const char* section;
}
static const icons[] =
{
- { "facebook", LPGEN("Facebook Icon"), IDI_FACEBOOK },
- { "mind", LPGEN("Mind"), IDI_MIND },
+ { "facebook", LPGEN("Facebook Icon"), IDI_FACEBOOK },
+ { "mind", LPGEN("Mind"), IDI_MIND },
+ { "removeFriend", LPGEN("Remove from server"), IDI_REMOVEFRIEND },
+ { "addFriend", LPGEN("Request friendship"), IDI_ADDFRIEND },
- { "homepage", LPGEN("Visit Profile"), 0, "core_main_2" },
+ { "homepage", LPGEN("Visit Profile"), 0, "core_main_2" },
};
static HANDLE hIconLibItem[SIZEOF(icons)];
@@ -98,8 +100,18 @@ HANDLE GetIconHandle(const char* name)
return 0;
}
+char *GetIconDescription(const char* name)
+{
+ for(size_t i=0; i<SIZEOF(icons); i++)
+ {
+ if(strcmp(icons[i].name,name) == 0)
+ return icons[i].descr;
+ }
+ return "";
+}
+
// Contact List menu stuff
-HANDLE g_hMenuItems[2];
+HANDLE g_hMenuItems[4];
// Helper functions
static FacebookProto * GetInstanceByHContact(HANDLE hContact)
@@ -131,7 +143,7 @@ static int PrebuildContactMenu(WPARAM wParam,LPARAM lParam)
return proto ? proto->OnPrebuildContactMenu(wParam,lParam) : 0;
}
-HANDLE hHookPreBuildMenu,sVisitProfile;
+HANDLE hHookPreBuildMenu,sVisitProfile,sAddFriend,sRemoveFriend;
void InitContactMenus()
{
hHookPreBuildMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU,PrebuildContactMenu);
@@ -141,11 +153,27 @@ void InitContactMenus()
mi.position=-2000006000;
mi.icolibItem = GetIconHandle("homepage");
- mi.pszName = LPGEN("Visit Profile");
+ mi.pszName = GetIconDescription("homepage");
mi.pszService = "FacebookProto/VisitProfile";
sVisitProfile = CreateServiceFunction(mi.pszService,GlobalService<&FacebookProto::VisitProfile>);
g_hMenuItems[1] = reinterpret_cast<HANDLE>(
CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi) );
+
+ mi.position=-2000006000;
+ mi.icolibItem = GetIconHandle("removeFriend");
+ mi.pszName = GetIconDescription("removeFriend");
+ mi.pszService = "FacebookProto/RemoveFriend";
+ sRemoveFriend = CreateServiceFunction(mi.pszService,GlobalService<&FacebookProto::RemoveFriend>);
+ g_hMenuItems[2] = reinterpret_cast<HANDLE>(
+ CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi) );
+
+ mi.position=-2000006000;
+ mi.icolibItem = GetIconHandle("addFriend");
+ mi.pszName = GetIconDescription("addFriend");
+ mi.pszService = "FacebookProto/AddFriend";
+ sAddFriend = CreateServiceFunction(mi.pszService,GlobalService<&FacebookProto::AddFriend>);
+ g_hMenuItems[3] = reinterpret_cast<HANDLE>(
+ CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi) );
}
void UninitContactMenus()
@@ -154,15 +182,17 @@ void UninitContactMenus()
CallService(MS_CLIST_REMOVECONTACTMENUITEM,(WPARAM)g_hMenuItems[i],0);
UnhookEvent(hHookPreBuildMenu);
DestroyServiceFunction(sVisitProfile);
+ DestroyServiceFunction(sRemoveFriend);
+ DestroyServiceFunction(sAddFriend);
}
-void ShowContactMenus(bool show)
+void ShowContactMenus(bool show, bool deleted)
{
for(size_t i=0; i<SIZEOF(g_hMenuItems); i++)
{
CLISTMENUITEM item = { sizeof(item) };
item.flags = CMIM_FLAGS;
- if(!show)
+ if(!show || (i == 3 && !deleted) || (i == 2 && deleted)) // 2 = REMOVE CONTACT; 3 = ADD CONTACT
item.flags |= CMIF_HIDDEN;
CallService(MS_CLIST_MODIFYMENUITEM,reinterpret_cast<WPARAM>(g_hMenuItems[i]),
diff --git a/FacebookRM/theme.h b/FacebookRM/theme.h
index 87db9d1..5eccc91 100644
--- a/FacebookRM/theme.h
+++ b/FacebookRM/theme.h
@@ -32,4 +32,4 @@ HANDLE GetIconHandle(const char *name);
void InitContactMenus(void);
void UninitContactMenus(void);
-void ShowContactMenus(bool show);
+void ShowContactMenus(bool show, bool deleted = false);
diff --git a/FacebookRM/utils.cpp b/FacebookRM/utils.cpp
index 096f1fa..5d32091 100644
--- a/FacebookRM/utils.cpp
+++ b/FacebookRM/utils.cpp
@@ -215,6 +215,9 @@ std::string utils::text::remove_html( std::string data )
if ( data.at(i) == '<' && data.at(i+1) != ' ' )
{
i = data.find( ">", i );
+ if (i == std::string::npos)
+ break;
+
continue;
}
@@ -269,6 +272,21 @@ std::string utils::text::trim( std::string data )
return (begin != std::string::npos) ? data.substr( begin, end - begin ) : "";
}
+void utils::text::explode(std::string str, std::string separator, std::vector<std::string>* results){
+ std::string::size_type pos;
+ pos = str.find_first_of(separator);
+ while(pos != std::string::npos){
+ if(pos > 0){
+ results->push_back(str.substr(0,pos));
+ }
+ str = str.substr(pos+1);
+ pos = str.find_first_of(separator);
+ }
+ if(str.length() > 0){
+ results->push_back(str);
+ }
+}
+
std::string utils::text::source_get_value( std::string* data, unsigned int argument_count, ... )
{
va_list arg;
diff --git a/FacebookRM/utils.h b/FacebookRM/utils.h
index 0978283..f7fe1c8 100644
--- a/FacebookRM/utils.h
+++ b/FacebookRM/utils.h
@@ -95,6 +95,7 @@ namespace utils
std::string trim( std::string data );
std::string source_get_value( std::string* data, unsigned int argument_count, ... );
std::string source_get_value2( std::string* data, const char *term, const char *endings);
+ void explode(std::string str, std::string separator, std::vector<std::string>* results);
};
namespace conversion