summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/VKontakte/res/resource.rc5
-rw-r--r--protocols/VKontakte/src/resource.h8
-rw-r--r--protocols/VKontakte/src/version.h2
-rw-r--r--protocols/VKontakte/src/vk_options.cpp18
-rw-r--r--protocols/VKontakte/src/vk_proto.cpp24
-rw-r--r--protocols/VKontakte/src/vk_proto.h10
-rw-r--r--protocols/VKontakte/src/vk_thread.cpp171
7 files changed, 224 insertions, 14 deletions
diff --git a/protocols/VKontakte/res/resource.rc b/protocols/VKontakte/res/resource.rc
index 4b70ce0494..3f305ca6cc 100644
--- a/protocols/VKontakte/res/resource.rc
+++ b/protocols/VKontakte/res/resource.rc
@@ -54,6 +54,11 @@ BEGIN
CONTROL "Hide chats on startup",IDC_HIDECHATS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,134,278,10
CONTROL "Automatically wipe local contacts missing in your Friends list",IDC_AUTOCLEAN,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,148,278,10
+ CONTROL "Always notify as unread for all incoming message",IDC_MESASUREAD,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,162,278,10
+ CONTROL "Mark read on reply",IDC_MARKREADONREPLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,176,278,10
+ CONTROL "Automatically sync last messages ",IDC_SYNCHISTOTYONONLINE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,190,278,10
END
IDD_CAPTCHAFORM DIALOGEX 0, 0, 258, 224
diff --git a/protocols/VKontakte/src/resource.h b/protocols/VKontakte/src/resource.h
index 8eaf42c489..a05f84ae78 100644
--- a/protocols/VKontakte/src/resource.h
+++ b/protocols/VKontakte/src/resource.h
@@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by D:\Myranda\protocols\VKontakte\res\resource.rc
+// Used by d:\svn\protocols\VKontakte\res\resource.rc
//
#define IDD_ACCMGRUI 101
#define IDD_CAPTCHAFORM 102
@@ -24,6 +24,10 @@
#define IDC_HIDECHATS 1014
#define IDC_CONTACT 1015
#define IDC_AUTOCLEAN 1020
+#define IDC_MESASUREAD 1025
+#define IDC_MARKREADONREPLY 1026
+#define IDC_SYNCHISTOTYONONLINE 1027
+
// Next default values for new objects
//
@@ -32,7 +36,7 @@
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1021
+#define _APS_NEXT_CONTROL_VALUE 1030
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/protocols/VKontakte/src/version.h b/protocols/VKontakte/src/version.h
index d27d6162d7..c5f142ecb8 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 0
-#define __BUILD_NUM 11
+#define __BUILD_NUM 12
#include <stdver.h>
diff --git a/protocols/VKontakte/src/vk_options.cpp b/protocols/VKontakte/src/vk_options.cpp
index 2a270e7005..46fc46a137 100644
--- a/protocols/VKontakte/src/vk_options.cpp
+++ b/protocols/VKontakte/src/vk_options.cpp
@@ -121,6 +121,9 @@ INT_PTR CALLBACK CVkProto::OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, L
CheckDlgButton(hwndDlg, IDC_DELIVERY, ppro->m_bServerDelivery);
CheckDlgButton(hwndDlg, IDC_HIDECHATS, ppro->m_bHideChats);
CheckDlgButton(hwndDlg, IDC_AUTOCLEAN, ppro->getByte("AutoClean", 0));
+ CheckDlgButton(hwndDlg, IDC_MESASUREAD, ppro->m_bMesAsUnread);
+ CheckDlgButton(hwndDlg, IDC_MARKREADONREPLY, ppro->m_bMarkReadOnReply);
+ CheckDlgButton(hwndDlg, IDC_SYNCHISTOTYONONLINE, ppro->m_bAutoSyncHistory);
return TRUE;
case WM_COMMAND:
@@ -139,6 +142,9 @@ INT_PTR CALLBACK CVkProto::OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, L
case IDC_DELIVERY:
case IDC_HIDECHATS:
case IDC_AUTOCLEAN:
+ case IDC_MESASUREAD:
+ case IDC_MARKREADONREPLY:
+ case IDC_SYNCHISTOTYONONLINE:
if (HIWORD(wParam) == BN_CLICKED && (HWND)lParam == GetFocus())
SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
break;
@@ -156,7 +162,7 @@ INT_PTR CALLBACK CVkProto::OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, L
ppro->setGroup(str);
ppro->setTString("ProtoGroup", str);
}
-
+
GetDlgItemText(hwndDlg, IDC_PASSWORD, str, SIZEOF(str));
ptrA szRawPasswd(mir_utf8encodeT(str));
if (szRawPasswd != NULL)
@@ -169,6 +175,16 @@ INT_PTR CALLBACK CVkProto::OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, L
ppro->setByte("HideChats", ppro->m_bHideChats);
ppro->setByte("AutoClean", IsDlgButtonChecked(hwndDlg, IDC_AUTOCLEAN) == BST_CHECKED);
+
+ ppro->m_bMesAsUnread = IsDlgButtonChecked(hwndDlg, IDC_MESASUREAD) == BST_CHECKED;
+ ppro->setByte("MesAsUnread", ppro->m_bMesAsUnread);
+
+ ppro->m_bMarkReadOnReply = IsDlgButtonChecked(hwndDlg, IDC_MARKREADONREPLY) == BST_CHECKED;
+ ppro->setByte("MarkReadOnReply", ppro->m_bMarkReadOnReply);
+
+ ppro->m_bAutoSyncHistory = IsDlgButtonChecked(hwndDlg, IDC_SYNCHISTOTYONONLINE) == BST_CHECKED;
+ ppro->setByte("AutoSyncHistory", ppro->m_bAutoSyncHistory);
+
}
break;
diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp
index 6d36ad8d0b..f08e004b08 100644
--- a/protocols/VKontakte/src/vk_proto.cpp
+++ b/protocols/VKontakte/src/vk_proto.cpp
@@ -54,6 +54,9 @@ CVkProto::CVkProto(const char *szModuleName, const TCHAR *ptszUserName) :
m_bServerDelivery = getBool("ServerDelivery", true);
m_bHideChats = getBool("HideChats", true);
+ m_bMesAsUnread = getBool("MesAsUnread", false);
+ m_bMarkReadOnReply = getBool("MarkReadOnReply", false);
+ m_bAutoSyncHistory = getBool("AutoSyncHistory", true);
// Set all contacts offline -- in case we crashed
SetAllContactStatuses(ID_STATUS_OFFLINE);
@@ -91,6 +94,20 @@ int CVkProto::OnModulesLoaded(WPARAM wParam, LPARAM lParam)
mi.icolibItem = LoadSkinnedIconHandle(SKINICON_CHAT_JOIN);
mi.pszName = LPGEN("Create new chat");
Menu_AddProtoMenuItem(&mi);
+
+ //Server History
+ CreateProtoService(PS_GETALLSERVERHISTORY, &CVkProto::SvcGetAllServerHistory);
+
+ mir_snprintf(szService, sizeof(szService), "%s%s", m_szModuleName, PS_GETALLSERVERHISTORY);
+ mi.pszService = szService;
+ mi.pszContactOwner = m_szModuleName;
+ mi.flags = CMIF_TCHAR;
+ mi.position = -200001000+1;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_HISTORY);
+ mi.position = -201001000+102;
+ mi.ptszName = LPGENT("Reload all messages from vk.com");
+ Menu_AddContactMenuItem(&mi);
+
return 0;
}
@@ -201,7 +218,12 @@ void CVkProto::OnSendMessage(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
JSONROOT pRoot;
JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot);
if (pResponse != NULL) {
- m_sendIds.insert((HANDLE)json_as_int(pResponse));
+ UINT mid = json_as_int(pResponse);
+ m_sendIds.insert((HANDLE)mid);
+ if (mid>getDword(param->hContact, "lastmsgid", 0))
+ setDword(param->hContact, "lastmsgid", mid);
+ if (m_bMarkReadOnReply)
+ MarkMessagesRead(param->hContact);
iResult = ACKRESULT_SUCCESS;
}
}
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h
index 2ecdd0001b..e0d0501f96 100644
--- a/protocols/VKontakte/src/vk_proto.h
+++ b/protocols/VKontakte/src/vk_proto.h
@@ -16,6 +16,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define PS_CREATECHAT "/CreateNewChat"
+#define PS_GETALLSERVERHISTORY "/GetAllServerHystory"
+#define MAXHISTORYMIDSPERONE 200
struct CVkProto;
typedef void (CVkProto::*VK_REQUEST_HANDLER)(NETLIBHTTPREQUEST*, struct AsyncHttpRequest*);
@@ -185,6 +187,7 @@ struct CVkProto : public PROTO<CVkProto>
INT_PTR __cdecl SvcCreateAccMgrUI(WPARAM, LPARAM);
INT_PTR __cdecl SvcGetAvatarInfo(WPARAM, LPARAM);
INT_PTR __cdecl SvcGetAvatarCaps(WPARAM, LPARAM);
+ INT_PTR __cdecl SvcGetAllServerHistory(WPARAM wParam, LPARAM);
//==== Misc ==========================================================================
@@ -200,11 +203,14 @@ struct CVkProto : public PROTO<CVkProto>
void OnReceiveFriends(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
void MarkMessagesRead(const CMStringA &mids);
+ void MarkMessagesRead(const MCONTACT hContact);
void RetrieveMessagesByIds(const CMStringA &mids);
void RetrieveUnreadMessages();
void OnReceiveMessages(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
void OnSendMessage(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
-
+ void OnReceiveHistoryMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq);
+ void GetHistoryDlg(MCONTACT hContact, int iLastMsg);
+ void GetHistoryDlgMessages(MCONTACT hContact, int iOffset, int iMaxCount, int lastcount);
void RetrievePollingInfo();
void OnReceivePollingInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
@@ -277,7 +283,7 @@ private:
void __cdecl SendMsgAck(void *param);
- bool m_bOnline, m_bHideChats;
+ bool m_bOnline, m_bHideChats, m_bMesAsUnread, m_bMarkReadOnReply, m_bAutoSyncHistory;
LONG m_myUserId;
ptrA m_szAccessToken;
diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp
index db858501bf..92c7237fb5 100644
--- a/protocols/VKontakte/src/vk_thread.cpp
+++ b/protocols/VKontakte/src/vk_thread.cpp
@@ -375,6 +375,16 @@ void CVkProto::MarkMessagesRead(const CMStringA &mids)
<< CHAR_PARAM("mids", mids));
}
+void CVkProto::MarkMessagesRead(const MCONTACT hContact)
+{
+ LONG userID = getDword(hContact, "ID", -1);
+ if (-1==userID)
+ return;
+
+ Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.markAsRead.json", true, &CVkProto::OnReceiveSmth)
+ << INT_PARAM("peer_id", userID));
+}
+
void CVkProto::RetrieveMessagesByIds(const CMStringA &mids)
{
if (mids.IsEmpty())
@@ -414,9 +424,15 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe
continue;
int chatid = json_as_int(json_get(pDlg, "chat_id"));
- if (chatid != 0)
- if (m_chats.find((CVkChatInfo*)&chatid) == NULL) {
- AppendChat(chatid, pDlg);
+ if (chatid != 0){
+ if (m_chats.find((CVkChatInfo*)&chatid) == NULL)
+ AppendChat(chatid, pDlg);
+ }else if (m_bAutoSyncHistory){
+ int mid = json_as_int(json_get(pDlg, "mid"));
+ int uid = json_as_int(json_get(pDlg, "uid"));
+ MCONTACT hContact = FindUser(uid, true);
+ debugLogA("CVkProto::GetHistoryDlg %d", mid);
+ GetHistoryDlg(hContact, mid);
}
}
}
@@ -436,7 +452,7 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe
if (pMsg == NULL)
continue;
- int mid = json_as_int(json_get(pMsg, "mid"));
+ UINT mid = json_as_int(json_get(pMsg, "mid"));
char szMid[40];
_itoa(mid, szMid, 10);
@@ -473,7 +489,7 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe
PROTORECVEVENT recv = { 0 };
recv.flags = PREF_TCHAR;
- if (isRead)
+ if (isRead&&!m_bMesAsUnread)
recv.flags |= PREF_CREATEREAD;
if (isOut)
recv.flags |= PREF_SENT;
@@ -486,16 +502,132 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe
recv.lParam = isOut;
recv.pCustomData = szMid;
recv.cbCustomDataSize = (int)strlen(szMid);
- if (!CheckMid(mid))
+ Sleep(100);
+ if (!CheckMid(mid)){
ProtoChainRecvMsg(hContact, &recv);
+ if (mid>getDword(hContact, "lastmsgid", -1))
+ setDword(hContact, "lastmsgid", mid);
+ }
}
- MarkMessagesRead(mids);
+ if (!m_bMarkReadOnReply)
+ MarkMessagesRead(mids);
RetrieveMessagesByIds(lmids);
}
/////////////////////////////////////////////////////////////////////////////////////////
+void CVkProto::GetHistoryDlg(MCONTACT hContact, int iLastMsg)
+{
+ int lastmsgid = getDword(hContact, "lastmsgid", -1);
+ if (-1==lastmsgid){
+ setDword(hContact, "lastmsgid", iLastMsg);
+ return;
+ }
+ int maxOffset = iLastMsg - lastmsgid;
+ setDword(hContact, "new_lastmsgid", iLastMsg);
+ GetHistoryDlgMessages (hContact, 0, maxOffset, -1);
+}
+
+void CVkProto::GetHistoryDlgMessages(MCONTACT hContact, int iOffset, int iMaxCount, int lastcount)
+{
+ LONG userID = getDword(hContact, "ID", -1);
+ if (-1==userID)
+ return;
+
+ if ((0==lastcount)||(iMaxCount<1)){
+ setDword(hContact, "lastmsgid", getDword(hContact, "new_lastmsgid", -1));
+ db_unset(hContact, m_szModuleName, "new_lastmsgid");
+ db_unset(hContact, m_szModuleName, "ImportHistory");
+ return;
+ }
+
+ int iReqCount = iMaxCount>MAXHISTORYMIDSPERONE?MAXHISTORYMIDSPERONE:iMaxCount;
+
+ debugLogA("CVkProto::GetHistoryDlgMessages %d %d %d", userID, iOffset, iReqCount);
+ AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.getHistory.json", true, &CVkProto::OnReceiveHistoryMessages)
+ << INT_PARAM("offset", iOffset)
+ << INT_PARAM("count", iReqCount)
+ << INT_PARAM("user_id", userID)
+ << CHAR_PARAM("v", "5.24");
+
+ pReq->pUserInfo = new CVkSendMsgParam(hContact, iOffset);
+ Push(pReq);
+}
+
+void CVkProto::OnReceiveHistoryMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
+{
+ debugLogA("CVkProto::OnReceiveHistoryMessages %d", reply->resultCode);
+ if (reply->resultCode != 200)
+ return;
+
+ JSONROOT pRoot;
+ JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot);
+ if (pResponse == NULL)
+ return;
+
+ CMStringA mids;
+ CVkSendMsgParam *param = (CVkSendMsgParam*)pReq->pUserInfo;
+ int numMessages = json_as_int(json_get(pResponse, "count")),
+ i = 0,
+ lastmsgid = getDword(param->hContact, "lastmsgid", -1),
+ mid = -1;
+
+ JSONNODE *pMsgs = json_get(pResponse, "items");
+
+ int new_lastmsgid = getDword(param->hContact, "new_lastmsgid", -1);
+ int his = getByte(param->hContact, "ImportHistory", 0);
+
+ for (i = 0; i < numMessages; i++) {
+ JSONNODE *pMsg = json_at(pMsgs, i);
+ if (pMsg == NULL)
+ break;
+
+ mid = json_as_int(json_get(pMsg, "id"));
+ if (his&&(-1==new_lastmsgid)){
+ new_lastmsgid = mid;
+ setDword(param->hContact, "new_lastmsgid", mid);
+ }
+ if (mid <= lastmsgid)
+ break;
+
+ char szMid[40];
+ _itoa(mid, szMid, 10);
+
+ ptrT ptszBody(json_as_string(json_get(pMsg, "body")));
+ int datetime = json_as_int(json_get(pMsg, "date"));
+ int isOut = json_as_int(json_get(pMsg, "out"));
+ int isRead = json_as_int(json_get(pMsg, "read_state"));
+ int uid = json_as_int(json_get(pMsg, "user_id"));
+
+ JSONNODE *pAttachments = json_get(pMsg, "attachments");
+ if (pAttachments != NULL)
+ ptszBody = mir_tstrdup(CMString(ptszBody) + GetAttachmentDescr(pAttachments));
+
+ MCONTACT hContact = FindUser(uid, true);
+ PROTORECVEVENT recv = { 0 };
+ recv.flags = PREF_TCHAR;
+ if (isRead)
+ recv.flags |= PREF_CREATEREAD;
+ if (isOut)
+ recv.flags |= PREF_SENT;
+ recv.timestamp = datetime;
+
+ CMStringW szBody = ptszBody;
+ MyHtmlDecode(szBody);
+ recv.tszMessage = szBody.GetBuffer();
+ recv.lParam = isOut;
+ recv.pCustomData = szMid;
+ recv.cbCustomDataSize = (int)strlen(szMid);
+ ProtoChainRecvMsg(hContact, &recv);
+ }
+
+ int inewCount = mid - getDword(param->hContact, "lastmsgid", -1);
+ inewCount = (0>mid)?0:inewCount;
+ GetHistoryDlgMessages(param->hContact, param->iMsgID+i, inewCount, i);
+ delete param;
+}
+
void CVkProto::RetrievePollingInfo()
{
debugLogA("CVkProto::RetrievePollingInfo");
@@ -521,6 +653,31 @@ void CVkProto::OnReceivePollingInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *
m_hPollingThread = ForkThreadEx(&CVkProto::PollingThread, NULL, NULL);
}
+INT_PTR __cdecl CVkProto::SvcGetAllServerHistory(WPARAM wParam, LPARAM)
+{
+ LPCWSTR str = LPGENT("Are you sure to reload all messages from vk.com?\n")
+ LPGENT("Local contact history will be delete and reload from the server.\n")
+ LPGENT("It may take a long time. \nDo you want to continue?");
+ if (IDNO==MessageBox(NULL, str,
+ LPGENT("Attention!"), MB_ICONWARNING|MB_YESNO))
+ return 0;
+
+ LONG userID = getDword((MCONTACT)wParam, "ID", -1);
+ if (-1==userID)
+ return 0;
+
+ setByte((MCONTACT)wParam, "ImportHistory", 1);
+ setDword((MCONTACT)wParam, "lastmsgid", 0);
+
+ while (HANDLE hd = db_event_first((MCONTACT)wParam))
+ db_event_delete((MCONTACT)wParam, hd);
+
+ debugLogA("CVkProto::SvcGetAllServerHistory");
+ GetHistoryDlgMessages((MCONTACT)wParam, 0, INT_MAX, -1);
+ return 1;
+}
+
+
/////////////////////////////////////////////////////////////////////////////////////////
void CVkProto::PollUpdates(JSONNODE *pUpdates)