diff --git a/src/core/DiscordInstance.cpp b/src/core/DiscordInstance.cpp index bf1df456..601e2da9 100644 --- a/src/core/DiscordInstance.cpp +++ b/src/core/DiscordInstance.cpp @@ -1541,6 +1541,36 @@ void DiscordInstance::RequestDeleteMessage(Snowflake chan, Snowflake msg) ); } +void DiscordInstance::RequestPinMessage(Snowflake chan, Snowflake msg) +{ + std::string url = GetDiscordAPI() + "channels/" + std::to_string(chan) + "/messages/pins/" + std::to_string(msg); + + GetHTTPClient()->PerformRequest( + true, + NetRequest::PUT, + url, + 0, + DiscordRequest::PIN_MESSAGE, + "", + m_token + ); +} + +void DiscordInstance::RequestUnpinMessage(Snowflake chan, Snowflake msg) +{ + std::string url = GetDiscordAPI() + "channels/" + std::to_string(chan) + "/messages/pins/" + std::to_string(msg); + + GetHTTPClient()->PerformRequest( + true, + NetRequest::DELETE_, + url, + 0, + DiscordRequest::UNPIN_MESSAGE, + "", + m_token + ); +} + void DiscordInstance::UpdateSubscriptions(Snowflake guildId, Snowflake channelId, bool typing, bool activities, bool threads, int rangeMembers) { Json j, data; diff --git a/src/core/DiscordInstance.hpp b/src/core/DiscordInstance.hpp index db7d2a1b..35d8c728 100644 --- a/src/core/DiscordInstance.hpp +++ b/src/core/DiscordInstance.hpp @@ -462,6 +462,12 @@ class DiscordInstance // Request a message deletion. void RequestDeleteMessage(Snowflake chan, Snowflake msg); + // Request a message to be pinned. + void RequestPinMessage(Snowflake chan, Snowflake msg); + + // Request a message to be unpinned. + void RequestUnpinMessage(Snowflake chan, Snowflake msg); + // Request to leave a guild. void RequestLeaveGuild(Snowflake guild); diff --git a/src/core/models/Message.cpp b/src/core/models/Message.cpp index aac15896..061a25fe 100644 --- a/src/core/models/Message.cpp +++ b/src/core/models/Message.cpp @@ -288,6 +288,9 @@ void Message::Load(Json& data, Snowflake guild) m_avatar = pf->m_avatarlnk; } + if (data["pinned"].is_boolean()) + m_bIsPinned = data["pinned"]; + if (data["attachments"].is_array()) { m_attachments.clear(); diff --git a/src/core/models/Message.hpp b/src/core/models/Message.hpp index d1cb9e8b..790aad43 100644 --- a/src/core/models/Message.hpp +++ b/src/core/models/Message.hpp @@ -111,6 +111,7 @@ class Message std::set m_roleMentions; bool m_bMentionedEveryone = false; bool m_bIsAuthorBot = false; + bool m_bIsPinned = false; bool m_bRead = false; // valid only for the notification viewer messages bool m_bIsForward = false; Snowflake m_refMessageGuild = 0; diff --git a/src/core/network/DiscordRequest.hpp b/src/core/network/DiscordRequest.hpp index faab2d23..8ee41b4c 100644 --- a/src/core/network/DiscordRequest.hpp +++ b/src/core/network/DiscordRequest.hpp @@ -16,6 +16,8 @@ namespace DiscordRequest DELETE_MESSAGE, ACK, PINS, + PIN_MESSAGE, + UNPIN_MESSAGE, MESSAGE_CREATE, UPLOAD_ATTACHMENT, UPLOAD_ATTACHMENT_2, diff --git a/src/resource.h b/src/resource.h index 000e1a71..c6ee8382 100644 --- a/src/resource.h +++ b/src/resource.h @@ -333,6 +333,8 @@ #define IDS_SAVED_STRING_EXE 773 #define IDS_GET_TOKEN_TUTORIAL 774 #define IDS_CANT_LAUNCH_URL_UNS 775 +#define IDS_CONFIRM_UNPIN 776 +#define IDS_CONFIRM_UNPIN_TITLE 777 #define IDC_OPTIONS_TABS 801 #define IDC_MY_ACCOUNT_BOX 802 #define IDC_MY_ACCOUNT_NAME 803 @@ -513,6 +515,7 @@ #define ID_DUMMY_SAVEIMAGE 1081 #define ID_DUMMY_COPYIMAGE 1082 #define ID_DUMMY_OPENIMAGELINK 1083 +#define ID_DUMMYPOPUP_UNPINMESSAGE 1099 #define IDR_MAIN_ACCELS 1201 #define IDA_SEARCH 1301 #define IDA_QUICKSWITCHER 1302 @@ -536,7 +539,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 104 -#define _APS_NEXT_COMMAND_VALUE 1099 +#define _APS_NEXT_COMMAND_VALUE 1100 #define _APS_NEXT_CONTROL_VALUE 918 #define _APS_NEXT_SYMED_VALUE 40000 #endif diff --git a/src/resource.rc b/src/resource.rc index 6cee042d..c042b0c4 100644 --- a/src/resource.rc +++ b/src/resource.rc @@ -133,6 +133,7 @@ BEGIN END MENUITEM "Edit Message", ID_DUMMYPOPUP_EDITMESSAGE MENUITEM "Pin Message", ID_DUMMYPOPUP_PINMESSAGE + MENUITEM "Unpin Message", ID_DUMMYPOPUP_UNPINMESSAGE MENUITEM "Reply", ID_DUMMYPOPUP_REPLY MENUITEM "Copy Text", ID_DUMMYPOPUP_COPYTEXT MENUITEM "Mark Unread", ID_DUMMYPOPUP_MARKUNREAD @@ -1687,6 +1688,8 @@ BEGIN IDS_SAVED_STRING_EXE "Your downloaded file was saved at the following path: %s\n\nWARNING: This file might be malicious. Make sure you trust the sender/author of this file.\nWould you like to open it?" IDS_GET_TOKEN_TUTORIAL "Here are a few steps you can use to get your Discord token:\n\no Open a web browser, then navigate to discord.com\n\no Log in using your Discord account.\n\no Navigate to any channel.\n\no Press Ctrl+Shift+I while focused on that channel.\n\no Navigate to the Network tab, and then send a message.\n\no Check the ""messages"" request, and in the Request Headers, find the ""Authorization"" string.\n\no That's your token! Make sure to copy it without any quote marks, then paste it here.\n\nEnjoy!" IDS_CANT_LAUNCH_URL_UNS "The specified link %s couldn't be opened, because Windows returned ""%s"". Most likely, your Windows version does not support directly opening URLs." + IDS_CONFIRM_UNPIN "You sure you want to remove this pinned message?\n\n%s (%s)\n\n%s" + IDS_CONFIRM_UNPIN_TITLE "Discord Messenger - Unpin Message" END #endif // English (United States) resources diff --git a/src/windows/MessageList.cpp b/src/windows/MessageList.cpp index 08c34607..4b0c1202 100644 --- a/src/windows/MessageList.cpp +++ b/src/windows/MessageList.cpp @@ -3288,6 +3288,13 @@ void MessageList::HandleRightClickMenuCommand(int command) } case ID_DUMMYPOPUP_EDITMESSAGE: { + Channel* pChan = GetDiscordInstance()->GetCurrentChannel(); + if (!pChan) + break; + + if (!pChan->HasPermission(PERM_SEND_MESSAGES)) + break; + SendMessage(g_Hwnd, WM_STARTEDITING, 0, (LPARAM) &rightClickedMessage); break; } @@ -3336,7 +3343,10 @@ void MessageList::HandleRightClickMenuCommand(int command) if (!pChan) break; - if (!pChan->HasPermission(PERM_SEND_MESSAGES)) + if (!pChan->HasPermission(PERM_MANAGE_MESSAGES)) + break; + + if (IsActionMessage(pMsg->m_msg->m_type)) break; static char buffer[8192]; @@ -3346,7 +3356,32 @@ void MessageList::HandleRightClickMenuCommand(int command) if (MessageBox(g_Hwnd, xstr, TmGetTString(IDS_CONFIRM_PIN_TITLE), MB_YESNO | MB_ICONQUESTION) == IDYES) { - // TODO + GetDiscordInstance()->RequestPinMessage(m_channelID, rightClickedMessage); + } + + free((void*)xstr); + break; + } + case ID_DUMMYPOPUP_UNPINMESSAGE: + { + Channel* pChan = GetDiscordInstance()->GetCurrentChannel(); + if (!pChan) + break; + + if (!pChan->HasPermission(PERM_MANAGE_MESSAGES)) + break; + + if (IsActionMessage(pMsg->m_msg->m_type)) + break; + + static char buffer[8192]; + snprintf(buffer, sizeof buffer, TmGetString(IDS_CONFIRM_UNPIN).c_str(), pMsg->m_msg->m_author.c_str(), pMsg->m_msg->m_dateFull.c_str(), pMsg->m_msg->m_message.c_str()); + + LPCTSTR xstr = ConvertCppStringToTString(buffer); + + if (MessageBox(g_Hwnd, xstr, TmGetTString(IDS_CONFIRM_UNPIN_TITLE), MB_YESNO | MB_ICONQUESTION) == IDYES) + { + GetDiscordInstance()->RequestUnpinMessage(m_channelID, rightClickedMessage); } free((void*)xstr); @@ -3685,11 +3720,14 @@ LRESULT CALLBACK MessageList::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA bool maySendMessages = pChan->HasPermission(PERM_SEND_MESSAGES); bool isActionMessage = IsActionMessage(pRCMsg->m_msg->m_type) || IsClientSideMessage(pRCMsg->m_msg->m_type); bool isForward = pRCMsg->m_msg->m_bIsForward; + bool isPinned = pRCMsg->m_msg->m_bIsPinned; + bool isDM = pChan->IsDM(); bool mayCopy = !isForward && !isActionMessage; - bool mayDelete = isThisMyMessage || mayManageMessages; + bool mayDelete = isThisMyMessage || (mayManageMessages && !isDM); bool mayEdit = isThisMyMessage && !isForward && !isActionMessage && maySendMessages; - bool mayPin = mayManageMessages; + bool mayPin = mayManageMessages && !isPinned && !isActionMessage; + bool mayUnpin = mayManageMessages && isPinned && !isActionMessage; bool maySpeak = !isActionMessage && !pRCMsg->m_msg->m_message.empty(); bool mayReply = (!isActionMessage || IsReplyableActionMessage(pRCMsg->m_msg->m_type)) && maySendMessages; @@ -3697,6 +3735,7 @@ LRESULT CALLBACK MessageList::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA EnableMenuItem(menu, ID_DUMMYPOPUP_DELETEMESSAGE, mayDelete ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_DUMMYPOPUP_EDITMESSAGE, mayEdit ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_DUMMYPOPUP_PINMESSAGE, mayPin ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(menu, ID_DUMMYPOPUP_UNPINMESSAGE, mayUnpin ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_DUMMYPOPUP_SPEAKMESSAGE, maySpeak ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_DUMMYPOPUP_COPYTEXT, mayCopy ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_DUMMYPOPUP_REPLY, mayReply ? MF_ENABLED : MF_GRAYED); @@ -3704,6 +3743,7 @@ LRESULT CALLBACK MessageList::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA if (!mayDelete) RemoveMenu(menu, ID_DUMMYPOPUP_DELETEMESSAGE, MF_BYCOMMAND); if (!mayEdit) RemoveMenu(menu, ID_DUMMYPOPUP_EDITMESSAGE, MF_BYCOMMAND); if (!mayPin) RemoveMenu(menu, ID_DUMMYPOPUP_PINMESSAGE, MF_BYCOMMAND); + if (!mayUnpin) RemoveMenu(menu, ID_DUMMYPOPUP_UNPINMESSAGE, MF_BYCOMMAND); if (!maySpeak) RemoveMenu(menu, ID_DUMMYPOPUP_SPEAKMESSAGE, MF_BYCOMMAND); if (!mayCopy) RemoveMenu(menu, ID_DUMMYPOPUP_COPYTEXT, MF_BYCOMMAND); if (!mayReply) RemoveMenu(menu, ID_DUMMYPOPUP_REPLY, MF_BYCOMMAND);