From f7782fbf614361339617da21e6220044ffcf6822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Mon, 1 Dec 2014 13:32:25 +0000 Subject: Facebook: Fix sending private message to user in chat, which is not in contactlist yet git-svn-id: http://svn.miranda-ng.org/main/trunk@11193 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/FacebookRM/src/chat.cpp | 909 +++++++++++++++++----------------- protocols/FacebookRM/src/contacts.cpp | 7 +- protocols/FacebookRM/src/proto.cpp | 17 +- protocols/FacebookRM/src/proto.h | 2 +- 4 files changed, 473 insertions(+), 462 deletions(-) (limited to 'protocols/FacebookRM/src') 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 . - -*/ - -#include "common.h" -#include -#include - -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(&gce)); - - // TODO: keep it here or move it somewhere else? - std::map::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(&gce)); -} - -int FacebookProto::OnGCEvent(WPARAM wParam,LPARAM lParam) -{ - GCHOOK *hook = reinterpret_cast(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(&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(&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(&gce)); - gce.ptszStatus = TranslateT("Friend"); - CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast(&gce)); - gce.ptszStatus = TranslateT("User"); - CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast(&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(&gce)); - CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast(&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(&gce)); - gce.ptszStatus = TranslateT("Friend"); - CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast(&gce)); - gce.ptszStatus = TranslateT("User"); - CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast(&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(&gce)); - CallServiceSync(MS_GC_EVENT,SESSION_TERMINATE,reinterpret_cast(&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(&gce)); - CallServiceSync(MS_GC_EVENT,SESSION_ONLINE, reinterpret_cast(&gce)); - } - else - { - CallServiceSync(MS_GC_EVENT,SESSION_OFFLINE,reinterpret_cast(&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(&gce)); - CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast(&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(&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 . + +*/ + +#include "common.h" +#include +#include + +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(&gce)); + + // TODO: keep it here or move it somewhere else? + std::map::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(&gce)); +} + +int FacebookProto::OnGCEvent(WPARAM wParam,LPARAM lParam) +{ + GCHOOK *hook = reinterpret_cast(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(&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(&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(&gce)); + gce.ptszStatus = TranslateT("Friend"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast(&gce)); + gce.ptszStatus = TranslateT("User"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast(&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(&gce)); + CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast(&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(&gce)); + gce.ptszStatus = TranslateT("Friend"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast(&gce)); + gce.ptszStatus = TranslateT("User"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast(&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(&gce)); + CallServiceSync(MS_GC_EVENT,SESSION_TERMINATE,reinterpret_cast(&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(&gce)); + CallServiceSync(MS_GC_EVENT,SESSION_ONLINE, reinterpret_cast(&gce)); + } + else + { + CallServiceSync(MS_GC_EVENT,SESSION_OFFLINE,reinterpret_cast(&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(&gce)); + CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast(&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(&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); -- cgit v1.2.3