diff options
Diffstat (limited to 'protocols/Facebook/src/groupchats.cpp')
-rw-r--r-- | protocols/Facebook/src/groupchats.cpp | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/protocols/Facebook/src/groupchats.cpp b/protocols/Facebook/src/groupchats.cpp new file mode 100644 index 0000000000..281fc49611 --- /dev/null +++ b/protocols/Facebook/src/groupchats.cpp @@ -0,0 +1,235 @@ +/* + +Facebook plugin for Miranda NG +Copyright © 2019-20 Miranda NG team + +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 "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// +// Invitation dialog + +class CGroupchatInviteDlg : public CFBDlgBase +{ + CCtrlClc m_clc; + SESSION_INFO *m_si; + + void FilterList(CCtrlClc *) + { + for (auto &hContact : Contacts()) { + char *proto = Proto_GetBaseAccountName(hContact); + if (mir_strcmp(proto, m_proto->m_szModuleName) || m_proto->isChatRoom(hContact)) + if (HANDLE hItem = m_clc.FindContact(hContact)) + m_clc.DeleteItem(hItem); + } + } + + void ResetListOptions(CCtrlClc *) + { + m_clc.SetBkBitmap(0, nullptr); + m_clc.SetBkColor(GetSysColor(COLOR_WINDOW)); + m_clc.SetGreyoutFlags(0); + m_clc.SetLeftMargin(4); + m_clc.SetIndent(10); + m_clc.SetHideEmptyGroups(1); + m_clc.SetHideOfflineRoot(1); + for (int i = 0; i <= FONTID_MAX; i++) + m_clc.SetTextColor(i, GetSysColor(COLOR_WINDOWTEXT)); + } + +public: + CGroupchatInviteDlg(FacebookProto *ppro, SESSION_INFO *si) : + CFBDlgBase(ppro, IDD_GROUPCHAT_INVITE), + m_si(si), + m_clc(this, IDC_CLIST) + { + m_clc.OnNewContact = + m_clc.OnListRebuilt = Callback(this, &CGroupchatInviteDlg::FilterList); + m_clc.OnOptionsChanged = Callback(this, &CGroupchatInviteDlg::ResetListOptions); + } + + bool OnInitDialog() override + { + SetWindowLongPtr(m_clc.GetHwnd(), GWL_STYLE, + GetWindowLongPtr(m_clc.GetHwnd(), GWL_STYLE) | CLS_SHOWHIDDEN | CLS_HIDEOFFLINE | CLS_CHECKBOXES | CLS_HIDEEMPTYGROUPS | CLS_USEGROUPS | CLS_GREYALTERNATE | CLS_GROUPCHECKBOXES); + m_clc.SendMsg(CLM_SETEXSTYLE, CLS_EX_DISABLEDRAGDROP | CLS_EX_TRACKSELECT, 0); + + ResetListOptions(&m_clc); + FilterList(&m_clc); + return true; + } + + bool OnApply() override + { + JSONNode list(JSON_ARRAY); + + for (auto &hContact : m_proto->AccContacts()) { + if (m_proto->isChatRoom(hContact)) + continue; + + if (HANDLE hItem = m_clc.FindContact(hContact)) { + if (m_clc.GetCheck(hItem)) { + JSONNode user; user << CHAR_PARAM("type", "id") << CHAR_PARAM("id", m_proto->getMStringA(DBKEY_ID)); + list << user; + } + } + } + + auto *pReq = m_proto->CreateRequest(FB_API_URL_PARTS, "addMembers", "POST"); + pReq << CHAR_PARAM("to", list.write().c_str()) << WCHAR_PARAM("id", CMStringW(FORMAT, L"t_%s", m_si->ptszID)); + pReq->CalcSig(); + + JsonReply reply(m_proto->ExecuteRequest(pReq)); + return true; + } +}; + +void FacebookProto::Chat_InviteUser(SESSION_INFO *si) +{ + CGroupchatInviteDlg dlg(this, si); + if (si->pDlg) + dlg.SetParent(((CDlgBase *)si->pDlg)->GetHwnd()); + dlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Group chats + +enum ChatMenuItems +{ + IDM_INVITE = 10, IDM_LEAVE +}; + +static gc_item sttLogListItems[] = +{ + { LPGENW("&Invite a user"), IDM_INVITE, MENU_ITEM }, + { nullptr, 0, MENU_SEPARATOR }, + { LPGENW("&Leave/destroy chat"), IDM_LEAVE, MENU_ITEM } +}; + +int FacebookProto::GroupchatMenuHook(WPARAM, LPARAM lParam) +{ + GCMENUITEMS *gcmi = (GCMENUITEMS *)lParam; + if (gcmi == nullptr) + return 0; + + if (mir_strcmpi(gcmi->pszModule, m_szModuleName)) + return 0; + + SESSION_INFO *si = g_chatApi.SM_FindSession(gcmi->pszID, gcmi->pszModule); + if (si == nullptr) + return 0; + + if (gcmi->Type == MENU_ON_LOG) + Chat_AddMenuItems(gcmi->hMenu, _countof(sttLogListItems), sttLogListItems, &g_plugin); + + return 0; +} + +int FacebookProto::GroupchatEventHook(WPARAM, LPARAM lParam) +{ + GCHOOK *gch = (GCHOOK *)lParam; + if (gch == nullptr) + return 0; + + if (mir_strcmpi(gch->pszModule, m_szModuleName)) + return 0; + + SESSION_INFO *si = g_chatApi.SM_FindSession(gch->ptszID, gch->pszModule); + if (si == nullptr) + return 0; + + switch (gch->iType) { + case GC_USER_MESSAGE: + rtrimw(gch->ptszText); + if (!mir_wstrlen(gch->ptszText)) + break; + + if (m_bOnline) { + wchar_t *wszText = NEWWSTR_ALLOCA(gch->ptszText); + Chat_UnescapeTags(wszText); + SendMsg(si->hContact, 0, T2Utf(wszText)); + } + break; + + case GC_USER_PRIVMESS: + Chat_SendPrivateMessage(gch); + break; + + case GC_USER_LOGMENU: + Chat_ProcessLogMenu(si, gch->dwData); + break; + } + + return 0; +} + +void FacebookProto::Chat_ProcessLogMenu(SESSION_INFO *si, int iChoice) +{ + switch (iChoice) { + case IDM_INVITE: + Chat_InviteUser(si); + break; + + case IDM_LEAVE: + Chat_Leave(si); + break; + } +} + +void FacebookProto::Chat_SendPrivateMessage(GCHOOK *gch) +{ + auto *pUser = FindUser(_wtoi64(gch->ptszUID)); + if (pUser == nullptr) { + pUser = AddContact(gch->ptszUID, true); + setWString(pUser->hContact, "Nick", gch->ptszNick); + db_set_b(pUser->hContact, "CList", "Hidden", 1); + db_set_dw(pUser->hContact, "Ignore", "Mask1", 0); + } + + CallService(MS_MSG_SENDMESSAGE, pUser->hContact, 0); +} + +int FacebookProto::Chat_KickUser(SESSION_INFO *si, const wchar_t *pwszUid) +{ + auto *pReq = CreateRequest(FB_API_URL_PARTS, "removeMembers", "DELETE"); + pReq << WCHAR_PARAM("id", CMStringW(FORMAT, L"t_%s", si->ptszID)); + if (pwszUid != nullptr) { + JSONNode list(JSON_ARRAY); + JSONNode user; user << CHAR_PARAM("type", "id") << WCHAR_PARAM("id", pwszUid); + list << user; + pReq << CHAR_PARAM("to", list.write().c_str()); + } + pReq->CalcSig(); + + JsonReply reply(ExecuteRequest(pReq)); + return reply.error(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static void __cdecl DestroyRoomThread(SESSION_INFO *si) +{ + ::Sleep(100); + Chat_Terminate(si->pszModule, si->ptszID, true); +} + +void FacebookProto::Chat_Leave(SESSION_INFO *si) +{ + if (Chat_KickUser(si, nullptr) == 0) + mir_forkThread<SESSION_INFO>(DestroyRoomThread, si); +} |