diff options
author | ElzorFox <elzorfox@ya.ru> | 2025-06-17 19:50:40 +0500 |
---|---|---|
committer | ElzorFox <elzorfox@ya.ru> | 2025-06-17 19:50:40 +0500 |
commit | ecae8cfa27189ebf9612b62a6a6a9204c84f642e (patch) | |
tree | e1a0072cb7cd175499eb5e94dd9398a37ee991a0 | |
parent | 723fb1f1cc490e497247d8fa66a26d5a8a638d46 (diff) |
VKontakte:
fix loading max 100 online contacts
rework procedure for loading contact statuses
new hidden option TimeoutAfterUserGet (default 0) for fix ‘user.get’ flood
remove old code for replace option name
version bump
-rw-r--r-- | protocols/VKontakte/src/version.h | 4 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.h | 7 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_struct.cpp | 9 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_struct.h | 2 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_thread.cpp | 129 | ||||
-rw-r--r-- | protocols/VKontakte/src/vkjs.js | 31 |
6 files changed, 122 insertions, 60 deletions
diff --git a/protocols/VKontakte/src/version.h b/protocols/VKontakte/src/version.h index c7d2f51ba6..7973129c49 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 18
-#define __BUILD_NUM 7
+#define __RELEASE_NUM 19
+#define __BUILD_NUM 0
#include <stdver.h>
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index 9ad64b825e..21f00c6280 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -47,7 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define MAXHISTORYMIDSPERONE 100
#define MAX_RETRIES 10
-#define MAX_CONTACTS_PER_REQUEST 530
+#define MAX_CONTACTS_PER_REQUEST 100
struct CVkProto : public PROTO<CVkProto>
{
@@ -333,7 +333,8 @@ private: //====================================================================================
void SetServerStatus(int);
- void RetrieveUsersInfo(bool bFlag = false, bool bRepeat = false);
+ void RetrieveUsersFrameInfo(CMStringA& userIDs, bool bFreeOffline, bool bSendOnline, bool bRepeat);
+ void RetrieveUsersInfo(bool bFreeOffline = false);
void RetrieveStatusMsg(const CMStringW &StatusMsg);
void RetrieveStatusMusic(const CMStringW &StatusMsg);
void OnReceiveStatus(MHttpResponse*, AsyncHttpRequest*);
@@ -345,7 +346,7 @@ private: void RetrieveUserInfo(VKUserID_t iUserId);
void RetrieveGroupInfo(VKUserID_t iGroupID);
void RetrieveGroupInfo(CMStringA & groupIDs);
- void OnReceiveUserInfo(MHttpResponse*, AsyncHttpRequest*);
+ void OnReceiveUserFrameInfo(MHttpResponse* reply, AsyncHttpRequest* pReq);
void OnReceiveGroupInfo(MHttpResponse * reply, AsyncHttpRequest * pReq);
void RetrieveFriends(bool bCleanNonFriendContacts = false);
void OnReceiveFriends(MHttpResponse*, AsyncHttpRequest*);
diff --git a/protocols/VKontakte/src/vk_struct.cpp b/protocols/VKontakte/src/vk_struct.cpp index a36a53a0d0..ca17e025a5 100644 --- a/protocols/VKontakte/src/vk_struct.cpp +++ b/protocols/VKontakte/src/vk_struct.cpp @@ -240,17 +240,10 @@ CVKOptions::CVKOptions(PROTO_INTERFACE* proto) : iInvisibleInterval(proto, "InvisibleInterval", 10),
iMaxFriendsCount(proto, "MaxFriendsCount", 1000),
iStickerSize(proto, "StickerSize", 128),
+ iTimeoutAfterUserGet(proto, "TimeoutAfterUserGet", 0),
pwszDefaultGroup(proto, "ProtoGroup", L"VKontakte"),
pwszVKLang(proto, "VKLang", nullptr)
{
- // Note: Delete this code after next stable build
- int iStikersAsSmyles = db_get_b(0, proto->m_szModuleName, "StikersAsSmyles", -1);
- if (iStikersAsSmyles != -1) {
- bStikersAsSmileys = iStikersAsSmyles == 1;
- db_set_b(0, proto->m_szModuleName, "StikersAsSmileys", (uint8_t)iStikersAsSmyles);
- db_unset(0, proto->m_szModuleName, "StikersAsSmyles");
- }
- // Note
}
\ No newline at end of file diff --git a/protocols/VKontakte/src/vk_struct.h b/protocols/VKontakte/src/vk_struct.h index aac60bf2ef..45b3c34a4b 100644 --- a/protocols/VKontakte/src/vk_struct.h +++ b/protocols/VKontakte/src/vk_struct.h @@ -327,6 +327,8 @@ struct CVKOptions { CMOption<uint32_t> iMaxFriendsCount;
CMOption<uint32_t> iStickerSize;
+ CMOption<uint32_t> iTimeoutAfterUserGet;
+
CMOption<wchar_t*> pwszDefaultGroup;
CMOption<wchar_t*> pwszVKLang;
diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index ccd57be40b..fe33329ad2 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -539,11 +539,12 @@ void CVkProto::RetrieveUserInfo(VKUserID_t iUserId) return;
}
- Push(new AsyncHttpRequest(this, REQUEST_POST, "/method/execute.RetrieveUserInfo", true, &CVkProto::OnReceiveUserInfo)
+ CMStringA szUserId(FORMAT, "%d", iUserId);
+
+ Push(new AsyncHttpRequest(this, REQUEST_POST, "/method/execute.RetrieveUserInfo", true, &CVkProto::OnReceiveUserFrameInfo)
<< INT_PARAM("userid", iUserId)
<< CHAR_PARAM("fields", szFieldsName)
- );
-
+ )->pUserInfo = mir_strdup(szUserId.c_str());
}
void CVkProto::RetrieveGroupInfo(VKUserID_t iGroupId)
@@ -568,77 +569,74 @@ void CVkProto::RetrieveGroupInfo(CMStringA& groupIDs) << CHAR_PARAM("group_ids", groupIDs));
}
-void CVkProto::RetrieveUsersInfo(bool bFreeOffline, bool bRepeat)
+void CVkProto::RetrieveUsersFrameInfo(CMStringA& szUserIds, bool bFreeOffline, bool bSendOnline, bool bRepeat)
{
- debugLogA("CVkProto::RetrieveUsersInfo");
- if (!IsOnline())
+ debugLogA("CVkProto::RetrieveUsersFrameInfo %s", szUserIds);
+ if (!IsOnline() || szUserIds.IsEmpty())
return;
-
- CMStringA userIDs;
- int i = 0;
- for (auto &hContact : AccContacts()) {
- VKUserID_t iUserId = ReadVKUserID(hContact);
- if (iUserId == VK_INVALID_USER || iUserId == VK_FEED_USER || iUserId < 0 || isChatRoom(hContact))
- continue;
-
- bool bIsFriend = !getBool(hContact, "Auth", true);
- if (bFreeOffline && !m_vkOptions.bLoadFullCList && bIsFriend)
- continue;
-
- if (!userIDs.IsEmpty())
- userIDs.AppendChar(',');
- userIDs.AppendFormat("%i", iUserId);
-
- if (i == MAX_CONTACTS_PER_REQUEST)
- break;
- i++;
- }
-
- Push(new AsyncHttpRequest(this, REQUEST_POST, "/method/execute.RetrieveUsersInfo", true, &CVkProto::OnReceiveUserInfo)
- << CHAR_PARAM("userids", userIDs)
+
+ Push(new AsyncHttpRequest(this, REQUEST_POST, "/method/execute.RetrieveUsersFrameInfo", true, &CVkProto::OnReceiveUserFrameInfo)
+ << CHAR_PARAM("userids", szUserIds)
<< CHAR_PARAM("fields", (bFreeOffline ? "online,status,can_write_private_message" : szFieldsName))
<< INT_PARAM("norepeat", (int)bRepeat)
- << INT_PARAM("setonline", (int)m_bNeedSendOnline)
+ << INT_PARAM("setonline", (int)(m_bNeedSendOnline && bSendOnline))
<< INT_PARAM("func_v", (bFreeOffline && !m_vkOptions.bLoadFullCList) ? 1 : 2)
- );
-
+ )->pUserInfo = mir_strdup(szUserIds.c_str());
}
-void CVkProto::OnReceiveUserInfo(MHttpResponse *reply, AsyncHttpRequest *pReq)
+void CVkProto::OnReceiveUserFrameInfo(MHttpResponse* reply, AsyncHttpRequest* pReq)
{
- debugLogA("CVkProto::OnReceiveUserInfo %d", reply->resultCode);
+ debugLogA("CVkProto::OnReceiveUserFrameInfo %d", reply->resultCode);
if (reply->resultCode != 200 || !IsOnline())
return;
JSONNode jnRoot;
- const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot);
+ const JSONNode& jnResponse = CheckJsonResponse(pReq, reply, jnRoot);
if (!jnResponse)
return;
- const JSONNode &jnUsers = jnResponse["users"];
+ const JSONNode& jnUsers = jnResponse["users"];
if (!jnUsers)
return;
+ CMStringA szUserIds;
+ if (pReq->pUserInfo) {
+ szUserIds = ((const char*)pReq->pUserInfo);
+ mir_free(pReq->pUserInfo);
+ }
+
if (!jnResponse["norepeat"].as_bool() && jnResponse["usercount"].as_int() == 0) {
- RetrieveUsersInfo(true, true);
+ Sleep(5000);
+ RetrieveUsersFrameInfo(szUserIds, true, false, true);
return;
}
LIST<void> arContacts(10, PtrKeySortT);
- for (auto &hContact : AccContacts())
- if (!isChatRoom(hContact) && !IsGroupUser(hContact))
- arContacts.insert((HANDLE)hContact);
+ for (auto& hContact : AccContacts())
+ if (!isChatRoom(hContact) && !IsGroupUser(hContact)) {
+ if (szUserIds.IsEmpty()) {
+ if (!getBool(hContact, "Auth", true))
+ arContacts.insert((HANDLE)hContact);
+ }
+ else {
+ VKUserID_t iUserId = ReadVKUserID(hContact);
+ char szId[40];
+ ltoa(iUserId, szId, 10);
+ if (szUserIds.Find(szId) >= 0)
+ arContacts.insert((HANDLE)hContact);
+ }
+ }
- for (auto &it : jnUsers) {
+ for (auto& it : jnUsers) {
MCONTACT hContact = SetContactInfo(it);
if (hContact)
arContacts.remove((HANDLE)hContact);
}
if (jnResponse["freeoffline"].as_bool())
- for (auto &it : arContacts) {
+ for (auto& it : arContacts) {
MCONTACT cc = (UINT_PTR)it;
VKUserID_t iUserId = ReadVKUserID(cc);
if (iUserId == m_iMyUserId || iUserId == VK_FEED_USER)
@@ -655,14 +653,16 @@ void CVkProto::OnReceiveUserInfo(MHttpResponse *reply, AsyncHttpRequest *pReq) }
arContacts.destroy();
- AddFeedSpecialUser();
- const JSONNode &jnRequests = jnResponse["requests"];
+ if (m_vkOptions.iTimeoutAfterUserGet) // for 'error 9' fix
+ Sleep(m_vkOptions.iTimeoutAfterUserGet > 5000 ? 5000 : m_vkOptions.iTimeoutAfterUserGet);
+
+ const JSONNode& jnRequests = jnResponse["requests"];
if (!jnRequests)
return;
int iCount = jnRequests["count"].as_int();
- const JSONNode &jnItems = jnRequests["items"];
+ const JSONNode& jnItems = jnRequests["items"];
if (!iCount || !jnItems)
return;
@@ -676,10 +676,45 @@ void CVkProto::OnReceiveUserInfo(MHttpResponse *reply, AsyncHttpRequest *pReq) if (!IsAuthContactLater(hContact)) {
RetrieveUserInfo(iUserId);
AddAuthContactLater(hContact);
- CVkDBAddAuthRequestThreadParam *param = new CVkDBAddAuthRequestThreadParam(hContact, false);
- ForkThread(&CVkProto::DBAddAuthRequestThread, (void *)param);
+ CVkDBAddAuthRequestThreadParam* param = new CVkDBAddAuthRequestThreadParam(hContact, false);
+ ForkThread(&CVkProto::DBAddAuthRequestThread, (void*)param);
+ }
+ }
+}
+
+void CVkProto::RetrieveUsersInfo(bool bFreeOffline)
+{
+ debugLogA("CVkProto::RetrieveUsersInformation");
+ if (!IsOnline())
+ return;
+
+ CMStringA szUserIds;
+ int i = 0;
+ bool bSendOnline = true;
+
+ for (auto& hContact : AccContacts()) {
+ VKUserID_t iUserId = ReadVKUserID(hContact);
+ if (iUserId == VK_INVALID_USER || iUserId == VK_FEED_USER || iUserId < 0 || isChatRoom(hContact))
+ continue;
+
+ if (!szUserIds.IsEmpty())
+ szUserIds.AppendChar(',');
+ szUserIds.AppendFormat("%i", iUserId);
+
+ if (i < (MAX_CONTACTS_PER_REQUEST - 1))
+ i++;
+ else {
+ RetrieveUsersFrameInfo(szUserIds, bFreeOffline, bSendOnline, false);
+ i = 0;
+ szUserIds.Empty();
+ bSendOnline = false;
}
}
+
+ if(!szUserIds.IsEmpty())
+ RetrieveUsersFrameInfo(szUserIds, bFreeOffline, bSendOnline, false);
+
+ AddFeedSpecialUser();
}
void CVkProto::OnReceiveGroupInfo(MHttpResponse *reply, AsyncHttpRequest *pReq)
diff --git a/protocols/VKontakte/src/vkjs.js b/protocols/VKontakte/src/vkjs.js index 8e1faadcdb..43bf1aa167 100644 --- a/protocols/VKontakte/src/vkjs.js +++ b/protocols/VKontakte/src/vkjs.js @@ -17,6 +17,37 @@ // 4. Create additional version(s) stored procedure (if required) +// Stored procedure name: RetrieveUsersFrameInfo = Begin +// Arguments: +// Args.userids +// Args.fields +// Args.norepeat +// Args.setonline + +// ver 1 +var Req =[]; +if (Args.setonline == 1) { + API.account.setOnline(); + Req = API.friends.getRequests({ "extended": 0, "need_mutual": 0, "out": 0 }); +}; +var res = []; +var US = API.users.get({ "user_ids": Args.userids, "fields": Args.fields, "name_case": "nom" }); +var index = US.length; +while (index > 0) { + index = index - 1; + if (US[index].online != 0) { + res.push(US[index]); + }; +}; +return { "freeoffline": 1, "norepeat": parseInt(Args.norepeat), "usercount": res.length, "users": res , "requests": Req}; + +// ver 2 +if (Args.setonline == 1) + API.account.setOnline(); +var res = API.users.get({ "user_ids": Args.userids, "fields": Args.fields, "name_case": "nom" }); +return { "freeoffline": 0, "norepeat": parseInt(Args.norepeat), "usercount": res.length, "users": res, "requests": API.friends.getRequests({ "extended": 0, "need_mutual": 0, "out": 0 })}; +// Stored procedure name: RetrieveUsersFrameInfo = End + // Stored procedure name: RetrieveUserInfo = Begin // Arguments: // Args.userid |