CallbackApiLongPoll возвращает пустой объект Message

Рейтинг: 4Ответов: 1Опубликовано: 18.03.2023

Описание проблемы.

Пишу бота для беседы с использованием Java SDK от VK. Использую версию com.vk.api.sdk 1.0.14. Хочу отлавливать сообщения, которые приходят (будь то личные сообщения сообществу или в беседе), для этого использую описанный способ на главной странице Java SDK - https://dev.vk.com/sdk/java. Дело в том, что ко мне приходят события, что сообщение новое пришло, а сам объект получается пустой. Все видно на скриншотах. Куски кода прилагаю.

Запуск handler'a в файле App.java:

        //Init clients
        TransportClient transportClient = new HttpTransportClient();
        VkApiClient vkClient = new VkApiClient(transportClient);

        //Create service actor
        Integer groupId = {MyGroupId};
        String accessToken = "{MyAccessToken}";
        GroupActor actor = new GroupActor(groupId, accessToken);
        vkClient.groups().setLongPollSettings(actor, groupId).enabled(true)
                .messageNew(true)
                .execute();
        GroupLongPollApiHandler handler = new GroupLongPollApiHandler(vkClient, actor, 2000);
        handler.run();
}}

Код в файле GroupLongPollApiHandler.java(наш handler):

public class GroupLongPollApiHandler extends GroupLongPollApi {
    public GroupLongPollApiHandler(VkApiClient client, GroupActor actor, int waitTime) {
        super(client, actor, waitTime);
    }

    @Override
    public void messageNew(Integer groupId, Message message){

        System.out.println("NEW MSG: "+message.toString());
        System.out.println("NEW MSG: "+message.getText());
        System.out.println("NEW MSG: "+message.getPeerId());
}}

Что выводит метод MessageNew: Вывод в консоли

Как видно, пустой объект приходит. У меня в коде класс GroupLongPollApi наследуется, а в примере CallbackApiLongPoll. Такое ощущение, что разницы никакой (исходники смотрел). Судя по всему второе это из старых версий, но и используя как в примере от VK тот же самый пустой объект приходит. Надеюсь понятно объяснил. Буду благодарен, если кто-то знает как получать нормальный объект с данными о сообщениb и поможет мне с этим.

UPD: заметил, что со временем выводится такая непонятная штучка введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

Ответы

▲ 1Принят

Нашел решение проблемы.

Предполагаю, все пошло не по плану из-за неправильного timestamp (идентификатор, определяющий последнее событие). Нашел страницу по Bots Long Poll API и обнаружил, что по запросу по ссылке {$server}?act=a_check&key={$key}&ts={$ts}&wait=25 приходит ответ в виде JSON, в котором можно забрать тип события и все что с ним связано, а также новый timestamp для следующего запроса. Также на этой странице можно увидеть какие объекты с какой структурой приходят в ответе.

Переписал код так:

        TransportClient transportClient = new HttpTransportClient();
        VkApiClient vk = new VkApiClient(transportClient);
        GroupActor actor = new GroupActor(GROUP_ID, ACCESS_TOKEN);
        GroupCommandHandler handler = new GroupCommandHandler(vk, actor);

        GroupsGetLongPollServerQuery serverQuery = vk.groups().getLongPollServer(actor,GROUP_ID);
        GetLongPollServerResponse response = serverQuery.execute();
        String key = response.getKey();
        String serverUrl = response.getServer();
        Integer ts = Integer.valueOf(response.getTs());

while (true) {
            Thread.sleep(2500);
            url = serverUrl + "?act=a_check&key=" + key + "&ts=" + ts + "&wait=25";
            String json = VkApiClientUtils.loadJson(url);
            JsonObject messageObject = gs.fromJson(json, JsonObject.class);
            ts = messageObject.get("ts").getAsInt();
            JsonArray msg_array = messageObject.getAsJsonArray("updates");
            for (JsonElement ob: msg_array) handler.handle(ob.getAsJsonObject());
        }

Ответ получаю в методе loadJson(), откуда делаю запрос по этой ссылке. Потом преобразую из строки объект сообщений в Json объект. Дальше получаю массив событий и ловлю в handler'e, где происходит обработка. Объект сообщений, потому что в updates(событиях) приходит массив. updates (array) — массив, элементы которого содержат представление новых событий. gs - ссылочная переменная на объект класса Gson, который помогает получить Json объект.

Код метода loadJson:

public static String loadJson(String url) throws IOException {
        URL obj = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) obj.openConnection();
        connection.setRequestMethod("GET");
        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String inputLine;
        StringBuilder response = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        return response.toString();
    }

Казалось бы, ничего сложного. Однако на странице JAVA SDK описан неработающий для меня способ, нужно было заглянуть в Bots Long Poll API. Буду рад, если у кого-то есть советы по упрощениям или улучшениям в коде.