All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ru.codeoff.bots.sdk.longpoll.LongPoll Maven / Gradle / Ivy

package ru.codeoff.bots.sdk.longpoll;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.codeoff.bots.sdk.callbacks.Callback;
import ru.codeoff.bots.sdk.clients.Client;
import ru.codeoff.bots.sdk.longpoll.responses.GetLongPollServerResponse;
import ru.codeoff.bots.sdk.utils.web.Connection;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * com.petersamokhin.bots.sdk.Main class for work with VK longpoll server
 * More: link
 */
public class LongPoll {

    private static final Logger LOG = LoggerFactory.getLogger(LongPoll.class);

    private String server = null;
    private String key = null;
    private Integer ts = null;
    public Integer pts = null;

    private Integer wait = 25;

    /**
     * 2 + 32 + 128
     * attachments + pts + random_id
     */
    private Integer mode = 162;

    private Integer version = 2;
    private Integer need_pts = 1;
    private Double API = 5.103;

    private volatile boolean on = false;

    private UpdatesHandler updatesHandler;
    private Client client;

    private Boolean islongpolllog = true;

    /**
     * Simple default constructor that requires only access token
     *
     * @param client client with your access token key, more: link
     */
    public LongPoll(Client client) {


        this.updatesHandler = new UpdatesHandler(client);
        this.updatesHandler.start();
        this.client = client;

        boolean dataSetted = setData(null, null, null, null, null);

        while (!dataSetted) {
            LOG.error("Произошла ошибка при попытке получить настройки VK LongPoll, прерывание. Попытка снова через 1 сек.");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {
            }
            dataSetted = setData(null, null, null, null, null);
        }

        if (!on) {
            on = true;
            Thread threadLongpollListener = new Thread(this::startListening);
            threadLongpollListener.setName("threadLongpollListener");
            threadLongpollListener.start();
        }
    }

    /**
     * Custom constructor
     *
     * @param client   client with your access token key, more: link
     * @param need_pts more: link
     * @param version  more: link
     * @param API      more: link
     * @param wait     more: link
     * @param mode     more: link
     */
    public LongPoll(Client client, Integer need_pts, Integer version, Double API, Integer wait, Integer mode) {

        this.updatesHandler = new UpdatesHandler(client);
        this.updatesHandler.start();
        this.client = client;

        boolean dataSetted = setData(need_pts, version, API, wait, mode);

        while(!dataSetted) {
            LOG.error("Произошла ошибка при попытке получить настройки VK LongPoll, прерывание. Попытка снова через 1 сек.");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {
            }
            dataSetted = setData(need_pts, version, API, wait, mode);
        }

        if (!on) {
            on = true;
            Thread threadLongpollListener = new Thread(this::startListening);
            threadLongpollListener.setName("threadLongpollListener");
            threadLongpollListener.start();
        }
    }

    /**
     * If you need to set new longpoll server, or restart listening
     * off old before.
     */
    public void off() {
        on = false;
    }

    public void longPollLogger(Boolean enable) {
        this.islongpolllog = enable;
    }

    /**
     * Add callback to the map
     *
     * @param name     Callback name
     * @param callback Callback
     */
    public void registerCallback(String name, Callback callback) {
        updatesHandler.registerCallback(name, callback);
    }

    /**
     * Setting all necessary parameters
     *
     * @param need_pts param, info: link
     * @param version  param, info: link
     * @param API      param, info: link
     * @param wait     param, info: link
     * @param mode     param, info: link
     */
    private boolean setData(Integer need_pts, Integer version, Double API, Integer wait, Integer mode) {

        this.need_pts = need_pts == null ? this.need_pts : need_pts;
        this.version = version == null ? this.version : version;
        this.API = API == null ? this.API : API;
        this.wait = wait == null ? this.wait : wait;
        this.mode = mode == null ? this.mode : mode;

        GetLongPollServerResponse serverResponse = getLongPollServer(client.getAccessToken());

        if (serverResponse == null) {
            LOG.error("Произошла ошибка, получен неверный ответ при получении настроек сервера VK LongPoll (server, key, ts, pts).");
            return false;
        }

        this.server = serverResponse.getServer();
        this.key = serverResponse.getKey();
        this.ts = serverResponse.getTs();
        this.pts = serverResponse.getPts();

        return true;
    }

    /**
     * First getting of longpoll server params
     *
     * @param access_token Access token
     * @return LongPoll params
     */
    private GetLongPollServerResponse getLongPollServer(String access_token) {

        StringBuilder query = new StringBuilder();
        query.append("https://api.vk.com/method/messages.getLongPollServer?need_pts=").append(need_pts).append("&lp_version=").append(version).append("&access_token=").append(access_token).append("&v=").append(API);

        JSONObject response = new JSONObject(Connection.getRequestResponse(query.toString()));

        LOG.info("Получение ответов сервера VK LongPoll: \n{}\n", response);

        if (!response.has("response") || !response.getJSONObject("response").has("key") || !response.getJSONObject("response").has("server") || !response.getJSONObject("response").has("ts")) {
            LOG.error("Плохой ответ на получение сервера VK LongPoll!\nЗапрос: {}\n Ответ: {}", query, response);
            return null;
        }

        JSONObject data = response.getJSONObject("response");

        return new GetLongPollServerResponse(
                data.getString("key"),
                data.getString("server"),
                data.getInt("ts"),
                data.getInt("pts")
        );
    }


    /**
     * Listening to events from VK longpoll server
     * and call callbacks on events.
     * You can override only necessary methods in callback to get necessary events.
     */
    private void startListening() {

        LOG.info("Началось логирование событий с сервера VK LongPoll...");

        while (on) {

            JSONObject response;
            String responseString = "";

            try {
                responseString = Connection.getRequestResponse("https://" + server + "?act=a_check&key=" + key + "&ts=" + ts + "&wait=" + wait + "&mode=" + mode + "&version=" + version + "&msgs_limit=100000");
                response = new JSONObject(responseString);
            } catch (JSONException ignored) {
                LOG.error("Произошла ошибка, с сервера VK LongPoll не было обновлений: {}", responseString);
                continue;
            }

            LOG.info("Ответ получения обновлений: \n{}\n", response);

            if (response.has("failed")) {

                int code = response.getInt("failed");

                LOG.error("Ответ VK LongPoll с кодом ошибки {}", code);

                switch (code) {

                    default: {

                        if (response.has("ts")) {
                            ts = response.getInt("ts");
                        }

                        setData(null, null, null, null, null);
                        break;
                    }

                    case 4: {

                        version = response.getInt("max_version");
                        setData(null, null, null, null, null);
                        break;
                    }
                }
            } else {

                if (response.has("ts"))
                    ts = response.getInt("ts");

                if (response.has("pts"))
                    this.pts = response.getInt("pts");

                if (this.updatesHandler.callbacksCount() > 0 || this.updatesHandler.commandsCount() > 0) {

                    if (response.has("ts") && response.has("updates")) {

                        this.updatesHandler.handle(response.getJSONArray("updates"));

                    } else {
                        LOG.error("Неверный ответ от сервера VK LongPoll: no `ts` or `updates` array: {}", response);
                    }
                }
            }
        }
    }

    /**
     * If the client need to start typing
     * after receiving message
     * and until client's message is sent
     */
    public void enableTyping(boolean enable) {
        this.updatesHandler.sendTyping = enable;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy