telegram-rs / telegram-bot Goto Github PK
View Code? Open in Web Editor NEWRust Library for creating a Telegram Bot
License: MIT License
Rust Library for creating a Telegram Bot
License: MIT License
A message containing pinned_message (which in itself is a message object) crashes the bot wit the elusive error JsonDecode(ApplicationError("No field for inferring message type is set"))
.
I'm not sure how to fix this myself, as the message object makes it non-trivial.
[Also I'm running the supergroup-migration branch and would like it to be added to stable]
There have been a few changes to the official Telegram bot API:
https://core.telegram.org/bots/api-changelog
This library isn't up to date right now -- Someone need to fix that. I don't know when I find some free time for that.
We might want to change the crate name from telegram-bot
to something else. To word crate names are a bit ugly in my opinion. Therefore it would be nice to come up with a nice one-word name. Note that we are likely to split this library into at least two crates: the standard one and a -raw
version to include more low level features. So consider all name suggestions here with a -raw
postfix, too.
In order to make it easier for everyone to express their opinion, I will (and you should, too) create one comment for each name suggestion. That way everyone can use emojis.
Also, before suggesting names, please make sure that the name is still available on crates.io
.
Hi,
I'm trying to send message from another thread than the one which run the event loop.
I tried to use a Remote instead of a Handle but I don't work by just changing that.
I'm currently learning rust and trying to find a way to be able to use Remote or Handle in ApiInner, but I think you may have a better/faster idea to do that.
EDIT: I found a way to do that using an other crate in addition to this one.
Can the bot send the live location? I wanna use the bot for tracking. Should I just send new location via telegram_bot::types::requests::SendLocation
repeatedly for this or there is another way?
It can prevent busy looping in some cases, network errors, for example.
Maybe it should return String
.
We can't release a new version until async hyper release, but there is stable tokio-curl.
Hello.
I need to explicitly check that the certificate can be trusted (i.e. is issued by a proper CA, valid and not expired nor revoked) each time when connecting to api.telegram.org via HTTPS to avoid potential MitM attacks.
Also I'd like to force that only the latest supported version of TLS is used, the crypto key length is adequate enough and the TLS setup doesn't allow for certain silly vulnerabilities (like infamous Padding Oracle attack) to be exploited by a man in the middle.
I'm playing with this library (master) but find that it's unable to pattern matching on chat
field of a Message
.
The Message
struct looks like:
pub struct Message {
pub id: MessageId,
pub from: User,
pub date: Integer,
pub chat: MessageChat,
pub forward: Option<Forward>,
pub reply_to_message: Option<Box<MessageOrChannelPost>>,
pub edit_date: Option<Integer>,
pub kind: MessageKind,
}
The chat
field has type of MessageChat
, which is defined in telegram_bot_raw::types::chat
module. This module is not re-exported in the top level module of telegram-bot crate, so I'm not able to use it directly.
Now I have to include the telegram-bot-raw crate to achieve my goal, but I think this might not be intended.
As can be seen with this test:
#[test]
fn decode_groupchat_chat() {
use Chat;
let group = r#"{"title":"This is a group chat","id":-12345678}"#;
let chat: Chat = json::decode(&group).unwrap();
assert!(chat.is_group());
}
I guess User::decode(d)
consumes the data, so that if it fails, there's nothing left for the second decode
call to decode.
impl Decodable for Chat {
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
// If the object can be decoded as User: Return the user. Otherwise
// try to decode the object as Group.
match User::decode(d) {
Ok(user) => Ok(Chat::User(user)),
Err(_) => Ok(Chat::Group(try!(Decodable::decode(d)))),
}
}
}
We might still change the name of this organization.
I, however, think that this name is actually pretty good. Keep in mind that this organization might host multiple things, not just this library. Maybe we even want to maintain our own bot to... I don't know... mimic the playbot from IRC. So the organization is about "Telegram" and "Rust".
Please signal with emoji on this comment whether or not you agree with me :)
Right now the listener is blocking, so if there's a command handler that takes long, it will block the entire bot. Also, a panic will take down the entire chatbot.
Could we maybe run all handler code in background threads, e.g. using a thread pool? That would be similar to the way Iron handles requests, I think.
To keep things simple, you could also offer two version of the listen loop, listener.listen
and listener.listen_threaded
.
Since Supergroup updated the id to 1e13, default i32 will suffer a panic because it is too big for i32.
Missing methods, without multipart dependency and without inline bots and games support:
API design:
Unknown
variants in enums and make enums non-exhaustiveIO:
UpdatesStream
Docs:
Right now the library uses a GET request to send messages. It also doesn't bother to URL encode the message text, which means that you can easily send messages with parameters in the text to invoke API features.
For example, you can send text like this
test&disable_notification=true
or this
random reply&reply_to_message_id=1337
or this
test force reply&reply_markup={"force_reply":true}
or this
test reply keyboard&reply_markup={"keyboard":[[{"text":"Bad"},{"text":"Worse"}],[{"text":"Awful"}]],"resize_keyboard":true}
or even this
test inline&reply_markup={"inline_keyboard":[[{"text":"🔥","callback_data":"fire"},{"text":"👍","callback_data":"+1"},{"text":"😂","callback_data":"haha"}],[{"text":"google","url":"https://google.com/"}]]}
Anyway this is really bad. For instance, if you write a Telegram <-> IRC mirror bot, or anything else where other users have control over the text of the message sent.
Using a POST request will completely avoid all of this junk.
It can be easily implemented via async interface, just with Result
instead of TelegramFuture
.
The bot can currently recieve files, but it would be great if it could also send them.
Yesterday (April 6) suddenly my bot stopped working, getting this JSON error when parsing Telegram update obects. I've checked that simple
example of the telegram-bot library is crashing now too.
There were no recent changes in Telgram Bot API, so this behaviour is strange.
The error of the future, passed to updates stream:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err`
value: Error(Raw(Json(ErrorImpl { code: Message("invalid type: map, expected a string"),
line: 2, column: 268 })), State { next_error: None, backtrace: None })'
The examples in the repo end with something like:
let res = listener.listen(|u| {
})
if let Err(e) = res {
println!("An error occured: {}", e);
}
The easy way to deal with errors is to put a loop around this. But ... what would be the suggested way to do it? For example, it would be nice to retry if a network error occurs but maybe it should fail for other errors.
Hyper merged async IO but warned that merge would be a breaking change.
Maybe this would become a breaking change for telegram-bot too.
Hi, I'm getting this error for a message when trying to use the library.
JsonDecode(ApplicationError("No field for inferring message type is set"))
Seems like it's encountering a message type the library doesn't know?
I can give you the source code if needed but it's almost the same as the example.
If you can't reproduce it I am willing to give you the bot token so you can see it happening.
Also taking a look at trying to fix it myself, but I cannot promise anything on that front.
Telegram just released this: https://telegram.org/blog/bots-2-0
Tracking issue for implementing those features...
this code
if let MessageKind::Text {ref data, ..} = message.kind {
// Print received text message to stdout.
println!("<{}>: {}", first_name, data);
// Answer message with "Hi".
api.spawn(message.text_reply(
format!("Hi, {}! You just wrote '{}'", first_name, data)
));
}
repies with a quote. How to reply without one?
Hi there :)
Futures just got updated to v0.2 about a week ago. As a result the examples break, if you try to run it with the newest version.
Hi!
I've been playing with this library learning Rust from a while, and I'm doing some changes and adding new things (all the send* methods for example), I don't know too much Rust, but I know the API so well xD
I just want to let you know that I'm working on it, I don't have good internet until september but I will try to clean my code and do a PR before 😄
Thanks for the library =D
See sendMessage
The use case:
How I do it:
let mut core = Core::new().unwrap();
let api = Api::configure(token).build(core.handle());
let send_message = SendMessage::new(UserId(user_id), "Hello");
let future = api.send(send_message);
core.run(future).unwrap();
Error message I get:
--> src/main.rs:84:15
|
84 | let uid = UserId(user_id);
| ^^^^^^ did you mean `UserId { /* fields */ }`?
Solution proposal:
UserId
field public.pub struct UserId(Integer);
But it works fine with:
pub struct UserId(pub Integer);
Probably some other structs must be updated this way as well. What do you think?
See changelog.
I'm interested in working on the Inlinekeyboard features and Callback Interface.
Can you give some hints where to start? I already saw some stubbed / commented out infrastructure.
let reply_keyboard = reply_markup!(reply_keyboard, selective, one_time, resize,
["button", "button"],
["button" contact], // Request contact
["button" location] // Request location
);
let remove_keyboard = reply_markup!(remove_keyboard);
let selective_remove_keyboard = reply_markup!(remove_keyboard, selective);
let force_reply = reply_markup!(force_reply);
let selective_force_reply = reply_markup!(force_reply, selective);
let inline_keyboard = reply_markup!(inline_keyboard,
["button" callback "0,0", "button" callback "0,1"],
["button" callback "1,0", "button" callback "1,1", "button" callback "1,2"]
);
There are new chat types: supergroup
and channel
.
hi , we trying to create a bot ... actually , we almost finish it but when we trying to use it with my friends at the same time bot get crushed and do every command -that we save them in data base- mixed up and do every thing wrong , but when we use it one by one it do pretty well . please help us .
I just added the method set_webhook
on the dev branch. However, I wasn't able to provide a listen
method that works similar to long_pull
, but uses the webhook to acquire updates.
There are several problems that stop me from implementing listen
, but mainly I didn't do it for this reason: I can't test it. Telegram sends updates via HTTPS only and does NOT accept self signed certs. Maybe this will change in the future, but right now I don't have time to get one and test more http stuff.
Just use long_pull
for now.
I'm wondering why one should clone an Api
. hyper::Client
does not implement Clone
, implementing it for Api
introduces unnecessary complexity (especially with http timeouts). I also want to discourage users from cloning the Api
, because it doesn't make sense (right?).
Sadly removing something like this is a breaking change 😞
@knsd any thoughts on this?
We could use the log
crate to add more logging. This would help debugging bots and reporting bugs with accurate information.
Apparently sending a message via the Api::send_message
function is very slow, at least for me. It takes up to 550ms to send a single message for me, where as my bot written in Go takes only ~50ms.
I measured it using the time
crate, using the function time::precise_time_ns
.
Thanks for working on this but I am facing an issue.
I tried to compile simple.rs with my token but it gives me
Compiling telegram_test v0.1.0 (file:///home/pi/scripts/rust/telegram_test)
error[E0433]: failed to resolve. Use of undeclared type or moduleUpdateKind
--> src/main.rs:21:16
|
21 | if let UpdateKind::Message(message) = update.kind {
| ^^^^^^^^^^^^^^^^^^^ Use of undeclared type or moduleUpdateKind
error[E0433]: failed to resolve. Use of undeclared type or moduleMessageKind
--> src/main.rs:29:20
|
29 | if let MessageKind::Text {ref data, ..} = message.kind {
| ^^^^^^^^^^^^^^^^^ Use of undeclared type or moduleMessageKind
error: no associated item namedconfigure
found for typetelegram_bot::Api
in the current scope
--> src/main.rs:15:15
|
15 | let api = Api::configure(token).build(core.handle());
| ^^^^^^^^^^^^^^
error: aborting due to previous error
error: Could not compiletelegram_test
.
To learn more, run the command again with --verbose.
My dependencies section in Cargo.toml
[dependencies]
futures = "0.1.13"
telegram-bot = "0.5"
tokio-core = "0.1.7"
Output of cargo -V
cargo 0.18.0 (fe7b0cdcf 2017-04-24)
Output of rustc -V
rustc 1.17.0 (56124baa9 2017-04-24)
Output of uname -a
Linux raspberrypi 4.4.50-v7+ #970 SMP Mon Feb 20 19:18:29 GMT 2017 armv7l GNU/Linux
Am I missing something?
Is there a way to send messages to some user using stored user id in database? There is no such examples and i can't find a way to manually create Message struct.
The development of this library is horribly slow; not due to the developers but due to me maintaining it. The problem is that merging code every few months requires me to re-understand the whole library and Telegram-API in order to decide if the changes are valid. This is the reason for why this library is bit-rotting 😞
To finally ease development, I suggest to add a very good integration test. This test should test all features of the API with a real bot, if somehow possible. I want to be able to merge immediately if the code looks clean and all tests passed.
Any comments? What do you think @knsd @dns2utf8 @neuschaefer @rockneurotiko?
Hi folks,
Telegram Bot API document recommends bot clients to answer to CallbackQuery with an answerCallbackQuery request. Quoted below (source):
NOTE: After the user presses a callback button, Telegram clients will display a progress bar until you call answerCallbackQuery. It is, therefore, necessary to react by calling answerCallbackQuery even if no notification to the user is needed (e.g., without specifying any of the optional parameters).
However, the text and other stuff are optional. In this crate, there's a request struct AnswerCallbackQuery
, where the text is required. I think the field should be optional because sometimes alerts can be spammy when users interact to inline keyboard, especially when they're pressing quite frequently.
I think this can be improve to match the official doc by making the text field a Option<Cow<'t, str>>
type. What do you think?
If you think it's worth-doing, I can file a pull request later. Thanks :)
An error occured: JsonDecode(ApplicationError("No field for inferring message type is set"))
Hello,
First, thanks for this great crate.
I'm wondering how the rewrite is going since the last commit dates from more than 6 months. Is it happening outside Github or in a hidden branch?
Thanks
I have a bot that works just fine just after starting it. However, it stops responding after some time without usage. I do not see anything weird in the logs. Any clue?
DEBUG:hyper::net: https scheme
DEBUG:hyper::http::h1: request line: Post "/<redacted>/getUpdates" Http11
DEBUG:hyper::http::h1: headers=Headers { Content-Type: application/x-www-form-urlencoded, Host: api.telegram.org, Content-Length: 27, Connection: close, }
DEBUG:hyper::client::response: version=Http11, status=Ok
DEBUG:hyper::client::response: headers=Headers { Access-Control-Allow-Origin: *, Content-Length: 23, Access-Control-Allow-Methods: GET, POST, OPTIONS, Strict-Transport-Security: max-age=31536000; includeSubdomains, Connection: close, Content-Type: application/json, Server: nginx/1.6.2, Date: Tue, 22 Mar 2016 07:34:11 GMT, }
DEBUG:hyper::net: https scheme
DEBUG:hyper::http::h1: request line: Post "/<redacted>/getUpdates" Http11
DEBUG:hyper::http::h1: headers=Headers { Host: api.telegram.org, Content-Type: application/x-www-form-urlencoded, Content-Length: 27, Connection: close, }
DEBUG:hyper::client::response: version=Http11, status=Ok
DEBUG:hyper::client::response: headers=Headers { Access-Control-Allow-Methods: GET, POST, OPTIONS, Content-Length: 23, Access-Control-Allow-Origin: *, Strict-Transport-Security: max-age=31536000; includeSubdomains, Date: Tue, 22 Mar 2016 07:34:42 GMT, Content-Type: application/json, Server: nginx/1.6.2, Connection: close, }
DEBUG:hyper::net: https scheme
DEBUG:hyper::http::h1: request line: Post "/<redacted>/getUpdates" Http11
DEBUG:hyper::http::h1: headers=Headers { Host: api.telegram.org, Connection: close, Content-Type: application/x-www-form-urlencoded, Content-Length: 27, }
DEBUG:hyper::client::response: version=Http11, status=Ok
DEBUG:hyper::client::response: headers=Headers { Strict-Transport-Security: max-age=31536000; includeSubdomains, Date: Tue, 22 Mar 2016 07:35:13 GMT, Content-Length: 23, Access-Control-Allow-Methods: GET, POST, OPTIONS, Connection: close, Content-Type: application/json, Access-Control-Allow-Origin: *, Server: nginx/1.6.2, }
DEBUG:hyper::net: https scheme
DEBUG:hyper::http::h1: request line: Post "/<redacted>/getUpdates" Http11
DEBUG:hyper::http::h1: headers=Headers { Connection: close, Content-Length: 27, Host: api.telegram.org, Content-Type: application/x-www-form-urlencoded, }
DEBUG:hyper::client::response: version=Http11, status=Ok
DEBUG:hyper::client::response: headers=Headers { Access-Control-Allow-Methods: GET, POST, OPTIONS, Strict-Transport-Security: max-age=31536000; includeSubdomains, Connection: close, Date: Tue, 22 Mar 2016 07:35:44 GMT, Content-Length: 23, Content-Type: application/json, Server: nginx/1.6.2, Access-Control-Allow-Origin: *, }
DEBUG:hyper::net: https scheme
DEBUG:hyper::http::h1: request line: Post "/<redacted>/getUpdates" Http11
DEBUG:hyper::http::h1: headers=Headers { Content-Length: 27, Content-Type: application/x-www-form-urlencoded, Connection: close, Host: api.telegram.org, }
How do these work? For example:
extern crate telegram_bot;
use telegram_bot::CanSendMessage;
fn main() {
let b = 12345;
b.text("Random message");
}
This gives me the following error:
error: no method named `text` found for type `{integer}` in the current scope
--> src/main.rs:9:7
|
9 | b.text("Random message");
| ^^^^
|
= note: the method `text` exists but the following trait bounds were not satisfied: `&{integer} : std::convert::Into<telegram_bot::ChatId>`
I'm new to rust so I apologise if this is basic stuff.
This is a weird bug that prevents me from using telegram-bot
, and I'm not sure whether the bug is here or in rustc-serialize
. I've added some work-in-progress test here. When I remove one of the Update
blocks in the decode_vector_of_updates
test, it doesn't fail anymore.
BTW, thanks for writing this library, the code is quite readable.
There are several types of requests in Telegram Bot Api:
This library support only first type right now.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.