From cf9398bf479f55b792fc932f1fdadfe7d1deb3c3 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 6 Jun 2024 15:00:35 +0300 Subject: Discord: ability to disable database histories for a certain guild --- protocols/Discord/src/dispatch.cpp | 70 ++++++++++++++++++++++---------------- protocols/Discord/src/guilds.cpp | 3 +- protocols/Discord/src/menus.cpp | 40 ++++++++++++++++++---- protocols/Discord/src/proto.cpp | 4 +-- protocols/Discord/src/proto.h | 8 +++-- protocols/Discord/src/stdafx.h | 27 ++++++++------- protocols/Discord/src/utils.cpp | 9 +++++ 7 files changed, 108 insertions(+), 53 deletions(-) diff --git a/protocols/Discord/src/dispatch.cpp b/protocols/Discord/src/dispatch.cpp index 3d886f3eb2..cab63a8d44 100644 --- a/protocols/Discord/src/dispatch.cpp +++ b/protocols/Discord/src/dispatch.cpp @@ -474,6 +474,7 @@ void CDiscordProto::OnCommandMessage(const JSONNode &pRoot, bool bIsNew) } // shift & store LastMsgId field + bool bIsChat = Contact::IsGroupChat(pUser->hContact); pUser->lastMsgId = msgId; SnowFlake lastId = getId(pUser->hContact, DB_KEY_LASTMSGID); // as stored in a database @@ -485,7 +486,7 @@ void CDiscordProto::OnCommandMessage(const JSONNode &pRoot, bool bIsNew) COwnMessage ownMsg(::getId(pRoot["nonce"]), 0); COwnMessage *p = arOwnMessages.find(&ownMsg); - if (p != nullptr && !Contact::IsGroupChat(pUser->hContact)) { // own message? skip it + if (p != nullptr && !bIsChat) { // own message? skip it ProtoBroadcastAck(pUser->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)p->reqId, (LPARAM)szMsgId); debugLogA("skipping own message with nonce=%lld, id=%lld", ownMsg.nonce, msgId); } @@ -494,42 +495,53 @@ void CDiscordProto::OnCommandMessage(const JSONNode &pRoot, bool bIsNew) if (wszText.IsEmpty()) return; - else { - // old message? try to restore it from database - bool bOurMessage = userId == m_ownId; - MEVENT hOldEvent = (bIsNew) ? 0 : db_event_getById(m_szModuleName, szMsgId); + // if we don't store guild's messages, simply push it to a chat + if (bIsChat && pUser->pGuild && !pUser->pGuild->m_bEnableHistory) { + _A2T wszUID(szUserId); + + GCEVENT gce = { pUser->si, GC_EVENT_MESSAGE }; + gce.dwFlags = GCEF_ADDTOLOG; + gce.pszUID.w = wszUID; + gce.pszText.w = wszText; + gce.time = time(0); + gce.bIsMe = userId == m_ownId; + Chat_Event(&gce); + return; + } - const JSONNode &edited = pRoot["edited_timestamp"]; - if (!edited.isnull()) - wszText.AppendFormat(L" (%s %s)", TranslateT("edited at"), edited.as_mstring().c_str()); + // old message? try to restore it from database + MEVENT hOldEvent = (bIsNew) ? 0 : db_event_getById(m_szModuleName, szMsgId); - // if a message has myself as an author, add some flags - DB::EventInfo dbei(hOldEvent); - if (bOurMessage) - dbei.flags |= DBEF_READ | DBEF_SENT; + const JSONNode &edited = pRoot["edited_timestamp"]; + if (!edited.isnull()) + wszText.AppendFormat(L" (%s %s)", TranslateT("edited at"), edited.as_mstring().c_str()); - if (auto &nReply = pRoot["message_reference"]) { - _i64toa(::getId(nReply["message_id"]), szReplyId, 10); - dbei.szReplyId = szReplyId; - } + // if a message has myself as an author, add some flags + DB::EventInfo dbei(hOldEvent); + if (userId == m_ownId) + dbei.flags |= DBEF_READ | DBEF_SENT; - debugLogA("store a message from private user %lld, channel id %lld", pUser->id, pUser->channelId); + if (auto &nReply = pRoot["message_reference"]) { + _i64toa(::getId(nReply["message_id"]), szReplyId, 10); + dbei.szReplyId = szReplyId; + } - dbei.timestamp = (uint32_t)StringToDate(pRoot["timestamp"].as_mstring()); - dbei.szId = szMsgId; - replaceStr(dbei.pBlob, mir_utf8encodeW(wszText)); - dbei.cbBlob = (int)mir_strlen(dbei.pBlob); + debugLogA("store a message from private user %lld, channel id %lld", pUser->id, pUser->channelId); - if (!pUser->bIsPrivate || pUser->bIsGroup) { - dbei.szUserId = szUserId; - ProcessChatUser(pUser, userId, pRoot); - } + dbei.timestamp = (uint32_t)StringToDate(pRoot["timestamp"].as_mstring()); + dbei.szId = szMsgId; + replaceStr(dbei.pBlob, mir_utf8encodeW(wszText)); + dbei.cbBlob = (int)mir_strlen(dbei.pBlob); - if (dbei) - db_event_edit(dbei.getEvent(), &dbei, true); - else - ProtoChainRecvMsg(pUser->hContact, dbei); + if (!pUser->bIsPrivate || pUser->bIsGroup) { + dbei.szUserId = szUserId; + ProcessChatUser(pUser, userId, pRoot); } + + if (dbei) + db_event_edit(dbei.getEvent(), &dbei, true); + else + ProtoChainRecvMsg(pUser->hContact, dbei); } } diff --git a/protocols/Discord/src/guilds.cpp b/protocols/Discord/src/guilds.cpp index 0972518154..35b1cd18fc 100644 --- a/protocols/Discord/src/guilds.cpp +++ b/protocols/Discord/src/guilds.cpp @@ -138,6 +138,7 @@ void CDiscordProto::ProcessGuild(const JSONNode &pRoot) pGuild->pParentSi = (SESSION_INFO*)si; pGuild->m_hContact = si->hContact; setId(pGuild->m_hContact, DB_KEY_CHANNELID, guildId); + pGuild->m_bEnableHistory = surelyGetBool(pGuild->m_hContact, DB_KEY_ENABLE_HIST); Chat_Control(si, WINDOW_HIDDEN); Chat_Control(si, SESSION_ONLINE); @@ -147,7 +148,7 @@ void CDiscordProto::ProcessGuild(const JSONNode &pRoot) BuildStatusList(pGuild, si); - if (!pGuild->m_bSynced && getByte(si->hContact, "EnableSync")) + if (!pGuild->m_bSynced && getByte(si->hContact, DB_KEY_ENABLE_SYNC)) GatewaySendGuildInfo(pGuild); // store all guild members diff --git a/protocols/Discord/src/menus.cpp b/protocols/Discord/src/menus.cpp index cc928221f3..1c248df24e 100644 --- a/protocols/Discord/src/menus.cpp +++ b/protocols/Discord/src/menus.cpp @@ -40,6 +40,19 @@ INT_PTR CDiscordProto::OnMenuCreateChannel(WPARAM hContact, LPARAM) ///////////////////////////////////////////////////////////////////////////////////////// +INT_PTR CDiscordProto::OnMenuDatabaseHistory(WPARAM hContact, LPARAM) +{ + bool bEnable = !getBool(hContact, DB_KEY_ENABLE_HIST); + setByte(hContact, DB_KEY_ENABLE_HIST, bEnable); + + if (auto *pGuild = FindGuild(getId(hContact, DB_KEY_CHANNELID))) + pGuild->m_bEnableHistory = bEnable; + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + INT_PTR CDiscordProto::OnMenuJoinGuild(WPARAM, LPARAM) { ENTER_STRING es = { m_szModuleName, "guild_name", TranslateT("Enter invitation code you received"), nullptr, ESF_COMBO, 5 }; @@ -78,8 +91,8 @@ INT_PTR CDiscordProto::OnMenuLoadHistory(WPARAM hContact, LPARAM) INT_PTR CDiscordProto::OnMenuToggleSync(WPARAM hContact, LPARAM) { - bool bEnabled = !getBool(hContact, "EnableSync"); - setByte(hContact, "EnableSync", bEnabled); + bool bEnabled = !getBool(hContact, DB_KEY_ENABLE_SYNC); + setByte(hContact, DB_KEY_ENABLE_SYNC, bEnabled); if (bEnabled) if (auto *pGuild = FindGuild(getId(hContact, DB_KEY_CHANNELID))) @@ -99,11 +112,16 @@ int CDiscordProto::OnMenuPrebuild(WPARAM hContact, LPARAM) if (!bIsGuild && getWord(hContact, "ApparentMode") != 0) Menu_ShowItem(GetMenuItem(PROTO_MENU_REQ_AUTH), true); - - if (getByte(hContact, "EnableSync")) + + if (getByte(hContact, DB_KEY_ENABLE_SYNC)) Menu_ModifyItem(m_hMenuToggleSync, LPGENW("Disable sync"), Skin_GetIconHandle(SKINICON_CHAT_LEAVE)); else Menu_ModifyItem(m_hMenuToggleSync, LPGENW("Enable sync"), Skin_GetIconHandle(SKINICON_CHAT_JOIN)); + + if (getByte(hContact, DB_KEY_ENABLE_HIST)) + Menu_ModifyItem(m_hMenuDatabaseHistory, LPGENW("Disable database history for a guild"), Skin_GetIconHandle(SKINICON_CHAT_LEAVE)); + else + Menu_ModifyItem(m_hMenuDatabaseHistory, LPGENW("Enable database history for a guild"), Skin_GetIconHandle(SKINICON_CHAT_JOIN)); return 0; } @@ -149,14 +167,14 @@ void CDiscordProto::InitMenus() CreateProtoService(mi.pszService, &CDiscordProto::OnMenuCreateChannel); SET_UID(mi, 0x6EF11AD6, 0x6111, 0x4E29, 0xBA, 0x8B, 0xA7, 0xB2, 0xE0, 0x22, 0xE1, 0x8D); mi.name.a = LPGEN("Create new channel"); - mi.position = -200001001; + mi.position++; mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_ADDCONTACT); m_hMenuCreateChannel = Menu_AddContactMenuItem(&mi, m_szModuleName); SET_UID(mi, 0x6EF11AD6, 0x6111, 0x4E29, 0xBA, 0x8B, 0xA7, 0xB2, 0xE0, 0x22, 0xE1, 0x8E); mi.pszService = "/CopyId"; mi.name.a = LPGEN("Copy ID"); - mi.position = -200001002; + mi.position++; mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_USERONLINE); Menu_AddContactMenuItem(&mi, m_szModuleName); @@ -164,9 +182,17 @@ void CDiscordProto::InitMenus() CreateProtoService(mi.pszService, &CDiscordProto::OnMenuToggleSync); SET_UID(mi, 0x6EF11AD6, 0x6111, 0x4E29, 0xBA, 0x8B, 0xA7, 0xB2, 0xE0, 0x22, 0xE1, 0x8F); mi.name.a = LPGEN("Enable guild sync"); - mi.position = -200001003; + mi.position++; mi.hIcolibItem = Skin_GetIconHandle(SKINICON_CHAT_JOIN); m_hMenuToggleSync = Menu_AddContactMenuItem(&mi, m_szModuleName); + mi.pszService = "/DatabaseHistory"; + CreateProtoService(mi.pszService, &CDiscordProto::OnMenuDatabaseHistory); + SET_UID(mi, 0x6EF11AD6, 0x6111, 0x4E29, 0xBA, 0x8B, 0xA7, 0xB2, 0xE0, 0x22, 0xE1, 0x90); + mi.name.a = LPGEN("Enable database history for a guild"); + mi.position++; + mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_HISTORY); + m_hMenuDatabaseHistory = Menu_AddContactMenuItem(&mi, m_szModuleName); + HookProtoEvent(ME_CLIST_PREBUILDCONTACTMENU, &CDiscordProto::OnMenuPrebuild); } diff --git a/protocols/Discord/src/proto.cpp b/protocols/Discord/src/proto.cpp index cea528e5b7..32ad2f6c01 100644 --- a/protocols/Discord/src/proto.cpp +++ b/protocols/Discord/src/proto.cpp @@ -150,8 +150,8 @@ void CDiscordProto::OnModulesLoaded() switch (getByte(hContact, "ChatRoom")) { case 2: // guild delSetting(hContact, DB_KEY_CHANNELID); - if (getDword(hContact, "EnableSync", -1) == -1) - setDword(hContact, "EnableSync", 1); + surelyGetBool(hContact, DB_KEY_ENABLE_HIST); + surelyGetBool(hContact, DB_KEY_ENABLE_SYNC); break; case 1: // group chat diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h index 117e7a90ba..98a3b1343b 100644 --- a/protocols/Discord/src/proto.h +++ b/protocols/Discord/src/proto.h @@ -212,7 +212,8 @@ struct CDiscordGuild : public MZeroedObject MCONTACT m_hContact; MGROUP m_groupId; bool m_bSynced = false; - + bool m_bEnableHistory = true; + SESSION_INFO *pParentSi; LIST arChannels; OBJLIST arChatUsers; @@ -383,12 +384,13 @@ class CDiscordProto : public PROTO INT_PTR __cdecl OnMenuCopyId(WPARAM, LPARAM); INT_PTR __cdecl OnMenuCreateChannel(WPARAM, LPARAM); + INT_PTR __cdecl OnMenuDatabaseHistory(WPARAM, LPARAM); INT_PTR __cdecl OnMenuJoinGuild(WPARAM, LPARAM); INT_PTR __cdecl OnMenuLeaveGuild(WPARAM, LPARAM); INT_PTR __cdecl OnMenuLoadHistory(WPARAM, LPARAM); INT_PTR __cdecl OnMenuToggleSync(WPARAM, LPARAM); - HGENMENU m_hMenuLeaveGuild, m_hMenuCreateChannel, m_hMenuToggleSync; + HGENMENU m_hMenuLeaveGuild, m_hMenuCreateChannel, m_hMenuToggleSync, m_hMenuDatabaseHistory; ////////////////////////////////////////////////////////////////////////////////////// // guilds @@ -463,6 +465,8 @@ class CDiscordProto : public PROTO void setId(const char *szName, SnowFlake iValue); void setId(MCONTACT hContact, const char *szName, SnowFlake iValue); + bool surelyGetBool(MCONTACT hContact, const char *szSetting); + public: CDiscordProto(const char*,const wchar_t*); ~CDiscordProto(); diff --git a/protocols/Discord/src/stdafx.h b/protocols/Discord/src/stdafx.h index 1623cbafa6..9987d6a256 100644 --- a/protocols/Discord/src/stdafx.h +++ b/protocols/Discord/src/stdafx.h @@ -54,18 +54,21 @@ extern IconItem g_iconList[]; -#define DB_KEY_ID "id" -#define DB_KEY_TOKEN "AccessToken" -#define DB_KEY_PASSWORD "Password" -#define DB_KEY_DISCR "Discriminator" -#define DB_KEY_MFA "MfaEnabled" -#define DB_KEY_NICK "Nick" -#define DB_KEY_OWNERID "OwnerID" -#define DB_KEY_AVHASH "AvatarHash" -#define DB_KEY_CHANNELID "ChannelID" -#define DB_KEY_LASTMSGID "LastMessageID" -#define DB_KEY_REQAUTH "ReqAuth" -#define DB_KEY_DONT_FETCH "DontFetch" +#define DB_KEY_ID "id" +#define DB_KEY_TOKEN "AccessToken" +#define DB_KEY_PASSWORD "Password" +#define DB_KEY_DISCR "Discriminator" +#define DB_KEY_MFA "MfaEnabled" +#define DB_KEY_NICK "Nick" +#define DB_KEY_OWNERID "OwnerID" +#define DB_KEY_AVHASH "AvatarHash" +#define DB_KEY_CHANNELID "ChannelID" +#define DB_KEY_LASTMSGID "LastMessageID" +#define DB_KEY_REQAUTH "ReqAuth" +#define DB_KEY_DONT_FETCH "DontFetch" + +#define DB_KEY_ENABLE_SYNC "EnableSync" +#define DB_KEY_ENABLE_HIST "EnableDbHistory" #define DB_KEYVAL_GROUP L"Discord" diff --git a/protocols/Discord/src/utils.cpp b/protocols/Discord/src/utils.cpp index e8480c80e2..983cd6201b 100644 --- a/protocols/Discord/src/utils.cpp +++ b/protocols/Discord/src/utils.cpp @@ -135,6 +135,15 @@ void CDiscordProto::setId(MCONTACT hContact, const char *szSetting, SnowFlake iV db_set_blob(hContact, m_szModuleName, szSetting, &iValue, sizeof(iValue)); } +bool CDiscordProto::surelyGetBool(MCONTACT hContact, const char *szSetting) +{ + int iValue = getDword(hContact, szSetting, -1); + if (iValue == -1) + setByte(hContact, szSetting, iValue = 1); + + return iValue != 0; +} + ///////////////////////////////////////////////////////////////////////////////////////// void CopyId(const CMStringW &nick) -- cgit v1.2.3