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

com.petersamokhin.bots.sdk.longpoll.LongPoll Maven / Gradle / Ivy

There is a newer version: 0.1.3
Show newest version
package com.petersamokhin.bots.sdk.longpoll;

import com.petersamokhin.bots.sdk.callbacks.Callback;
import com.petersamokhin.bots.sdk.callbacks.messages.*;
import com.petersamokhin.bots.sdk.clients.Client;
import com.petersamokhin.bots.sdk.longpoll.responses.GetLongPollServerResponse;
import com.petersamokhin.bots.sdk.objects.Message;
import com.petersamokhin.bots.sdk.utils.Connection;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

import static org.apache.commons.lang3.StringUtils.containsIgnoreCase;

/**
 * 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 access_token = null;

    private String server = null;
    private String key = null;
    private Integer ts = null;
    private 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.67;

    private volatile boolean on = false;


    /**
     * Map with callbacks
     */
    private volatile Map callbacks = new HashMap<>();

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

        setData(access_token, null, null, null, null, null);

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

    /**
     * Custom constructor
     *
     * @param access_token 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(String access_token, Integer need_pts, Integer version, Double API, Integer wait, Integer mode) {

        setData(access_token, need_pts, version, API, wait, mode);

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

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

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

    /**
     * Setting all necessary parameters
     *
     * @param access_token Access token of user or group
     * @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 void setData(String access_token, Integer need_pts, Integer version, Double API, Integer wait, Integer mode) {

        this.access_token = (access_token != null && access_token.length() > 5) ? access_token : this.access_token;

        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(this.access_token);

        if (serverResponse == null) {
            LOG.error("Some error occured, can't start.");
            return;
        }

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

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

        String query = "https://api.vk.com/method/messages.getLongPollServer?need_pts=" + need_pts + "&lp_version=" + version + "&access_token=" + access_token + "&v=" + API;

        JSONObject response = Connection.getRequestResponse(query);

        if (!response.has("response")) {
            LOG.error("No response! Error: {}", 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.error("Started listening to events from VK LongPoll server...");

        while (on) {

            StringBuilder query = new StringBuilder();

            query.append("https://").append(server).append("?act=a_check&key=").append(key).append("&ts=").append(ts).append("&wait=").append(wait).append("&mode=").append(mode).append("&version=").append(version).append("&msgs_limit=100000");

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

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

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

                LOG.error("Response of VK LongPoll fallen with error code {}", code);

                switch (code) {

                    default: {

                        ts = response.has("ts") ? response.getInt("ts") : ts;
                        setData(null, null, null, null, null, null);
                        break;
                    }

                    case 4: {

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

                if (Client.commands.size() > 0 || callbacks.size() > 0) {

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

                        Integer new_ts = response.getInt("ts");

                        Integer new_pts = response.has("pts") ? response.getInt("pts") : pts;

                        JSONArray updates = response.getJSONArray("updates");

                        for (Object currentUpdateObject : updates) {

                            JSONArray currentUpdate = (JSONArray) currentUpdateObject;

                            int updateType = currentUpdate.getInt(0);

                            switch (updateType) {

                                // Handling new message
                                case 4: {

                                    int messageFlags = currentUpdate.getInt(2);

                                    // Check if message is received
                                    if ((messageFlags & 2) == 0) {

                                        Message message = new Message(
                                                access_token,
                                                currentUpdate.getInt(1),
                                                currentUpdate.getInt(2),
                                                currentUpdate.getInt(3),
                                                currentUpdate.getInt(4),
                                                currentUpdate.getString(5),
                                                (currentUpdate.length() > 6 ? (currentUpdate.get(6).toString().startsWith("{") ? new JSONObject(currentUpdate.get(6).toString()) : null) : null),
                                                currentUpdate.length() > 7 ? currentUpdate.getInt(7) : null
                                        );

                                        // check for commands
                                        handleCommands(message);

                                        switch (message.messageType()) {

                                            case "voiceMessage": {
                                                if (callbacks.containsKey("OnVoiceMessageCallback")) {
                                                    ((OnVoiceMessageCallback) callbacks.get("OnVoiceMessageCallback")).OnVoiceMessage(message);
                                                }
                                                break;
                                            }

                                            case "stickerMessage": {
                                                if (callbacks.containsKey("OnStickerMessageCallback")) {
                                                    ((OnStickerMessageCallback) callbacks.get("OnStickerMessageCallback")).OnStickerMessage(message);
                                                }
                                                break;
                                            }

                                            case "gifMessage": {
                                                if (callbacks.containsKey("OnGifMessageCallback")) {
                                                    ((OnGifMessageCallback) callbacks.get("OnGifMessageCallback")).OnGifMessage(message);
                                                }
                                                break;
                                            }

                                            case "audioMessage": {
                                                if (callbacks.containsKey("OnAudioMessageCallback")) {
                                                    ((OnAudioMessageCallback) callbacks.get("OnAudioMessageCallback")).onAudioMessage(message);
                                                }
                                                break;
                                            }

                                            case "videoMessage": {
                                                if (callbacks.containsKey("OnVideoMessageCallback")) {
                                                    ((OnVideoMessageCallback) callbacks.get("OnVideoMessageCallback")).onVideoMessage(message);
                                                }
                                                break;
                                            }

                                            case "docMessage": {
                                                if (callbacks.containsKey("OnDocMessageCallback")) {
                                                    ((OnDocMessageCallback) callbacks.get("OnDocMessageCallback")).OnDocMessage(message);
                                                }
                                                break;
                                            }

                                            case "wallMessage": {
                                                if (callbacks.containsKey("OnWallMessageCallback")) {
                                                    ((OnVoiceMessageCallback) callbacks.get("OnWallMessageCallback")).OnVoiceMessage(message);
                                                }
                                                break;
                                            }

                                            case "photoMessage": {
                                                if (callbacks.containsKey("OnPhotoMessageCallback")) {
                                                    ((OnPhotoMessageCallback) callbacks.get("OnPhotoMessageCallback")).onPhotoMessage(message);
                                                }
                                                break;
                                            }

                                            case "linkMessage": {
                                                if (callbacks.containsKey("OnLinkMessageCallback")) {
                                                    ((OnLinkMessageCallback) callbacks.get("OnLinkMessageCallback")).OnLinkMessage(message);
                                                }
                                                break;
                                            }

                                            case "simpleTextMessage": {
                                                if (callbacks.containsKey("OnSimpleTextMessageCallback")) {
                                                    ((OnSimpleTextMessageCallback) callbacks.get("OnSimpleTextMessageCallback")).OnSimpleTextMessage(message);
                                                }
                                                break;
                                            }
                                        }

                                        if (callbacks.containsKey("OnMessageCallback")) {
                                            ((OnMessageCallback) callbacks.get("OnMessageCallback")).onMessage(message);
                                        }
                                    }
                                    break;
                                }

                                case 61: {

                                    if (callbacks.containsKey("OnTypingCallback")) {
                                        ((OnTypingCallback) callbacks.get("OnTypingCallback")).OnTyping(currentUpdate.getInt(1));
                                    }
                                    break;
                                }
                            }
                        }

                        ts = new_ts;

                    } else {
                        LOG.error("Bad response from VK LongPoll server: no `ts` or `updates` array: {}", response);
                    }
                }
            }
        }
    }

    /**
     * Handle message and call back if it contains any command
     *
     * @param message received message
     */
    private void handleCommands(Message message) {

        for (Client.Commmand command : Client.commands) {
            for (int i = 0; i < command.getCommands().length; i++)
                if (containsIgnoreCase(message.getText(), command.getCommands()[i].toString()))
                    command.getCallback().OnCommand(message);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy