summaryrefslogtreecommitdiff
path: root/protocols/Discord/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2017-02-13 23:05:38 +0300
committerGeorge Hazan <ghazan@miranda.im>2017-02-13 23:05:46 +0300
commita727a5f4cb61f721cef5a6afa6c2054a06659fea (patch)
tree3f9bf1677486c0cdbe38ccfba3de72b0f4030d1e /protocols/Discord/src
parent653fe9968498470fddda828959c26b886efecbac (diff)
Discord: displaying roles correctly
Diffstat (limited to 'protocols/Discord/src')
-rw-r--r--protocols/Discord/src/dispatch.cpp103
-rw-r--r--protocols/Discord/src/groupchat.cpp15
-rw-r--r--protocols/Discord/src/proto.cpp6
-rw-r--r--protocols/Discord/src/proto.h30
-rw-r--r--protocols/Discord/src/server.cpp2
-rw-r--r--protocols/Discord/src/stdafx.h1
-rw-r--r--protocols/Discord/src/version.h2
7 files changed, 139 insertions, 20 deletions
diff --git a/protocols/Discord/src/dispatch.cpp b/protocols/Discord/src/dispatch.cpp
index 0da160b973..dbbd4e41e4 100644
--- a/protocols/Discord/src/dispatch.cpp
+++ b/protocols/Discord/src/dispatch.cpp
@@ -32,10 +32,14 @@ static handlers[] = // these structures must me sorted alphabetically
{ L"CHANNEL_DELETE", &CDiscordProto::OnCommandChannelDeleted },
{ L"CHANNEL_UPDATE", &CDiscordProto::OnCommandChannelUpdated },
- { L"GUILD_CREATE", &CDiscordProto::OnCommandGuildCreate },
- { L"GUILD_DELETE", &CDiscordProto::OnCommandGuildDelete },
- { L"GUILD_MEMBER_REMOVE", &CDiscordProto::OnCommandGuildRemoveMember },
- { L"GUILD_MEMBER_UPDATE", &CDiscordProto::OnCommandGuildUpdateMember },
+ { L"GUILD_CREATE", &CDiscordProto::OnCommandGuildCreated },
+ { L"GUILD_DELETE", &CDiscordProto::OnCommandGuildDeleted },
+ { L"GUILD_MEMBER_ADD", &CDiscordProto::OnCommandGuildMemberAdded },
+ { L"GUILD_MEMBER_REMOVE", &CDiscordProto::OnCommandGuildMemberRemoved },
+ { L"GUILD_MEMBER_UPDATE", &CDiscordProto::OnCommandGuildMemberUpdated },
+ { L"GUILD_ROLE_CREATE", &CDiscordProto::OnCommandRoleCreated },
+ { L"GUILD_ROLE_DELETE", &CDiscordProto::OnCommandRoleDeleted },
+ { L"GUILD_ROLE_UPDATE", &CDiscordProto::OnCommandRoleCreated },
{ L"GUILD_SYNC", &CDiscordProto::OnCommandGuildSync },
{ L"MESSAGE_ACK", &CDiscordProto::OnCommandMessageAck },
@@ -159,9 +163,25 @@ static SnowFlake sttGetLastRead(const JSONNode &reads, const wchar_t *wszChannel
return 0;
}
+void CDiscordProto::ProcessRole(SnowFlake guildId, const JSONNode &role)
+{
+ SnowFlake id = ::getId(role["id"]);
+ CDiscordRole *p = arRoles.find((CDiscordRole*)&id);
+ if (p == nullptr) {
+ p = new CDiscordRole();
+ p->id = id;
+ arRoles.insert(p);
+ }
+ p->guildId = guildId;
+ p->color = role["color"].as_int();
+ p->position = role["position"].as_int();
+ p->permissions = role["permissions"].as_int();
+ p->wszName = role["name"].as_mstring();
+}
+
void CDiscordProto::ProcessGuild(const JSONNode &readState, const JSONNode &p)
{
- SnowFlake guildId = ::getId(p["id"]);
+ SnowFlake guildId = ::getId(p["id"]), ownerId = ::getId(p["owner_id"]);
GatewaySendGuildInfo(guildId);
CMStringW wszGuildName = p["name"].as_mstring();
@@ -170,6 +190,10 @@ void CDiscordProto::ProcessGuild(const JSONNode &readState, const JSONNode &p)
Chat_Control(m_szModuleName, wszGuildName, SESSION_ONLINE);
setId(si->hContact, DB_KEY_CHANNELID, guildId);
+ const JSONNode &roles = p["roles"];
+ for (auto itr = roles.begin(); itr != roles.end(); ++itr)
+ ProcessRole(guildId, *itr);
+
const JSONNode &channels = p["channels"];
for (auto itc = channels.begin(); itc != channels.end(); ++itc) {
const JSONNode &pch = *itc;
@@ -182,7 +206,9 @@ void CDiscordProto::ProcessGuild(const JSONNode &readState, const JSONNode &p)
SnowFlake channelId = _wtoi64(wszChannelId);
si = Chat_NewSession(GCW_CHATROOM, m_szModuleName, wszChannelId, wszGuildName + L"#" + wszChannelName);
- Chat_AddGroup(m_szModuleName, wszChannelId, TranslateT("User"));
+ setId(si->hContact, DB_KEY_OWNERID, ownerId);
+ BuildStatusList(guildId, wszChannelId);
+
Chat_Control(m_szModuleName, wszChannelId, WINDOW_HIDDEN);
Chat_Control(m_szModuleName, wszChannelId, SESSION_ONLINE);
@@ -213,7 +239,7 @@ void CDiscordProto::ProcessGuild(const JSONNode &readState, const JSONNode &p)
}
}
-void CDiscordProto::OnCommandGuildCreate(const JSONNode &pRoot)
+void CDiscordProto::OnCommandGuildCreated(const JSONNode &pRoot)
{
ProcessGuild(JSONNode(), pRoot);
OnCommandGuildSync(pRoot);
@@ -234,14 +260,27 @@ void CDiscordProto::OnCommandGuildSync(const JSONNode &pRoot)
if (pUser.guildId != guildId)
continue;
+ CDiscordRole *pRole = nullptr;
+ const JSONNode &pRoles = m["roles"];
+ for (auto itr = pRoles.begin(); itr != pRoles.end(); ++itr) {
+ SnowFlake roleId = ::getId(*itr);
+ if (pRole = arRoles.find((CDiscordRole*)&roleId))
+ break;
+ }
+
GCDEST gcd = { m_szModuleName, pUser.wszUsername, GC_EVENT_JOIN };
GCEVENT gce = { &gcd };
CMStringW wszNick = m["nick"].as_mstring();
CMStringW wszUsername = m["user"]["username"].as_mstring() + L"#" + m["user"]["discriminator"].as_mstring();
CMStringW wszUserId = m["user"]["id"].as_mstring();
- SnowFlake userid = _wtoi64(wszUserId);
- gce.bIsMe = (userid == m_ownId);
+ SnowFlake userId = _wtoi64(wszUserId);
+ if (userId == getId(pUser.hContact, DB_KEY_OWNERID))
+ gce.ptszStatus = L"@owner";
+ else
+ gce.ptszStatus = (pRole == nullptr) ? L"@everyone" : pRole->wszName;
+
+ gce.bIsMe = (userId == m_ownId);
gce.ptszUID = wszUserId;
gce.ptszNick = wszNick.IsEmpty() ? wszUsername : wszNick;
Chat_Event(&gce);
@@ -259,7 +298,7 @@ void CDiscordProto::OnCommandGuildSync(const JSONNode &pRoot)
}
}
-void CDiscordProto::OnCommandGuildDelete(const JSONNode &pRoot)
+void CDiscordProto::OnCommandGuildDeleted(const JSONNode &pRoot)
{
SnowFlake guildId = ::getId(pRoot["id"]);
@@ -274,7 +313,11 @@ void CDiscordProto::OnCommandGuildDelete(const JSONNode &pRoot)
Chat_Terminate(m_szModuleName, pRoot["name"].as_mstring(), true);
}
-void CDiscordProto::OnCommandGuildRemoveMember(const JSONNode &pRoot)
+void CDiscordProto::OnCommandGuildMemberAdded(const JSONNode &pRoot)
+{
+}
+
+void CDiscordProto::OnCommandGuildMemberRemoved(const JSONNode &pRoot)
{
SnowFlake guildId = ::getId(pRoot["guild_id"]);
CMStringW wszUserId = pRoot["user"]["id"].as_mstring();
@@ -291,7 +334,7 @@ void CDiscordProto::OnCommandGuildRemoveMember(const JSONNode &pRoot)
}
}
-void CDiscordProto::OnCommandGuildUpdateMember(const JSONNode &pRoot)
+void CDiscordProto::OnCommandGuildMemberUpdated(const JSONNode &pRoot)
{
SnowFlake guildId = ::getId(pRoot["guild_id"]);
CMStringW wszUserId = pRoot["user"]["id"].as_mstring();
@@ -318,6 +361,42 @@ void CDiscordProto::OnCommandGuildUpdateMember(const JSONNode &pRoot)
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// roles
+
+void CDiscordProto::OnCommandRoleCreated(const JSONNode &pRoot)
+{
+ ProcessRole(::getId(pRoot["guild_id"]), pRoot["role"]);
+}
+
+void CDiscordProto::OnCommandRoleDeleted(const JSONNode &pRoot)
+{
+ SnowFlake id = ::getId(pRoot["role_id"]), guildId = ::getId(pRoot["guild_id"]);
+ CDiscordRole *pRole = arRoles.find((CDiscordRole*)&id);
+ if (pRole == nullptr)
+ return;
+
+ int iOldPosition = pRole->position;
+ arRoles.remove(pRole);
+
+ for (int i = 0; i < arRoles.getCount(); i++) {
+ CDiscordRole &p = arRoles[i];
+ if (p.guildId == guildId && p.position > iOldPosition)
+ p.position--;
+ }
+
+ for (int i = 0; i < arUsers.getCount(); i++) {
+ CDiscordUser &p = arUsers[i];
+ if (p.guildId != guildId)
+ continue;
+
+ SESSION_INFO *si = pci->SM_FindSession(p.wszUsername, m_szModuleName);
+ if (si != nullptr) {
+ pci->TM_RemoveAll(&si->pStatuses);
+ BuildStatusList(guildId, p.wszUsername);
+ }
+ }
+}
/////////////////////////////////////////////////////////////////////////////////////////
// reading a new message
diff --git a/protocols/Discord/src/groupchat.cpp b/protocols/Discord/src/groupchat.cpp
index 5525f6658f..6641a4fd88 100644
--- a/protocols/Discord/src/groupchat.cpp
+++ b/protocols/Discord/src/groupchat.cpp
@@ -23,6 +23,21 @@ enum {
IDM_CHANGENICK, IDM_CHANGETOPIC, IDM_INVITE
};
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CDiscordProto::BuildStatusList(SnowFlake guildId, const CMStringW &wszChannelId)
+{
+ Chat_AddGroup(m_szModuleName, wszChannelId, L"@owner");
+
+ for (int i = 0; i < arRoles.getCount(); i++) {
+ CDiscordRole &r = arRoles[i];
+ if (r.guildId == guildId)
+ Chat_AddGroup(m_szModuleName, wszChannelId, r.wszName);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
static gc_item sttLogListItems[] =
{
{ LPGENW("Change &nickname"), IDM_CHANGENICK, MENU_ITEM },
diff --git a/protocols/Discord/src/proto.cpp b/protocols/Discord/src/proto.cpp
index e102d86fb1..ed5d9fe3e7 100644
--- a/protocols/Discord/src/proto.cpp
+++ b/protocols/Discord/src/proto.cpp
@@ -27,6 +27,11 @@ static int compareRequests(const AsyncHttpRequest *p1, const AsyncHttpRequest *p
return p1->m_iReqNum - p2->m_iReqNum;
}
+static int compareRoles(const CDiscordRole *p1, const CDiscordRole *p2)
+{
+ return p1->id - p2->id;
+}
+
static int compareUsers(const CDiscordUser *p1, const CDiscordUser *p2)
{
return p1->id - p2->id;
@@ -40,6 +45,7 @@ CDiscordProto::CDiscordProto(const char *proto_name, const wchar_t *username) :
m_wszEmail(this, DB_KEY_EMAIL, L""),
arMarkReadQueue(1, compareUsers),
arOwnMessages(1, compareMessages),
+ arRoles(10, compareRoles),
arUsers(50, compareUsers)
{
// Services
diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h
index 133ff1f40c..122b3a9e40 100644
--- a/protocols/Discord/src/proto.h
+++ b/protocols/Discord/src/proto.h
@@ -81,7 +81,18 @@ JSONNode& operator<<(JSONNode &json, const WCHAR_PARAM &param);
/////////////////////////////////////////////////////////////////////////////////////////
-enum CDiscordHitoryOp
+struct CDiscordRole : public MZeroedObject
+{
+ SnowFlake id, guildId;
+ COLORREF color;
+ DWORD permissions;
+ int position;
+ CMStringW wszName;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+enum CDiscordHistoryOp
{
MSG_NOFILTER, MSG_AFTER, MSG_BEFORE
};
@@ -179,6 +190,7 @@ class CDiscordProto : public PROTO<CDiscordProto>
mir_cs csMarkReadQueue;
LIST<CDiscordUser> arMarkReadQueue;
+ OBJLIST<CDiscordRole> arRoles;
OBJLIST<CDiscordUser> arUsers;
OBJLIST<SnowFlake> arOwnMessages;
CDiscordUser* FindUser(SnowFlake id);
@@ -206,6 +218,8 @@ class CDiscordProto : public PROTO<CDiscordProto>
void Chat_SendPrivateMessage(GCHOOK *gch);
void Chat_ProcessLogMenu(GCHOOK *gch);
+
+ void BuildStatusList(SnowFlake guildId, const CMStringW &wszChannelId);
void ParseSpecialChars(SESSION_INFO *si, CMStringW &str);
//////////////////////////////////////////////////////////////////////////////////////
@@ -262,10 +276,11 @@ public:
void OnCommandChannelCreated(const JSONNode&);
void OnCommandChannelDeleted(const JSONNode&);
void OnCommandChannelUpdated(const JSONNode&);
- void OnCommandGuildCreate(const JSONNode&);
- void OnCommandGuildDelete(const JSONNode&);
- void OnCommandGuildRemoveMember(const JSONNode&);
- void OnCommandGuildUpdateMember(const JSONNode&);
+ void OnCommandGuildCreated(const JSONNode&);
+ void OnCommandGuildDeleted(const JSONNode&);
+ void OnCommandGuildMemberAdded(const JSONNode&);
+ void OnCommandGuildMemberRemoved(const JSONNode&);
+ void OnCommandGuildMemberUpdated(const JSONNode&);
void OnCommandGuildSync(const JSONNode&);
void OnCommandFriendAdded(const JSONNode&);
void OnCommandFriendRemoved(const JSONNode&);
@@ -273,6 +288,8 @@ public:
void OnCommandMessageAck(const JSONNode&);
void OnCommandPresence(const JSONNode&);
void OnCommandReady(const JSONNode&);
+ void OnCommandRoleCreated(const JSONNode&);
+ void OnCommandRoleDeleted(const JSONNode&);
void OnCommandTyping(const JSONNode&);
void OnCommandUserUpdate(const JSONNode&);
void OnCommandUserSettingsUpdate(const JSONNode&);
@@ -296,7 +313,7 @@ public:
void RetrieveUserInfo(MCONTACT hContact);
void OnReceiveUserInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
- void RetrieveHistory(MCONTACT hContact, CDiscordHitoryOp iOp = MSG_NOFILTER, SnowFlake msgid = 0, int iLimit = 50);
+ void RetrieveHistory(MCONTACT hContact, CDiscordHistoryOp iOp = MSG_NOFILTER, SnowFlake msgid = 0, int iLimit = 50);
void OnReceiveHistory(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
bool RetrieveAvatar(MCONTACT hContact);
@@ -304,6 +321,7 @@ public:
// Misc
void ProcessGuild(const JSONNode &pStatuses, const JSONNode &pRoot);
+ void ProcessRole(SnowFlake guildId, const JSONNode&);
void ProcessType(CDiscordUser *pUser, const JSONNode&);
void SetServerStatus(int iStatus);
void RemoveFriend(SnowFlake id);
diff --git a/protocols/Discord/src/server.cpp b/protocols/Discord/src/server.cpp
index 5033e5aefd..bd23659b3e 100644
--- a/protocols/Discord/src/server.cpp
+++ b/protocols/Discord/src/server.cpp
@@ -28,7 +28,7 @@ void CDiscordProto::RemoveFriend(SnowFlake id)
/////////////////////////////////////////////////////////////////////////////////////////
// retrieves server history
-void CDiscordProto::RetrieveHistory(MCONTACT hContact, CDiscordHitoryOp iOp, SnowFlake msgid, int iLimit)
+void CDiscordProto::RetrieveHistory(MCONTACT hContact, CDiscordHistoryOp iOp, SnowFlake msgid, int iLimit)
{
CDiscordUser *pUser = FindUser(getId(hContact, DB_KEY_ID));
if (pUser == NULL)
diff --git a/protocols/Discord/src/stdafx.h b/protocols/Discord/src/stdafx.h
index a5022fb7d6..0794bc5df3 100644
--- a/protocols/Discord/src/stdafx.h
+++ b/protocols/Discord/src/stdafx.h
@@ -58,6 +58,7 @@ extern HWND g_hwndHeartbeat;
#define DB_KEY_NICK "Nick"
#define DB_KEY_AVHASH "AvatarHash"
#define DB_KEY_CHANNELID "ChannelID"
+#define DB_KEY_OWNERID "OwnerID"
#define DB_KEY_LASTMSGID "LastMessageID"
#define DB_KEY_REQAUTH "ReqAuth"
diff --git a/protocols/Discord/src/version.h b/protocols/Discord/src/version.h
index 1844aa3c1e..b57f31665b 100644
--- a/protocols/Discord/src/version.h
+++ b/protocols/Discord/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 3
#define __RELEASE_NUM 1
-#define __BUILD_NUM 2
+#define __BUILD_NUM 3
#include <stdver.h>