Страницы

Поиск по вопросам

Показаны сообщения с ярлыком telegram-api. Показать все сообщения
Показаны сообщения с ярлыком telegram-api. Показать все сообщения

воскресенье, 1 марта 2020 г.

Как взаимодействовать с API Telegram в обход блокировки?

#telegram_bot #telegram_api #telegram

Начал писать Telegram бота.
Сразу столкнулся с проблемой, что не могу получить ответ (видимо из-за блокировки РКН)

Попробовал прокси - не помогло - или я что-то не так настроил....



Есть ли сейчас способы обойти блокировку и написать Telegram бота? 
    


Ответы

Ответ 1



Для обхода блокировки, нужно подключаться к SOCKS5 прокси: /*** PHP CODE ***/ /****************/ $prxy = 'http://94.130.223.179:1080'; // адрес:порт прокси $prxy_auth = 'auth_user:auth_pass'; // логин:пароль для аутентификации /****************/ $ch = curl_init(); $url = "https://api.telegram.org/botXXXXX/sendMessage?chat_id=XXXXX&text=XXXXX"; // где XXXXX - ваши значения curl_setopt_array ($ch, array(CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true)); /********************* Код для подключения к прокси *********************/ curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); // тип прокси curl_setopt($ch, CURLOPT_PROXY, $prxy); // ip, port прокси curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxy_auth); // авторизация на прокси curl_setopt($ch, CURLOPT_HEADER, false); // отключение передачи заголовков в запросе curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // возврат результата в качестве строки curl_setopt($ch, CURLOPT_POST, 1); // использование простого HTTP POST curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // отмена проверки сертификата удаленным сервером /***********************************************************************/ $result = curl_exec($ch); // DIGITAL RESISTANCE! curl_close($ch); Не забудьте подставить рабочий прокси адрес ($prxy) и, если необходимо, данные для аутентификации ($prxy_auth), а также свой запрос ($url)

среда, 12 февраля 2020 г.

Как посмотреть кто и что писал в чат боту телеграм? getUpdates выдает только - {“ok”:true,“result”:[]}

#python #python_3x #telegram_api #telegram_bot #бот

Почему метод:

https://api.telegram.org/botXXXXXXXXXX/getUpdates


выдает только:

{"ok":true,"result":[]}


?

Сообщения боту отправлялись и он на них реагировал.

Как получить выдачу типа: 



