From 04da76c5fae4f4ef3eda995641b0251671d6edd0 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sat, 4 Apr 2015 22:00:18 +0000 Subject: SkypeWeb: support of actions (/me ...) git-svn-id: http://svn.miranda-ng.org/main/trunk@12600 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/SkypeWeb/src/common.h | 2 + protocols/SkypeWeb/src/requests/messages.h | 6 +- protocols/SkypeWeb/src/skype_accounts.cpp | 1 + protocols/SkypeWeb/src/skype_messages.cpp | 71 +++++++++++++++++++++--- protocols/SkypeWeb/src/skype_poll_processing.cpp | 19 ++++--- protocols/SkypeWeb/src/skype_proto.cpp | 5 ++ protocols/SkypeWeb/src/skype_proto.h | 10 +++- protocols/SkypeWeb/src/version.h | 2 +- 8 files changed, 94 insertions(+), 22 deletions(-) diff --git a/protocols/SkypeWeb/src/common.h b/protocols/SkypeWeb/src/common.h index 84060c4eba..bbe6addfb1 100644 --- a/protocols/SkypeWeb/src/common.h +++ b/protocols/SkypeWeb/src/common.h @@ -68,4 +68,6 @@ extern HINSTANCE g_hInstance; #define SKYPE_SETTINGS_PASSWORD "Password" #define SKYPE_SETTINGS_GROUP "DefaultGroup" +#define SKYPE_DB_EVENT_TYPE_ACTION 10001 + #endif //_COMMON_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/requests/messages.h b/protocols/SkypeWeb/src/requests/messages.h index d2c000d8be..c3ac040579 100644 --- a/protocols/SkypeWeb/src/requests/messages.h +++ b/protocols/SkypeWeb/src/requests/messages.h @@ -4,7 +4,7 @@ class SendMsgRequest : public HttpRequest { public: - SendMsgRequest(const char *regToken, const char *username, const char *message, const char *server = "client-s.gateway.messenger.live.com") : + SendMsgRequest(const char *regToken, const char *username, const char *clientMsgId, const char *message, const char *server = "client-s.gateway.messenger.live.com") : HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/conversations/8:%s/messages", server, username) { Headers @@ -18,7 +18,7 @@ public: << CHAR_VALUE("Connection", "keep-alive"); CMStringA data; - data.AppendFormat("{\"clientmessageid\":\"\",\"content\":\"%s\",\"messagetype\":\"RichText\",\"contenttype\":\"text\"}", message); + data.AppendFormat("{\"clientmessageid\":\"%s\",\"content\":\"%s\",\"messagetype\":\"RichText\",\"contenttype\":\"text\"}", clientMsgId, message); Body << VALUE(data); } @@ -27,7 +27,7 @@ public: class SendTypingRequest : public HttpRequest { public: - SendTypingRequest(const char *regToken, const char *username,bool bstate, const char *server = "client-s.gateway.messenger.live.com") : + SendTypingRequest(const char *regToken, const char *username, bool bstate, const char *server = "client-s.gateway.messenger.live.com") : HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/conversations/8:%s/messages", server, mir_urlEncode(username)) { Headers diff --git a/protocols/SkypeWeb/src/skype_accounts.cpp b/protocols/SkypeWeb/src/skype_accounts.cpp index 6a383045f2..ea9fe30489 100644 --- a/protocols/SkypeWeb/src/skype_accounts.cpp +++ b/protocols/SkypeWeb/src/skype_accounts.cpp @@ -32,6 +32,7 @@ CSkypeProto* CSkypeProto::GetContactAccount(MCONTACT hContact) int CSkypeProto::OnAccountLoaded(WPARAM, LPARAM) { HookProtoEvent(ME_OPT_INITIALISE, &CSkypeProto::OnOptionsInit); + HookProtoEvent(ME_MSG_PRECREATEEVENT, &CSkypeProto::OnPreCreateMessage); return 0; } diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp index b863fa57fd..66c53fc29d 100644 --- a/protocols/SkypeWeb/src/skype_messages.cpp +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -2,33 +2,57 @@ /* MESSAGE RECEIVING */ -// writing message/even into db -int CSkypeProto::OnReceiveMessage(const char *from, const char *convLink, time_t timestamp, char *content) +// incoming message flow +int CSkypeProto::OnReceiveMessage(const char *messageId, const char *from, const char *to, time_t timestamp, char *content, int emoteOffset) { setDword("LastMsgTime", timestamp); PROTORECVEVENT recv = { 0 }; recv.flags = PREF_UTF; recv.timestamp = timestamp; - recv.szMessage = content; + recv.szMessage = &content[emoteOffset]; + recv.lParam = emoteOffset == 0 + ? EVENTTYPE_MESSAGE + : SKYPE_DB_EVENT_TYPE_ACTION; + recv.pCustomData = (void*)messageId; + recv.cbCustomDataSize = mir_strlen(messageId); ptrA skypename(ContactUrlToName(from)); debugLogA("Incoming message from %s", skypename); if (IsMe(skypename)) { recv.flags |= PREF_SENT; - MCONTACT hContact = GetContact(ContactUrlToName(convLink)); + MCONTACT hContact = GetContact(ptrA(ContactUrlToName(to))); return ProtoChainRecvMsg(hContact, &recv); } MCONTACT hContact = GetContact(skypename); return ProtoChainRecvMsg(hContact, &recv); } +// writing message/even into db +int CSkypeProto::SaveMessageToDb(MCONTACT hContact, PROTORECVEVENT *pre) +{ + //return Proto_RecvMessage(hContact, pre); + if (pre->szMessage == NULL) + return NULL; + + DBEVENTINFO dbei = { sizeof(dbei) }; + dbei.szModule = GetContactProto(hContact); + dbei.timestamp = pre->timestamp; + dbei.flags = DBEF_UTF; + dbei.eventType = pre->lParam; + dbei.cbBlob = (DWORD)strlen(pre->szMessage) + 1; + dbei.pBlob = (PBYTE)pre->szMessage; + + return (INT_PTR)db_event_add(hContact, &dbei); +} + /* MESSAGE SENDING */ struct SendMessageParam { MCONTACT hContact; HANDLE hMessage; + char *clientMsgId; }; // outcoming message flow @@ -42,9 +66,11 @@ int CSkypeProto::OnSendMessage(MCONTACT hContact, int flags, const char *szMessa return 0; } + CMStringA clientMsgId(FORMAT, "%d000", time(NULL)); SendMessageParam *param = new SendMessageParam(); param->hContact = hContact; param->hMessage = (HANDLE)hMessage; + param->clientMsgId = mir_strdup(clientMsgId); ptrA message; if (flags & PREF_UNICODE) @@ -57,7 +83,11 @@ int CSkypeProto::OnSendMessage(MCONTACT hContact, int flags, const char *szMessa ptrA server(getStringA("Server")); ptrA token(getStringA("registrationToken")); ptrA username(getStringA(hContact, "Skypename")); - PushRequest(new SendMsgRequest(token, username, message, server), &CSkypeProto::OnMessageSent, param); + if (strncmp(message, "/me ", 4) == 0) + { + // TODO: make /me action send when it will work in skype web + } + PushRequest(new SendMsgRequest(token, username, clientMsgId, message, server), &CSkypeProto::OnMessageSent, param); return hMessage; } @@ -67,9 +97,10 @@ void CSkypeProto::OnMessageSent(const NETLIBHTTPREQUEST *response, void *arg) SendMessageParam *param = (SendMessageParam*)arg; MCONTACT hContact = param->hContact; HANDLE hMessage = param->hMessage; + ptrA clientMsgId(param->clientMsgId); delete param; - if (response->resultCode != 200 || response->resultCode != 201) + if (response->resultCode != 200 && response->resultCode != 201) { CMStringA error = "Unknown error"; if (response) @@ -87,6 +118,29 @@ void CSkypeProto::OnMessageSent(const NETLIBHTTPREQUEST *response, void *arg) ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, hMessage, 0); } +// preparing message/action to writing into db +int CSkypeProto::OnPreCreateMessage(WPARAM, LPARAM lParam) +{ + MessageWindowEvent *evt = (MessageWindowEvent*)lParam; + if (mir_strcmp(GetContactProto(evt->hContact), m_szModuleName)) + return 0; + + char *message = (char*)evt->dbei->pBlob; + if (strncmp(message, "/me ", 4) == 0) + { + evt->dbei->cbBlob = evt->dbei->cbBlob - 4; + PBYTE action = (PBYTE)mir_alloc(evt->dbei->cbBlob); + memcpy(action, &evt->dbei->pBlob[4], evt->dbei->cbBlob); + mir_free(evt->dbei->pBlob); + evt->dbei->pBlob = action; + evt->dbei->eventType = SKYPE_DB_EVENT_TYPE_ACTION; + } + + return 1; +} + +/* HISTORY SYNC */ + void CSkypeProto::OnGetServerHistory(const NETLIBHTTPREQUEST *response) { if (response == NULL) @@ -110,6 +164,9 @@ void CSkypeProto::OnGetServerHistory(const NETLIBHTTPREQUEST *response) ptrA conversationLink(mir_t2a(ptrT(json_as_string(json_get(message, "conversationLink"))))); time_t timestamp = IsoToUnixTime(composeTime); if (conversationLink != NULL && strstr(conversationLink, "/8:")) - OnReceiveMessage(from, conversationLink, timestamp, content); + { + int emoteOffset = json_as_int(json_get(message, "skypeemoteoffset")); + OnReceiveMessage(clientMsgId, from, conversationLink, timestamp, content, emoteOffset); + } } } \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_poll_processing.cpp b/protocols/SkypeWeb/src/skype_poll_processing.cpp index e2f0f6c0de..9f0cc24fa1 100644 --- a/protocols/SkypeWeb/src/skype_poll_processing.cpp +++ b/protocols/SkypeWeb/src/skype_poll_processing.cpp @@ -76,13 +76,13 @@ void CSkypeProto::ProcessUserPresenceRes(JSONNODE *node) void CSkypeProto::ProcessNewMessageRes(JSONNODE *node) { ptrA clientMsgId(mir_t2a(ptrT(json_as_string(json_get(node, "clientmessageid"))))); - ptrA skypeeditedid(mir_t2a(ptrT(json_as_string(json_get(node, "skypeeditedid"))))); - ptrA messagetype(mir_t2a(ptrT(json_as_string(json_get(node, "messagetype"))))); + ptrA skypeEditedId(mir_t2a(ptrT(json_as_string(json_get(node, "skypeeditedid"))))); + ptrA messageType(mir_t2a(ptrT(json_as_string(json_get(node, "messagetype"))))); ptrA from(mir_t2a(ptrT(json_as_string(json_get(node, "from"))))); ptrA content(mir_t2a(ptrT(json_as_string(json_get(node, "content"))))); - TCHAR *composeTime = json_as_string (json_get(node, "composetime")); + ptrT composeTime(json_as_string (json_get(node, "composetime"))); ptrA conversationLink(mir_t2a(ptrT(json_as_string(json_get(node, "conversationLink"))))); - time_t timeStamp = IsoToUnixTime(composeTime); + time_t timestamp = IsoToUnixTime(composeTime); char *convname; if (strstr(conversationLink, "/19:")) { @@ -93,21 +93,22 @@ void CSkypeProto::ProcessNewMessageRes(JSONNODE *node) } else if (strstr(conversationLink, "/8:")) { - if (!mir_strcmpi(messagetype, "Control/Typing")) + if (!mir_strcmpi(messageType, "Control/Typing")) { MCONTACT hContact = GetContact(ContactUrlToName(from)); CallService(MS_PROTO_CONTACTISTYPING, hContact, 5); } - else if (!mir_strcmpi(messagetype, "Control/ClearTyping")) + else if (!mir_strcmpi(messageType, "Control/ClearTyping")) { MCONTACT hContact = GetContact(ContactUrlToName(from)); CallService(MS_PROTO_CONTACTISTYPING, hContact, 0); } - else if (!mir_strcmpi(messagetype, "Text") || !mir_strcmpi(messagetype, "RichText")) + else if (!mir_strcmpi(messageType, "Text") || !mir_strcmpi(messageType, "RichText")) { - OnReceiveMessage(from, conversationLink, timeStamp, content); + int emoteOffset = json_as_int(json_get(node, "skypeemoteoffset")); + OnReceiveMessage(clientMsgId, from, conversationLink, timestamp, content, emoteOffset); } - else if (!mir_strcmpi(messagetype, "Event/SkypeVideoMessage")) + else if (!mir_strcmpi(messageType, "Event/SkypeVideoMessage")) { return; //not supported } diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index eb420ad998..f7ceb14f7c 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -104,6 +104,11 @@ HWND CSkypeProto::SearchAdvanced(HWND owner) { return 0; } HWND CSkypeProto::CreateExtendedSearchUI(HWND owner) { return 0; } +int CSkypeProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre) +{ + return SaveMessageToDb(hContact, pre); +} + int CSkypeProto::RecvContacts(MCONTACT, PROTORECVEVENT*) { return 0; } int CSkypeProto::RecvFile(MCONTACT hContact, PROTOFILEEVENT *pre) { return 0; } diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index 1be152508d..6de26e05d5 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -43,6 +43,7 @@ public: virtual HWND __cdecl SearchAdvanced(HWND owner); virtual HWND __cdecl CreateExtendedSearchUI(HWND owner); + virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre); virtual int __cdecl RecvContacts(MCONTACT hContact, PROTORECVEVENT*); virtual int __cdecl RecvFile(MCONTACT hContact, PROTOFILEEVENT*); virtual int __cdecl RecvUrl(MCONTACT hContact, PROTORECVEVENT*); @@ -173,17 +174,22 @@ private: int __cdecl OnContactDeleted(MCONTACT, LPARAM); // messages - int OnReceiveMessage(const char *from, const char *convLink, time_t timestamp, char *content); + int OnReceiveMessage(const char *messageId, const char *from, const char *to, time_t timestamp, char *content, int emoteOffset = 0); + int SaveMessageToDb(MCONTACT hContact, PROTORECVEVENT *pre); + int OnSendMessage(MCONTACT hContact, int flags, const char *message); - void __cdecl CSkypeProto::SendMsgThread(void *arg); void OnMessageSent(const NETLIBHTTPREQUEST *response, void *arg); + int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam); + void OnGetServerHistory(const NETLIBHTTPREQUEST *response); + //polling void __cdecl ParsePollData(JSONNODE *data); void __cdecl PollingThread(void*); void CSkypeProto::ProcessEndpointPresenceRes(JSONNODE *node); void CSkypeProto::ProcessUserPresenceRes(JSONNODE *node); void CSkypeProto::ProcessNewMessageRes(JSONNODE *node); + // utils bool IsOnline(); time_t __stdcall IsoToUnixTime(const TCHAR *stamp); diff --git a/protocols/SkypeWeb/src/version.h b/protocols/SkypeWeb/src/version.h index 6af653b5c6..e84c003545 100644 --- a/protocols/SkypeWeb/src/version.h +++ b/protocols/SkypeWeb/src/version.h @@ -7,7 +7,7 @@ #define __PLUGIN_NAME "Skype protocol (Web)" #define __FILENAME "SkypeWeb.dll" -#define __DESCRIPTION "Skype protocol support for Miranda NG. Based on new Skype for Web API." +#define __DESCRIPTION "Skype protocol support for Miranda NG. Based on new Skype for Web." #define __AUTHOR "Miranda NG Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/p/SkypeWeb/" -- cgit v1.2.3