summaryrefslogtreecommitdiff
path: root/protocols/Facebook/src/groupchats.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Facebook/src/groupchats.cpp')
-rw-r--r--protocols/Facebook/src/groupchats.cpp235
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);
+}