Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it OK? #246

Open
Dim00 opened this issue Nov 2, 2021 · 12 comments
Open

Is it OK? #246

Dim00 opened this issue Nov 2, 2021 · 12 comments
Assignees

Comments

@Dim00
Copy link

Dim00 commented Nov 2, 2021

import com.vk.api.sdk.httpclient.HttpTransportClient;
import com.vk.api.sdk.client.*;
import com.vk.api.sdk.objects.*;
import com.vk.api.sdk.objects.messages.*;
import com.vk.api.sdk.client.actors.GroupActor;
import com.vk.api.sdk.exceptions.ApiException;
import com.vk.api.sdk.exceptions.ClientException;
import com.vk.api.sdk.queries.messages.*;
import com.vk.api.sdk.events.*;
import com.vk.api.sdk.events.longpoll.*;

class MyHandler extends GroupLongPollApi
{
	public MyHandler (VkApiClient client, GroupActor actor)
		{ super (client, actor, 25); }
	@Override
	protected void messageNew (Integer groupId, Message message)
	{
		System.out.println (message.getText());
	}
}

public class App
{
	private static final String token = "......";
	private static final int group_id = .......;
	public static void main (String[] args) throws ClientException, ApiException, InterruptedException
	{
		VkApiClient vk = new VkApiClient (HttpTransportClient.getInstance());
		GroupActor actor = new GroupActor (group_id, token);
		MyHandler myhnd = new MyHandler (vk, actor);
		myhnd.run();
		System.out.println ("READY");
	}
}

Запускается. Если написать самой группе, то выводит null, если зайти в диалог с группой и начать печатать сообщения для отправки, то ошибка NullPointerException. Если написать сообщение в беседе, куда добавлена группа (как бот), то нет никакой реакции. Это вообще нормально? Зачем выкладывать такой SDK, что код выше не работает?
П.С. Пробовал переделать так, что сервер LongPoll получается по запросу "client.messages().getLongPollServer(actor)" (т.е. запрос не groups.getLongPollServer, а messages.getLongPollServer; если первое только для событий самой группы, а не тех бесед, куда её добавили как бота), тоже ниего неработает, но это другой вопрос конечно

@mkfl3x
Copy link
Contributor

mkfl3x commented Nov 2, 2021

Чтобы увидеть что приходит от сервера можно поставить точку останова на строке 191 класса EventsHandler и в дебаггере посмотреть что объект message содержит валидный json, где в поле body можно увидеть сообщение, отправленное группе.
Проблема в том, что модель, в которую десериализуется этот json, не соответствует. Из-за этого в уже переопределённый метод messageNew попадет неконсистентный объект, у которого поле text пустое, поэтому и выводится null
Следовательно, сам хендлер работает и проблема кроется в объекте модели, и проблема эта уже известна (сам жду когда починят :))

@Dim00
Copy link
Author

Dim00 commented Nov 3, 2021

Хорошо. Я ПОЛНОСТЬЮ осознал всё; и позже напишу с чем ошибки связаны (их две разные, на разных сторонах, и они не компенсируют друг друга). И сегодня могу отправить код, показать как исправил, что переделал так, что всё должно работать как часы. Но даст ли ВК какую-нибудь премию за это? (если да, то чем). В случае, если код окажется подходящим.

@Dim00
Copy link
Author

Dim00 commented Nov 5, 2021

Нет, не совсем так...
Ошибки такие:

  1. Если есть поле body, та значит пользователь выбрал раннюю версию API, не 130-ую.
  2. Обработка enum, получаемого из парсинга json. (в EventsHandler) Например
enum E { C1, C2; }
void somefun (E e) {
    switch (e) {
    case C1: System.println("C1"); break
    default: System.println("Unexpected");
    }
}

Вызов somefun (new E (E.C2)) приведёт к выводу "Unexpected", а вот при somefun(null) будет NullPointerException и "вылет". Т.е. нужно как-то так

void somefun (E e) {
    if (e == null) {System.println("Unexpected"); return;}
    switch (e) {
    case C1: System.println("C1"); break
    default: System.println("Unhandled");
    }
}
  1. Неоднозначности в самой схеме API, а именно часть callback_***** описывает сам объект события, другая поле object у него. Для части событий (напрмер "typing_state" или как-то так) объект вообще не описал, с другой стороны есть объекты связанные с донатами, для которых не определено одноимённый тип события. Посмотрев на MessageNew, я заметил, что оно представляет сам event типа "message_new" и наследуется от Base (который тоже представляет event), и в MessageNew определено поле object типа MessageObject, чья структура соотв. API. Но оказалось, что таких только несколько штук, наследуемых от Base...
  2. Да и то, пришлось закомментировать поле type у них вручную, т.к. оно наследуется от Base (ошибка от json, что два поля с равными аннотациями); а в Base также вручную переправить private на protected у всех полей.
  3. Ну и конечно сам список event'ов важно иметь согласованный с API, до этого он был из старой версии; при этом строки по-моему кое-где "съехали" на одну позицию (как вроде описывают objet для события на 2 строки выше).

Основываясь на таком наследовании (как MessageNew от Base, отображая event типа "message_new") написал код. и загрузил сюда. Правда, там еще есть небольшие изменения "под себя" (например run это исполнение в текущем потоке, runThread -- в новом), но основные изменения описаны выше.
https://github.com/Dim00/vk-java-sdk

