From 658e9da63709d6bea4097f9ee767da9a7e93ecd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB?= <90477403+zavolo@users.noreply.github.com> Date: Sun, 20 Sep 2026 17:38:19 +0200 Subject: [PATCH 1/4] fix(messages): always return array items and string next_from from getHistoryAttachments The shared-attachments screen (opened from a chat user profile) issues many getHistoryAttachments calls; when the broker returned a null items list the client failed every request. Coerce items to an array and next_from to a string on the success path, matching the error-path defaults. --- VKAPI/Handlers/Messages.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/VKAPI/Handlers/Messages.php b/VKAPI/Handlers/Messages.php index cf65140e7..79cd739cd 100644 --- a/VKAPI/Handlers/Messages.php +++ b/VKAPI/Handlers/Messages.php @@ -3532,6 +3532,13 @@ public function getHistoryAttachments( $this->hydrateExtendedData($data, $fields); } + if (!isset($data["items"]) || !is_array($data["items"])) { + $data["items"] = []; + } + if (!isset($data["next_from"]) || !is_string($data["next_from"])) { + $data["next_from"] = ""; + } + return (object) $data; } From 8fe50ea0a0311b0de337114d3242f07ff8d53cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB?= <90477403+zavolo@users.noreply.github.com> Date: Sun, 20 Sep 2026 17:38:19 +0200 Subject: [PATCH 2/4] fix(users): gate users.get is_closed/can_access_closed type by API version Booleans are required by modern clients (the VK Messenger parses them with getBoolean) but break strictly-typed older clients that decode them as integers (e.g. OpenVK iOS VKUserProfile.isClosed: Int?). Emit booleans only for API version >= 5.200 and keep integers for older versions. --- VKAPI/Handlers/Users.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/VKAPI/Handlers/Users.php b/VKAPI/Handlers/Users.php index 21b953db5..f17a684ef 100644 --- a/VKAPI/Handlers/Users.php +++ b/VKAPI/Handlers/Users.php @@ -107,8 +107,8 @@ public function get(string $user_ids = "0", string $fields = "", int $offset = 0 "id" => $usr->getId(), "first_name" => $firstName, "last_name" => $lastName, - "is_closed" => (bool) $usr->isClosed(), - "can_access_closed" => (bool) $canView, + "is_closed" => $this->usesBooleanClosedFlags() ? (bool) $usr->isClosed() : (int) $usr->isClosed(), + "can_access_closed" => $this->usesBooleanClosedFlags() ? (bool) $canView : (int) $canView, ]; $response[$i]->photo_base = $usr->getAvatarUrl("normal"); @@ -744,4 +744,23 @@ public function report(int $user_id, string $type = "spam", string $comment = "" return 1; } + + /** + * Modern VK API versions (>= 5.200, e.g. the VK Messenger client) expect + * users.get is_closed/can_access_closed as JSON booleans, while older + * clients (OpenVK Legacy/Refresh/iOS, Kate/FreeKate) read them as integers. + * Gate the type by the requested API version to keep both working. + */ + private function usesBooleanClosedFlags(): bool + { + if (!defined("VKAPI_DECL_VER_MAJOR")) { + return false; + } + if (VKAPI_DECL_VER_MAJOR > 5) { + return true; + } + return VKAPI_DECL_VER_MAJOR === 5 + && defined("VKAPI_DECL_VER_MINOR") + && VKAPI_DECL_VER_MINOR >= 200; + } } From 133f0d7c3602b0a2cb970ea3ed7536b021fe10d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB?= <90477403+zavolo@users.noreply.github.com> Date: Sun, 20 Sep 2026 18:14:49 +0200 Subject: [PATCH 3/4] fix(account): return link_redirects as an empty JSON object string in getInfo The client stores account.getInfo link_redirects into AccountInfo.linkRedirectsJson and eagerly parses it with new JSONObject(...) at startup; a null value threw and was reported as a caught non-fatal on every launch. Return "{}" so the parse succeeds. --- VKAPI/Handlers/Account.php | 1 + 1 file changed, 1 insertion(+) diff --git a/VKAPI/Handlers/Account.php b/VKAPI/Handlers/Account.php index 2bc882eac..197d26dfb 100644 --- a/VKAPI/Handlers/Account.php +++ b/VKAPI/Handlers/Account.php @@ -65,6 +65,7 @@ public function getInfo(): object "eu_user" => false, # TODO "https_required" => 1, "phone" => "", + "link_redirects" => "{}", "intro" => 0, "community_comments" => false, "is_live_streaming_enabled" => false, From fbcedb12874d4541027a472846844b611398bf3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB?= <90477403+zavolo@users.noreply.github.com> Date: Sun, 20 Sep 2026 18:19:17 +0200 Subject: [PATCH 4/4] fix(queue): point queue.subscribe base_url at the /queue endpoint over HTTPS Build the subscription base_url as https:///queue (stripping any api. prefix) so the client long-polls the broker queue keep-alive endpoint instead of the messages /nim endpoint, keeping the queue connection alive. --- VKAPI/Handlers/Queue.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/VKAPI/Handlers/Queue.php b/VKAPI/Handlers/Queue.php index 7438310db..fad393043 100644 --- a/VKAPI/Handlers/Queue.php +++ b/VKAPI/Handlers/Queue.php @@ -12,7 +12,8 @@ public function subscribe(string $queue_id = "", string $queue_ids = "", int $ts { $this->requireUser(); - $baseUrl = IMBroker::i()->getLongPollBaseUrl(); + $scheme = ((($_SERVER["HTTP_X_FORWARDED_PROTO"] ?? "") === "https") || ovk_is_ssl()) ? "https://" : "http://"; + $baseUrl = preg_replace("~^https?://~i", $scheme, str_replace("/nim", "/queue", IMBroker::i()->getLongPollBaseUrl()), 1); $now = time(); $ids = [];