{"ok":true,"result":{"update_id":8393,"message":{"message_id":3,"from":{"id":7474,"first_name":"AAA"},"chat":{"id":,"title":""},"date":25497,"new_chat_participant":{"id":71,"first_name":"NAME","username":"YOUR_BOT_NAME"}}}

    


Ответы

Ответ 1



Данный метод возвращает только новые сообщения. Если бот уже реагировал на некие отправляемые ему сообщения, то он их уже получил (скорее всего этим же методом) и они помечены сервером Telegram как полученные. Соответственно, при каждом новом запросе они возвращаться уже не будут, иначе вы бы каждый раз получали всю историю сообщений с момента создания бота. В данном случае, у вас есть два варианта: Вести лог получаемых ботом сообщений и пользоваться им на своё усмотрение. Поиграться с параметром offset метода getUpdates. Подробнее здесь: https://core.telegram.org/bots/api#getupdates Например: https://api.telegram.org/botXXXXXXXXXX/getUpdates?offset=-10

пятница, 24 января 2020 г.

Направление движения транспорта с помощью картинки Python

#python #python_3x #telegram_api #telegram_bot

Пишу телеграмм бота, который показывает движение транспорта на карте. Делаю это на
питоне. 

C картами телеграмм работает ограничено показывает только булавку, а мне нужно нарисовать
и направление?



вот пример данных, которые я получаю 

1, 1, 39692550, 47219635, 12, 138, 344,
тип, номер_широта, долгота_скорость, курс, номер


предпоследний параметр показывает градусы по окружности.

Идея была такая, взять картинку со стрелкой и наклонять ее насколько надо.
И просто отправлять ее после карты ниже. Реализовал все с помощью библиотеки PIL
, но получается плохо. После каждого поворота картинки, приходиться ее сохранять и
под конец, она уже выглядит как набор пикселей.

Можете ли вы мне подсказать другие варианты?
Может все таки можно нанести на карту стрелку движения как в навигаторе. А может
можно с помощью какой-нибудь математической библиотеки рисовать каждый раз компас с
направлением и отправлять его как картинку? 

Даже для юмора хотел реализовать все с помощью черепашки, но как создать изображение
я так не разобрался.

Решил проблему используя google charts, передаю градусы по ссылке и гугл рисует сам
картинку с направлением. Но все же вопрос в том,можно ли присылать локацию со стрелкой,
а не с булавкой ?
    


Ответы

Ответ 1



Но все же вопрос в том,можно ли присылать локацию со стрелкой, а не с булавкой ? Ответ на этот вопрос - нет. Локация - это точка на карте, как следует из документации: Location This object represents a point on the map. А метод sendLocation предназначен только для этого: Use this method to send point on the map. Если Вам нужен какой-то специфичный функционал, то попробуйте использовать какие-то сторонние сервисы, генерирующие необходимое Вам изображение и посылайте его в виде фото.

среда, 22 января 2020 г.

Сохранение сессии Telegram API

#java #telegram_api

Приветствую.

Возник вопрос по поводу Telegram API (не Bot API). Не могу понять, как сохранить
данные пользователя после его первой аутентификации в приложении. В данный момент при
каждом входе идет запрос кода. 

После первого удачного входа пробовал сохранять phoneCodeHash, номер телефона и phoneCode.
В принципе, это работает до истечения срока кода аутентификации.

Возможно, сейчас я путаю, потому что использую представление данного API на Java
с библиотекой Kotlogram. Реализация аутентификации в сэмпле:

ApiStorage.java

public static class ApiStorage implements TelegramApiStorage {

//Create File variable for auth.key and dc.save
public static final File AUTH_KEY_FILE = new File("Properties/auth.key");
public static final File NEAREST_DC_FILE = new File("Properties/dc.save");

@Override
public void saveAuthKey(@NotNull AuthKey authKey) {
    try {
        FileUtils.writeByteArrayToFile(AUTH_KEY_FILE, authKey.getKey());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Nullable
@Override
public AuthKey loadAuthKey() {
    try {
        return new AuthKey(FileUtils.readFileToByteArray(AUTH_KEY_FILE));
    } catch (IOException e) {
        if (!(e instanceof FileNotFoundException))
            e.printStackTrace();
    }

    return null;
}

@Override
public void saveDc(@NotNull DataCenter dataCenter) {
    try {
        FileUtils.write(NEAREST_DC_FILE, dataCenter.toString());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Nullable
@Override
public DataCenter loadDc() {
    try {
        String[] infos = FileUtils.readFileToString(NEAREST_DC_FILE).split(":");
        return new DataCenter(infos[0], Integer.parseInt(infos[1]));
    } catch (IOException e) {
        if (!(e instanceof FileNotFoundException))
            e.printStackTrace();
    }

    return null;
}

@Override
public void deleteAuthKey() {
    try {
        FileUtils.forceDelete(AUTH_KEY_FILE);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void deleteDc() {
    try {
        FileUtils.forceDelete(NEAREST_DC_FILE);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void saveSession(@Nullable MTSession session) {

}

@Nullable
@Override
public MTSession loadSession() {
    return null;
}
}


Сама аутентификация в Java Console.

public class Main {
// Get them from Telegram's console
public static final int API_ID = api id;
public static final String API_HASH = api hash;

// What you want to appear in the "all sessions" screen
public static final String APP_VERSION = "AppVersion";
public static final String MODEL = "Model";
public static final String SYSTEM_VERSION = "SysVer";
public static final String LANG_CODE = "en";

public static TelegramApp application = new TelegramApp(API_ID, API_HASH, MODEL,
SYSTEM_VERSION, APP_VERSION, LANG_CODE);
public static final String PHONE_NUMBER = "тут был телефон"; // International format

public static void main(String[] args) {
    TelegramClient client = Kotlogram.getDefaultClient(application, new ApiStorage());

    try {
        TLSentCode sentCode = client.authSendCode(false, PHONE_NUMBER, true);
        System.out.println("Authentication code: ");
        String code = new Scanner(System.in).nextLine();

        TLAuthorization authorization = client.authSignIn(PHONE_NUMBER, sentCode.getPhoneCodeHash(),
code);
        TLUser self = authorization.getUser().getAsUser();
        System.out.println("You are now signed in as " + self.getFirstName() + "
" + self.getLastName() + " @" + self.getUsername());
    } catch (RpcErrorException | IOException e) {
        e.printStackTrace();
    } finally {
        client.close(); // Important, do not forget this, or your process won't finish
    }
}
}


Данную реализацию я использую в Android приложении. Конечно, все раскидано по асинхронным
потокам. Но каждый раз при входе в приложение идет проверка кода авторизации. Из-за
этого я за сегодня заблокировал 3 разных аккаунта на день по причине флуда авторизации.

В качестве обходного варианта я использовал подстановку значений в данном методе,
запоминая их при удачной авторизации. 

client.authSignIn(phoneNumber, phoneCodeHash, phoneCode);


Это работает только до того момента, пока код не истечет.
Возможно, кто-то знает как это решается на уровне самого API, а не библиотеки, или
сможет предложить вариант использования других подходов для работы с Telegram API:
стандартный API, TDlib или какое-либо другое решение для авторизации пользователей
в приложении через Telegram на Java.

Честно, не смог ни с чем другим разобраться. 
Заранее благодарю за ответы.
    


Ответы

Ответ 1



Нашел решение методом научного тыка. Я был действительно не прав, т.к. данная библиотека сама умеет отрабатывать сессии. Просто делает это (на мой взгляд) очень неочевидно. Прикладываю ниже рабочее решение в виде консольного приложения на Java. Это же решение работает и для Android приложения. public class Main { // Get them from Telegram's console private static final int API_ID = /*put api id here*/; private static final String API_HASH = "put hash here"; // What you want to appear in the "all sessions" screen private static final String APP_VERSION = "AppVersion"; private static final String MODEL = "Model"; private static final String SYSTEM_VERSION = "SysVer"; private static final String LANG_CODE = "en"; private static TelegramApp application = new TelegramApp(API_ID, API_HASH, MODEL, SYSTEM_VERSION, APP_VERSION, LANG_CODE); private static final String PHONE_NUMBER = "put a phone number here"; // International format public static void main(String[] args) { TelegramClient client = Kotlogram.getDefaultClient(application, new ApiStorage()); try { TLUserFull userFull = client.usersGetFullUser(new TLInputUserSelf()); TLUser self = userFull.getUser().getAsUser(); showUserInfo(self); } catch (RpcErrorException e) { if (e.getTag().equals("AUTH_KEY_UNREGISTERED")) signInUser(client); else e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { client.close(); } } private static void signInUser(TelegramClient client) { try { // Send code to account TLSentCode sentCode = client.authSendCode(false, PHONE_NUMBER, true); System.out.println("Authentication code: "); String code = new Scanner(System.in).nextLine(); TLAuthorization authorization = client.authSignIn(PHONE_NUMBER, sentCode.getPhoneCodeHash(), code); TLUser self = authorization.getUser().getAsUser(); showUserInfo(self); } catch (Exception e) { e.printStackTrace(); } } private static void showUserInfo(TLUser user) { System.out.println("You are now signed in as " + user.getFirstName() + " " + user.getLastName() + " @" + user.getUsername()); } } Не знаю, кто плюсовал данный вопрос, но, надеюсь, что оно кому-нибудь поможет. Спасибо.

пятница, 10 января 2020 г.

Последовательность диалогов Telegram

#python #telegram_api

Как я могу реализовать диалог с ботом? (должна быть последовательность)

К примеру, при вводе /start, бот выводит: " выбор: x или y", показывается клавиатура
с x и y. Когда человек нажимает x, должны выполняться какие-то действия, при нажатии
y - другие.  после этого он уже не должен написать y, и инициировать выполнение уже
других действий. ЛИБО X, ЛИБО Y. Чтобы выбрать y, надо писать заново /start. Проверяю
входящие сообщения так:

if text == '/start':
  bot.sendMessage(author, strings.starts)
  show_keyboard = {'keyboard': [["x", "y"], ["z"]]}
  bot.sendMessage(author, 'Please, choose', reply_markup=show_keyboard)
if text == 'y':
*some actions*


нужна последовательность. помогите, пожалуйста.
желательно, с примерам
    


Ответы

Ответ 1



Вот мой вариант import telebot #pyTelegramBotAPI from telebot import types import shelve bot = telebot.TeleBot('token') @bot.message_handler(command=['start']) def start(mess): chat_id = mess.chat.id storage = shelve.open('shelve') storage[str(chat_id)] = 'init' storage.close() markup = types.ReplyKeyboardMarkup() btn_x = types.KeyboardButton('x') btn_y = types.KeyboardButton('y') markup.add(btn_x, btn_y) bot.send_message(chat_id, 'x или y', reply_markup=markup) @bot.message_handler(func=lambda mess: mess.text == 'y' and mess.content_type == 'text') def y(mess): chat_id = mess.chat.id storage = shelve.open('shelve') state = storage[str(chat_id)] if state != 'init': pass storage.close() else: storage[str(chat_id)] = 'y' storage.close() #твой код @bot.message_handler(func=lambda mess: mess.text == 'x' and mess.content_type == 'text') def x(mess): chat_id = mess.chat.id storage = shelve.open('shelve') state = storage[str(chat_id)] if state != 'init': pass storage.close() else: storage[str(chat_id)] = 'y' storage.close() #твой код if __name__ == '__main__': bot.polling(True)

вторник, 31 декабря 2019 г.

telegram-bot в общем чате

#python #telegram_api #telegram_bot

Сделал простого telegram-бота:

import telebot
@bot.message_handler(content_types=["text"])
def repeat_all_messages(message):
    if (message.text.split(" ")[0].upper() == 'BOT,'):
        bot.send_message(message.chat.id, 'I\'m here')


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


Ответы

Ответ 1



Вариантов несколько: Можно обращаться к боту через слеш / - /YourMessage, если в группе несколько ботов, то с упоминанием его юзернейма - /YourMessage@YourBotName. Можно задать боту список команд с помощью @BotFather, тогда при вводе слеша пользователь увидит список всех доступных команд и сможет выбрать нужную. Можно отключить privacy mode, тогда к бот будет получать все сообщения от группы, кроме сообщений от других ботов. По умолчанию privacy mode включен. Можно сделать бота администратором группы, что так же позволит получать все сообщения от группы, кроме сообщений от других ботов. What messages will my bot get? Your bot will receive all messages from users in one-on-one chats. Privacy mode only applies to messages in groups (or supergroups). Privacy mode is always disabled if your bot is an admin in the group. For supergroups, privacy mode is set to what your bot was using when it joined the group — if you change it later, you'll need to remove the bot and add it again for changes to take effect. By default, your bot runs in privacy mode and only sees the following messages in groups (or supergroups): Replies to the bot's own messages (messages sent via a custom keyboard are always a reply to the bot). Commands from users meant for your bot (e.g. /start@YourBot). General commands from users (e.g. /start) if your bot was the last bot that sent a message to the group. Service messages (e.g. when somebody leaves or joins a group, group name or photo changes, etc.). If your bot is an admin or if privacy mode is disabled, your bot will get all messages sent to the group, except for messages from other bots. Ссылка

понедельник, 23 декабря 2019 г.

Как создать клавиатуру, которая не будет сразу отправлять?

#python #telegram_api #telegram_bot

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

клавиатура:
1 2 3 +
4 5 6 -
7 8 9 *
0 . / 


Как сделать, чтобы после нажатия символы появлялись в строке, а не сразу отправлялись
боту? 
    


Ответы

Ответ 1



В текущей версии Telegram Bot API (Bot API 3.0, 18/05/2017) это не реализовано. Вы можете использовать для этого встроенную клавиатуру, выполняя свои вычисления и после нажатия кнопки = отправлять сообщение с результатом вычислений пользователю. Unlike with custom reply keyboards, pressing buttons on inline keyboards doesn't result in messages sent to the chat. Так же по теме - Telegram Bot API кастомная клавиатура, отправка нескольких значений в одном сообщении

суббота, 21 декабря 2019 г.

Telegram bot php. Inline keyboard. Подскажите, что делать дальше с callback_data. Что бы после нажатия на кнопку inline keyboard - бот ее обработал

#php #telegram_api #telegram_bot

Подскажите, пожалуйста как написать простой сценарий для бота, например:
написал команду "/test",
 бот спрашивает: "Вы уверены?"
пишешь в ответ: "Да"
бот отправляет следующее сообщение по сценарию, если пишешь "нет" - сценарий заканчивается.
Важно, что бы мой ответ "Да" не обрабатывался ботом, пока он не спросит "Вы уверены?"(после
команды /test)  

"First Button","callback_data"=>"test1");
$x2 = array("text"=>"Second Button","callback_data"=>"test2");
$opz = [[$x1,$x2]];
$keyboard=array("inline_keyboard"=>$opz);
$keyboard = json_encode($keyboard);  
      sendMessage($chat_id, "testt2", $keyboard);
      break;


т.е. сейчас при нажатии на кнопку ничего не вывыодится
    


Ответы

Ответ 1



Вот рабочий код, если кому нужен. "Google url","url"=>"http://google.com"); $inline_button2 = array("text"=>"work plz","callback_data"=>'/plz'); $inline_keyboard = [[$inline_button1,$inline_button2]]; $keyboard=array("inline_keyboard"=>$inline_keyboard); $replyMarkup = json_encode($keyboard); sendMessage($chat_id, "ok", $replyMarkup); break; } switch($data){ case '/plz': sendMessage($chat_id_in, "plz"); break; } function sendMessage($chat_id, $message, $replyMarkup) { file_get_contents($GLOBALS['api'] . '/sendMessage?chat_id=' . $chat_id . '&text=' . urlencode($message) . '&reply_markup=' . $replyMarkup); }

Отправка письма в telegram

#php #telegram_api

Подскажите, кто нибудь сталкивался в отправкой письма с помощью php в телеграмм конкретному
статичному пользователю? 

Намекните хоть как идти? API у них чет не особое.
    


Ответы

Ответ 1



Как идти Сначала сюда (на англ.). Описано что такое боты, зачем и как написать. Затем следуете инструкции: в Телеграме начните диалог с ботом BotFather – командой /newbot создадите нового бота и получите для него токен; Получаете сообщения для вашего бота одним из двух способов: сами периодически запрашиваете обновления у Телеграма для вашего бота («Эй, есть новые сообщения?»); указываете Телеграму URL, по которому тот сам будет к вам стучать, как только получит сообщение для вашего бота. Получив сообщение от пользователя, вы можете в ответ отправить, документ, картинку, видео, ещё много, чего, или просто сообщение. Я пока такой простенький метод написал для вызова методов API Telegram: private function callApi( $method, $params) { $url = sprintf( "https://api.telegram.org/bot%s/%s", Config::get('telegram.token'), $method ); $ch = curl_init(); curl_setopt_array( $ch, array( CURLOPT_URL => $url, CURLOPT_POST => TRUE, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_FOLLOWLOCATION => FALSE, CURLOPT_HEADER => FALSE, CURLOPT_TIMEOUT => 10, CURLOPT_HTTPHEADER => array( 'Accept-Language: ru,en-us'), CURLOPT_POSTFIELDS => $params, )); $response = curl_exec($ch); return json_decode( $response); } Например, уже получив сообщение $data, можно на него ответить примерно так: $this->callApi( 'sendMessage', array( 'chat_id' => $data->message->chat->id, 'text' => "Здесь сообщение от нашего бота", // 'reply_to_message_id' => $data->message->message_id, ));

Ответ 2



Начни с отправки самого POST запроса через браузер, пойми как работает это: https://api.telegram.org/bot<токен бота>/sendMessage?chat_id=<айди чата, куда хочешь отправить>&text= затем разложи это на переменные в коде и отправляй. вот рабочий код, вставь только токен бота:

Ответ 3



Отличное API у них. // прочитываем входящую инфо $content = file_get_contents("php://input"); // принимаем JSON строку и преобразуем ее в переменную PHP $update = json_decode($content, true); //получаем ID чата $chatID = $update["message"]["chat"]["id"]; $uID = $update["message"]["from"]["username"]

Ответ 4



Попробуй вот это PHP Wrapper and Drupal module using Telegram CLI. Обертка PHP для Телеграма для командной строки

Ответ 5



Смотрите akalongman/php-telegram-bot https://github.com/akalongman/php-telegram-bot

вторник, 10 декабря 2019 г.

Достать все сообщения с публичного чата Telegram

#php #laravel #telegram_bot #telegram_api #telegram

Как спарсить заданное пользователем количество сообщений с публичного чата Telegram?

На входе пользователь вводит url чата и количество сообщений которое нужно спарсить.
Раньше никогда не работал ни с ботами Телеграм, ни с его АПИ. Как лучше это реализовать?
Возможно есть готовые библиотеки для данной задачи? 
    


Ответы

Ответ 1



Если нужно парсить с любого рандомного публичного чата, то через Telegram-Bot-API этого не сделать. Потому что бот читает только из чата, куда он добавлен сам. Для ботов есть только один способ получать сообщения - метод getUpdates получает все сообщения за определенный период, но надо понимать, что в ответ приходит данные по всем чатам и определять нужный придется самостоятельно. Для понимания как писать именно ботов для Telegram можно почитать вот эту статью - https://netology.ru/blog/bot-php ну или любую другую по запросу telegram бот на php их достаточно много=) Для того что бы парсить из любого чата, нужно писать свой клиент для Telegram, тогда можно будет использовать метод messages.getHistory() Нашел реализацию клиента Telegram на PHP - MadelineProto, можно попробовать использовать ее. Дополнительно можно почитать: https://stackoverflow.com/questions/34687435/telegram-api-with-php-not-bot - в ответах есть краткое описание шагов по созданию клиента для Telegram https://core.telegram.org/#getting-started - дока по TelegramAPI

воскресенье, 8 декабря 2019 г.

Уведомления с сайта в Telegram

#php #веб_программирование #telegram_bot #telegram_api #notifications

Есть сайт, созданный без использования движков. Хочу прикрутить форму обратной связи,
чтобы посетитель оставил свой номер и имя в специальной форме, а эти данные потом передались
менеджеру в Telegram. Можете подробно объяснить, как это делается?
    


Ответы

Ответ 1



Создаешь нового бота в Telegram, пишешь сюда: t.me/botFather сначала /start, затем /newbot. Узнаешь ID твоего аккаунта в Telegram. Сделать это можно, написав боту t.me/userinfobot Создаешь ссылку на API Telegram для отправки сообщения в чат с тобой (предварительно нужно начать чат с твоим ботом в Telegram, для этого нужно нажать /start). Ссылка выглядит таким образом: https://api.telegram.org/bot[Токен бота]/sendMessage?chat_id=[Твой ID]&text=[Текст] Затем нужно настроить обработчик твоей формы. Тут уже по твоей части, просто берем данные, к примеру: $phone = $_POST['phone']; $email = $_POST['email']; $firstname = $_POST['firstname']; Затем генерируем сообщение, которое хотим отправить в Telegram. Опять же, для примера: $msg = "Новая заявка на сайте! \nE-mail: $email \nТелефон: $phone \n Имя: $name"; Затем необходимо отправить эти данные в телеграм. Делать это можно разными способами, самый простой: $token = *Вставь сюда токен своего бота*; $telegram_admin_id = *Сюда твой ID, взятый из userinfobot*; $msg = "Новая заявка на сайте! \nE-mail: $email \nТелефон: $phone \n Имя: $name"; file_get_contents(https://api.telegram.org/bot'. $token .'/sendMessage? chat_id='. $telegram_admin_id .'&text=' . urlencode($msg));

пятница, 12 июля 2019 г.

Сохранение сессии Telegram API

Приветствую.
Возник вопрос по поводу Telegram API (не Bot API). Не могу понять, как сохранить данные пользователя после его первой аутентификации в приложении. В данный момент при каждом входе идет запрос кода.
После первого удачного входа пробовал сохранять phoneCodeHash, номер телефона и phoneCode. В принципе, это работает до истечения срока кода аутентификации.
Возможно, сейчас я путаю, потому что использую представление данного API на Java с библиотекой Kotlogram. Реализация аутентификации в сэмпле:
ApiStorage.java
public static class ApiStorage implements TelegramApiStorage {
//Create File variable for auth.key and dc.save public static final File AUTH_KEY_FILE = new File("Properties/auth.key"); public static final File NEAREST_DC_FILE = new File("Properties/dc.save");
@Override public void saveAuthKey(@NotNull AuthKey authKey) { try { FileUtils.writeByteArrayToFile(AUTH_KEY_FILE, authKey.getKey()); } catch (IOException e) { e.printStackTrace(); } }
@Nullable @Override public AuthKey loadAuthKey() { try { return new AuthKey(FileUtils.readFileToByteArray(AUTH_KEY_FILE)); } catch (IOException e) { if (!(e instanceof FileNotFoundException)) e.printStackTrace(); }
return null; }
@Override public void saveDc(@NotNull DataCenter dataCenter) { try { FileUtils.write(NEAREST_DC_FILE, dataCenter.toString()); } catch (IOException e) { e.printStackTrace(); } }
@Nullable @Override public DataCenter loadDc() { try { String[] infos = FileUtils.readFileToString(NEAREST_DC_FILE).split(":"); return new DataCenter(infos[0], Integer.parseInt(infos[1])); } catch (IOException e) { if (!(e instanceof FileNotFoundException)) e.printStackTrace(); }
return null; }
@Override public void deleteAuthKey() { try { FileUtils.forceDelete(AUTH_KEY_FILE); } catch (IOException e) { e.printStackTrace(); } }
@Override public void deleteDc() { try { FileUtils.forceDelete(NEAREST_DC_FILE); } catch (IOException e) { e.printStackTrace(); } }
@Override public void saveSession(@Nullable MTSession session) {
}
@Nullable @Override public MTSession loadSession() { return null; } }
Сама аутентификация в Java Console.
public class Main { // Get them from Telegram's console public static final int API_ID = api id; public static final String API_HASH = api hash;
// What you want to appear in the "all sessions" screen public static final String APP_VERSION = "AppVersion"; public static final String MODEL = "Model"; public static final String SYSTEM_VERSION = "SysVer"; public static final String LANG_CODE = "en";
public static TelegramApp application = new TelegramApp(API_ID, API_HASH, MODEL, SYSTEM_VERSION, APP_VERSION, LANG_CODE); public static final String PHONE_NUMBER = "тут был телефон"; // International format
public static void main(String[] args) { TelegramClient client = Kotlogram.getDefaultClient(application, new ApiStorage());
try { TLSentCode sentCode = client.authSendCode(false, PHONE_NUMBER, true); System.out.println("Authentication code: "); String code = new Scanner(System.in).nextLine();
TLAuthorization authorization = client.authSignIn(PHONE_NUMBER, sentCode.getPhoneCodeHash(), code); TLUser self = authorization.getUser().getAsUser(); System.out.println("You are now signed in as " + self.getFirstName() + " " + self.getLastName() + " @" + self.getUsername()); } catch (RpcErrorException | IOException e) { e.printStackTrace(); } finally { client.close(); // Important, do not forget this, or your process won't finish } } }
Данную реализацию я использую в Android приложении. Конечно, все раскидано по асинхронным потокам. Но каждый раз при входе в приложение идет проверка кода авторизации. Из-за этого я за сегодня заблокировал 3 разных аккаунта на день по причине флуда авторизации.
В качестве обходного варианта я использовал подстановку значений в данном методе, запоминая их при удачной авторизации.
client.authSignIn(phoneNumber, phoneCodeHash, phoneCode);
Это работает только до того момента, пока код не истечет. Возможно, кто-то знает как это решается на уровне самого API, а не библиотеки, или сможет предложить вариант использования других подходов для работы с Telegram API: стандартный API, TDlib или какое-либо другое решение для авторизации пользователей в приложении через Telegram на Java.
Честно, не смог ни с чем другим разобраться. Заранее благодарю за ответы.


Ответ

Нашел решение методом научного тыка. Я был действительно не прав, т.к. данная библиотека сама умеет отрабатывать сессии. Просто делает это (на мой взгляд) очень неочевидно. Прикладываю ниже рабочее решение в виде консольного приложения на Java. Это же решение работает и для Android приложения.
public class Main { // Get them from Telegram's console private static final int API_ID = /*put api id here*/; private static final String API_HASH = "put hash here";
// What you want to appear in the "all sessions" screen private static final String APP_VERSION = "AppVersion"; private static final String MODEL = "Model"; private static final String SYSTEM_VERSION = "SysVer"; private static final String LANG_CODE = "en";
private static TelegramApp application = new TelegramApp(API_ID, API_HASH, MODEL, SYSTEM_VERSION, APP_VERSION, LANG_CODE); private static final String PHONE_NUMBER = "put a phone number here"; // International format
public static void main(String[] args) { TelegramClient client = Kotlogram.getDefaultClient(application, new ApiStorage());
try { TLUserFull userFull = client.usersGetFullUser(new TLInputUserSelf()); TLUser self = userFull.getUser().getAsUser(); showUserInfo(self); } catch (RpcErrorException e) { if (e.getTag().equals("AUTH_KEY_UNREGISTERED")) signInUser(client); else e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { client.close(); } }
private static void signInUser(TelegramClient client) { try { // Send code to account TLSentCode sentCode = client.authSendCode(false, PHONE_NUMBER, true); System.out.println("Authentication code: "); String code = new Scanner(System.in).nextLine();
TLAuthorization authorization = client.authSignIn(PHONE_NUMBER, sentCode.getPhoneCodeHash(), code); TLUser self = authorization.getUser().getAsUser();
showUserInfo(self); } catch (Exception e) { e.printStackTrace(); } }
private static void showUserInfo(TLUser user) { System.out.println("You are now signed in as " + user.getFirstName() + " " + user.getLastName() + " @" + user.getUsername()); } }
Не знаю, кто плюсовал данный вопрос, но, надеюсь, что оно кому-нибудь поможет. Спасибо.

понедельник, 8 июля 2019 г.

Как Telegram боту узнать новых пользователей, которые добавляются в чат? - C#

Пишу бота для администрирования чата. Подскажите, как боту узнать новых пользователей, которые добавляются в чат? Как это реализовать?


Ответ

Это делается очень просто - у объекта Message есть поле new_chat_member типа User, соответственно при получении апдейтов проверяйте объект Message на наличие непустого поля new_chat_member, это и будет означать, что в чат добавлен новый юзер.
Пример
if (update.Type == UpdateType.MessageUpdate && update.Message.NewChatMember != null) { await bot.SendTextMessageAsync(update.Message.Chat.Id, $"*{update.Message.NewChatMember.FirstName}, добро пожаловать!*", true, false, 0, null, ParseMode.Markdown); return; }

вторник, 30 апреля 2019 г.

Telegram bot php. Inline keyboard. Подскажите, что делать дальше с callback_data. Что бы после нажатия на кнопку inline keyboard - бот ее обработал

Подскажите, пожалуйста как написать простой сценарий для бота, например: написал команду "/test", бот спрашивает: "Вы уверены?" пишешь в ответ: "Да" бот отправляет следующее сообщение по сценарию, если пишешь "нет" - сценарий заканчивается. Важно, что бы мой ответ "Да" не обрабатывался ботом, пока он не спросит "Вы уверены?"(после команды /test)
$access_token = '...'; $api = 'https://api.telegram.org/bot' . $access_token;
$output = json_decode(file_get_contents('php://input'), TRUE); $chat_id = $output['message']['chat']['id']; $first_name = $output['message']['chat']['first_name']; $message = $output['message']['text']; switch($message) { case '/test': sendMessage($chat_id, "Вы уверены?"); break; default: $sorry_text = $first_name . ' , мне нечего ответить'; sendMessage($chat_id, $sorry_text); } function sendMessage($chat_id, $message, $encodedMarkup) { file_get_contents($GLOBALS['api'] . '/sendMessage?chat_id=' . $chat_id . '&text=' . urlencode($message) . $encodedMarkup); }
Понял, что это делается через ForceReply, но как пока не разобрался. UPDATE сделал inline keybord, но пока не понял как выводить сообщение в зависимости от нажатой кнопки case '/test':
$x1 = array("text"=>"First Button","callback_data"=>"test1"); $x2 = array("text"=>"Second Button","callback_data"=>"test2"); $opz = [[$x1,$x2]]; $keyboard=array("inline_keyboard"=>$opz); $keyboard = json_encode($keyboard); sendMessage($chat_id, "testt2", $keyboard); break;
т.е. сейчас при нажатии на кнопку ничего не вывыодится


Ответ

Вот рабочий код, если кому нужен.
"Google url","url"=>"http://google.com"); $inline_button2 = array("text"=>"work plz","callback_data"=>'/plz'); $inline_keyboard = [[$inline_button1,$inline_button2]]; $keyboard=array("inline_keyboard"=>$inline_keyboard); $replyMarkup = json_encode($keyboard); sendMessage($chat_id, "ok", $replyMarkup); break; } switch($data){ case '/plz': sendMessage($chat_id_in, "plz"); break; } function sendMessage($chat_id, $message, $replyMarkup) { file_get_contents($GLOBALS['api'] . '/sendMessage?chat_id=' . $chat_id . '&text=' . urlencode($message) . '&reply_markup=' . $replyMarkup); }

понедельник, 18 марта 2019 г.

Направление движения транспорта с помощью картинки Python

Пишу телеграмм бота, который показывает движение транспорта на карте. Делаю это на питоне.
C картами телеграмм работает ограничено показывает только булавку, а мне нужно нарисовать и направление?

вот пример данных, которые я получаю
1, 1, 39692550, 47219635, 12, 138, 344, тип, номер_широта, долгота_скорость, курс, номер
предпоследний параметр показывает градусы по окружности.
Идея была такая, взять картинку со стрелкой и наклонять ее насколько надо. И просто отправлять ее после карты ниже. Реализовал все с помощью библиотеки PIL , но получается плохо. После каждого поворота картинки, приходиться ее сохранять и под конец, она уже выглядит как набор пикселей.
Можете ли вы мне подсказать другие варианты? Может все таки можно нанести на карту стрелку движения как в навигаторе. А может можно с помощью какой-нибудь математической библиотеки рисовать каждый раз компас с направлением и отправлять его как картинку?
Даже для юмора хотел реализовать все с помощью черепашки, но как создать изображение я так не разобрался.
Решил проблему используя google charts, передаю градусы по ссылке и гугл рисует сам картинку с направлением. Но все же вопрос в том,можно ли присылать локацию со стрелкой, а не с булавкой ?


Ответ

Но все же вопрос в том,можно ли присылать локацию со стрелкой, а не с булавкой ?
Ответ на этот вопрос - нет. Локация - это точка на карте, как следует из документации
Location This object represents a point on the map.
А метод sendLocation предназначен только для этого:
Use this method to send point on the map.
Если Вам нужен какой-то специфичный функционал, то попробуйте использовать какие-то сторонние сервисы, генерирующие необходимое Вам изображение и посылайте его в виде фото.

четверг, 10 января 2019 г.

telegram-bot в общем чате

Сделал простого telegram-бота:
import telebot @bot.message_handler(content_types=["text"]) def repeat_all_messages(message): if (message.text.split(" ")[0].upper() == 'BOT,'): bot.send_message(message.chat.id, 'I\'m here')
Все отлично работает, но когда добавляю его в групповой чат, то он молчит. Подскажите, как сделать его адаптированным к групповым чатам ?


Ответ

Вариантов несколько:
Можно обращаться к боту через слеш / - /YourMessage, если в группе несколько ботов, то с упоминанием его юзернейма - /YourMessage@YourBotName Можно задать боту список команд с помощью @BotFather, тогда при вводе слеша пользователь увидит список всех доступных команд и сможет выбрать нужную. Можно отключить privacy mode, тогда к бот будет получать все сообщения от группы, кроме сообщений от других ботов. По умолчанию privacy mode включен. Можно сделать бота администратором группы, что так же позволит получать все сообщения от группы, кроме сообщений от других ботов.
What messages will my bot get? Your bot will receive all messages from users in one-on-one chats. Privacy mode only applies to messages in groups (or supergroups). Privacy mode is always disabled if your bot is an admin in the group. For supergroups, privacy mode is set to what your bot was using when it joined the group — if you change it later, you'll need to remove the bot and add it again for changes to take effect. By default, your bot runs in privacy mode and only sees the following messages in groups (or supergroups): Replies to the bot's own messages (messages sent via a custom keyboard are always a reply to the bot). Commands from users meant for your bot (e.g. /start@YourBot). General commands from users (e.g. /start) if your bot was the last bot that sent a message to the group. Service messages (e.g. when somebody leaves or joins a group, group name or photo changes, etc.). If your bot is an admin or if privacy mode is disabled, your bot will get all messages sent to the group, except for messages from other bots.
Ссылка

вторник, 20 ноября 2018 г.

Как создать клавиатуру, которая не будет сразу отправлять?

Создал клавиатуру в своем боте, но она отправляет сразу после нажатия, а мне надо, чтобы она работала как стандартная: пока не нажал отправить, он не отправит, например:
клавиатура: 1 2 3 + 4 5 6 - 7 8 9 * 0 . /
Как сделать, чтобы после нажатия символы появлялись в строке, а не сразу отправлялись боту?


Ответ

В текущей версии Telegram Bot API (Bot API 3.0, 18/05/2017) это не реализовано. Вы можете использовать для этого встроенную клавиатуру, выполняя свои вычисления и после нажатия кнопки = отправлять сообщение с результатом вычислений пользователю.
Unlike with custom reply keyboards, pressing buttons on inline keyboards doesn't result in messages sent to the chat.

Так же по теме - Telegram Bot API кастомная клавиатура, отправка нескольких значений в одном сообщении

суббота, 27 октября 2018 г.

Достать все сообщения с публичного чата Telegram

Как спарсить заданное пользователем количество сообщений с публичного чата Telegram?
На входе пользователь вводит url чата и количество сообщений которое нужно спарсить. Раньше никогда не работал ни с ботами Телеграм, ни с его АПИ. Как лучше это реализовать? Возможно есть готовые библиотеки для данной задачи?


Ответ

Если нужно парсить с любого рандомного публичного чата, то через Telegram-Bot-API этого не сделать. Потому что бот читает только из чата, куда он добавлен сам.
Для ботов есть только один способ получать сообщения - метод getUpdates получает все сообщения за определенный период, но надо понимать, что в ответ приходит данные по всем чатам и определять нужный придется самостоятельно.
Для понимания как писать именно ботов для Telegram можно почитать вот эту статью - https://netology.ru/blog/bot-php ну или любую другую по запросу telegram бот на php их достаточно много=)
Для того что бы парсить из любого чата, нужно писать свой клиент для Telegram, тогда можно будет использовать метод messages.getHistory()
Нашел реализацию клиента Telegram на PHP - MadelineProto, можно попробовать использовать ее.
Дополнительно можно почитать: https://stackoverflow.com/questions/34687435/telegram-api-with-php-not-bot - в ответах есть краткое описание шагов по созданию клиента для Telegram https://core.telegram.org/#getting-started - дока по TelegramAPI