summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2024-05-04 17:29:25 +0300
committerGeorge Hazan <george.hazan@gmail.com>2024-05-04 17:29:25 +0300
commit7e1ecf7d6f1006e6e74c5c726cd873032948a141 (patch)
treef6bc9fb808797e53397f10c73cae60e19040d018
parentecc3520594c4bf18bf4321c82753f8e8b9478cda (diff)
fixes #4400 (Discord: добавление и изгнание других людей из чата)
-rw-r--r--protocols/Discord/res/discord.rc19
-rw-r--r--protocols/Discord/src/groupchat.cpp167
-rw-r--r--protocols/Discord/src/proto.h2
-rw-r--r--protocols/Discord/src/resource.h4
4 files changed, 160 insertions, 32 deletions
diff --git a/protocols/Discord/res/discord.rc b/protocols/Discord/res/discord.rc
index 3f4796137e..b272538e49 100644
--- a/protocols/Discord/res/discord.rc
+++ b/protocols/Discord/res/discord.rc
@@ -126,6 +126,16 @@ BEGIN
COMBOBOX IDC_ANOTHER,7,32,133,30,CBS_DROPDOWNLIST | WS_TABSTOP
END
+IDD_GROUPCHAT_INVITE DIALOGEX 0, 0, 215, 260
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Send group chat invitation"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x1,4,6,204,232,WS_EX_CLIENTEDGE
+ DEFPUSHBUTTON "&Invite",IDOK,106,243,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,160,243,50,14
+END
+
/////////////////////////////////////////////////////////////////////////////
//
@@ -150,6 +160,10 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 45
END
+
+ IDD_GROUPCHAT_INVITE, DIALOG
+ BEGIN
+ END
END
#endif // APSTUDIO_INVOKED
@@ -169,6 +183,11 @@ BEGIN
0
END
+IDD_GROUPCHAT_INVITE AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/Discord/src/groupchat.cpp b/protocols/Discord/src/groupchat.cpp
index 4918e5c2c7..95948fc5f3 100644
--- a/protocols/Discord/src/groupchat.cpp
+++ b/protocols/Discord/src/groupchat.cpp
@@ -21,9 +21,25 @@ enum {
IDM_CANCEL,
IDM_COPY_ID,
- IDM_CHANGENICK, IDM_CHANGETOPIC, IDM_RENAME, IDM_DESTROY, IDM_LEAVE
+ IDM_CHANGENICK, IDM_CHANGETOPIC, IDM_RENAME, IDM_DESTROY, IDM_LEAVE,
+
+ IDM_KICK, IDM_INVITE
};
+static void sttDisableMenuItem(int nItems, gc_item *items, uint32_t id, bool disabled)
+{
+ for (int i = 0; i < nItems; i++)
+ if (items[i].dwID == id)
+ items[i].bDisabled = disabled;
+}
+
+static void sttShowGcMenuItem(int nItems, gc_item *items, uint32_t id, int type)
+{
+ for (int i = 0; i < nItems; i++)
+ if (items[i].dwID == id)
+ items[i].uType = type;
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
static int SortRolesByPosition(const CDiscordRole *p1, const CDiscordRole *p2)
@@ -48,6 +64,8 @@ void BuildStatusList(const CDiscordGuild *pGuild, SESSION_INFO *si)
static gc_item sttLogListItems[] =
{
{ LPGENW("Change &nickname"), IDM_CHANGENICK, MENU_ITEM },
+ { nullptr, 0, MENU_SEPARATOR },
+ { LPGENW("Invite users"), IDM_INVITE, MENU_ITEM },
{ LPGENW("Channel control"), FALSE, MENU_NEWPOPUP },
{ LPGENW("Change &topic"), IDM_CHANGETOPIC, MENU_POPUPITEM },
{ LPGENW("&Rename channel"), IDM_RENAME, MENU_POPUPITEM },
@@ -59,6 +77,8 @@ static gc_item sttLogListItems[] =
static gc_item sttNicklistItems[] =
{
{ LPGENW("Copy ID"), IDM_COPY_ID, MENU_ITEM },
+ { nullptr, 0, MENU_SEPARATOR },
+ { LPGENW("Kick user"), IDM_KICK, MENU_ITEM },
};
int CDiscordProto::GroupchatMenuHook(WPARAM, LPARAM lParam)
@@ -71,22 +91,25 @@ int CDiscordProto::GroupchatMenuHook(WPARAM, LPARAM lParam)
return 0;
CDiscordUser *pChat = FindUserByChannel(_wtoi64(gcmi->pszID));
- if (pChat == nullptr)
+ if (pChat == nullptr || pChat->si == nullptr)
return 0;
+ bool isOwner = getId(pChat->hContact, DB_KEY_OWNERID) == m_ownId;
+
if (gcmi->Type == MENU_ON_LOG) {
if (pChat->pGuild == nullptr)
- sttLogListItems[0].uType = 0;
-
- if (getId(pChat->hContact, DB_KEY_OWNERID) == m_ownId)
- sttLogListItems[6].uType = 0;
- else
- sttLogListItems[5].uType = 0;
+ sttShowGcMenuItem(_countof(sttLogListItems), sttLogListItems, IDM_CHANGENICK, 0);
+
+ sttShowGcMenuItem(_countof(sttLogListItems), sttLogListItems, IDM_LEAVE, isOwner ? 0 : MENU_POPUPITEM);
+ sttShowGcMenuItem(_countof(sttLogListItems), sttLogListItems, IDM_DESTROY, isOwner ? 0 : MENU_POPUPITEM);
Chat_AddMenuItems(gcmi->hMenu, _countof(sttLogListItems), sttLogListItems, &g_plugin);
}
- else if (gcmi->Type == MENU_ON_NICKLIST)
+ else if (gcmi->Type == MENU_ON_NICKLIST) {
+ sttDisableMenuItem(_countof(sttNicklistItems), sttNicklistItems, IDM_KICK, !isOwner);
+
Chat_AddMenuItems(gcmi->hMenu, _countof(sttNicklistItems), sttNicklistItems, &g_plugin);
+ }
return 0;
}
@@ -117,6 +140,86 @@ void CDiscordProto::Chat_SendPrivateMessage(GCHOOK *gch)
CallService(MS_MSG_SENDMESSAGE, hContact, 0);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// Invitation dialog
+
+class CGroupchatInviteDlg : public CDiscordDlgBase
+{
+ CCtrlClc m_clc;
+ SnowFlake m_iChatId;
+
+ 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.SetHideEmptyGroups(true);
+ m_clc.SetHideOfflineRoot(true);
+ }
+
+public:
+ CGroupchatInviteDlg(CDiscordProto *ppro, SnowFlake chatId) :
+ CDiscordDlgBase(ppro, IDD_GROUPCHAT_INVITE),
+ m_clc(this, IDC_CLIST),
+ m_iChatId(chatId)
+ {
+ 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_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
+ {
+ // invite users from roster
+ for (auto &hContact : m_proto->AccContacts()) {
+ if (m_proto->isChatRoom(hContact))
+ continue;
+
+ if (HANDLE hItem = m_clc.FindContact(hContact)) {
+ if (m_clc.GetCheck(hItem)) {
+ CMStringA szUrl(FORMAT, "/channels/%lld/recipients/%lld", m_iChatId, m_proto->getId(hContact, DB_KEY_ID));
+ m_proto->Push(new AsyncHttpRequest(m_proto, REQUEST_PUT, szUrl, 0));
+ }
+ }
+ }
+ return true;
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Log menu
+
+void CDiscordProto::LeaveChat(CDiscordUser *pChat)
+{
+ CMStringA szUrl(FORMAT, "/channels/%S", pChat->wszUsername.c_str());
+ Push(new AsyncHttpRequest(this, REQUEST_DELETE, szUrl, nullptr));
+}
+
+INT_PTR CDiscordProto::SvcLeaveChat(WPARAM hContact, LPARAM)
+{
+ if (auto *pUser = FindUserByChannel(getId(hContact, DB_KEY_CHANNELID)))
+ if (pUser->si)
+ LeaveChat(pUser);
+ return 0;
+}
+
void CDiscordProto::Chat_ProcessLogMenu(GCHOOK *gch)
{
CDiscordUser *pUser = FindUserByChannel(_wtoi64(gch->si->ptszID));
@@ -172,26 +275,44 @@ void CDiscordProto::Chat_ProcessLogMenu(GCHOOK *gch)
mir_free(es.ptszResult);
}
break;
+
+ case IDM_INVITE:
+ CGroupchatInviteDlg dlg(this, pUser->channelId);
+ if (gch->si->pDlg)
+ dlg.SetParent(gch->si->pDlg->GetHwnd());
+ dlg.DoModal();
+ break;
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// Nick list menu
+
+void CDiscordProto::KickChatUser(CDiscordUser *pChat, const wchar_t *pszUID)
+{
+ CMStringA szUrl(FORMAT, "/channels/%lld/recipients/%S", pChat->channelId, pszUID);
+ Push(new AsyncHttpRequest(this, REQUEST_DELETE, szUrl, 0));
+}
+
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)
+ if (pChannel == nullptr)
return;
switch (gch->dwData) {
case IDM_COPY_ID:
- CopyId(pUser->wszDiscordId);
+ CopyId(gch->ptszUID);
+ break;
+
+ case IDM_KICK:
+ KickChatUser(pChannel, gch->ptszUID);
break;
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
int CDiscordProto::GroupchatEventHook(WPARAM, LPARAM lParam)
{
GCHOOK *gch = (GCHOOK*)lParam;
@@ -254,19 +375,3 @@ int CDiscordProto::GroupchatEventHook(WPARAM, LPARAM lParam)
return 1;
}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CDiscordProto::LeaveChat(CDiscordUser *pChat)
-{
- CMStringA szUrl(FORMAT, "/channels/%S", pChat->wszUsername.c_str());
- Push(new AsyncHttpRequest(this, REQUEST_DELETE, szUrl, nullptr));
-}
-
-INT_PTR CDiscordProto::SvcLeaveChat(WPARAM hContact, LPARAM)
-{
- if (auto *pUser = FindUserByChannel(getId(hContact, DB_KEY_CHANNELID)))
- if (pUser->si)
- LeaveChat(pUser);
- return 0;
-}
diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h
index 8c6e045b5c..aafc627b4f 100644
--- a/protocols/Discord/src/proto.h
+++ b/protocols/Discord/src/proto.h
@@ -228,6 +228,7 @@ class CDiscordProto : public PROTO<CDiscordProto>
friend struct AsyncHttpRequest;
friend class CDiscardAccountOptions;
friend class CMfaDialog;
+ friend class CGroupchatInviteDlg;
class CDiscordProtoImpl
{
@@ -394,6 +395,7 @@ class CDiscordProto : public PROTO<CDiscordProto>
void Chat_ProcessNickMenu(GCHOOK* gch);
void CreateChat(CDiscordGuild *pGuild, CDiscordUser *pUser);
+ void KickChatUser(CDiscordUser *pChat, const wchar_t *pszUID);
void LeaveChat(CDiscordUser *pChat);
void ProcessChatUser(CDiscordUser *pChat, SnowFlake userId, const JSONNode &pRoot);
void ParseSpecialChars(SESSION_INFO *si, CMStringW &str);
diff --git a/protocols/Discord/src/resource.h b/protocols/Discord/src/resource.h
index b7f625fa1e..cf6c1a467d 100644
--- a/protocols/Discord/src/resource.h
+++ b/protocols/Discord/src/resource.h
@@ -10,6 +10,7 @@
#define IDI_VOICE_CALL 106
#define IDI_VOICE_ENDED 107
#define IDD_MFA 108
+#define IDD_GROUPCHAT_INVITE 109
#define IDC_PASSWORD 1001
#define IDC_USERNAME 1002
#define IDC_GROUP 1003
@@ -22,7 +23,8 @@
#define IDC_ANOTHER 1009
#define IDC_LABEL 1010
#define IDC_LOGOUT 1011
-#define IDC_COMBO1 1012
+#define IDC_CLIST 1012
+
// Next default values for new objects
//