From c84b27ebb4eaa5327c601f0b504249bf061ef3b5 Mon Sep 17 00:00:00 2001 From: aunsane Date: Thu, 16 Mar 2017 00:08:16 +0300 Subject: Slack: added im message send --- protocols/Slack/Slack.vcxproj.filters | 230 +------------------------------ protocols/Slack/src/api/api_chat.h | 34 +++++ protocols/Slack/src/api/api_im.h | 18 +++ protocols/Slack/src/slack_accounts.cpp | 4 +- protocols/Slack/src/slack_connection.cpp | 9 +- protocols/Slack/src/slack_contacts.cpp | 2 +- protocols/Slack/src/slack_messages.cpp | 79 ++++++++++- protocols/Slack/src/slack_options.cpp | 23 +--- protocols/Slack/src/slack_options.h | 14 -- protocols/Slack/src/slack_proto.cpp | 25 +++- protocols/Slack/src/slack_proto.h | 31 +++-- protocols/Slack/src/slack_requests.cpp | 18 +-- protocols/Slack/src/slack_utils.cpp | 5 - protocols/Slack/src/stdafx.h | 2 + 14 files changed, 195 insertions(+), 299 deletions(-) create mode 100644 protocols/Slack/src/api/api_chat.h create mode 100644 protocols/Slack/src/api/api_im.h (limited to 'protocols') diff --git a/protocols/Slack/Slack.vcxproj.filters b/protocols/Slack/Slack.vcxproj.filters index 2d048d8f94..8f90aeb3d5 100644 --- a/protocols/Slack/Slack.vcxproj.filters +++ b/protocols/Slack/Slack.vcxproj.filters @@ -1,232 +1,4 @@  - - - Source Files - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - Source Files - - - - - - - - - - - - - - - Header Files - - - - - - - - - Header Files - - - - - - - - - Header Files - - - - - - - - - Header Files - - - - - - - - - Header Files - - - - - - - - - Header Files - - - - - - - - - Header Files - - - - - - - - - - - Resource Files - - - - Resource Files - - - - - - Resource Files - - - \ No newline at end of file + diff --git a/protocols/Slack/src/api/api_chat.h b/protocols/Slack/src/api/api_chat.h new file mode 100644 index 0000000000..434b612943 --- /dev/null +++ b/protocols/Slack/src/api/api_chat.h @@ -0,0 +1,34 @@ +#ifndef _SLACK_API_CHAT_H_ +#define _SLACK_API_CHAT_H_ + +class SendMessageRequest : public HttpRequest +{ +public: + SendMessageRequest(const char *token, const char *channel, const char *message) : + HttpRequest(HttpMethod::HttpPost, SLACK_API_URL "/chat.postMessage") + { + Headers + << CHAR_VALUE("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + Content + << CHAR_VALUE("token", token) + << CHAR_VALUE("channel", channel) + << CHAR_VALUE("text", message); + } +}; + +class SendActionRequest : public HttpRequest +{ +public: + SendActionRequest(const char *token, const char *channel, const char *message) : + HttpRequest(HttpMethod::HttpPost, SLACK_API_URL "/chat.meMessage") + { + Headers + << CHAR_VALUE("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + Content + << CHAR_VALUE("token", token) + << CHAR_VALUE("channel", channel) + << CHAR_VALUE("text", message); + } +}; + +#endif //_SLACK_API_CHAT_H_ \ No newline at end of file diff --git a/protocols/Slack/src/api/api_im.h b/protocols/Slack/src/api/api_im.h new file mode 100644 index 0000000000..ae4076a788 --- /dev/null +++ b/protocols/Slack/src/api/api_im.h @@ -0,0 +1,18 @@ +#ifndef _SLACK_API_IM_H_ +#define _SLACK_API_IM_H_ + +class OpenImChannelRequest : public HttpRequest +{ +public: + OpenImChannelRequest(const char *token, const char *user) : + HttpRequest(HttpMethod::HttpPost, SLACK_API_URL "/im.open") + { + Headers + << CHAR_VALUE("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + Content + << CHAR_VALUE("token", token) + << CHAR_VALUE("user", user); + } +}; + +#endif //_SLACK_API_IM_H_ \ No newline at end of file diff --git a/protocols/Slack/src/slack_accounts.cpp b/protocols/Slack/src/slack_accounts.cpp index 1887c9fc95..50640ae37a 100644 --- a/protocols/Slack/src/slack_accounts.cpp +++ b/protocols/Slack/src/slack_accounts.cpp @@ -37,7 +37,7 @@ int CSlackProto::OnAccountLoaded(WPARAM, LPARAM) return 0; } -INT_PTR CSlackProto::OnAccountManagerInit(WPARAM, LPARAM lParam) +INT_PTR CSlackProto::OnAccountManagerInit(WPARAM, LPARAM) { - return (INT_PTR)(CSlackOptionsMain::CreateAccountManagerPage(this, (HWND)lParam))->GetHwnd(); + return NULL;// (INT_PTR)(CSlackOptionsMain::CreateAccountManagerPage(this, (HWND)lParam))->GetHwnd(); } \ No newline at end of file diff --git a/protocols/Slack/src/slack_connection.cpp b/protocols/Slack/src/slack_connection.cpp index b8b0652618..0cbb73992a 100644 --- a/protocols/Slack/src/slack_connection.cpp +++ b/protocols/Slack/src/slack_connection.cpp @@ -1,5 +1,10 @@ #include "stdafx.h" +bool CSlackProto::IsOnline() +{ + return !isTerminated && m_iStatus > ID_STATUS_OFFLINE; +} + void CSlackProto::Login() { ptrA token(getStringA("TokenSecret")); @@ -29,7 +34,7 @@ void CSlackProto::Login() PushRequest(request, &CSlackProto::OnAuthorize); } -void CSlackProto::OnAuthorize(JSONNode &root) +void CSlackProto::OnAuthorize(JSONNode &root, void*) { if (!root) { @@ -56,7 +61,7 @@ void CSlackProto::OnAuthorize(JSONNode &root) CMStringW teamName = root["team_name"].as_mstring(); setWString("TeamName", teamName); - if (!teamName.IsEmpty() > 0 && !Clist_GroupExists(teamName)) + if (!teamName.IsEmpty() && !Clist_GroupExists(teamName)) Clist_GroupCreate(0, teamName); json_string teamId = root["team_id"].as_string(); diff --git a/protocols/Slack/src/slack_contacts.cpp b/protocols/Slack/src/slack_contacts.cpp index 185d5110b8..5054e6003c 100644 --- a/protocols/Slack/src/slack_contacts.cpp +++ b/protocols/Slack/src/slack_contacts.cpp @@ -94,7 +94,7 @@ void CSlackProto::OnGotUserProfile(MCONTACT hContact, JSONNode &root) setWString(hContact, "LastName", lastName); } -void CSlackProto::OnGotUserList(JSONNode &root) +void CSlackProto::OnGotUserList(JSONNode &root, void*) { if (!root) { diff --git a/protocols/Slack/src/slack_messages.cpp b/protocols/Slack/src/slack_messages.cpp index f78ba3e9db..012e9451de 100644 --- a/protocols/Slack/src/slack_messages.cpp +++ b/protocols/Slack/src/slack_messages.cpp @@ -26,9 +26,84 @@ int CSlackProto::OnReceiveMessage(MCONTACT hContact, PROTORECVEVENT *pre) /* MESSAGE SENDING */ // outcoming message flow -int CSlackProto::OnSendMessage(MCONTACT hContact, int flags, const char *szMessage) +void CSlackProto::OnMessageSent(JSONNode &root, void *arg) { - return 0; + SendMessageParam *param = (SendMessageParam*)arg; + + if (!root) + { + ProtoBroadcastAck(param->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)param->hMessage, (LPARAM)Translate("Unable to send message.")); + return; + } + + bool isOk = root["ok"].as_bool(); + if (!isOk) + { + json_string error = root["error"].as_string(); + debugLogA(__FUNCTION__": %s", error); + ProtoBroadcastAck(param->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)param->hMessage, (LPARAM)error.c_str()); + return; + } + + ProtoBroadcastAck(param->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)param->hMessage, 0); +} + +void CSlackProto::OnImChannelOppened(JSONNode &root, void *arg) +{ + SendMessageParam *param = (SendMessageParam*)arg; + + if (!root) + { + ProtoBroadcastAck(param->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)param->hMessage, (LPARAM)Translate("Unable to open im channel.")); + mir_free(param->message); + mir_free(param); + return; + } + + bool isOk = root["ok"].as_bool(); + if (!isOk) + { + json_string error = root["error"].as_string(); + debugLogA(__FUNCTION__": %s", error); + ProtoBroadcastAck(param->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)param->hMessage, (LPARAM)error.c_str()); + mir_free(param->message); + mir_free(param); + return; + } + + JSONNode channel = root["channel"].as_node(); + json_string channelId = channel["id"].as_string(); + + ptrA token(getStringA("TokenSecret")); + + char *message = param->message; + HttpRequest *request; + if (mir_strncmpi(message, "/me ", 4) == 0) + { + message += 4; + request = new SendActionRequest(token, channelId.c_str(), message); + } + else + request = new SendMessageRequest(token, channelId.c_str(), message); + + SendRequest(request, &CSlackProto::OnMessageSent, param); +} + +void CSlackProto::SendMessageThread(void *arg) +{ + Thread_SetName("SLACK: SendMessageThread"); + + SendMessageParam *param = (SendMessageParam*)arg; + + ptrA token(getStringA("TokenSecret")); + ptrA user(getStringA(param->hContact, "UserId")); + SendRequest(new OpenImChannelRequest(token, user), &CSlackProto::OnImChannelOppened, param); +} + +void CSlackProto::SendMessageAckThread(void *arg) +{ + Sleep(100); + ProtoBroadcastAck((MCONTACT)arg, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)1, (LPARAM)Translate("You cannot send when you are offline")); } // message is received by the other side diff --git a/protocols/Slack/src/slack_options.cpp b/protocols/Slack/src/slack_options.cpp index 49544935c1..c057017bf4 100644 --- a/protocols/Slack/src/slack_options.cpp +++ b/protocols/Slack/src/slack_options.cpp @@ -1,25 +1,13 @@ #include "stdafx.h" CSlackOptionsMain::CSlackOptionsMain(CSlackProto *proto, int idDialog) - : CSuper(proto, idDialog, false), - m_team(this, IDC_TEAM), m_email(this, IDC_EMAIL), - m_password(this, IDC_PASSWORD), m_group(this, IDC_GROUP) + : CSuper(proto, idDialog, false) { - - CreateLink(m_team, "Team", L""); - CreateLink(m_email, "Email", L""); - CreateLink(m_password, "Password", L""); - CreateLink(m_group, "DefaultGroup", _A2W(MODULE)); } void CSlackOptionsMain::OnInitDialog() { CSuper::OnInitDialog(); - - SendMessage(m_team.GetHwnd(), EM_LIMITTEXT, 21, 0); - SendMessage(m_email.GetHwnd(), EM_LIMITTEXT, 40, 0); - SendMessage(m_password.GetHwnd(), EM_LIMITTEXT, 40, 0); - SendMessage(m_group.GetHwnd(), EM_LIMITTEXT, 64, 0); } void CSlackOptionsMain::OnApply() @@ -30,14 +18,5 @@ void CSlackOptionsMain::OnApply() int CSlackProto::OnOptionsInit(WPARAM wParam, LPARAM) { - OPTIONSDIALOGPAGE odp = { 0 }; - odp.szTitle.w = m_tszUserName; - odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE | ODPF_DONTTRANSLATE; - odp.szGroup.w = LPGENW("Network"); - - odp.szTab.w = LPGENW("Account"); - odp.pDialog = CSlackOptionsMain::CreateOptionsPage(this); - //Options_AddPage(wParam, &odp); - return 0; } diff --git a/protocols/Slack/src/slack_options.h b/protocols/Slack/src/slack_options.h index e0eeda70a3..5d0356f8b7 100644 --- a/protocols/Slack/src/slack_options.h +++ b/protocols/Slack/src/slack_options.h @@ -6,10 +6,6 @@ class CSlackOptionsMain : public CProtoDlgBase typedef CProtoDlgBase CSuper; private: - CCtrlEdit m_team; - CCtrlEdit m_email; - CCtrlEdit m_password; - CCtrlEdit m_group; protected: void OnInitDialog(); @@ -17,16 +13,6 @@ protected: public: CSlackOptionsMain(CSlackProto *proto, int idDialog); - - static CDlgBase *CreateAccountManagerPage(void *param, HWND owner) - { - CSlackOptionsMain *page = new CSlackOptionsMain((CSlackProto*)param, IDD_ACCOUNT_MANAGER); - page->SetParent(owner); - page->Show(); - return page; - } - - static CDlgBase *CreateOptionsPage(void *param) { return new CSlackOptionsMain((CSlackProto*)param, IDD_OPTIONS_MAIN); } }; #endif //_SLACK_OPTIONS_H_ diff --git a/protocols/Slack/src/slack_proto.cpp b/protocols/Slack/src/slack_proto.cpp index 8a37838c28..e3731794d4 100644 --- a/protocols/Slack/src/slack_proto.cpp +++ b/protocols/Slack/src/slack_proto.cpp @@ -1,7 +1,8 @@ #include "stdafx.h" CSlackProto::CSlackProto(const char* protoName, const TCHAR* userName) : - PROTO(protoName, userName), requestQueue(1) + PROTO(protoName, userName), requestQueue(1), + hMessageProcess(1) { InitNetlib(); @@ -20,11 +21,11 @@ DWORD_PTR CSlackProto::GetCaps(int type, MCONTACT) switch (type) { case PFLAGNUM_1: - return PF1_IM; + return PF1_IMSEND; case PFLAGNUM_2: - return PF2_ONLINE | PF2_LONGAWAY; + return PF2_ONLINE; case PFLAGNUM_3: - return PF2_ONLINE | PF2_LONGAWAY; + return PF2_ONLINE; case PFLAG_UNIQUEIDTEXT: return (INT_PTR)"User Id"; case PFLAG_UNIQUEIDSETTING: @@ -57,7 +58,21 @@ int CSlackProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre) int CSlackProto::SendMsg(MCONTACT hContact, int flags, const char *msg) { - return OnSendMessage(hContact, flags, msg); + if (!IsOnline()) + { + ForkThread(&CSlackProto::SendMessageAckThread, (void*)hContact); + return 1; + } + + UINT hMessage = InterlockedIncrement(&hMessageProcess); + + SendMessageParam *param = (SendMessageParam*)mir_calloc(sizeof(SendMessageParam)); + param->hContact = hContact; + param->hMessage = hMessage; + param->message = mir_strdup(msg); + ForkThread(&CSlackProto::SendMessageThread, param); + + return hMessage; } int CSlackProto::SetStatus(int iNewStatus) diff --git a/protocols/Slack/src/slack_proto.h b/protocols/Slack/src/slack_proto.h index f47c70f946..25b667eea2 100644 --- a/protocols/Slack/src/slack_proto.h +++ b/protocols/Slack/src/slack_proto.h @@ -6,13 +6,21 @@ struct CSlackProto : public PROTO friend class CSlackOptionsMain; friend class CSlackOAuth; - typedef void(CSlackProto::*HttpCallback)(HttpResponse&); - typedef void(CSlackProto::*JsonCallback)(JSONNode&); + typedef void(CSlackProto::*HttpCallback)(HttpResponse&, void*); + typedef void(CSlackProto::*JsonCallback)(JSONNode&, void*); struct RequestQueueItem { HttpRequest *request; HttpCallback httpCallback; JsonCallback jsonCallback; + void *param; + }; + + struct SendMessageParam + { + MCONTACT hContact; + UINT hMessage; + char *message; }; public: @@ -60,14 +68,15 @@ private: HANDLE hRequestsQueueEvent; HANDLE hRequestQueueThread; LIST requestQueue; + ULONG hMessageProcess; // requests void SendRequest(HttpRequest *request); - void SendRequest(HttpRequest *request, HttpCallback callback); - void SendRequest(HttpRequest *request, JsonCallback callback); + void SendRequest(HttpRequest *request, HttpCallback callback, void *param = NULL); + void SendRequest(HttpRequest *request, JsonCallback callback, void *param = NULL); void PushRequest(HttpRequest *request); - void PushRequest(HttpRequest *request, HttpCallback callback); - void PushRequest(HttpRequest *request, JsonCallback callback); + void PushRequest(HttpRequest *request, HttpCallback callback, void *param = NULL); + void PushRequest(HttpRequest *request, JsonCallback callback, void *param = NULL); void __cdecl RequestQueueThread(void*); // network @@ -90,7 +99,7 @@ private: // login void Login(); void LogOut(); - void OnAuthorize(JSONNode &root); + void OnAuthorize(JSONNode &root, void*); // icons static IconItemT Icons[]; @@ -114,7 +123,7 @@ private: void OnGotUserProfile(JSONNode &root); void OnGotUserProfile(MCONTACT hContact, JSONNode &root); - void OnGotUserList(JSONNode &root); + void OnGotUserList(JSONNode &root, void*); INT_PTR __cdecl OnRequestAuth(WPARAM hContact, LPARAM lParam); INT_PTR __cdecl OnGrantAuth(WPARAM hContact, LPARAM); @@ -123,7 +132,11 @@ private: // messages int OnReceiveMessage(MCONTACT hContact, PROTORECVEVENT *pre); - int OnSendMessage(MCONTACT hContact, int flags, const char *message); + + void OnMessageSent(JSONNode &root, void *arg); + void OnImChannelOppened(JSONNode &root, void *arg); + void __cdecl SendMessageThread(void*); + void __cdecl SendMessageAckThread(void*); int OnUserIsTyping(MCONTACT hContact, int type); diff --git a/protocols/Slack/src/slack_requests.cpp b/protocols/Slack/src/slack_requests.cpp index 7fd0ef4805..ad99b198a3 100644 --- a/protocols/Slack/src/slack_requests.cpp +++ b/protocols/Slack/src/slack_requests.cpp @@ -7,23 +7,23 @@ void CSlackProto::SendRequest(HttpRequest *request) delete request; } -void CSlackProto::SendRequest(HttpRequest *request, HttpCallback callback) +void CSlackProto::SendRequest(HttpRequest *request, HttpCallback callback, void *param) { NETLIBHTTPREQUEST *pResp = Netlib_HttpTransaction(m_hNetlibUser, (NETLIBHTTPREQUEST*)request); HttpResponse response(request, pResp); if (callback) - (this->*callback)(response); + (this->*callback)(response, param); delete request; } -void CSlackProto::SendRequest(HttpRequest *request, JsonCallback callback) +void CSlackProto::SendRequest(HttpRequest *request, JsonCallback callback, void *param) { NETLIBHTTPREQUEST *pResp = Netlib_HttpTransaction(m_hNetlibUser, (NETLIBHTTPREQUEST*)request); HttpResponse response(request, pResp); if (callback) { JSONNode root = JSONNode::parse(response.Content); - (this->*callback)(root); + (this->*callback)(root, param); } delete request; } @@ -39,11 +39,12 @@ void CSlackProto::PushRequest(HttpRequest *request) SetEvent(hRequestsQueueEvent); } -void CSlackProto::PushRequest(HttpRequest *request, HttpCallback callback) +void CSlackProto::PushRequest(HttpRequest *request, HttpCallback callback, void *param) { RequestQueueItem *item = new RequestQueueItem(); item->request = request; item->httpCallback = callback; + item->param = param; { mir_cslock lock(requestQueueLock); requestQueue.insert(item); @@ -51,11 +52,12 @@ void CSlackProto::PushRequest(HttpRequest *request, HttpCallback callback) SetEvent(hRequestsQueueEvent); } -void CSlackProto::PushRequest(HttpRequest *request, JsonCallback callback) +void CSlackProto::PushRequest(HttpRequest *request, JsonCallback callback, void *param) { RequestQueueItem *item = new RequestQueueItem(); item->request = request; item->jsonCallback = callback; + item->param = param; { mir_cslock lock(requestQueueLock); requestQueue.insert(item); @@ -81,9 +83,9 @@ void CSlackProto::RequestQueueThread(void*) requestQueue.remove(0); } if (item->httpCallback) - SendRequest(item->request, item->httpCallback); + SendRequest(item->request, item->httpCallback, item->param); else if (item->jsonCallback) - SendRequest(item->request, item->jsonCallback); + SendRequest(item->request, item->jsonCallback, item->param); else SendRequest(item->request); delete item; diff --git a/protocols/Slack/src/slack_utils.cpp b/protocols/Slack/src/slack_utils.cpp index bd40f58ee7..40a6680788 100644 --- a/protocols/Slack/src/slack_utils.cpp +++ b/protocols/Slack/src/slack_utils.cpp @@ -1,10 +1,5 @@ #include "stdafx.h" -bool CSlackProto::IsOnline() -{ - return false; -} - void CSlackProto::ShowNotification(const TCHAR *caption, const TCHAR *message, int flags, MCONTACT hContact) { if (Miranda_IsTerminated()) diff --git a/protocols/Slack/src/stdafx.h b/protocols/Slack/src/stdafx.h index ce5ebf1a80..8a24cb29f7 100644 --- a/protocols/Slack/src/stdafx.h +++ b/protocols/Slack/src/stdafx.h @@ -52,6 +52,8 @@ struct CSlackProto; #include "slack_proto.h" #include "api\api_users.h" +#include "api\api_chat.h" +#include "api\api_im.h" extern HINSTANCE g_hInstance; -- cgit v1.2.3