/* Copyright © 2016-22 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 . */ #include "stdafx.h" enum { IDM_CANCEL, IDM_COPY_ID, IDM_CHANGENICK, IDM_CHANGETOPIC, IDM_RENAME, IDM_DESTROY }; ///////////////////////////////////////////////////////////////////////////////////////// static int SortRolesByPosition(const CDiscordRole *p1, const CDiscordRole *p2) { return p1->position - p2->position; } void BuildStatusList(const CDiscordGuild *pGuild, SESSION_INFO *si) { Chat_AddGroup(si, L"@owner"); LIST roles(pGuild->arRoles.getCount(), SortRolesByPosition); for (auto &it : pGuild->arRoles) roles.insert(it); for (auto &it : roles) Chat_AddGroup(si, it->wszName); } ///////////////////////////////////////////////////////////////////////////////////////// static gc_item sttLogListItems[] = { { LPGENW("Change &nickname"), IDM_CHANGENICK, MENU_ITEM }, { LPGENW("Channel control"), FALSE, MENU_NEWPOPUP }, { LPGENW("Change &topic"), IDM_CHANGETOPIC, MENU_POPUPITEM }, { LPGENW("&Rename channel"), IDM_RENAME, MENU_POPUPITEM }, { nullptr, 0, MENU_POPUPSEPARATOR }, { LPGENW("&Destroy channel"), IDM_DESTROY, MENU_POPUPITEM }, }; static gc_item sttNicklistItems[] = { { LPGENW("Copy ID"), IDM_COPY_ID, MENU_ITEM }, }; int CDiscordProto::GroupchatMenuHook(WPARAM, LPARAM lParam) { GCMENUITEMS* gcmi = (GCMENUITEMS*)lParam; if (gcmi == nullptr) return 0; if (mir_strcmpi(gcmi->pszModule, m_szModuleName)) return 0; CDiscordUser *pChat = FindUserByChannel(_wtoi64(gcmi->pszID)); if (pChat == nullptr) return 0; if (gcmi->Type == MENU_ON_LOG) Chat_AddMenuItems(gcmi->hMenu, _countof(sttLogListItems), sttLogListItems, &g_plugin); else if (gcmi->Type == MENU_ON_NICKLIST) Chat_AddMenuItems(gcmi->hMenu, _countof(sttNicklistItems), sttNicklistItems, &g_plugin); return 0; } ///////////////////////////////////////////////////////////////////////////////////////// void CDiscordProto::Chat_SendPrivateMessage(GCHOOK *gch) { SnowFlake userId = _wtoi64(gch->ptszUID); MCONTACT hContact; CDiscordUser *pUser = FindUser(userId); if (pUser == nullptr) { PROTOSEARCHRESULT psr = { sizeof(psr) }; psr.id.w = (wchar_t*)gch->ptszUID; psr.nick.w = (wchar_t*)gch->ptszNick; if ((hContact = AddToList(PALF_TEMPORARY, &psr)) == 0) return; setId(hContact, DB_KEY_ID, userId); setId(hContact, DB_KEY_CHANNELID, _wtoi64(gch->si->ptszID)); setWString(hContact, DB_KEY_NICK, gch->ptszNick); Contact::Hide(hContact); db_set_dw(hContact, "Ignore", "Mask1", 0); } else hContact = pUser->hContact; CallService(MS_MSG_SENDMESSAGE, hContact, 0); } void CDiscordProto::Chat_ProcessLogMenu(GCHOOK *gch) { CDiscordUser *pUser = FindUserByChannel(_wtoi64(gch->si->ptszID)); if (pUser == nullptr) return; ENTER_STRING es = {}; es.szModuleName = m_szModuleName; switch (gch->dwData) { case IDM_DESTROY: if (IDYES == MessageBox(nullptr, TranslateT("Do you really want to destroy this channel? This action is non-revertable."), m_tszUserName, MB_YESNO | MB_ICONQUESTION)) { CMStringA szUrl(FORMAT, "/channels/%S", pUser->wszUsername.c_str()); Push(new AsyncHttpRequest(this, REQUEST_DELETE, szUrl, nullptr)); } break; case IDM_RENAME: es.caption = TranslateT("Enter new channel name:"); es.type = ESF_COMBO; es.szDataPrefix = "chat_rename"; if (EnterString(&es)) { JSONNode root; root << WCHAR_PARAM("name", es.ptszResult); CMStringA szUrl(FORMAT, "/channels/%S", pUser->wszUsername.c_str()); Push(new AsyncHttpRequest(this, REQUEST_PATCH, szUrl, nullptr, &root)); mir_free(es.ptszResult); } break; case IDM_CHANGETOPIC: es.caption = TranslateT("Enter new topic:"); es.type = ESF_RICHEDIT; es.szDataPrefix = "chat_topic"; if (EnterString(&es)) { JSONNode root; root << WCHAR_PARAM("topic", es.ptszResult); CMStringA szUrl(FORMAT, "/channels/%S", pUser->wszUsername.c_str()); Push(new AsyncHttpRequest(this, REQUEST_PATCH, szUrl, nullptr, &root)); mir_free(es.ptszResult); } break; case IDM_CHANGENICK: es.caption = TranslateT("Enter your new nick name:"); es.type = ESF_COMBO; es.szDataPrefix = "chat_nick"; es.recentCount = 5; if (EnterString(&es)) { JSONNode root; root << WCHAR_PARAM("nick", es.ptszResult); CMStringA szUrl(FORMAT, "/guilds/%lld/members/@me/nick", pUser->pGuild->m_id); Push(new AsyncHttpRequest(this, REQUEST_PATCH, szUrl, nullptr, &root)); mir_free(es.ptszResult); } break; } } void CDiscordProto::Chat_ProcessNickMenu(GCHOOK* gch) { auto *pChannel = FindUserByChannel(_wtoi64(gch->si->ptszID)); if (pChannel == nullptr || pChannel->pGuild == nullptr) return; auto* pUser = pChannel->pGuild->FindUser(_wtoi64(gch->ptszUID)); if (pUser == nullptr) return; switch (gch->dwData) { case IDM_COPY_ID: CopyId(pUser->wszDiscordId); break; } } int CDiscordProto::GroupchatEventHook(WPARAM, LPARAM lParam) { GCHOOK *gch = (GCHOOK*)lParam; if (gch == nullptr) return 0; if (mir_strcmpi(gch->si->pszModule, m_szModuleName)) return 0; switch (gch->iType) { case GC_USER_MESSAGE: if (m_bOnline && mir_wstrlen(gch->ptszText) > 0) { CMStringW wszText(gch->ptszText); wszText.TrimRight(); int pos = wszText.Find(':'); if (pos != -1) { auto wszWord = wszText.Left(pos); wszWord.Trim(); if (auto *si = Chat_Find(gch->si->ptszID, gch->si->pszModule)) { USERINFO *pUser = nullptr; for (auto &U : si->getUserList()) if (wszWord == U->pszNick) { pUser = U; break; } if (pUser) { wszText.Delete(0, pos); wszText.Insert(0, L"<@" + CMStringW(pUser->pszUID) + L">"); } } } Chat_UnescapeTags(wszText.GetBuffer()); JSONNode body; body << WCHAR_PARAM("content", wszText); CMStringA szUrl(FORMAT, "/channels/%S/messages", gch->si->ptszID); Push(new AsyncHttpRequest(this, REQUEST_POST, szUrl, nullptr, &body)); } break; case GC_USER_PRIVMESS: Chat_SendPrivateMessage(gch); break; case GC_USER_LOGMENU: Chat_ProcessLogMenu(gch); break; case GC_USER_NICKLISTMENU: Chat_ProcessNickMenu(gch); break; case GC_USER_TYPNOTIFY: UserIsTyping(gch->si->hContact, (int)gch->dwData); break; } return 1; }