From 99bdd52455ce99e89da7e1f0dafd019ac38af18d Mon Sep 17 00:00:00 2001 From: ElzorFox Date: Tue, 5 Dec 2023 15:22:09 +0500 Subject: VKontakte: add forwarding message support small code unification version bump --- protocols/VKontakte/res/forward.ico | Bin 0 -> 4286 bytes protocols/VKontakte/res/resource.rc | 44 +++++++++--------- protocols/VKontakte/src/misc.cpp | 3 +- protocols/VKontakte/src/resource.h | 12 +++-- protocols/VKontakte/src/version.h | 2 +- protocols/VKontakte/src/vk.h | 1 + protocols/VKontakte/src/vk_chats.cpp | 32 ++++++++++++- protocols/VKontakte/src/vk_dialogs.cpp | 72 +++++++++++++++++------------ protocols/VKontakte/src/vk_dialogs.h | 19 ++++++-- protocols/VKontakte/src/vk_messages.cpp | 77 +++++++++++++++++++++++++++++++- protocols/VKontakte/src/vk_proto.cpp | 42 ++++++++++++++--- protocols/VKontakte/src/vk_proto.h | 3 ++ 12 files changed, 240 insertions(+), 67 deletions(-) create mode 100644 protocols/VKontakte/res/forward.ico (limited to 'protocols') diff --git a/protocols/VKontakte/res/forward.ico b/protocols/VKontakte/res/forward.ico new file mode 100644 index 0000000000..61648e1058 Binary files /dev/null and b/protocols/VKontakte/res/forward.ico differ diff --git a/protocols/VKontakte/res/resource.rc b/protocols/VKontakte/res/resource.rc index 521d06721e..46b2720f1a 100644 --- a/protocols/VKontakte/res/resource.rc +++ b/protocols/VKontakte/res/resource.rc @@ -51,6 +51,8 @@ IDI_MARKMESSAGESASREAD ICON "markread.ico" IDI_REPLY ICON "reply.ico" +IDI_FORWARD ICON "forward.ico" + ///////////////////////////////////////////////////////////////////////////// // @@ -126,14 +128,6 @@ BEGIN BOTTOMMARGIN, 58 END - IDD_GC_CREATE, DIALOG - BEGIN - LEFTMARGIN, 4 - RIGHTMARGIN, 210 - TOPMARGIN, 7 - BOTTOMMARGIN, 225 - END - IDD_WALLPOST, DIALOG BEGIN LEFTMARGIN, 7 @@ -150,6 +144,14 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 80 END + + IDD_VKUSERFORM, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 210 + TOPMARGIN, 7 + BOTTOMMARGIN, 257 + END END #endif // APSTUDIO_INVOKED @@ -356,19 +358,6 @@ BEGIN COMBOBOX IDC_CONTACT,7,26,177,99,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP END -IDD_GC_CREATE DIALOGEX 0, 0, 215, 229 -STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Create group chat" -FONT 8, "MS Shell Dlg", 0, 0, 0x1 -BEGIN - CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x1,4,17,206,116,WS_EX_CLIENTEDGE - LTEXT "Mark users you want to invite to a new chat",IDC_STATIC,4,7,206,8 - LTEXT "New chat's title:",IDC_STATIC,9,142,198,8 - EDITTEXT IDC_TITLE,4,153,206,52,ES_MULTILINE | ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDOK,107,211,50,14 - PUSHBUTTON "Cancel",IDCANCEL,160,211,50,14 -END - IDD_WALLPOST DIALOGEX 0, 0, 316, 134 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_CONTROLPARENT @@ -393,6 +382,19 @@ BEGIN CONTROL "",IDC_CH_CLEARHISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,29,45,253,10 END +IDD_VKUSERFORM DIALOGEX 0, 0, 215, 261 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Mark contacts" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_CONTACTLIST,"CListControl",WS_TABSTOP | 0x1,4,17,206,155,WS_EX_CLIENTEDGE + LTEXT "Mark contacts",IDC_STATIC_MARKCONTAKTS,4,7,206,8 + LTEXT "Message",IDC_STATIC_MESSAGE,9,174,198,8 + EDITTEXT IDC_MESSAGE,4,185,206,52,ES_MULTILINE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,107,243,50,14 + PUSHBUTTON "Cancel",IDCANCEL,160,243,50,14 +END + #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index d0d092c6ae..07a737377c 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -62,7 +62,8 @@ static IconItem iconList[] = { LPGEN("Status icon"), "status", IDI_STATUS }, { LPGEN("Wall message icon"), "wall", IDI_WALL }, { LPGEN("Mark messages as read icon"), "markread", IDI_MARKMESSAGESASREAD }, - { LPGEN("Reply icon"), "reply", IDI_REPLY } + { LPGEN("Reply icon"), "reply", IDI_REPLY }, + { LPGEN("Forward icon"), "forward", IDI_FORWARD } }; void InitIcons() diff --git a/protocols/VKontakte/src/resource.h b/protocols/VKontakte/src/resource.h index fc8fbfd354..6dcb35d31d 100644 --- a/protocols/VKontakte/src/resource.h +++ b/protocols/VKontakte/src/resource.h @@ -7,7 +7,6 @@ #define IDD_CAPTCHAFORM 102 #define IDD_OPT_MAIN 103 #define IDD_INVITE 104 -#define IDD_GC_CREATE 105 #define IDD_OPT_ADV 106 #define IDD_OPT_FEEDS 107 #define IDI_NOTIFICATION 109 @@ -26,7 +25,9 @@ #define IDI_MARKMESSAGESASREAD 122 #define IDD_OPT_MENU 122 #define IDD_CONTACTDELETE 123 +#define IDD_VKUSERFORM 124 #define IDI_REPLY 125 +#define IDI_FORWARD 126 #define IDC_LOGIN 1001 #define IDC_PASSWORD 1002 #define IDC_URL 1003 @@ -39,7 +40,6 @@ #define IDC_SUBMIT 1010 #define IDC_DELIVERY 1011 #define IDC_GROUPNAME 1012 -#define IDC_CLIST 1013 #define IDC_HIDECHATS 1014 #define IDC_CONTACT 1015 #define IDC_LASTHISTORYLOAD 1019 @@ -131,15 +131,19 @@ #define IDC_STATIC_TXT 1114 #define IDC_CH_REMOVE_FROM_FRIEND 1115 #define IDC_CH_CLEARHISTORY 1116 +#define IDC_CONTACTLIST 1117 +#define IDC_MESSAGE 1118 +#define IDC_STATIC_MARKCONTAKTS 1119 +#define IDC_STATIC_MESSAGE 1120 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 126 +#define _APS_NEXT_RESOURCE_VALUE 127 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1116 +#define _APS_NEXT_CONTROL_VALUE 1121 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/protocols/VKontakte/src/version.h b/protocols/VKontakte/src/version.h index dbd5b70c91..ec1dd9e795 100644 --- a/protocols/VKontakte/src/version.h +++ b/protocols/VKontakte/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 1 #define __RELEASE_NUM 15 -#define __BUILD_NUM 3 +#define __BUILD_NUM 4 #include diff --git a/protocols/VKontakte/src/vk.h b/protocols/VKontakte/src/vk.h index f0b1b0a97d..fa0490283c 100644 --- a/protocols/VKontakte/src/vk.h +++ b/protocols/VKontakte/src/vk.h @@ -100,6 +100,7 @@ along with this program. If not, see . #define VK_USERID_MIN2 200000000000 #define VK_USERID_MAX2 1000000000000 +#define VK_MAX_FORWARD_MESSAGES 100 #if defined(_DEBUG) #define VK_NODUMPHEADERS 0 diff --git a/protocols/VKontakte/src/vk_chats.cpp b/protocols/VKontakte/src/vk_chats.cpp index 21aca51fde..8a3d27b41d 100644 --- a/protocols/VKontakte/src/vk_chats.cpp +++ b/protocols/VKontakte/src/vk_chats.cpp @@ -987,8 +987,36 @@ INT_PTR CVkProto::SvcCreateChat(WPARAM, LPARAM) if (!IsOnline()) return (INT_PTR)1; - CVkGCCreateForm dlg(this); - return (INT_PTR)!dlg.DoModal(); + CVkUserListForm dlg( + this, + "", + TranslateT("Create group chat"), + TranslateT("Mark users you want to invite to a new chat"), + TranslateT("New chat's title:") + ); + + if (!dlg.DoModal()) + return 0; + + CMStringA szUIds; + for (auto& hContact : dlg.lContacts) { + if (isChatRoom((UINT_PTR)hContact)) + continue; + + VKUserID_t iUserId = ReadVKUserID((UINT_PTR)hContact); + if (iUserId != 0) { + if (!szUIds.IsEmpty()) + szUIds.AppendChar(','); + szUIds.AppendFormat("%d", iUserId); + } + } + + if (szUIds.IsEmpty()) + return 0; + + CreateNewChat(szUIds, dlg.wszMessage); + + return 1; } void CVkProto::CreateNewChat(LPCSTR uids, LPCWSTR pwszTitle) diff --git a/protocols/VKontakte/src/vk_dialogs.cpp b/protocols/VKontakte/src/vk_dialogs.cpp index be16beda54..afe7e1d4ae 100644 --- a/protocols/VKontakte/src/vk_dialogs.cpp +++ b/protocols/VKontakte/src/vk_dialogs.cpp @@ -166,61 +166,77 @@ bool CVkInviteChatForm::OnApply() return true; } -////////////////////////////////// IDD_GC_CREATE ////////////////////////////////////////// +////////////////////////////////// IDD_VKUSERFORM ////////////////////////////////////////// + +CVkUserListForm::CVkUserListForm(CVkProto* proto) : + CVkDlgBase(proto, IDD_VKUSERFORM), + m_clc(this, IDC_CONTACTLIST), + m_edtMessage(this, IDC_MESSAGE), + m_stListCaption(this, IDC_STATIC_MARKCONTAKTS), + m_stMessageCaption(this, IDC_STATIC_MESSAGE), + lContacts(20, NumericKeySortT) +{ + m_clc.OnListRebuilt = Callback(this, &CVkUserListForm::FilterList); +} + -CVkGCCreateForm::CVkGCCreateForm(CVkProto *proto) : - CVkDlgBase(proto, IDD_GC_CREATE), - m_clc(this, IDC_CLIST), - m_edtTitle(this, IDC_TITLE) +CVkUserListForm::CVkUserListForm(CVkProto* proto, CMStringW _wszMessage, CMStringW _wszFormCaption, CMStringW _wszListCaption, CMStringW _wszMessageCaption) : + CVkDlgBase(proto, IDD_VKUSERFORM), + m_clc(this, IDC_CONTACTLIST), + m_edtMessage(this, IDC_MESSAGE), + m_stListCaption(this, IDC_STATIC_MARKCONTAKTS), + m_stMessageCaption(this, IDC_STATIC_MESSAGE), + wszMessage(_wszMessage), + wszFormCaption(_wszFormCaption), + wszListCaption(_wszListCaption), + wszMessageCaption(_wszMessageCaption), + lContacts(5, PtrKeySortT) { - m_clc.OnListRebuilt = Callback(this, &CVkGCCreateForm::FilterList); + m_clc.OnListRebuilt = Callback(this, &CVkUserListForm::FilterList); } -bool CVkGCCreateForm::OnInitDialog() +bool CVkUserListForm::OnInitDialog() { SetWindowLongPtr(m_clc.GetHwnd(), GWL_STYLE, GetWindowLongPtr(m_clc.GetHwnd(), GWL_STYLE) | CLS_CHECKBOXES | CLS_HIDEEMPTYGROUPS | CLS_USEGROUPS | CLS_GREYALTERNATE); m_clc.SendMsg(CLM_SETEXSTYLE, CLS_EX_DISABLEDRAGDROP | CLS_EX_TRACKSELECT, 0); ResetListOptions(); + + m_stListCaption.SetText(wszListCaption.c_str()); + m_stMessageCaption.SetText(wszMessageCaption.c_str()); + m_edtMessage.SetText(wszMessage.c_str()); + SetCaption(wszFormCaption.c_str()); + return true; } -bool CVkGCCreateForm::OnApply() +bool CVkUserListForm::OnApply() { CMStringA szUIds; - for (auto &hContact : m_proto->AccContacts()) { - if (m_proto->isChatRoom(hContact)) - continue; - + for (auto& hContact : m_proto->AccContacts()) { HANDLE hItem = m_clc.FindContact(hContact); - if (hItem && m_clc.GetCheck(hItem)) { - VKUserID_t iUserId = m_proto->ReadVKUserID(hContact); - if (iUserId != 0) { - if (!szUIds.IsEmpty()) - szUIds.AppendChar(','); - szUIds.AppendFormat("%d", iUserId); - } - } + if (hItem && m_clc.GetCheck(hItem)) + lContacts.insert((HANDLE)hContact); + } - bool bRes = !szUIds.IsEmpty(); - if (bRes) - m_proto->CreateNewChat(szUIds, ptrW(m_edtTitle.GetText())); + wszMessage = m_edtMessage.GetText(); + return true; } -void CVkGCCreateForm::FilterList(CCtrlClc*) +void CVkUserListForm::FilterList(CCtrlClc*) { - for (auto &hContact : Contacts()) { - char *proto = Proto_GetBaseAccountName(hContact); - if (mir_strcmp(proto, m_proto->m_szModuleName) || m_proto->isChatRoom(hContact) || m_proto->ReadVKUserID(hContact) == VK_FEED_USER) + for (auto& hContact : Contacts()) { + char* proto = Proto_GetBaseAccountName(hContact); + if (mir_strcmp(proto, m_proto->m_szModuleName) || Contact::IsReadonly(hContact) || m_proto->ReadVKUserID(hContact) == VK_FEED_USER) if (HANDLE hItem = m_clc.FindContact(hContact)) m_clc.DeleteItem(hItem); } } -void CVkGCCreateForm::ResetListOptions() +void CVkUserListForm::ResetListOptions() { m_clc.SetBkColor(GetSysColor(COLOR_WINDOW)); m_clc.SetHideEmptyGroups(true); diff --git a/protocols/VKontakte/src/vk_dialogs.h b/protocols/VKontakte/src/vk_dialogs.h index ee3f7893cd..a0b6ce11a1 100644 --- a/protocols/VKontakte/src/vk_dialogs.h +++ b/protocols/VKontakte/src/vk_dialogs.h @@ -109,15 +109,26 @@ public: bool OnApply() override; }; -////////////////////////////////// IDD_GC_CREATE ////////////////////////////////////////// -class CVkGCCreateForm : public CVkDlgBase +////////////////////////////////// IDD_VKUSERFORM ////////////////////////////////////////// + +class CVkUserListForm : public CVkDlgBase { CCtrlClc m_clc; - CCtrlEdit m_edtTitle; + CCtrlEdit m_edtMessage; + CCtrlBase m_stListCaption; + CCtrlBase m_stMessageCaption; + public: - CVkGCCreateForm(CVkProto *proto); + CMStringW wszFormCaption; + CMStringW wszListCaption; + CMStringW wszMessageCaption; + CMStringW wszMessage; + LIST lContacts; + + CVkUserListForm(CVkProto* proto); + CVkUserListForm(CVkProto* proto, CMStringW _wszMessage, CMStringW _wszFormCaption, CMStringW _wszListCaption, CMStringW _wszMessageCaption); bool OnInitDialog() override; bool OnApply() override; diff --git a/protocols/VKontakte/src/vk_messages.cpp b/protocols/VKontakte/src/vk_messages.cpp index 4220deb3f1..d51a0f5f0b 100644 --- a/protocols/VKontakte/src/vk_messages.cpp +++ b/protocols/VKontakte/src/vk_messages.cpp @@ -19,6 +19,81 @@ along with this program. If not, see . ////////////////////////////////////////////////////////////////////////////// +int CVkProto::ForwardMsg(MCONTACT hContact, std::vector& vForvardEvents, const char* szMsg) +{ + debugLogA("CVkProto::ForwardMsg"); + if (!IsOnline() || !vForvardEvents.size()) + return -1; + + bool bIsChat = isChatRoom(hContact); + + VKUserID_t iUserId = ReadVKUserID(hContact); + if (iUserId == VK_INVALID_USER || iUserId == VK_FEED_USER) { + ProtoBroadcastAsync(hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, 0); + return 0; + } + + int StickerId = 0; + ptrA pszRetMsg(GetStickerId(szMsg, StickerId)); + + CMStringA szIds; + int i = 0; + for (auto &mEvnt : vForvardEvents) { + DB::EventInfo dbei(mEvnt, false); + if (dbei && mir_strlen(dbei.szId) > 0 && i < VK_MAX_FORWARD_MESSAGES) { + if (!szIds.IsEmpty()) + szIds.AppendChar(','); + szIds += dbei.szId; + i++; + } + } + + ULONG uMsgId = ::InterlockedIncrement(&m_iMsgId); + AsyncHttpRequest* pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, + bIsChat ? &CVkProto::OnSendChatMsg : &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh); + + pReq + << INT_PARAM(bIsChat ? "chat_id" : "peer_id", iUserId) + << INT_PARAM("random_id", ((long)time(0)) * 100 + uMsgId % 100) + << CHAR_PARAM("forward_messages", szIds); + + pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); + + if (StickerId) + pReq << INT_PARAM("sticker_id", StickerId); + else if (!IsEmpty(szMsg)) { + pReq << CHAR_PARAM("message", szMsg); + if (m_vkOptions.bSendVKLinksAsAttachments) { + CMStringA szAttachments = GetAttachmentsFromMessage(szMsg); + if (!szAttachments.IsEmpty()) { + debugLogA("CVkProto::ForwardMsg Attachments = %s", szAttachments.c_str()); + pReq << CHAR_PARAM("attachment", szAttachments); + } + } + } + + if (!bIsChat) + pReq->pUserInfo = new CVkSendMsgParam(hContact, uMsgId); + + Push(pReq); + + if (!m_vkOptions.bServerDelivery && !bIsChat) + ProtoBroadcastAsync(hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)uMsgId); + + if (vForvardEvents.size() > VK_MAX_FORWARD_MESSAGES) { + std::vector vNextForvardEvents(vForvardEvents.begin() + VK_MAX_FORWARD_MESSAGES, vForvardEvents.end()); + ForwardMsg(hContact, vNextForvardEvents, ""); + } + + if (!IsEmpty(pszRetMsg)) + SendMsg(hContact, 0, pszRetMsg); + else if (m_iStatus == ID_STATUS_INVISIBLE) + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/account.setOffline.json", true, &CVkProto::OnReceiveSmth)); + + return uMsgId; +} + + int CVkProto::SendMsg(MCONTACT hContact, MEVENT hReplyEvent, const char *szMsg) { debugLogA("CVkProto::SendMsg hReplyEvent = %d", hReplyEvent); @@ -45,7 +120,7 @@ int CVkProto::SendMsg(MCONTACT hContact, MEVENT hReplyEvent, const char *szMsg) if (hReplyEvent) { DB::EventInfo dbei(hReplyEvent, false); - if (dbei && mir_strlen(dbei.szId)) + if (dbei && mir_strlen(dbei.szId) > 0) pReq << CHAR_PARAM("reply_to", dbei.szId); } diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp index 78086e3303..2283459cea 100644 --- a/protocols/VKontakte/src/vk_proto.cpp +++ b/protocols/VKontakte/src/vk_proto.cpp @@ -217,8 +217,13 @@ void CVkProto::InitMenus() CMenuItem mi(&g_plugin); mi.pszService = szServiceName; - mi.hIcolibItem = g_plugin.getIconHandle(IDI_REPLY); + mi.hIcolibItem = g_plugin.getIconHandle(IDI_FORWARD); + mi.position = 10000000 + NSMI_FORWARD; + mi.name.a = LPGEN("Forward"); + m_hNewStoryMenuItems[NSMI_FORWARD] = Menu_AddNewStoryMenuItem(&mi, NSMI_FORWARD); + + mi.hIcolibItem = g_plugin.getIconHandle(IDI_REPLY); mi.position = 10000000 + NSMI_REPLY; mi.name.a = LPGEN("Reply"); m_hNewStoryMenuItems[NSMI_REPLY] = Menu_AddNewStoryMenuItem(&mi, NSMI_REPLY); @@ -429,12 +434,39 @@ int CVkProto::OnPrebuildNSMenu(WPARAM hContact, LPARAM lParam) INT_PTR CVkProto::SvcNSExecMenu(WPARAM iCommand, LPARAM pHandle) { MEVENT hCurrentEvent = NS_GetCurrent((HANDLE)pHandle); + if (hCurrentEvent == -1) + return 1; switch (iCommand) { - case NSMI_REPLY: // reply - if (hCurrentEvent != -1) - if (auto* pDlg = NS_GetSrmm((HANDLE)pHandle)) - pDlg->SetQuoteEvent(hCurrentEvent); + case NSMI_FORWARD: + { + std::vector vIds = NS_GetSelection(HANDLE(pHandle)); + wchar_t wszMsg[2048] = L""; + if (auto* pDlg = NS_GetSrmm((HANDLE)pHandle)) + GetWindowText(pDlg->GetInput(), wszMsg, 2048); + + CVkUserListForm dlg( + this, + wszMsg, + TranslateT("Mark contacts for forwarding messages"), + TranslateT("Mark contacts you want to forward messages"), + TranslateT("Enter accompanying messages") + ); + if (!dlg.DoModal()) + break; + + if (!vIds.size()) + vIds.push_back(hCurrentEvent); + T2Utf pszMsg(dlg.wszMessage.c_str()); + for (auto &hContact : dlg.lContacts) + ForwardMsg((UINT_PTR)hContact, vIds, pszMsg); + + } + break; + case NSMI_REPLY: + if (auto* pDlg = NS_GetSrmm((HANDLE)pHandle)) + pDlg->SetQuoteEvent(hCurrentEvent); + break; } return 0; diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index bc54a46dc3..f0dd5cab62 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -142,6 +142,8 @@ struct CVkProto : public PROTO VKUserID_t ReadVKUserID(MCONTACT hContact); void WriteVKUserID(MCONTACT hContact, VKUserID_t iUserId); + int ForwardMsg(MCONTACT hContact, std::vector &vForvardEvents, const char* szMsg); + private: VKPeerType GetVKPeerType(VKUserID_t iPeerId); @@ -191,6 +193,7 @@ private: }; enum NewStoryMenuIndexes { + NSMI_FORWARD, NSMI_REPLY, NSMI_COUNT }; -- cgit v1.2.3