summaryrefslogtreecommitdiff
path: root/protocols/ICQ-WIM/src/groupchats.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/ICQ-WIM/src/groupchats.cpp')
-rw-r--r--protocols/ICQ-WIM/src/groupchats.cpp303
1 files changed, 303 insertions, 0 deletions
diff --git a/protocols/ICQ-WIM/src/groupchats.cpp b/protocols/ICQ-WIM/src/groupchats.cpp
new file mode 100644
index 0000000000..5d4253bc15
--- /dev/null
+++ b/protocols/ICQ-WIM/src/groupchats.cpp
@@ -0,0 +1,303 @@
+// -----------------------------------------------------------------------------
+// ICQ plugin for Miranda NG
+// -----------------------------------------------------------------------------
+// Copyright © 2018-19 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, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+// -----------------------------------------------------------------------------
+
+#include "stdafx.h"
+
+void CIcqProto::LoadChatInfo(SESSION_INFO *si)
+{
+ int memberCount = getDword(si->hContact, "MemberCount");
+ for (int i = 0; i < memberCount; i++) {
+ char buf[100];
+ mir_snprintf(buf, "m%d", i);
+ ptrW szSetting(getWStringA(si->hContact, buf));
+ JSONNode *node = json_parse(T2Utf(szSetting));
+ if (node == nullptr)
+ continue;
+
+ CMStringW nick((*node)["nick"].as_mstring());
+ CMStringW role((*node)["role"].as_mstring());
+ CMStringW sn((*node)["sn"].as_mstring());
+
+ GCEVENT gce = { m_szModuleName, si->ptszID, GC_EVENT_JOIN };
+ gce.dwFlags = GCEF_SILENT;
+ gce.ptszNick = nick;
+ gce.ptszUID = sn;
+ gce.time = ::time(0);
+ gce.bIsMe = _wtoi(sn) == (int)m_dwUin;
+ gce.ptszStatus = TranslateW(role);
+ Chat_Event(&gce);
+
+ json_delete(node);
+ }
+}
+
+void CIcqProto::OnGetChatInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq)
+{
+ SESSION_INFO *si = (SESSION_INFO*)pReq->pUserInfo;
+
+ RobustReply root(pReply);
+ if (root.error() != 20000)
+ return;
+
+ int n = 0;
+ char buf[100];
+ const JSONNode &results = root.results();
+ for (auto &it : results["members"]) {
+ mir_snprintf(buf, "m%d", n++);
+
+ CMStringW friendly = it["friendly"].as_mstring();
+ CMStringW role = it["role"].as_mstring();
+ CMStringW sn = it["sn"].as_mstring();
+
+ JSONNode member;
+ member << WCHAR_PARAM("nick", friendly) << WCHAR_PARAM("role", role) << WCHAR_PARAM("sn", sn);
+ ptrW text(json_write(&member));
+ setWString(si->hContact, buf, text);
+ }
+
+ setDword(si->hContact, "MemberCount", n);
+ setId(si->hContact, "InfoVersion", _wtoi64(results["infoVersion"].as_mstring()));
+ setId(si->hContact, "MembersVersion", _wtoi64(results["membersVersion"].as_mstring()));
+
+ LoadChatInfo(si);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Invitation dialog
+
+class CGroupchatInviteDlg : public CProtoDlgBase<CIcqProto>
+{
+ typedef CProtoDlgBase<CIcqProto> CSuper;
+
+ CCtrlClc m_clc;
+ SESSION_INFO *m_si;
+
+ void FilterList(CCtrlClc*)
+ {
+ for (auto &hContact : Contacts()) {
+ char *proto = GetContactProto(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(CIcqProto *ppro, SESSION_INFO *si) :
+ CSuper(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
+ {
+ CMStringA szMembers;
+ for (auto &hContact : m_proto->AccContacts()) {
+ if (m_proto->isChatRoom(hContact))
+ continue;
+
+ if (HANDLE hItem = m_clc.FindContact(hContact)) {
+ if (m_clc.GetCheck(hItem)) {
+ if (!szMembers.IsEmpty())
+ szMembers.AppendChar(',');
+ szMembers.Append(m_proto->GetUserId(hContact));
+ }
+ }
+ }
+
+ auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, ICQ_API_SERVER "/mchat/AddChat");
+ pReq << CHAR_PARAM("f", "json") << WCHAR_PARAM("chat_id", m_si->ptszID) << CHAR_PARAM("aimsid", m_proto->m_aimsid) << CHAR_PARAM("r", pReq->m_reqId) << CHAR_PARAM("members", szMembers);
+ m_proto->Push(pReq);
+ return true;
+ }
+};
+
+void CIcqProto::InviteUserToChat(SESSION_INFO *si)
+{
+ CGroupchatInviteDlg dlg(this, si);
+ if (si->pDlg)
+ dlg.SetParent(((CDlgBase*)si->pDlg)->GetHwnd());
+ dlg.DoModal();
+}
+
+void CIcqProto::LeaveDestroyChat(SESSION_INFO *si)
+{
+ auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, ICQ_API_SERVER "/buddylist/hideChat");
+ pReq << CHAR_PARAM("f", "json") << CHAR_PARAM("aimsid", m_aimsid) << WCHAR_PARAM("buddy", si->ptszID)
+ << CHAR_PARAM("r", pReq->m_reqId) << INT64_PARAM("lastMsgId", getId(si->hContact, DB_KEY_LASTMSGID));
+ Push(pReq);
+
+ Chat_Terminate(si->pszModule, si->ptszID, true);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Group chats
+
+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 CIcqProto::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 CIcqProto::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 CIcqProto::Chat_ProcessLogMenu(SESSION_INFO *si, int iChoice)
+{
+ switch (iChoice) {
+ case IDM_INVITE:
+ InviteUserToChat(si);
+ break;
+
+ case IDM_LEAVE:
+ LeaveDestroyChat(si);
+ break;
+ }
+}
+
+void CIcqProto::Chat_SendPrivateMessage(GCHOOK *gch)
+{
+ MCONTACT hContact;
+ DWORD dwUin = _wtoi(gch->ptszUID);
+ auto *pCache = FindContactByUIN(dwUin);
+ if (pCache == nullptr) {
+ hContact = CreateContact(dwUin, true);
+ setWString(hContact, "Nick", gch->ptszNick);
+ db_set_b(hContact, "CList", "Hidden", 1);
+ db_set_dw(hContact, "Ignore", "Mask1", 0);
+ }
+ else hContact = pCache->m_hContact;
+
+ CallService(MS_MSG_SENDMESSAGE, hContact, 0);
+}
+
+void CIcqProto::ProcessGroupChat(const JSONNode &ev)
+{
+ for (auto &it : ev["mchats"]) {
+ CMStringW wszId(it["sender"].as_mstring());
+ SESSION_INFO *si = g_chatApi.SM_FindSession(wszId, m_szModuleName);
+ if (si == nullptr)
+ continue;
+
+ CMStringW method(it["method"].as_mstring());
+ GCEVENT gce = { m_szModuleName, si->ptszID, (method == "add_members") ? GC_EVENT_JOIN : GC_EVENT_PART };
+
+ int iStart = 0;
+ CMStringW members(it["members"].as_mstring());
+ while (true) {
+ CMStringW member = members.Tokenize(L",", iStart);
+ if (member.IsEmpty())
+ break;
+
+ auto *pCache = FindContactByUIN(_wtoi(member));
+ if (pCache == nullptr)
+ continue;
+
+ gce.ptszNick = Clist_GetContactDisplayName(pCache->m_hContact);
+ gce.ptszUID = member;
+ gce.time = ::time(0);
+ gce.bIsMe = _wtoi(member) == (int)m_dwUin;
+ Chat_Event(&gce);
+ }
+ }
+}