Учим Телеграм-ботов работать через proxy

2.29K1

April 18, 2018

Всем известно, что 16 апреля 2018 года началась массовая блокировка IP адресов серверов Telegram, что явилось причиной выхода из строя серверов сторонних компаний, но никак не самого Telegram. Пока все клиенты Телеграм-мессенджера продолжают работать, что не скажешь о ботах. Боты не получают информацию о новых IP адресах серверов Telegram. Что делать, если использование Телеграм - необходимость, на которой, вероятно, построен твой бизнес? - Нужно научить бота ходить через proxy.

Выбор платформы для бота

Как подсказывает нам официальный сайт Telegram, TelegramBots является одним из удобных решений для реализации бота на Java.

Действительно, с ее помощью можно легко создать бота, а код при этом будет выглядеть весьма лаконично:

public class MyBot extends AbilityBot {

    protected MyBot(String botToken, String botUsername) {
        super(botToken, botUsername);
    }

    public int creatorId() {
        return 0;
    }

    public Ability hello() {
        return Ability.builder()
                .name("test")
                .info("hello bot")
                .locality(ALL)
                .privacy(PUBLIC)
                .action(ctx -> silent.send("hello!", ctx.chatId()))
                .build();
    }
}

Запуск и регистрация бота также не выглядит сложной:

public class Main {

    private static String BOT_NAME = "My test bot";
    private static String BOT_TOKEN = "..." /* your bot's token here */;


    public static void main(String[] args) {
        try {

            ApiContextInitializer.init();

            // Create the TelegramBotsApi object to register your bots
            TelegramBotsApi botsApi = new TelegramBotsApi();

            // Register your newly created AbilityBot
            MyBot bot = new MyBot(BOT_TOKEN, BOT_NAME);

            botsApi.registerBot(bot);

        } catch (TelegramApiException e) {
            e.printStackTrace();
        }
    }
}

Учим бота ходить через proxy

С версии 3.6.1 библиотека TelegramBots научилась устанавливать соединения с серверами Telegram через proxy. Для реализации этой возможности я сделал pull-request, в котором реализовал функционал использования http-proxy сервера.

Подключаем TelegramBots

Укажите в зависимостях версию библиотеки не ниже 3.6.1

для Maven

    <!--TelegramAPI-->
    <dependency>
        <groupId>org.telegram</groupId>
        <artifactId>telegrambots-abilities</artifactId>
        <version>3.6.1</version>
    </dependency>

для Gradle

    // telegram bot api
    compile 'org.telegram:telegrambots:3.6.1'

Настройка proxy для бота

Научите класс бота передавать DefaultBotOptions в класс-родитель

public class MyBot extends AbilityBot {

    protected MyBot(String botToken, String botUsername, DefaultBotOptions options) {
        super(botToken, botUsername, options);
    }
    
    /* ... */
    
}

Использование Proxy с авторизацией

Код инициализации бота для использования proxy будет выглядеть так:

public class Main {

    private static String BOT_NAME = "My test bot";
    private static String BOT_TOKEN = "..." /* your bot's token here */;

    private static String PROXY_HOST = "..." /* proxy host */;
    private static Integer PROXY_PORT = 3128 /* proxy port */;
    private static String PROXY_USER = "..." /* proxy user */;
    private static String PROXY_PASSWORD = "..." /* proxy password */;

    public static void main(String[] args) {
        try {

            ApiContextInitializer.init();

            // Create the TelegramBotsApi object to register your bots
            TelegramBotsApi botsApi = new TelegramBotsApi();

            // Set up Http proxy
            DefaultBotOptions botOptions = ApiContext.getInstance(DefaultBotOptions.class);

            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(
                    new AuthScope(PROXY_HOST, PROXY_PORT),
                    new UsernamePasswordCredentials(PROXY_USER, PROXY_PASSWORD));

            HttpHost httpHost = new HttpHost(PROXY_HOST, PROXY_PORT);

            RequestConfig requestConfig = RequestConfig.custom().setProxy(httpHost).setAuthenticationEnabled(true).build();
            botOptions.setRequestConfig(requestConfig);
            botOptions.setCredentialsProvider(credsProvider);
            botOptions.setHttpProxy(httpHost);

            // Register your newly created AbilityBot
            MyBot bot = new MyBot(BOT_TOKEN, BOT_NAME, botOptions);

            botsApi.registerBot(bot);

        } catch (TelegramApiException e) {
            e.printStackTrace();
        }
    }
}

Если прокси настроен без авторизации

Не передавайте credentials в DefaultBotOptions:

public class Main {

    private static String BOT_NAME = "My test bot";
    private static String BOT_TOKEN = "..." /* your bot's token here */;

    private static String PROXY_HOST = "..." /* proxy host */;
    private static Integer PROXY_PORT = 3128 /* proxy port */;

    public static void main(String[] args) {
        try {

            // Create the TelegramBotsApi object to register your bots
            TelegramBotsApi botsApi = new TelegramBotsApi();

            // Set up Http proxy
            DefaultBotOptions botOptions = ApiContext.getInstance(DefaultBotOptions.class);

            HttpHost httpHost = new HttpHost(PROXY_HOST, PROXY_PORT);

            RequestConfig requestConfig = RequestConfig.custom().setProxy(httpHost).setAuthenticationEnabled(false).build();
            botOptions.setRequestConfig(requestConfig);
            botOptions.setHttpProxy(httpHost);

            // Register your newly created AbilityBot
            MyBot bot = new MyBot(BOT_TOKEN, BOT_NAME, botOptions);

            botsApi.registerBot(bot);

        } catch (TelegramApiException e) {
            e.printStackTrace();
        }
    }
}

Итог

В итоге мы теряем немного в скорости старта проекта и ответах бота. Но зато бот продолжить работать, и у вас будет время для принятия решения: использовать Telegram в дальнейшем или уйти на другую платформу.