예제 #1
0
void CVkProto::RetrieveUnreadNews(time_t tLastNewsTime)
{
	debugLogA("CVkProto::RetrieveUnreadNews");
	if (!IsOnline())
		return;

	time_t tLastNewsReqTime = getDword("LastNewsReqTime", time(NULL) - 24 * 60 * 60);
	if (time(NULL) - tLastNewsReqTime < 3 * 60)
		return;
		
	CMStringA szFilter;
	szFilter = m_bNewsFilterPosts ? "post" : "";

	szFilter += szFilter.IsEmpty() ? "" : ",";
	szFilter += m_bNewsFilterPhotos ? "photo" : "";

	szFilter += szFilter.IsEmpty() ? "" : ",";
	szFilter += m_bNewsFilterTags ? "photo_tag" : "";

	szFilter += szFilter.IsEmpty() ? "" : ",";
	szFilter += m_bNewsFilterWallPhotos ? "wall_photo" : "";

	if (szFilter.IsEmpty()) {
		debugLogA("CVkProto::RetrieveUnreadNews szFilter empty");
		return;
	}

	CMStringA szSource;
	szSource = m_bNewsSourceFriends ? "friends" : "";

	szSource += szSource.IsEmpty() ? "" : ",";
	szSource += m_bNewsSourceGroups ? "groups" : "";

	szSource += szSource.IsEmpty() ? "" : ",";
	szSource += m_bNewsSourcePages ? "pages" : "";

	szSource += szSource.IsEmpty() ? "" : ",";
	szSource += m_bNewsSourceFollowing ? "following" : "";

	if (szSource.IsEmpty()) {
		debugLogA("CVkProto::RetrieveUnreadNews szSource empty");
		return;
	}
			
	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/newsfeed.get.json", true, &CVkProto::OnReceiveUnreadNews))
		<< INT_PARAM("count", 100)
		<< INT_PARAM("return_banned", m_bNewsSourceIncludeBanned ? 1 : 0)
		<< INT_PARAM("max_photos", m_iMaxLoadNewsPhoto)
		<< INT_PARAM("start_time", tLastNewsTime + 1)
		<< CHAR_PARAM("filters", szFilter)
		<< CHAR_PARAM("source_ids", szSource)
		<< VER_API;

	setDword("LastNewsReqTime", (DWORD)time(NULL));
}
예제 #2
0
int CVkProto::SendMsg(MCONTACT hContact, int, const char *szMsg)
{
	debugLogA("CVkProto::SendMsg");
	if (!IsOnline())
		return 0;

	bool bIsChat = isChatRoom(hContact);
	LONG iUserID = getDword(hContact, bIsChat ? "vk_chat_id" : "ID" , -1);

	if (iUserID == -1 || iUserID == VK_FEED_USER) {
		ForkThread(&CVkProto::SendMsgAck, new CVkSendMsgParam(hContact));
		return 0;
	}

	int StickerId = 0;
	ptrA pszRetMsg(GetStickerId(szMsg, StickerId));

	ULONG uMsgId = ::InterlockedIncrement(&m_msgId);
	AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, bIsChat? &CVkProto::OnSendChatMsg : &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh)
		<< INT_PARAM(bIsChat ? "chat_id" : "user_id", iUserID)
		<< INT_PARAM("random_id", ((LONG) time(NULL)) * 100 + uMsgId % 100);
	pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded");

	if (StickerId)
		pReq << INT_PARAM("sticker_id", StickerId);
	else {
		pReq << CHAR_PARAM("message", szMsg);
		if (m_vkOptions.bSendVKLinksAsAttachments) {
			CMStringA szAttachments = GetAttachmentsFromMessage(szMsg);
			if (!szAttachments.IsEmpty()) {
				debugLogA("CVkProto::SendMsg Attachments = %s", szAttachments);
				pReq << CHAR_PARAM("attachment", szAttachments);
			}
		}
	}

	if (!bIsChat)
		pReq->pUserInfo = new CVkSendMsgParam(hContact, uMsgId);
	
	Push(pReq);

	if (!m_bServerDelivery && !bIsChat)
		ForkThread(&CVkProto::SendMsgAck, new CVkSendMsgParam(hContact, uMsgId));

	if (!IsEmpty(pszRetMsg)) 
		SendMsg(hContact, 0, pszRetMsg);

	return uMsgId;
}
예제 #3
0
int CVkProto::SendMsg(HANDLE hContact, int flags, const char *msg)
{ 
	LONG userID = getDword(hContact, "ID", -1);
	if (userID == -1)
		return 0;

	ptrA szMsg;
	if (flags & PREF_UTF)
		szMsg = mir_strdup(msg);
	else if (flags & PREF_UNICODE)
		msg = mir_utf8encodeW((wchar_t*)&msg[strlen(msg)+1]);
	else
		msg = mir_utf8encode(msg);

	ULONG msgId = ::InterlockedIncrement(&m_msgId);
	AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.send.json", true, &CVkProto::OnSendMessage)
		<< INT_PARAM("type", 0) << INT_PARAM("uid", userID) << CHAR_PARAM("message", msg);
	pReq->pData = (char*)hContact;
	pReq->pUserInfo = (void*)msgId;
	Push(pReq);

	if (!m_bServerDelivery)
		ForkThread(&CVkProto::SendMsgAck, new TFakeAckParams(hContact, msgId));
	return msgId;
}
예제 #4
0
AsyncHttpRequest::AsyncHttpRequest(CVkProto *ppro, int iRequestType, LPCSTR _url, bool bSecure, VK_REQUEST_HANDLER pFunc, RequestPriority rpPriority)
{
	cbSize = sizeof(NETLIBHTTPREQUEST);
	m_bApiReq = true;
	bIsMainConn = false;
	bExpUrlEncode = ppro->m_bUseNonStandardUrlEncode;
	AddHeader("Connection", "keep-alive");
	AddHeader("Accept-Encoding", "booo");

	flags = VK_NODUMPHEADERS | NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_REDIRECT;
	if (bSecure)
		flags |= NLHRF_SSL;

	if (*_url == '/') {	// relative url leads to a site
		m_szUrl = ((bSecure) ? "https://" : "http://") + CMStringA("api.vk.com");
		m_szUrl += _url;
		bIsMainConn = true;
	}
	else m_szUrl = _url;

	if (bSecure)
		this << CHAR_PARAM("access_token", ppro->m_szAccessToken);

	requestType = iRequestType;
	m_pFunc = pFunc;
	pUserInfo = NULL;
	m_iRetry = MAX_RETRIES;
	m_iErrorCode = 0;
	bNeedsRestart = false;
	m_reqNum = ::InterlockedIncrement(&m_reqCount);
	m_priority = rpPriority;
}
예제 #5
0
void CVkProto::RetrieveUnreadMessages()
{
	debugLogA("CVkProto::RetrieveMessages");

	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveMessages)
		<< CHAR_PARAM("code", "return { \"msgs\":API.messages.get({\"filters\":1}), \"dlgs\":API.messages.getDialogs() };"));
}
예제 #6
0
void CVkProto::RetrieveFriends()
{
	debugLogA("CVkProto::RetrieveFriends");
	
	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends)
		<< INT_PARAM("count", 1000) << CHAR_PARAM("fields", "uid,first_name,last_name,photo_medium,sex,country,timezone,contacts"));
}
예제 #7
0
void CVkProto::GetServerHistory(MCONTACT hContact, int iOffset, int iCount, int iTime, int iLastMsgId, bool once)
{
	debugLogA("CVkProto::GetServerHistory %d %d %d %d %d", iOffset, iCount, iTime, iLastMsgId, (int)once);
	if (!IsOnline())
		return;
	
	LONG userID = getDword(hContact, "ID", -1);
	if (-1 == userID || userID == VK_FEED_USER)
		return;

	CMStringA code(FORMAT, "var iOffset=%d;var iReqCount=%d;var userID=%d;var iTime=%d;var lastMid=%d;"
		"var Hist=API.messages.getHistory({\"user_id\":userID,\"count\":iReqCount,\"offset\":iOffset});"
		"var ext=Hist.items.length;var index=0;"
		"while(ext!=0){if(Hist.items[index].date>iTime){if(Hist.items[index].id>lastMid)"
		"{index=index+1;ext=ext-1;}else ext=0;}else ext=0;};"
		"var ret=Hist.items.slice(0,index);"
		"var [email protected]_messages;var Idx=0;var Uids=[];while(Idx<FMsgs.length){"
		"var Jdx=0;var CFMsgs=parseInt(FMsgs[Idx].length);while(Jdx<CFMsgs){"
		"Uids.unshift(FMsgs[Idx][Jdx].user_id);Jdx=Jdx+1;};Idx=Idx+1;};"
		"var FUsers=API.users.get({\"user_ids\":Uids,\"name_case\":\"gen\"});"
		"return{\"count\":index,\"datetime\":iTime,\"items\":ret,\"fwd_users\":FUsers,\"once\":%d,\"rcount\":iReqCount};", 
		iOffset, iCount, userID, iTime, iLastMsgId, (int)once);
	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveHistoryMessages)
		<< CHAR_PARAM("code", code)
		<< VER_API)->pUserInfo = new CVkSendMsgParam(hContact, iLastMsgId, iOffset);
}
예제 #8
0
void CVkProto::RetrieveMessagesByIds(const CMStringA &mids)
{
	if (mids.IsEmpty())
		return;

	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.getById.json", true, &CVkProto::OnReceiveMessages)
		<< CHAR_PARAM("mids", mids));
}
예제 #9
0
void CVkProto::MarkMessagesRead(const CMStringA &mids)
{
	if (mids.IsEmpty())
		return;

	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.markAsRead.json", true, &CVkProto::OnReceiveSmth)
		<< CHAR_PARAM("mids", mids));
}
예제 #10
0
INT_PTR __cdecl CVkProto::SvcBanUser(WPARAM hContact, LPARAM)
{
	debugLogA("CVkProto::SvcBanUser");
	LONG userID = getDword(hContact, "ID", -1);
	if (!IsOnline() || userID == -1 || userID == VK_FEED_USER)
		return 1;

	CMStringA code(FORMAT, "var userID=\"%d\";API.account.banUser({\"user_id\":userID});", userID);
	CMString tszVarWarning;

	if (m_bReportAbuse) {
		debugLogA("CVkProto::SvcBanUser m_bReportAbuse = true");
		code += "API.users.report({\"user_id\":userID,type:\"spam\"});";
		tszVarWarning = TranslateT(" report abuse on him/her");
	}
	if (m_bClearServerHistory) {
		debugLogA("CVkProto::SvcBanUser m_bClearServerHistory = true");
		code += "API.messages.deleteDialog({\"user_id\":userID,count:10000});";
		if (!tszVarWarning.IsEmpty())
			tszVarWarning.AppendChar(L',');
		tszVarWarning += TranslateT(" clear server history with him/her");
	}
	if (m_bRemoveFromFrendlist) {
		debugLogA("CVkProto::SvcBanUser m_bRemoveFromFrendlist = true");
		code += "API.friends.delete({\"user_id\":userID});";
		if (!tszVarWarning.IsEmpty())
			tszVarWarning.AppendChar(L',');
		tszVarWarning += TranslateT(" remove him/her from your friend list");
	}
	if (m_bRemoveFromClist) {
		debugLogA("CVkProto::SvcBanUser m_bRemoveFromClist = true");
		if (!tszVarWarning.IsEmpty())
			tszVarWarning.AppendChar(L',');
		tszVarWarning += TranslateT(" remove him/her from your contact list");
	}

	if (!tszVarWarning.IsEmpty())
		tszVarWarning += ".\n";
	code += "return 1;";

	ptrT ptszNick(db_get_tsa(hContact, m_szModuleName, "Nick"));
	CMString ptszMsg(FORMAT, TranslateT("Are you sure to ban %s? %s%sContinue?"),
		IsEmpty(ptszNick) ? TranslateT("(Unknown contact)") : ptszNick, 
		tszVarWarning.IsEmpty() ? _T(" ") : TranslateT("\nIt will also"),
		tszVarWarning.IsEmpty() ? _T("\n") : tszVarWarning);

	if (IDNO == MessageBox(NULL, ptszMsg, TranslateT("Attention!"), MB_ICONWARNING | MB_YESNO))
		return 1;
	
	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveSmth)
		<< CHAR_PARAM("code", code)
		<< VER_API);

	if (m_bRemoveFromClist)
		CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact);

	return 0;
}
예제 #11
0
void CVkProto::MarkMessagesRead(const CMStringA &mids)
{
	debugLogA("CVkProto::MarkMessagesRead (mids)");
	if (!IsOnline() || mids.IsEmpty())
		return;

	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.markAsRead.json", true, &CVkProto::OnReceiveSmth, AsyncHttpRequest::rpLow)
		<< CHAR_PARAM("message_ids", mids));
}
예제 #12
0
void CVkProto::RetrieveFriends(bool bCleanNonFriendContacts)
{
	debugLogA("CVkProto::RetrieveFriends");
	if (!IsOnline())
		return;
	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends)
		<< INT_PARAM("count", 1000) 
		<< CHAR_PARAM("fields", fieldsName)
		<< VER_API)->pUserInfo = new CVkSendMsgParam(NULL, bCleanNonFriendContacts ? 1 : 0);
}
예제 #13
0
void CVkProto::RetrieveFriends()
{
	debugLogA("CVkProto::RetrieveFriends");
	if (!IsOnline())
		return;
	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends)
		<< INT_PARAM("count", 1000) 
		<< CHAR_PARAM("fields", fieldsName)
		<<VER_API);
}
예제 #14
0
bool CVkProto::ApplyCaptcha(AsyncHttpRequest *pReq, const JSONNode &jnErrorNode)
{
	debugLogA("CVkProto::ApplyCaptcha");
	if (!IsOnline())
		return false;
	
	CMStringA szUrl(jnErrorNode["captcha_img"].as_mstring());
	CMStringA szSid(jnErrorNode["captcha_sid"].as_mstring());

	if (szUrl.IsEmpty() || szSid.IsEmpty())
		return false;

	CMStringA userReply;
	if (!RunCaptchaForm(szUrl, userReply))
		return false;

	pReq << CHAR_PARAM("captcha_sid", szSid) << CHAR_PARAM("captcha_key", userReply.GetString());
	pReq->bNeedsRestart = true;
	return true;
}
예제 #15
0
int CVkProto::UserIsTyping(MCONTACT hContact, int type)
{
	debugLogA("CVkProto::UserIsTyping");
	if (PROTOTYPE_SELFTYPING_ON == type) {
		LONG userID = getDword(hContact, "ID", -1);
		if (userID == -1 || !IsOnline() || userID == VK_FEED_USER)
			return 1;
		
		if (m_iMarkMessageReadOn == markOnTyping)
			MarkMessagesRead(hContact);
		
		Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.setActivity.json", true, &CVkProto::OnReceiveSmth, AsyncHttpRequest::rpLow)
			<< INT_PARAM("user_id", userID) 
			<< CHAR_PARAM("type", "typing")
			<< VER_API);
		return 0;
	}
	return 1;
}
예제 #16
0
INT_PTR __cdecl CVkProto::SvcReportAbuse(WPARAM hContact, LPARAM)
{
	debugLogA("CVkProto::SvcReportAbuse");
	LONG userID = getDword(hContact, "ID", -1);
	if (!IsOnline() || userID == -1 || userID == VK_FEED_USER)
		return 1;

	CMString tszNick(ptrT(db_get_tsa(hContact, m_szModuleName, "Nick"))),
		ptszMsg(FORMAT, TranslateT("Are you sure to report abuse on %s?"), tszNick.IsEmpty() ? TranslateT("(Unknown contact)") : tszNick);
	if (IDNO == MessageBox(NULL, ptszMsg, TranslateT("Attention!"), MB_ICONWARNING | MB_YESNO))
		return 1;

	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/users.report.json", true, &CVkProto::OnReceiveSmth)
		<< INT_PARAM("user_id", userID)
		<< CHAR_PARAM("type", "spam")
		<< VER_API);

	return 0;
}
예제 #17
0
void CVkProto::RetrieveChatInfo(CVkChatInfo *cc)
{
	CMStringA szQuery("return { ");

	// retrieve title & owner id
	szQuery.AppendFormat("\"info\": API.messages.getChat({\"chat_id\":%d}),", cc->m_chatid);

	// retrieve users
	szQuery.AppendFormat("\"users\": API.messages.getChatUsers({\"chat_id\":%d, \"fields\":\"uid,first_name,last_name\"})", cc->m_chatid);

	if (!cc->m_bHistoryRead)
		szQuery.AppendFormat(",\"msgs\": API.messages.getHistory({\"chat_id\":%d, \"count\":\"20\", \"rev\":\"0\"})", cc->m_chatid);

	szQuery.Append("};");

	debugLogA("CVkProto::RetrieveChantInfo(%d)", cc->m_chatid);

	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveChatInfo) 
		<< CHAR_PARAM("code", szQuery))->pUserInfo = cc;
}
예제 #18
0
void CVkProto::RetrieveMessagesByIds(const CMStringA &mids)
{
	debugLogA("CVkProto::RetrieveMessagesByIds");
	if (!IsOnline() || mids.IsEmpty())
		return;

	CMStringA code(FORMAT, "var Mids=\"%s\";"
		"var Msgs=API.messages.getById({\"message_ids\":Mids});"
		"var [email protected]_messages;"
		"var Idx=0;var Uids=[];"
		"while(Idx<FMsgs.length){"
		"var Jdx=0;var CFMsgs=parseInt(FMsgs[Idx].length);"
		"while(Jdx<CFMsgs){Uids.unshift(FMsgs[Idx][Jdx].user_id);"
		"Jdx=Jdx+1;};Idx=Idx+1;};"
		"var FUsers=API.users.get({\"user_ids\":Uids,\"name_case\":\"gen\"});"
		"return{\"Msgs\":Msgs,\"fwd_users\":FUsers};",
		mids
	);

	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveMessages, AsyncHttpRequest::rpHigh)
		<< CHAR_PARAM("code", code));
}
예제 #19
0
void CVkProto::CreateNewChat(LPCSTR uids, LPCTSTR ptszTitle)
{
	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.createChat.json", true, &CVkProto::OnCreateNewChat)
		<< TCHAR_PARAM("title", ptszTitle) << CHAR_PARAM("uids", uids));
}
예제 #20
0
void CVkProto::OnReciveUpload(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
{
	CVkFileUploadParam *fup = (CVkFileUploadParam *)pReq->pUserInfo;
	if (!IsOnline()) {
		SendFileFiled(fup, VKERR_OFFLINE);
		return;
	}

	debugLogA("CVkProto::OnReciveUploadServer %d", reply->resultCode);
	if (reply->resultCode != 200) {
		SendFileFiled(fup, VKERR_FILE_NOT_UPLOADED);
		return;
	}

	JSONNode jnRoot;
	CheckJsonResponse(pReq, reply, jnRoot);

	if (pReq->m_iErrorCode) {
		SendFileFiled(fup, pReq->m_iErrorCode);
		return;
	}

	if ((!jnRoot["server"] || !jnRoot["hash"]) && !jnRoot["file"]) {
		SendFileFiled(fup, VKERR_INVALID_PARAMETERS);
		return;
	}

	CMString server(jnRoot["server"].as_mstring());
	CMString hash(jnRoot["hash"].as_mstring());
	CMString upload;

	AsyncHttpRequest *pUploadReq;

	ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)fup);

	switch (fup->GetType()) {
	case CVkFileUploadParam::typeImg:
		upload = jnRoot["photo"].as_mstring();
		if (upload == _T("[]")) {
			SendFileFiled(fup, VKERR_INVALID_PARAMETERS);
			return;
		}
		pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/photos.saveMessagesPhoto.json", true, &CVkProto::OnReciveUploadFile)
			<< TCHAR_PARAM("server", server)
			<< TCHAR_PARAM("photo", upload)
			<< TCHAR_PARAM("hash", hash)
			<< VER_API;
		break;
	case CVkFileUploadParam::typeAudio:
		upload = jnRoot["audio"].as_mstring();
		if (upload == _T("[]")) {
			SendFileFiled(fup, VKERR_INVALID_PARAMETERS);
			return;
		}
		pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/audio.save.json", true, &CVkProto::OnReciveUploadFile)
			<< TCHAR_PARAM("server", server)
			<< TCHAR_PARAM("audio", upload)
			<< TCHAR_PARAM("hash", hash)
			<< VER_API;
		break;
	case CVkFileUploadParam::typeDoc:
		upload = jnRoot["file"].as_mstring();
		if (upload.IsEmpty()) {
			SendFileFiled(fup, VKERR_INVALID_PARAMETERS);
			return;
		}
		pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/docs.save.json", true, &CVkProto::OnReciveUploadFile)
			<< CHAR_PARAM("title", fup->fileName())
			<< TCHAR_PARAM("file", upload)	
			<< VER_API;
		break;
	default:
		SendFileFiled(fup, VKERR_FTYPE_NOT_SUPPORTED);
		return;
	}

	pUploadReq->pUserInfo = pReq->pUserInfo;
	Push(pUploadReq);
}
예제 #21
0
void CVkProto::RetrieveUserInfo(LONG userID)
{
	Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/getProfiles.json", true, &CVkProto::OnReceiveUserInfo)
		<< INT_PARAM("uids", userID) << CHAR_PARAM("fields", "uid,first_name,last_name,photo_medium,sex,bdate,city,relation"));
}
예제 #22
0
void CVkProto::WorkerThread(void*)
{
	debugLogA("CVkProto::WorkerThread: entering");
	m_bTerminated = m_prevError = false;
	m_szAccessToken = getStringA("AccessToken");

	char Score[] = "friends,photos,audio,docs,video,wall,messages,offline,status,notifications,groups";

	CMStringA szAccessScore(ptrA(getStringA("AccessScore")));
	if (szAccessScore != Score) {
		setString("AccessScore", Score);
		delSetting("AccessToken");
		m_szAccessToken = NULL;
	}

	if (m_szAccessToken != NULL)
		// try to receive a response from server
		RetrieveMyInfo();
	else {
		// Initialize new OAuth session
		extern char szBlankUrl[];
		AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "https://oauth.vk.com/authorize", false, &CVkProto::OnOAuthAuthorize)
			<< INT_PARAM("client_id", VK_APP_ID)
			<< CHAR_PARAM("scope", Score)
			<< CHAR_PARAM("redirect_uri", szBlankUrl)
			<< CHAR_PARAM("display", "mobile")
			<< CHAR_PARAM("response_type", "token")
			<< VER_API;
		pReq->m_bApiReq = false;
		pReq->bIsMainConn = true;
		Push(pReq);
	}

	m_hAPIConnection = NULL;

	while (true) {
		WaitForSingleObject(m_evRequestsQueue, 1000);
		if (m_bTerminated)
			break;

		AsyncHttpRequest *pReq;
		bool need_sleep = false;
		while (true) {
			{
				mir_cslock lck(m_csRequestsQueue);
				if (m_arRequestsQueue.getCount() == 0)
					break;

				pReq = m_arRequestsQueue[0];
				m_arRequestsQueue.remove(0);
				need_sleep = (m_arRequestsQueue.getCount() > 1) && (pReq->m_bApiReq); // more than two to not gather
			}
			if (m_bTerminated)
				break;
			ExecuteRequest(pReq);
			if (need_sleep) { // There can be maximum 3 requests to API methods per second from a client
				Sleep(330);	// (c) https://vk.com/dev/api_requests
				debugLogA("CVkProto::WorkerThread: need sleep");
			}
		}
	}

	if (m_hAPIConnection) {
		debugLogA("CVkProto::WorkerThread: Netlib_CloseHandle(m_hAPIConnection) beg");
		Netlib_CloseHandle(m_hAPIConnection);
		debugLogA("CVkProto::WorkerThread: Netlib_CloseHandle(m_hAPIConnection) end");
	}

	m_hAPIConnection = NULL;
	m_hWorkerThread = 0;
	debugLogA("CVkProto::WorkerThread: leaving m_bTerminated = %d", m_bTerminated ? 1 : 0);
}