С сообщениями работает отлично. Потом придётся видимо в "старом" стиле поправить, т.е. когда для каждого названия-типа события определён через перечисление тип object'а у его класса, например MessageObject у "message_new"; только нужно аккуратно сверять соответствие по схеме, названия не одноимённые; а классы Base, MessageNew, MessageEdit и т.д. вообще тогда удалить что-бы не смущали.

@aotd1 aotd1 self-assigned this Nov 7, 2021
@wtlgo
Copy link
Contributor

wtlgo commented Dec 8, 2021

Небольшой временный фикс этой проблемы, который я использую:

    static class MyLongPollHandler extends GroupLongPollApi {
        protected LongPollHandler(VkApiClient client, GroupActor actor, int waitTime) {
            super(client, actor, waitTime);
        }

        public void messageNewFix(Integer groupId, MessageFix messagefix) {
            var message = messagefix.getMessage();

            // Ваш код
        }

        private static class MessageFix {
            @SerializedName("message")
            private Message message;

            public Message getMessage() {
                return message;
            }
        }

        @Override
        protected String parse(CallbackMessage message) {
            if (message.getType() == Events.MESSAGE_NEW) {
                messageFixNew(message.getGroupId(), gson.fromJson(message.getObject(), MessageFix.class));
                return "OK";
            }

            return super.parse(message);
        }
    }

Он немного уродливый, конечно, но дело выполняет, так что, быть может, кому-то понадобится, пока не починят.

@a1k0u
Copy link

a1k0u commented Jun 6, 2023

Небольшой временный фикс этой проблемы, который я использую:

    static class MyLongPollHandler extends GroupLongPollApi {
        protected LongPollHandler(VkApiClient client, GroupActor actor, int waitTime) {
            super(client, actor, waitTime);
        }

        public void messageNewFix(Integer groupId, MessageFix messagefix) {
            var message = messagefix.getMessage();

            // Ваш код
        }

        private static class MessageFix {
            @SerializedName("message")
            private Message message;

            public Message getMessage() {
                return message;
            }
        }

        @Override
        protected String parse(CallbackMessage message) {
            if (message.getType() == Events.MESSAGE_NEW) {
                messageFixNew(message.getGroupId(), gson.fromJson(message.getObject(), MessageFix.class));
                return "OK";
            }

            return super.parse(message);
        }
    }

Он немного уродливый, конечно, но дело выполняет, так что, быть может, кому-то понадобится, пока не починят.

Пример отличный! Только падает с NPE, когда приходит событие "typing" и т.п., так как в SDK в принципе нет поддержки таких событий. Лечится очень просто - в методе parse всегда возвращайте OK, либо же парсите самостоятельно. Костыль-костыльный..

Можно также использовать com.vk.api.sdk.objects.callback.MessageObject, чтобы достичь такого же результата. В #265 лежит исправление с использованием этого объекта.

...
  public void messageObjectNew(Integer groupId, MessageObject messageObject) {
    var message = messageObject.getMessage();

    // ...
  }

  @Override
  protected String parse(CallbackMessage message) {
    if (message.getType() == null) {
         return "OK";
    }

    if (message.getType() == Events.MESSAGE_NEW) {
      messageObjectNew(
          message.getGroupId(), gson.fromJson(message.getObject(), MessageObject.class));
      return "OK";
    }
    return super.parse(message);
  }
...

Спасибо авторам за фиксы!

Актуально для 1.0.14

@H4kt
Copy link

H4kt commented Oct 30, 2023

Вариант временного фикса на Kotlin

    data class MessageWrapper(
        val message: Message
    )
    
    /* Workaround for empty object being passed to messageNew */
    override fun parse(message: CallbackMessage): String {

        if (message.type != Events.MESSAGE_NEW) {
            return super.parse(message)
        }

        val (chatMessage) = gson.fromJson(
            message.getObject(),
            MessageWrapper::class.java
        )

        messageNew(message.groupId, chatMessage)

        return "OK"
    }

Халатность разрабов ВК меня просто поражает

@wtlgo
Copy link
Contributor

wtlgo commented Oct 30, 2023

Я думаю, проблема не в халатности, а в том, что проект заброшен

@H4kt
Copy link

H4kt commented Oct 30, 2023

Я думаю, проблема не в халатности, а в том, что проект заброшен

Почему тогда репозиторий не переведён в статус архива?

@wtlgo
Copy link
Contributor

wtlgo commented Oct 30, 2023

Я думаю, проблема не в халатности, а в том, что проект заброшен

Почему тогда репозиторий не переведён в статус архива?

А ты лучше не подкидывай такие идеи, так может хоть вспомнят о нем в один день ;^)

@H4kt
Copy link

H4kt commented Oct 30, 2023

Я думаю, проблема не в халатности, а в том, что проект заброшен

Почему тогда репозиторий не переведён в статус архива?

А ты лучше не подкидывай такие идеи, так может хоть вспомнят о нем в один день ;^)

Может быть и так, однако библиотека обновилась 13 дней назад в централе

@aotd1
Copy link
Contributor

aotd1 commented Nov 13, 2023

Добраться до LongPoll'а не успели, рассчитываю что до нового года успеем с подарком починки.

@kkrinitskiy
Copy link

Добраться до LongPoll'а не успели, рассчитываю что до нового года успеем с подарком починки.

Молю добавьте уже тип "реакция" или проверку на null, ну шо мы тут костылями машем 😢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants