diff options
-rw-r--r-- | protocols/FacebookRM/src/chat.cpp | 909 | ||||
-rw-r--r-- | protocols/FacebookRM/src/contacts.cpp | 7 | ||||
-rw-r--r-- | protocols/FacebookRM/src/proto.cpp | 17 | ||||
-rw-r--r-- | protocols/FacebookRM/src/proto.h | 2 |
4 files changed, 473 insertions, 462 deletions
diff --git a/protocols/FacebookRM/src/chat.cpp b/protocols/FacebookRM/src/chat.cpp index fc02edf353..b9f416a632 100644 --- a/protocols/FacebookRM/src/chat.cpp +++ b/protocols/FacebookRM/src/chat.cpp @@ -1,451 +1,460 @@ -/*
-
-Facebook plugin for Miranda Instant Messenger
-_____________________________________________
-
-Copyright © 2011-13 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"
-#include <m_history.h>
-#include <m_userinfo.h>
-
-void FacebookProto::UpdateChat(const TCHAR *tchat_id, const char *id, const char *name, const char *message, DWORD timestamp, bool is_old)
-{
- // replace % to %% to not interfere with chat color codes
- std::string smessage = message;
- utils::text::replace_all(&smessage, "%", "%%");
-
- ptrT tid( mir_a2t(id));
- ptrT tnick( mir_a2t_cp(name,CP_UTF8));
- ptrT ttext( mir_a2t_cp(smessage.c_str(),CP_UTF8));
-
- GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_MESSAGE };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.ptszText = ttext;
- gce.time = timestamp ? timestamp : ::time(NULL);
- if (id != NULL)
- gce.bIsMe = !strcmp(id,facy.self_.user_id.c_str());
- gce.dwFlags |= GCEF_ADDTOLOG;
- if (is_old) {
- gce.dwFlags |= GCEF_NOTNOTIFY;
- gce.dwFlags &= ~GCEF_ADDTOLOG;
- }
- gce.ptszNick = tnick;
- gce.ptszUID = tid;
- CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce));
-
- // TODO: keep it here or move it somewhere else?
- std::map<std::tstring, facebook_chatroom*>::iterator chatroom = facy.chat_rooms.find(tchat_id);
- if (chatroom != facy.chat_rooms.end()) {
- chatroom->second->message_readers.clear();
- }
-}
-
-void FacebookProto::RenameChat(const char *chat_id, const char *name)
-{
- ptrT tchat_id( mir_a2t(chat_id));
- ptrT tname( mir_a2t_cp(name, CP_UTF8));
-
- GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_CHANGESESSIONAME };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.ptszText = tname;
- CallService(MS_GC_EVENT, 0, reinterpret_cast<LPARAM>(&gce));
-}
-
-int FacebookProto::OnGCEvent(WPARAM wParam,LPARAM lParam)
-{
- GCHOOK *hook = reinterpret_cast<GCHOOK*>(lParam);
-
- if (strcmp(hook->pDest->pszModule, m_szModuleName))
- return 0;
-
- // Ignore for special chatrooms
- if (!_tcscmp(hook->pDest->ptszID, _T(FACEBOOK_NOTIFICATIONS_CHATROOM)))
- return 0;
-
- switch(hook->pDest->iType)
- {
- case GC_USER_MESSAGE:
- {
- std::string msg = _T2A(hook->ptszText, CP_UTF8);
- std::string chat_id = _T2A(hook->pDest->ptszID, CP_UTF8);
-
- if (isOnline()) {
- debugLogA("**Chat - Outgoing message: %s", msg.c_str());
- ForkThread(&FacebookProto::SendChatMsgWorker, new send_chat(chat_id, msg));
- }
-
- break;
- }
-
- case GC_USER_PRIVMESS:
- {
- std::string id = _T2A(hook->ptszUID, CP_UTF8);
-
- MCONTACT hContact = ContactIDToHContact(id);
- if (!hContact)
- break; // TODO: create new temporary contact
-
- CallService(MS_MSG_SENDMESSAGET, hContact, 0);
- break;
- }
-
- /*
- case GC_USER_LOGMENU:
- {
- switch(hook->dwData)
- {
- case 10:
- DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE), NULL, invite_to_chat_dialog,
- LPARAM(new invite_chat_param(item->id, this)));
- break;
-
- case 20:
- //chat_leave(id);
- break;
- }
- break;
- }
- */
-
- case GC_USER_NICKLISTMENU:
- {
- std::string id = _T2A(hook->ptszUID, CP_UTF8);
-
- MCONTACT hContact = ContactIDToHContact(id);
- if (!hContact)
- break; // TODO: create new temporary contact
-
- switch (hook->dwData)
- {
- case 10:
- CallService(MS_USERINFO_SHOWDIALOG, hContact, 0);
- break;
-
- case 20:
- CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0);
- break;
-
- case 110:
- //chat_leave(id);
- break;
- }
-
- break;
- }
-
- case GC_USER_LEAVE:
- case GC_SESSION_TERMINATE:
- break;
- }
-
- return 0;
-}
-
-void FacebookProto::AddChatContact(const TCHAR *tchat_id, const char *id, const char *name)
-{
- ptrT tnick( mir_a2t_cp(name, CP_UTF8));
- ptrT tid( mir_a2t(id));
-
- GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_JOIN };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.pDest = &gcd;
- gce.dwFlags = GCEF_ADDTOLOG;
- gce.ptszNick = tnick;
- gce.ptszUID = tid;
- gce.time = ::time(NULL);
- gce.bIsMe = !strcmp(id, facy.self_.user_id.c_str());
-
- if (gce.bIsMe) {
- gce.ptszStatus = TranslateT("Myself");
- } else {
- MCONTACT hContact = ContactIDToHContact(id);
- if (hContact == NULL || getByte(hContact, FACEBOOK_KEY_CONTACT_TYPE, CONTACT_NONE) != CONTACT_FRIEND)
- gce.ptszStatus = TranslateT("User");
- else {
- gce.ptszStatus = TranslateT("Friend");
- }
- }
-
- CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast<LPARAM>(&gce));
-}
-
-void FacebookProto::RemoveChatContact(const TCHAR *tchat_id, const char *id, const char *name)
-{
- // We dont want to remove our self-contact from chat. Ever.
- if (!strcmp(id, facy.self_.user_id.c_str()))
- return;
-
- ptrT tnick(mir_a2t_cp(name, CP_UTF8));
- ptrT tid( mir_a2t(id));
-
- GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_PART };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.dwFlags = GCEF_ADDTOLOG;
- gce.ptszNick = tnick;
- gce.ptszUID = tid;
- gce.time = ::time(NULL);
- gce.bIsMe = false;
-
- CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce));
-}
-
-/** Caller must free result */
-char *FacebookProto::GetChatUsers(const TCHAR *chat_id)
-{
- GC_INFO gci = {0};
- gci.Flags = GCF_USERS;
- gci.pszModule = m_szModuleName;
- gci.pszID = chat_id;
- CallService(MS_GC_GETINFO, 0, (LPARAM)&gci);
-
- debugLogA("**Chat - Users in chat %s: %s", _T2A(chat_id), gci.pszUsers);
-
- // mir_free(gci.pszUsers);
- return gci.pszUsers;
-}
-
-bool FacebookProto::IsChatContact(const TCHAR *chat_id, const char *id)
-{
- ptrA users( GetChatUsers(chat_id));
- return (users != NULL && strstr(users, id) != NULL);
-}
-
-void FacebookProto::AddChat(const TCHAR *tid, const TCHAR *tname)
-{
- // Create the group chat session
- GCSESSION gcw = { sizeof(gcw) };
- gcw.iType = GCW_PRIVMESS;
- gcw.ptszID = tid;
- gcw.pszModule = m_szModuleName;
- gcw.ptszName = tname;
- CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw);
-
- // Send setting events
- GCDEST gcd = { m_szModuleName, tid, GC_EVENT_ADDGROUP };
- GCEVENT gce = { sizeof(gce), &gcd };
-
- // Create a user statuses
- gce.ptszStatus = TranslateT("Myself");
- CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce));
- gce.ptszStatus = TranslateT("Friend");
- CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce));
- gce.ptszStatus = TranslateT("User");
- CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce));
-
- // Finish initialization
- gcd.iType = GC_EVENT_CONTROL;
- gce.time = ::time(NULL);
- gce.pDest = &gcd;
-
- bool hideChats = getBool(FACEBOOK_KEY_HIDE_CHATS, DEFAULT_HIDE_CHATS);
-
- // Add self contact
- AddChatContact(tid, facy.self_.user_id.c_str(), facy.self_.real_name.c_str());
- CallServiceSync(MS_GC_EVENT, (hideChats ? WINDOW_HIDDEN : SESSION_INITDONE), reinterpret_cast<LPARAM>(&gce));
- CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast<LPARAM>(&gce));
-}
-
-INT_PTR FacebookProto::OnJoinChat(WPARAM hContact, LPARAM suppress)
-{
- // TODO: load info from server + old history,...
-
- ptrT idT( getTStringA(hContact, "ChatRoomID"));
- ptrT nameT( getTStringA(hContact, "Nick"));
-
- if (idT && nameT)
- AddChat(idT, nameT);
-
-/* GCSESSION gcw = {sizeof(gcw)};
-
- // Create the group chat session
- gcw.dwFlags = GC_TCHAR;
- gcw.iType = GCW_PRIVMESS;
- 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, m_tszUserName, GC_EVENT_ADDGROUP };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.ptszStatus = TranslateT("Myself");
- CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce));
- gce.ptszStatus = TranslateT("Friend");
- CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce));
- gce.ptszStatus = TranslateT("User");
- 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;
-}
-
-INT_PTR FacebookProto::OnLeaveChat(WPARAM wParam,LPARAM)
-{
- ptrT idT(wParam ? getTStringA(wParam, "ChatRoomID") : NULL);
-
- GCDEST gcd = { m_szModuleName, NULL, GC_EVENT_CONTROL };
- gcd.ptszID = idT;
-
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.time = ::time(NULL);
-
- 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, m_tszUserName, GC_EVENT_CONTROL };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.time = ::time(NULL);
-
- 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));
- }
-}
-*/
-
-int FacebookProto::OnGCMenuHook(WPARAM, LPARAM lParam)
-{
- GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;
-
- if (gcmi == NULL || _stricmp(gcmi->pszModule, m_szModuleName)) return 0;
-
- if (gcmi->Type == MENU_ON_LOG)
- {
- static const struct gc_item Items[] =
- {
- { LPGENT("&Invite user..."), 10, MENU_ITEM, FALSE },
- { LPGENT("&Leave chat session"), 20, MENU_ITEM, FALSE }
- };
- gcmi->nItems = SIZEOF(Items);
- gcmi->Item = (gc_item*)Items;
- }
- else if (gcmi->Type == MENU_ON_NICKLIST)
- {
- if (!_stricmp(facy.self_.user_id.c_str(), _T2A(gcmi->pszUID)))
- {
- /*static const struct gc_item Items[] =
- {
- { LPGENT("User &details"), 10, MENU_ITEM, FALSE },
- { LPGENT("User &history"), 20, MENU_ITEM, FALSE },
- { _T(""), 100, MENU_SEPARATOR, FALSE },
- { LPGENT("&Leave chat session"), 110, MENU_ITEM, FALSE }
- };
- gcmi->nItems = SIZEOF(Items);
- gcmi->Item = (gc_item*)Items;*/
- gcmi->nItems = 0;
- gcmi->Item = NULL;
- }
- else
- {
- static const struct gc_item Items[] =
- {
- { LPGENT("User &details"), 10, MENU_ITEM, FALSE },
- { LPGENT("User &history"), 20, MENU_ITEM, FALSE }
- };
- gcmi->nItems = SIZEOF(Items);
- gcmi->Item = (gc_item*)Items;
- }
- }
-
- return 0;
-}
-
-bool FacebookProto::IsSpecialChatRoom(MCONTACT hContact) {
- if (!isChatRoom(hContact))
- return false;
-
- ptrT idT(getTStringA(hContact, "ChatRoomID"));
- return idT && !_tcscmp(idT, _T(FACEBOOK_NOTIFICATIONS_CHATROOM));
-}
-
-void FacebookProto::PrepareNotificationsChatRoom() {
- if (!getBool(FACEBOOK_KEY_NOTIFICATIONS_CHATROOM, DEFAULT_NOTIFICATIONS_CHATROOM))
- return;
-
- // Prepare notifications chatroom if not exists
- TCHAR *gidT = _T(FACEBOOK_NOTIFICATIONS_CHATROOM);
-
- MCONTACT hNotificationsChatRoom = ChatIDToHContact(gidT);
- if (hNotificationsChatRoom == NULL || getDword(hNotificationsChatRoom, "Status", ID_STATUS_OFFLINE) != ID_STATUS_ONLINE) {
- TCHAR nameT[200];
- mir_sntprintf(nameT, SIZEOF(nameT), _T("%s: %s"), m_tszUserName, TranslateT("Notifications"));
-
- // Create the group chat session
- GCSESSION gcw = { sizeof(gcw) };
- gcw.iType = GCW_PRIVMESS;
- gcw.ptszID = gidT;
- gcw.pszModule = m_szModuleName;
- gcw.ptszName = nameT;
- CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw);
-
- // Send setting events
- GCDEST gcd = { m_szModuleName, gidT, GC_EVENT_CONTROL };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.time = ::time(NULL);
-
- CallServiceSync(MS_GC_EVENT, WINDOW_HIDDEN, reinterpret_cast<LPARAM>(&gce));
- CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast<LPARAM>(&gce));
- }
-}
-
-void FacebookProto::UpdateNotificationsChatRoom(facebook_notification *notification) {
- if (!getBool(FACEBOOK_KEY_NOTIFICATIONS_CHATROOM, DEFAULT_NOTIFICATIONS_CHATROOM))
- return;
-
- std::stringstream text;
- text << notification->text << "\n\n" << PrepareUrl(notification->link);
-
- std::string message = text.str();
- utils::text::replace_all(&message, "%", "%%");
-
- ptrT idT(mir_tstrdup(_T(FACEBOOK_NOTIFICATIONS_CHATROOM)));
- ptrT messageT(mir_a2t_cp(message.c_str(), CP_UTF8));
-
- GCDEST gcd = { m_szModuleName, _T(FACEBOOK_NOTIFICATIONS_CHATROOM), GC_EVENT_MESSAGE };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.ptszText = messageT;
- gce.time = notification->time ? notification->time : ::time(NULL);
- gce.bIsMe = false;
- gce.dwFlags |= GCEF_ADDTOLOG;
- gce.ptszNick = TranslateT("Notifications");
- gce.ptszUID = idT;
-
- CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast<LPARAM>(&gce));
+/* + +Facebook plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright � 2011-13 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" +#include <m_history.h> +#include <m_userinfo.h> + +void FacebookProto::UpdateChat(const TCHAR *tchat_id, const char *id, const char *name, const char *message, DWORD timestamp, bool is_old) +{ + // replace % to %% to not interfere with chat color codes + std::string smessage = message; + utils::text::replace_all(&smessage, "%", "%%"); + + ptrT tid( mir_a2t(id)); + ptrT tnick( mir_a2t_cp(name,CP_UTF8)); + ptrT ttext( mir_a2t_cp(smessage.c_str(),CP_UTF8)); + + GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_MESSAGE }; + GCEVENT gce = { sizeof(gce), &gcd }; + gce.ptszText = ttext; + gce.time = timestamp ? timestamp : ::time(NULL); + if (id != NULL) + gce.bIsMe = !strcmp(id,facy.self_.user_id.c_str()); + gce.dwFlags |= GCEF_ADDTOLOG; + if (is_old) { + gce.dwFlags |= GCEF_NOTNOTIFY; + gce.dwFlags &= ~GCEF_ADDTOLOG; + } + gce.ptszNick = tnick; + gce.ptszUID = tid; + CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce)); + + // TODO: keep it here or move it somewhere else? + std::map<std::tstring, facebook_chatroom*>::iterator chatroom = facy.chat_rooms.find(tchat_id); + if (chatroom != facy.chat_rooms.end()) { + chatroom->second->message_readers.clear(); + } +} + +void FacebookProto::RenameChat(const char *chat_id, const char *name) +{ + ptrT tchat_id( mir_a2t(chat_id)); + ptrT tname( mir_a2t_cp(name, CP_UTF8)); + + GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_CHANGESESSIONAME }; + GCEVENT gce = { sizeof(gce), &gcd }; + gce.ptszText = tname; + CallService(MS_GC_EVENT, 0, reinterpret_cast<LPARAM>(&gce)); +} + +int FacebookProto::OnGCEvent(WPARAM wParam,LPARAM lParam) +{ + GCHOOK *hook = reinterpret_cast<GCHOOK*>(lParam); + + if (strcmp(hook->pDest->pszModule, m_szModuleName)) + return 0; + + // Ignore for special chatrooms + if (!_tcscmp(hook->pDest->ptszID, _T(FACEBOOK_NOTIFICATIONS_CHATROOM))) + return 0; + + switch(hook->pDest->iType) + { + case GC_USER_MESSAGE: + { + std::string msg = _T2A(hook->ptszText, CP_UTF8); + std::string chat_id = _T2A(hook->pDest->ptszID, CP_UTF8); + + if (isOnline()) { + debugLogA("**Chat - Outgoing message: %s", msg.c_str()); + ForkThread(&FacebookProto::SendChatMsgWorker, new send_chat(chat_id, msg)); + } + + break; + } + + case GC_USER_PRIVMESS: + { + facebook_user fbu; + fbu.user_id = _T2A(hook->ptszUID, CP_UTF8); + + // Find this contact in list or add new temporary contact + MCONTACT hContact = AddToContactList(&fbu, CONTACT_NONE, false, true); + + if (!hContact) + break; + + CallService(MS_MSG_SENDMESSAGET, hContact, 0); + break; + } + + /* + case GC_USER_LOGMENU: + { + switch(hook->dwData) + { + case 10: + DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE), NULL, invite_to_chat_dialog, + LPARAM(new invite_chat_param(item->id, this))); + break; + + case 20: + //chat_leave(id); + break; + } + break; + } + */ + + case GC_USER_NICKLISTMENU: + { + MCONTACT hContact = NULL; + if (hook->dwData == 10 || hook->dwData == 20) { + facebook_user fbu; + fbu.user_id = _T2A(hook->ptszUID, CP_UTF8); + + // Find this contact in list or add new temporary contact + hContact = AddToContactList(&fbu, CONTACT_NONE, false, true); + + if (!hContact) + break; + } + + switch (hook->dwData) + { + case 10: + CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); + break; + + case 20: + CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); + break; + + case 110: + //chat_leave(id); + break; + } + + break; + } + + case GC_USER_LEAVE: + case GC_SESSION_TERMINATE: + break; + } + + return 0; +} + +void FacebookProto::AddChatContact(const TCHAR *tchat_id, const char *id, const char *name) +{ + ptrT tnick( mir_a2t_cp(name, CP_UTF8)); + ptrT tid( mir_a2t(id)); + + GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_JOIN }; + GCEVENT gce = { sizeof(gce), &gcd }; + gce.pDest = &gcd; + gce.dwFlags = GCEF_ADDTOLOG; + gce.ptszNick = tnick; + gce.ptszUID = tid; + gce.time = ::time(NULL); + gce.bIsMe = !strcmp(id, facy.self_.user_id.c_str()); + + if (gce.bIsMe) { + gce.ptszStatus = TranslateT("Myself"); + } else { + MCONTACT hContact = ContactIDToHContact(id); + if (hContact == NULL || getByte(hContact, FACEBOOK_KEY_CONTACT_TYPE, CONTACT_NONE) != CONTACT_FRIEND) + gce.ptszStatus = TranslateT("User"); + else { + gce.ptszStatus = TranslateT("Friend"); + } + } + + CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast<LPARAM>(&gce)); +} + +void FacebookProto::RemoveChatContact(const TCHAR *tchat_id, const char *id, const char *name) +{ + // We dont want to remove our self-contact from chat. Ever. + if (!strcmp(id, facy.self_.user_id.c_str())) + return; + + ptrT tnick(mir_a2t_cp(name, CP_UTF8)); + ptrT tid( mir_a2t(id)); + + GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_PART }; + GCEVENT gce = { sizeof(gce), &gcd }; + gce.dwFlags = GCEF_ADDTOLOG; + gce.ptszNick = tnick; + gce.ptszUID = tid; + gce.time = ::time(NULL); + gce.bIsMe = false; + + CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce)); +} + +/** Caller must free result */ +char *FacebookProto::GetChatUsers(const TCHAR *chat_id) +{ + GC_INFO gci = {0}; + gci.Flags = GCF_USERS; + gci.pszModule = m_szModuleName; + gci.pszID = chat_id; + CallService(MS_GC_GETINFO, 0, (LPARAM)&gci); + + debugLogA("**Chat - Users in chat %s: %s", _T2A(chat_id), gci.pszUsers); + + // mir_free(gci.pszUsers); + return gci.pszUsers; +} + +bool FacebookProto::IsChatContact(const TCHAR *chat_id, const char *id) +{ + ptrA users( GetChatUsers(chat_id)); + return (users != NULL && strstr(users, id) != NULL); +} + +void FacebookProto::AddChat(const TCHAR *tid, const TCHAR *tname) +{ + // Create the group chat session + GCSESSION gcw = { sizeof(gcw) }; + gcw.iType = GCW_PRIVMESS; + gcw.ptszID = tid; + gcw.pszModule = m_szModuleName; + gcw.ptszName = tname; + CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw); + + // Send setting events + GCDEST gcd = { m_szModuleName, tid, GC_EVENT_ADDGROUP }; + GCEVENT gce = { sizeof(gce), &gcd }; + + // Create a user statuses + gce.ptszStatus = TranslateT("Myself"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce)); + gce.ptszStatus = TranslateT("Friend"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce)); + gce.ptszStatus = TranslateT("User"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce)); + + // Finish initialization + gcd.iType = GC_EVENT_CONTROL; + gce.time = ::time(NULL); + gce.pDest = &gcd; + + bool hideChats = getBool(FACEBOOK_KEY_HIDE_CHATS, DEFAULT_HIDE_CHATS); + + // Add self contact + AddChatContact(tid, facy.self_.user_id.c_str(), facy.self_.real_name.c_str()); + CallServiceSync(MS_GC_EVENT, (hideChats ? WINDOW_HIDDEN : SESSION_INITDONE), reinterpret_cast<LPARAM>(&gce)); + CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast<LPARAM>(&gce)); +} + +INT_PTR FacebookProto::OnJoinChat(WPARAM hContact, LPARAM suppress) +{ + // TODO: load info from server + old history,... + + ptrT idT( getTStringA(hContact, "ChatRoomID")); + ptrT nameT( getTStringA(hContact, "Nick")); + + if (idT && nameT) + AddChat(idT, nameT); + +/* GCSESSION gcw = {sizeof(gcw)}; + + // Create the group chat session + gcw.dwFlags = GC_TCHAR; + gcw.iType = GCW_PRIVMESS; + 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, m_tszUserName, GC_EVENT_ADDGROUP }; + GCEVENT gce = { sizeof(gce), &gcd }; + gce.ptszStatus = TranslateT("Myself"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce)); + gce.ptszStatus = TranslateT("Friend"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce)); + gce.ptszStatus = TranslateT("User"); + 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; +} + +INT_PTR FacebookProto::OnLeaveChat(WPARAM wParam,LPARAM) +{ + ptrT idT(wParam ? getTStringA(wParam, "ChatRoomID") : NULL); + + GCDEST gcd = { m_szModuleName, NULL, GC_EVENT_CONTROL }; + gcd.ptszID = idT; + + GCEVENT gce = { sizeof(gce), &gcd }; + gce.time = ::time(NULL); + + 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, m_tszUserName, GC_EVENT_CONTROL }; + GCEVENT gce = { sizeof(gce), &gcd }; + gce.time = ::time(NULL); + + 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)); + } +} +*/ + +int FacebookProto::OnGCMenuHook(WPARAM, LPARAM lParam) +{ + GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam; + + if (gcmi == NULL || _stricmp(gcmi->pszModule, m_szModuleName)) return 0; + + if (gcmi->Type == MENU_ON_LOG) + { + static const struct gc_item Items[] = + { + { LPGENT("&Invite user..."), 10, MENU_ITEM, FALSE }, + { LPGENT("&Leave chat session"), 20, MENU_ITEM, FALSE } + }; + gcmi->nItems = SIZEOF(Items); + gcmi->Item = (gc_item*)Items; + } + else if (gcmi->Type == MENU_ON_NICKLIST) + { + if (!_stricmp(facy.self_.user_id.c_str(), _T2A(gcmi->pszUID))) + { + /*static const struct gc_item Items[] = + { + { LPGENT("User &details"), 10, MENU_ITEM, FALSE }, + { LPGENT("User &history"), 20, MENU_ITEM, FALSE }, + { _T(""), 100, MENU_SEPARATOR, FALSE }, + { LPGENT("&Leave chat session"), 110, MENU_ITEM, FALSE } + }; + gcmi->nItems = SIZEOF(Items); + gcmi->Item = (gc_item*)Items;*/ + gcmi->nItems = 0; + gcmi->Item = NULL; + } + else + { + static const struct gc_item Items[] = + { + { LPGENT("User &details"), 10, MENU_ITEM, FALSE }, + { LPGENT("User &history"), 20, MENU_ITEM, FALSE } + }; + gcmi->nItems = SIZEOF(Items); + gcmi->Item = (gc_item*)Items; + } + } + + return 0; +} + +bool FacebookProto::IsSpecialChatRoom(MCONTACT hContact) { + if (!isChatRoom(hContact)) + return false; + + ptrT idT(getTStringA(hContact, "ChatRoomID")); + return idT && !_tcscmp(idT, _T(FACEBOOK_NOTIFICATIONS_CHATROOM)); +} + +void FacebookProto::PrepareNotificationsChatRoom() { + if (!getBool(FACEBOOK_KEY_NOTIFICATIONS_CHATROOM, DEFAULT_NOTIFICATIONS_CHATROOM)) + return; + + // Prepare notifications chatroom if not exists + TCHAR *gidT = _T(FACEBOOK_NOTIFICATIONS_CHATROOM); + + MCONTACT hNotificationsChatRoom = ChatIDToHContact(gidT); + if (hNotificationsChatRoom == NULL || getDword(hNotificationsChatRoom, "Status", ID_STATUS_OFFLINE) != ID_STATUS_ONLINE) { + TCHAR nameT[200]; + mir_sntprintf(nameT, SIZEOF(nameT), _T("%s: %s"), m_tszUserName, TranslateT("Notifications")); + + // Create the group chat session + GCSESSION gcw = { sizeof(gcw) }; + gcw.iType = GCW_PRIVMESS; + gcw.ptszID = gidT; + gcw.pszModule = m_szModuleName; + gcw.ptszName = nameT; + CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw); + + // Send setting events + GCDEST gcd = { m_szModuleName, gidT, GC_EVENT_CONTROL }; + GCEVENT gce = { sizeof(gce), &gcd }; + gce.time = ::time(NULL); + + CallServiceSync(MS_GC_EVENT, WINDOW_HIDDEN, reinterpret_cast<LPARAM>(&gce)); + CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast<LPARAM>(&gce)); + } +} + +void FacebookProto::UpdateNotificationsChatRoom(facebook_notification *notification) { + if (!getBool(FACEBOOK_KEY_NOTIFICATIONS_CHATROOM, DEFAULT_NOTIFICATIONS_CHATROOM)) + return; + + std::stringstream text; + text << notification->text << "\n\n" << PrepareUrl(notification->link); + + std::string message = text.str(); + utils::text::replace_all(&message, "%", "%%"); + + ptrT idT(mir_tstrdup(_T(FACEBOOK_NOTIFICATIONS_CHATROOM))); + ptrT messageT(mir_a2t_cp(message.c_str(), CP_UTF8)); + + GCDEST gcd = { m_szModuleName, _T(FACEBOOK_NOTIFICATIONS_CHATROOM), GC_EVENT_MESSAGE }; + GCEVENT gce = { sizeof(gce), &gcd }; + gce.ptszText = messageT; + gce.time = notification->time ? notification->time : ::time(NULL); + gce.bIsMe = false; + gce.dwFlags |= GCEF_ADDTOLOG; + gce.ptszNick = TranslateT("Notifications"); + gce.ptszUID = idT; + + CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast<LPARAM>(&gce)); }
\ No newline at end of file diff --git a/protocols/FacebookRM/src/contacts.cpp b/protocols/FacebookRM/src/contacts.cpp index 5da990e616..61acec9b56 100644 --- a/protocols/FacebookRM/src/contacts.cpp +++ b/protocols/FacebookRM/src/contacts.cpp @@ -326,7 +326,7 @@ void FacebookProto::LoadChatInfo(facebook_chatroom *fbc) } -MCONTACT FacebookProto::AddToContactList(facebook_user* fbu, ContactType type, bool force_add) +MCONTACT FacebookProto::AddToContactList(facebook_user* fbu, ContactType type, bool force_add, bool add_temporarily) { // First, check if this contact exists (and if does, just return it) if (!force_add) { @@ -347,6 +347,11 @@ MCONTACT FacebookProto::AddToContactList(facebook_user* fbu, ContactType type, b // If we have some contact, we'll save its data if (hContact) { // Save these values only when adding new contact, not when updating existing + if (add_temporarily) { + db_set_b(hContact, "Clist", "Hidden", 1); + db_set_b(hContact, "Clist", "NotOnList", 1); + } + setString(hContact, FACEBOOK_KEY_ID, fbu->user_id.c_str()); std::string homepage = FACEBOOK_URL_PROFILE + fbu->user_id; diff --git a/protocols/FacebookRM/src/proto.cpp b/protocols/FacebookRM/src/proto.cpp index 463b7c1e89..ec8ee11424 100644 --- a/protocols/FacebookRM/src/proto.cpp +++ b/protocols/FacebookRM/src/proto.cpp @@ -288,16 +288,13 @@ MCONTACT FacebookProto::AddToList(int flags, PROTOSEARCHRESULT* psr) return NULL; } - MCONTACT hContact = AddToContactList(&fbu, CONTACT_NONE); - if (hContact) { - if (flags & PALF_TEMPORARY) { - db_set_b(hContact, "Clist", "Hidden", 1); - db_set_b(hContact, "Clist", "NotOnList", 1); - } - else if (db_get_b(hContact, "CList", "NotOnList", 0)) { - db_unset(hContact, "CList", "Hidden"); - db_unset(hContact, "CList", "NotOnList"); - } + bool add_temporarily = (flags & PALF_TEMPORARY); + MCONTACT hContact = AddToContactList(&fbu, CONTACT_NONE, false, add_temporarily); + + // Reset NotOnList flag if present and we're adding this contact not temporarily + if (hContact && !add_temporarily && db_get_b(hContact, "CList", "NotOnList", 0)) { + db_unset(hContact, "CList", "Hidden"); + db_unset(hContact, "CList", "NotOnList"); } return hContact; diff --git a/protocols/FacebookRM/src/proto.h b/protocols/FacebookRM/src/proto.h index 8f85582ca6..e0c95cf8f9 100644 --- a/protocols/FacebookRM/src/proto.h +++ b/protocols/FacebookRM/src/proto.h @@ -204,7 +204,7 @@ public: MCONTACT ChatIDToHContact(const std::tstring&); std::string ThreadIDToContactID(const std::string&); void LoadContactInfo(facebook_user* fbu); - MCONTACT AddToContactList(facebook_user*, ContactType type, bool force_add = false); + MCONTACT AddToContactList(facebook_user*, ContactType type, bool force_add = false, bool add_temporarily = false); void SetAllContactStatuses(int status); MCONTACT HContactFromAuthEvent(HANDLE hEvent); void StartTyping(MCONTACT hContact); |