diff options
author | George Hazan <george.hazan@gmail.com> | 2023-12-24 15:36:52 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2023-12-24 15:36:52 +0300 |
commit | 93af1070aaa1de81d573ff0ec879e74df036dd01 (patch) | |
tree | 502d4f5b3fa538e52acf1d595b36566df312433f | |
parent | c69b6df18206f22513bc83f93d29f95ecbd77977 (diff) |
ICQ: added messages' forwarding + "Add to favorites" NewStory menu item
-rw-r--r-- | protocols/ICQ-WIM/res/Forward.ico | bin | 0 -> 4286 bytes | |||
-rw-r--r-- | protocols/ICQ-WIM/res/resources.rc | 11 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/main.cpp | 1 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/menus.cpp | 172 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/proto.cpp | 27 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/proto.h | 13 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/resource.h | 4 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/server.cpp | 41 |
8 files changed, 203 insertions, 66 deletions
diff --git a/protocols/ICQ-WIM/res/Forward.ico b/protocols/ICQ-WIM/res/Forward.ico Binary files differnew file mode 100644 index 0000000000..0b6fa81f6c --- /dev/null +++ b/protocols/ICQ-WIM/res/Forward.ico diff --git a/protocols/ICQ-WIM/res/resources.rc b/protocols/ICQ-WIM/res/resources.rc index 7af238004a..5f2ec57b50 100644 --- a/protocols/ICQ-WIM/res/resources.rc +++ b/protocols/ICQ-WIM/res/resources.rc @@ -180,6 +180,16 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,102,53,50,14 END +IDD_FORWARD DIALOGEX 0, 0, 215, 267 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Forward message" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x1,8,4,201,239,WS_EX_CLIENTEDGE + DEFPUSHBUTTON "Forward",IDOK,104,248,50,14 + PUSHBUTTON "Cancel",IDCANCEL,158,248,50,14 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -278,6 +288,7 @@ IDI_INBOX ICON "Mail.ico" IDI_MAIL_NOTIFY ICON "MailNotify.ico" +IDI_FORWARD ICON "Forward.ico" #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// diff --git a/protocols/ICQ-WIM/src/main.cpp b/protocols/ICQ-WIM/src/main.cpp index b445bc7b29..db622413f1 100644 --- a/protocols/ICQ-WIM/src/main.cpp +++ b/protocols/ICQ-WIM/src/main.cpp @@ -84,6 +84,7 @@ static int OnModulesLoaded(WPARAM, LPARAM) static IconItem iconList[] =
{
+ { LPGEN("Forward"), "forward", IDI_FORWARD },
{ LPGEN("E-mail"), "icq_email", IDI_INBOX },
{ LPGEN("E-mail notification"), "icq_email_notif", IDI_MAIL_NOTIFY }
};
diff --git a/protocols/ICQ-WIM/src/menus.cpp b/protocols/ICQ-WIM/src/menus.cpp index b78b308f43..5c7fca94ad 100644 --- a/protocols/ICQ-WIM/src/menus.cpp +++ b/protocols/ICQ-WIM/src/menus.cpp @@ -19,6 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define MenuExecService "/NSExecMenu" +int CIcqProto::OnPrebuildMenu(WPARAM hContact, LPARAM lParam) +{ + if (!Proto_IsProtoOnContact(hContact, m_szModuleName)) { + Menu_ShowItem(hmiForward, false); + Menu_ShowItem(hmiConvert, false); + } + else { + auto *dbei = (DB::EventInfo *)lParam; + Menu_ShowItem(hmiForward, dbei->eventType == EVENTTYPE_MESSAGE || dbei->eventType == EVENTTYPE_FILE); + + ptrW wszText(DbEvent_GetTextW(dbei, CP_UTF8)); + Menu_ShowItem(hmiConvert, fileText2url(wszText.get())); + } + return 0; +} + void CIcqProto::InitMenus() { if (!HookProtoEvent(ME_NS_PREBUILDMENU, &CIcqProto::OnPrebuildMenu)) @@ -31,50 +47,134 @@ void CIcqProto::InitMenus() mi.pszService = szServiceName; mi.position = 1000000; + mi.hIcolibItem = g_plugin.getIconHandle(IDI_FORWARD); + mi.name.a = LPGEN("Forward"); + hmiForward = Menu_AddNewStoryMenuItem(&mi, 1); + + mi.position++; + mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_ADDCONTACT); + mi.name.a = LPGEN("Add to faforites"); + hmiConvert = Menu_AddNewStoryMenuItem(&mi, 2); + + mi.position++; mi.hIcolibItem = Skin_GetIconHandle(SKINICON_EVENT_FILE); mi.name.a = LPGEN("Convert a message into a file transfer"); - hmiConvert = Menu_AddNewStoryMenuItem(&mi, 1); + hmiConvert = Menu_AddNewStoryMenuItem(&mi, 3); } -INT_PTR CIcqProto::SvcExecMenu(WPARAM iCommand, LPARAM pHandle) +///////////////////////////////////////////////////////////////////////////////////////// +// Dialog for message forwarding + +class CForwardDlg : public CIcqDlgBase { - // convert a message into a file transfer - if (iCommand == 1) { - if (MEVENT hEvent = NS_GetCurrent(HANDLE(pHandle))) { - DB::EventInfo dbei(hEvent); - if (!dbei) - return 0; - - IcqFileInfo *pFileInfo = nullptr; - CMStringW wszText(ptrW(DbEvent_GetTextW(&dbei, CP_UTF8))); - if (CheckFile(dbei.hContact, wszText, pFileInfo)) { - if (!pFileInfo || pFileInfo->bIsSticker) { - // sticker is a simple text message prcoessed by SmileyAdd - T2Utf szBody(wszText); - mir_free(dbei.pBlob); - dbei.cbBlob = (int)mir_strlen(szBody.get()); - dbei.pBlob = szBody.detach(); - } - else { - // create the offline file event - dbei.eventType = EVENTTYPE_FILE; - - DB::FILE_BLOB blob(pFileInfo->wszDescr, wszText); - blob.setUrl(pFileInfo->szOrigUrl); - blob.setSize(pFileInfo->dwFileSize); - blob.write(dbei); - } - db_event_edit(hEvent, &dbei); - } - } + CCtrlClc m_clist; + MEVENT m_hEvent; + + void FilterList(CCtrlClc *) + { + for (auto &hContact : Contacts()) + if (!Proto_IsProtoOnContact(hContact, m_proto->m_szModuleName)) + if (HANDLE hItem = m_clist.FindContact(hContact)) + m_clist.DeleteItem(hItem); } - return 0; + + void ResetListOptions(CCtrlClc *) + { + m_clist.SetHideEmptyGroups(true); + m_clist.SetHideOfflineRoot(true); + } + +public: + CForwardDlg(CIcqProto *ppro, MEVENT hEvent) : + CIcqDlgBase(ppro, IDD_FORWARD), + m_hEvent(hEvent), + m_clist(this, IDC_CLIST) + { + m_clist.OnNewContact = + m_clist.OnListRebuilt = Callback(this, &CForwardDlg::FilterList); + m_clist.OnOptionsChanged = Callback(this, &CForwardDlg::ResetListOptions); + } + + bool OnInitDialog() override + { + SetWindowLongPtr(m_clist.GetHwnd(), GWL_STYLE, + GetWindowLongPtr(m_clist.GetHwnd(), GWL_STYLE) | CLS_SHOWHIDDEN | CLS_HIDEOFFLINE | CLS_CHECKBOXES | CLS_HIDEEMPTYGROUPS | CLS_USEGROUPS | CLS_GREYALTERNATE | CLS_GROUPCHECKBOXES); + m_clist.SendMsg(CLM_SETEXSTYLE, CLS_EX_DISABLEDRAGDROP | CLS_EX_TRACKSELECT, 0); + ResetListOptions(&m_clist); + FilterList(&m_clist); + return true; + } + + bool OnApply() override + { + for (auto &hContact : m_proto->AccContacts()) + if (HANDLE hItem = m_clist.FindContact(hContact)) + if (m_clist.GetCheck(hItem)) + m_proto->ForwardMessage(m_hEvent, hContact); + + return true; + } +}; + +void CIcqProto::ForwardMessage(MEVENT hEvent, MCONTACT to) +{ + DB::EventInfo dbei(hEvent); + if (!dbei || !dbei.szId || mir_strcmp(dbei.szModule, m_szModuleName)) + return; + + CMStringW wszId(GetUserId(dbei.hContact)); + ptrW wszText(DbEvent_GetTextW(&dbei, CP_UTF8)); + + JSONNode parts(JSON_ARRAY); + JSONNode msgText; msgText << CHAR_PARAM("mediaType", "forward") << WCHAR_PARAM("sn", wszId) << INT_PARAM("time", dbei.timestamp) + << CHAR_PARAM("msgId", dbei.szId) << WCHAR_PARAM("text", wszText); + parts.push_back(msgText); + + SendMessageParts(to, parts); } -int CIcqProto::OnPrebuildMenu(WPARAM, LPARAM lParam) +///////////////////////////////////////////////////////////////////////////////////////// + +INT_PTR CIcqProto::SvcExecMenu(WPARAM iCommand, LPARAM pHandle) { - auto *dbei = (DB::EventInfo *)lParam; - ptrW wszText(DbEvent_GetTextW(dbei, CP_UTF8)); - Menu_ShowItem(hmiConvert, fileText2url(wszText.get())); + MEVENT hEvent = NS_GetCurrent(HANDLE(pHandle)); + if (!hEvent) + return 0; + + switch (iCommand) { + case 1: // forward message + CForwardDlg(this, hEvent).DoModal(); + break; + + case 2: // Add to favorites + ForwardMessage(hEvent, m_hFavContact); + + case 3: // convert a message into a file transfer + DB::EventInfo dbei(hEvent); + if (!dbei) + return 0; + + IcqFileInfo *pFileInfo = nullptr; + CMStringW wszText(ptrW(DbEvent_GetTextW(&dbei, CP_UTF8))); + if (CheckFile(dbei.hContact, wszText, pFileInfo)) { + if (!pFileInfo || pFileInfo->bIsSticker) { + // sticker is a simple text message prcoessed by SmileyAdd + T2Utf szBody(wszText); + mir_free(dbei.pBlob); + dbei.cbBlob = (int)mir_strlen(szBody.get()); + dbei.pBlob = szBody.detach(); + } + else { + // create the offline file event + dbei.eventType = EVENTTYPE_FILE; + + DB::FILE_BLOB blob(pFileInfo->wszDescr, wszText); + blob.setUrl(pFileInfo->szOrigUrl); + blob.setSize(pFileInfo->dwFileSize); + blob.write(dbei); + } + db_event_edit(hEvent, &dbei); + } + } return 0; } diff --git a/protocols/ICQ-WIM/src/proto.cpp b/protocols/ICQ-WIM/src/proto.cpp index 9a58298890..b6f27ec26a 100644 --- a/protocols/ICQ-WIM/src/proto.cpp +++ b/protocols/ICQ-WIM/src/proto.cpp @@ -541,20 +541,6 @@ HANDLE CIcqProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, wcha int CIcqProto::SendMsg(MCONTACT hContact, MEVENT hReplyEvent, const char *pszSrc)
{
- CMStringA szUserid(GetUserId(hContact));
- if (szUserid.IsEmpty())
- return 0;
-
- int id = InterlockedIncrement(&m_msgId);
- auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, "/im/sendIM", &CIcqProto::OnSendMessage);
-
- auto *pOwn = new IcqOwnMessage(hContact, id, pReq->m_reqId, pszSrc);
- pReq->pUserInfo = pOwn;
- {
- mir_cslock lck(m_csOwnIds);
- m_arOwnIds.insert(pOwn);
- }
-
JSONNode parts(JSON_ARRAY);
if (hReplyEvent) {
DB::EventInfo dbei(hReplyEvent);
@@ -570,10 +556,15 @@ int CIcqProto::SendMsg(MCONTACT hContact, MEVENT hReplyEvent, const char *pszSrc JSONNode msgText; msgText << CHAR_PARAM("mediaType", "text") << CHAR_PARAM("text", pszSrc);
parts.push_back(msgText);
-
- pReq << AIMSID(this) << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", appId()) << CHAR_PARAM("mentions", "")
- << CHAR_PARAM("offlineIM", "true") << CHAR_PARAM("parts", parts.write().c_str()) << CHAR_PARAM("t", szUserid) << INT_PARAM("ts", TS());
- Push(pReq);
+
+ int id = InterlockedIncrement(&m_msgId);
+ auto *pOwn = new IcqOwnMessage(hContact, id, pszSrc);
+ {
+ mir_cslock lck(m_csOwnIds);
+ m_arOwnIds.insert(pOwn);
+ }
+
+ SendMessageParts(hContact, parts, pOwn);
return id;
}
diff --git a/protocols/ICQ-WIM/src/proto.h b/protocols/ICQ-WIM/src/proto.h index 1771a37e43..b236397541 100644 --- a/protocols/ICQ-WIM/src/proto.h +++ b/protocols/ICQ-WIM/src/proto.h @@ -146,12 +146,16 @@ struct IcqFileTransfer : public MZeroedObject struct IcqOwnMessage
{
- IcqOwnMessage(MCONTACT _hContact, int _msgid, const char *guid, const char *pszText) :
+ IcqOwnMessage(MCONTACT _hContact, int _msgid, const char *pszText) :
m_msgid(_msgid),
m_hContact(_hContact),
m_szText(mir_strdup(pszText))
{
- strncpy_s(m_guid, guid, _TRUNCATE);
+ }
+
+ void setGuid(const char *pszGuid)
+ {
+ strncpy_s(m_guid, pszGuid, _TRUNCATE);
}
MCONTACT m_hContact;
@@ -163,6 +167,7 @@ struct IcqOwnMessage class CIcqProto : public PROTO<CIcqProto>
{
+ friend class CForwardDlg;
friend struct AsyncRapiRequest;
class CIcqProtoImpl
@@ -207,6 +212,7 @@ class CIcqProto : public PROTO<CIcqProto> void CheckPassword(void);
void ConnectionFailed(int iReason, int iErrorCode = 0);
void EmailNotification(const wchar_t *pwszText);
+ void ForwardMessage(MEVENT hEVent, MCONTACT hContact);
void GetPermitDeny();
wchar_t* GetUIN(MCONTACT hContact);
void MoveContactToGroup(MCONTACT hContact, const wchar_t *pwszGroup, const wchar_t *pwszNewGroup);
@@ -217,6 +223,7 @@ class CIcqProto : public PROTO<CIcqProto> void RetrieveUserHistory(MCONTACT, __int64 startMsgId, bool bCreateRead);
void RetrieveUserInfo(MCONTACT hContact);
void SendMrimLogin(NETLIBHTTPREQUEST *pReply);
+ void SendMessageParts(MCONTACT hContact, const JSONNode &parts, IcqOwnMessage *pOwn = nullptr);
void SetOwnId(const CMStringW &wszId);
void SetServerStatus(int iNewStatus);
void ShutdownSession(void);
@@ -359,7 +366,7 @@ class CIcqProto : public PROTO<CIcqProto> ////////////////////////////////////////////////////////////////////////////////////////
// Menus
- HGENMENU hmiConvert;
+ HGENMENU hmiForward, hmiConvert;
void InitMenus();
diff --git a/protocols/ICQ-WIM/src/resource.h b/protocols/ICQ-WIM/src/resource.h index c0987e795e..38a48a0d35 100644 --- a/protocols/ICQ-WIM/src/resource.h +++ b/protocols/ICQ-WIM/src/resource.h @@ -13,6 +13,8 @@ #define IDD_OPTIONS_ADV 109 #define IDD_LOGINPW 110 #define IDD_EDITGROUPS 111 +#define IDD_FORWARD 112 +#define IDI_FORWARD 113 #define IDC_PASSWORD 1001 #define IDC_UIN 1002 #define IDC_UIN2 1003 @@ -45,7 +47,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 113 +#define _APS_NEXT_RESOURCE_VALUE 114 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1026 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/protocols/ICQ-WIM/src/server.cpp b/protocols/ICQ-WIM/src/server.cpp index 6d017376a2..3d068a831a 100644 --- a/protocols/ICQ-WIM/src/server.cpp +++ b/protocols/ICQ-WIM/src/server.cpp @@ -1151,7 +1151,8 @@ LBL_Error: int id = InterlockedIncrement(&m_msgId);
auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, "/im/sendIM", &CIcqProto::OnSendMessage);
- auto *pOwn = new IcqOwnMessage(pTransfer->pfts.hContact, id, pReq->m_reqId, T2Utf(wszUrl));
+ auto *pOwn = new IcqOwnMessage(pTransfer->pfts.hContact, id, T2Utf(wszUrl));
+ pOwn->setGuid(pReq->m_reqId);
pOwn->pTransfer = pTransfer;
pReq->pUserInfo = pOwn;
{
@@ -1368,22 +1369,24 @@ void CIcqProto::OnSearchResults(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pRe ProtoBroadcastAck(0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)pReq);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// Send message
+
void CIcqProto::OnSendMessage(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq)
{
IcqOwnMessage *ownMsg = (IcqOwnMessage *)pReq->pUserInfo;
JsonReply root(pReply);
if (root.error() != 200) {
- ProtoBroadcastAck(ownMsg->m_hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)ownMsg->m_msgid);
+ if (ownMsg) {
+ ProtoBroadcastAck(ownMsg->m_hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)ownMsg->m_msgid);
- mir_cslock lck(m_csOwnIds);
- m_arOwnIds.remove(ownMsg);
+ mir_cslock lck(m_csOwnIds);
+ m_arOwnIds.remove(ownMsg);
+ }
return;
}
- if (g_bMessageState)
- CallService(MS_MESSAGESTATE_UPDATE, ownMsg->m_hContact, MRD_TYPE_DELIVERED);
-
const JSONNode &data = root.data();
if (auto &jsonMsg = data.at("histMsgId")) {
CMStringA reqId(root.requestId());
@@ -1391,9 +1394,31 @@ void CIcqProto::OnSendMessage(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) CheckOwnMessage(reqId, msgId, false);
}
- CheckLastId(ownMsg->m_hContact, data);
+ if (ownMsg) {
+ if (g_bMessageState)
+ CallService(MS_MESSAGESTATE_UPDATE, ownMsg->m_hContact, MRD_TYPE_DELIVERED);
+ CheckLastId(ownMsg->m_hContact, data);
+ }
+}
+
+void CIcqProto::SendMessageParts(MCONTACT hContact, const JSONNode &parts, IcqOwnMessage *pOwn)
+{
+ CMStringA szUserid(GetUserId(hContact));
+ if (szUserid.IsEmpty())
+ return;
+
+ auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, "/im/sendIM", &CIcqProto::OnSendMessage);
+ pReq->pUserInfo = pOwn;
+ if (pOwn)
+ pOwn->setGuid(pReq->m_reqId);
+
+ pReq << AIMSID(this) << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", appId()) << CHAR_PARAM("mentions", "")
+ << CHAR_PARAM("offlineIM", "true") << CHAR_PARAM("parts", parts.write().c_str()) << CHAR_PARAM("t", szUserid) << INT_PARAM("ts", TS());
+ Push(pReq);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
void CIcqProto::OnSessionEnd(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *)
{
JsonReply root(pReply);
|