mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-14 21:53:44 +01:00
Merge rustfmt.toml
s
This commit is contained in:
parent
1a56c6fc77
commit
1d84b2b76a
67 changed files with 341 additions and 1107 deletions
|
@ -6,11 +6,8 @@ use teloxide_core::{adaptors::trace, prelude::*, types::ChatAction};
|
|||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
pretty_env_logger::init();
|
||||
|
||||
let chat_id = ChatId(
|
||||
std::env::var("CHAT_ID")
|
||||
.expect("Expected CHAT_ID env var")
|
||||
.parse::<i64>()?,
|
||||
);
|
||||
let chat_id =
|
||||
ChatId(std::env::var("CHAT_ID").expect("Expected CHAT_ID env var").parse::<i64>()?);
|
||||
|
||||
let trace_settings = match std::env::var("TRACE").as_deref() {
|
||||
Ok("EVERYTHING_VERBOSE") => trace::Settings::TRACE_EVERYTHING_VERBOSE,
|
||||
|
|
|
@ -7,19 +7,15 @@ use teloxide_core::{
|
|||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
pretty_env_logger::init();
|
||||
|
||||
let chat_id = ChatId(
|
||||
std::env::var("CHAT_ID")
|
||||
.expect("Expected CHAT_ID env var")
|
||||
.parse::<i64>()?,
|
||||
);
|
||||
let chat_id =
|
||||
ChatId(std::env::var("CHAT_ID").expect("Expected CHAT_ID env var").parse::<i64>()?);
|
||||
|
||||
let bot = Bot::from_env().parse_mode(ParseMode::MarkdownV2);
|
||||
|
||||
let Me { user: me, .. } = bot.get_me().await?;
|
||||
|
||||
bot.send_dice(chat_id).emoji(DiceEmoji::Dice).await?;
|
||||
bot.send_message(chat_id, format!("Hi, my name is **{}** 👋", me.first_name))
|
||||
.await?;
|
||||
bot.send_message(chat_id, format!("Hi, my name is **{}** 👋", me.first_name)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
format_code_in_doc_comments = true
|
||||
wrap_comments = true
|
||||
format_strings = true
|
||||
imports_granularity = "Crate"
|
||||
use_field_init_shorthand = true
|
||||
merge_derives = false
|
|
@ -32,10 +32,7 @@ impl<B> CacheMe<B> {
|
|||
///
|
||||
/// [`RequesterExt::cache_me`]: crate::requests::RequesterExt::cache_me
|
||||
pub fn new(bot: B) -> CacheMe<B> {
|
||||
Self {
|
||||
bot,
|
||||
me: Arc::new(OnceCell::new()),
|
||||
}
|
||||
Self { bot, me: Arc::new(OnceCell::new()) }
|
||||
}
|
||||
|
||||
/// Allows to access inner bot
|
||||
|
|
|
@ -24,9 +24,7 @@ impl<'a, E> ErasedRequester<'a, E> {
|
|||
where
|
||||
B: Requester<Err = E> + 'a,
|
||||
{
|
||||
Self {
|
||||
inner: Arc::new(requester),
|
||||
}
|
||||
Self { inner: Arc::new(requester) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,9 +37,7 @@ impl<E> std::fmt::Debug for ErasedRequester<'_, E> {
|
|||
// NB. hand-written impl to avoid `E: Clone` bound
|
||||
impl<E> Clone for ErasedRequester<'_, E> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: Arc::clone(&self.inner),
|
||||
}
|
||||
Self { inner: Arc::clone(&self.inner) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,9 +50,7 @@ pub struct ErasedRequest<'a, T, E> {
|
|||
// `T: Payload` required b/c of <https://github.com/rust-lang/rust/issues/102185>
|
||||
impl<'a, T: Payload, E> ErasedRequest<'a, T, E> {
|
||||
pub(crate) fn erase(request: impl Request<Payload = T, Err = E> + 'a) -> Self {
|
||||
Self {
|
||||
inner: Box::new(request),
|
||||
}
|
||||
Self { inner: Box::new(request) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,7 @@ impl<B> DefaultParseMode<B> {
|
|||
///
|
||||
/// [`RequesterExt::parse_mode`]: crate::requests::RequesterExt::parse_mode
|
||||
pub fn new(bot: B, parse_mode: ParseMode) -> Self {
|
||||
Self {
|
||||
bot,
|
||||
mode: parse_mode,
|
||||
}
|
||||
Self { bot, mode: parse_mode }
|
||||
}
|
||||
|
||||
/// Allows to access the inner bot.
|
||||
|
|
|
@ -88,10 +88,7 @@ impl<B> Throttle<B> {
|
|||
B: Requester + Clone,
|
||||
B::Err: AsResponseParameters,
|
||||
{
|
||||
let settings = Settings {
|
||||
limits,
|
||||
..<_>::default()
|
||||
};
|
||||
let settings = Settings { limits, ..<_>::default() };
|
||||
Self::with_settings(bot, settings)
|
||||
}
|
||||
|
||||
|
@ -108,11 +105,7 @@ impl<B> Throttle<B> {
|
|||
let (info_tx, info_rx) = mpsc::channel(2);
|
||||
|
||||
let worker = worker(settings, rx, info_rx, bot.clone());
|
||||
let this = Self {
|
||||
bot,
|
||||
queue: tx,
|
||||
info_tx,
|
||||
};
|
||||
let this = Self { bot, queue: tx, info_tx };
|
||||
|
||||
(this, worker)
|
||||
}
|
||||
|
@ -164,10 +157,7 @@ impl<B> Throttle<B> {
|
|||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
self.info_tx
|
||||
.send(InfoMessage::GetLimits { response: tx })
|
||||
.await
|
||||
.expect(WORKER_DIED);
|
||||
self.info_tx.send(InfoMessage::GetLimits { response: tx }).await.expect(WORKER_DIED);
|
||||
|
||||
rx.await.expect(WORKER_DIED)
|
||||
}
|
||||
|
@ -178,10 +168,7 @@ impl<B> Throttle<B> {
|
|||
pub async fn set_limits(&self, new: Limits) {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
self.info_tx
|
||||
.send(InfoMessage::SetLimits { new, response: tx })
|
||||
.await
|
||||
.ok();
|
||||
self.info_tx.send(InfoMessage::SetLimits { new, response: tx }).await.ok();
|
||||
|
||||
rx.await.ok();
|
||||
}
|
||||
|
|
|
@ -90,12 +90,7 @@ pub(super) struct FreezeUntil {
|
|||
// the request that it can be now executed, increase counts, add record to the
|
||||
// history.
|
||||
pub(super) async fn worker<B>(
|
||||
Settings {
|
||||
mut limits,
|
||||
mut on_queue_full,
|
||||
retry,
|
||||
check_slow_mode,
|
||||
}: Settings,
|
||||
Settings { mut limits, mut on_queue_full, retry, check_slow_mode }: Settings,
|
||||
mut rx: mpsc::Receiver<(ChatIdHash, RequestLock)>,
|
||||
mut info_rx: mpsc::Receiver<InfoMessage>,
|
||||
bot: B,
|
||||
|
@ -117,9 +112,8 @@ pub(super) async fn worker<B>(
|
|||
|
||||
let mut rx_is_closed = false;
|
||||
|
||||
let mut last_queue_full = Instant::now()
|
||||
.checked_sub(QUEUE_FULL_DELAY)
|
||||
.unwrap_or_else(Instant::now);
|
||||
let mut last_queue_full =
|
||||
Instant::now().checked_sub(QUEUE_FULL_DELAY).unwrap_or_else(Instant::now);
|
||||
|
||||
let (freeze_tx, mut freeze_rx) = mpsc::channel::<FreezeUntil>(1);
|
||||
|
||||
|
@ -214,10 +208,7 @@ pub(super) async fn worker<B>(
|
|||
|
||||
// as truncates which is ok since in case of truncation it would always be >=
|
||||
// limits.overall_s
|
||||
let used = history
|
||||
.iter()
|
||||
.take_while(|(_, time)| time > &sec_back)
|
||||
.count() as u32;
|
||||
let used = history.iter().take_while(|(_, time)| time > &sec_back).count() as u32;
|
||||
let mut allowed = limits.messages_per_sec_overall.saturating_sub(used);
|
||||
|
||||
if allowed == 0 {
|
||||
|
|
|
@ -249,11 +249,7 @@ where
|
|||
{
|
||||
if self.settings.contains(Settings::TRACE_RESPONSES_VERBOSE) {
|
||||
|response| {
|
||||
log::trace!(
|
||||
"Got response from `{}` request: {:?}",
|
||||
R::Payload::NAME,
|
||||
response
|
||||
)
|
||||
log::trace!("Got response from `{}` request: {:?}", R::Payload::NAME, response)
|
||||
}
|
||||
} else if self.settings.contains(Settings::TRACE_RESPONSES) {
|
||||
|_| log::trace!("Got response from `{}` request", R::Payload::NAME)
|
||||
|
@ -294,19 +290,13 @@ where
|
|||
fn send(self) -> Self::Send {
|
||||
self.trace_request();
|
||||
|
||||
Send {
|
||||
trace_fn: self.trace_response_fn(),
|
||||
inner: self.inner.send(),
|
||||
}
|
||||
Send { trace_fn: self.trace_response_fn(), inner: self.inner.send() }
|
||||
}
|
||||
|
||||
fn send_ref(&self) -> Self::SendRef {
|
||||
self.trace_request();
|
||||
|
||||
Send {
|
||||
trace_fn: self.trace_response_fn(),
|
||||
inner: self.inner.send_ref(),
|
||||
}
|
||||
Send { trace_fn: self.trace_response_fn(), inner: self.inner.send_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,9 +71,7 @@ impl Bot {
|
|||
where
|
||||
S: Into<String>,
|
||||
{
|
||||
let client = net::default_reqwest_settings()
|
||||
.build()
|
||||
.expect("Client creation failed");
|
||||
let client = net::default_reqwest_settings().build().expect("Client creation failed");
|
||||
|
||||
Self::with_client(token, client)
|
||||
}
|
||||
|
@ -98,11 +96,7 @@ impl Bot {
|
|||
.expect("Failed to parse default Telegram bot API url"),
|
||||
);
|
||||
|
||||
Self {
|
||||
token,
|
||||
api_url,
|
||||
client,
|
||||
}
|
||||
Self { token, api_url, client }
|
||||
}
|
||||
|
||||
/// Creates a new `Bot` with the `TELOXIDE_TOKEN` & `TELOXIDE_PROXY`
|
||||
|
|
|
@ -114,10 +114,7 @@ impl Requester for Bot {
|
|||
where
|
||||
C: Into<Recipient>,
|
||||
{
|
||||
Self::SendAnimation::new(
|
||||
self.clone(),
|
||||
payloads::SendAnimation::new(chat_id, animation),
|
||||
)
|
||||
Self::SendAnimation::new(self.clone(), payloads::SendAnimation::new(chat_id, animation))
|
||||
}
|
||||
|
||||
type SendVoice = MultipartRequest<payloads::SendVoice>;
|
||||
|
@ -135,10 +132,7 @@ impl Requester for Bot {
|
|||
where
|
||||
C: Into<Recipient>,
|
||||
{
|
||||
Self::SendVideoNote::new(
|
||||
self.clone(),
|
||||
payloads::SendVideoNote::new(chat_id, video_note),
|
||||
)
|
||||
Self::SendVideoNote::new(self.clone(), payloads::SendVideoNote::new(chat_id, video_note))
|
||||
}
|
||||
|
||||
type SendMediaGroup = MultipartRequest<payloads::SendMediaGroup>;
|
||||
|
@ -276,10 +270,7 @@ impl Requester for Bot {
|
|||
Q: Into<String>,
|
||||
O: IntoIterator<Item = String>,
|
||||
{
|
||||
Self::SendPoll::new(
|
||||
self.clone(),
|
||||
payloads::SendPoll::new(chat_id, question, options),
|
||||
)
|
||||
Self::SendPoll::new(self.clone(), payloads::SendPoll::new(chat_id, question, options))
|
||||
}
|
||||
|
||||
type SendDice = JsonRequest<payloads::SendDice>;
|
||||
|
@ -325,10 +316,7 @@ impl Requester for Bot {
|
|||
where
|
||||
C: Into<Recipient>,
|
||||
{
|
||||
Self::KickChatMember::new(
|
||||
self.clone(),
|
||||
payloads::KickChatMember::new(chat_id, user_id),
|
||||
)
|
||||
Self::KickChatMember::new(self.clone(), payloads::KickChatMember::new(chat_id, user_id))
|
||||
}
|
||||
|
||||
type BanChatMember = JsonRequest<payloads::BanChatMember>;
|
||||
|
@ -346,10 +334,7 @@ impl Requester for Bot {
|
|||
where
|
||||
C: Into<Recipient>,
|
||||
{
|
||||
Self::UnbanChatMember::new(
|
||||
self.clone(),
|
||||
payloads::UnbanChatMember::new(chat_id, user_id),
|
||||
)
|
||||
Self::UnbanChatMember::new(self.clone(), payloads::UnbanChatMember::new(chat_id, user_id))
|
||||
}
|
||||
|
||||
type RestrictChatMember = JsonRequest<payloads::RestrictChatMember>;
|
||||
|
@ -568,10 +553,7 @@ impl Requester for Bot {
|
|||
where
|
||||
C: Into<Recipient>,
|
||||
{
|
||||
Self::PinChatMessage::new(
|
||||
self.clone(),
|
||||
payloads::PinChatMessage::new(chat_id, message_id),
|
||||
)
|
||||
Self::PinChatMessage::new(self.clone(), payloads::PinChatMessage::new(chat_id, message_id))
|
||||
}
|
||||
|
||||
type UnpinChatMessage = JsonRequest<payloads::UnpinChatMessage>;
|
||||
|
@ -892,10 +874,7 @@ impl Requester for Bot {
|
|||
where
|
||||
C: Into<Recipient>,
|
||||
{
|
||||
Self::DeleteMessage::new(
|
||||
self.clone(),
|
||||
payloads::DeleteMessage::new(chat_id, message_id),
|
||||
)
|
||||
Self::DeleteMessage::new(self.clone(), payloads::DeleteMessage::new(chat_id, message_id))
|
||||
}
|
||||
|
||||
type SendSticker = MultipartRequest<payloads::SendSticker>;
|
||||
|
@ -1131,10 +1110,7 @@ impl Requester for Bot {
|
|||
where
|
||||
G: Into<String>,
|
||||
{
|
||||
Self::SendGame::new(
|
||||
self.clone(),
|
||||
payloads::SendGame::new(chat_id, game_short_name),
|
||||
)
|
||||
Self::SendGame::new(self.clone(), payloads::SendGame::new(chat_id, game_short_name))
|
||||
}
|
||||
|
||||
type SetGameScore = JsonRequest<payloads::SetGameScore>;
|
||||
|
|
|
@ -26,9 +26,7 @@ fn ensure_rustfmt(sh: &Shell) {
|
|||
// FIXME(waffle): find a better way to set toolchain
|
||||
let toolchain = "nightly-2022-09-23";
|
||||
|
||||
let version = cmd!(sh, "rustup run {toolchain} rustfmt --version")
|
||||
.read()
|
||||
.unwrap_or_default();
|
||||
let version = cmd!(sh, "rustup run {toolchain} rustfmt --version").read().unwrap_or_default();
|
||||
|
||||
if !version.contains("nightly") {
|
||||
panic!(
|
||||
|
@ -81,12 +79,7 @@ pub fn ensure_files_contents<'a>(
|
|||
let mut err_count = 0;
|
||||
|
||||
for (path, contents) in files_and_contents {
|
||||
let mut file = fs::File::options()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path)
|
||||
.unwrap();
|
||||
let mut file = fs::File::options().read(true).write(true).create(true).open(path).unwrap();
|
||||
let mut old_contents = String::with_capacity(contents.len());
|
||||
file.read_to_string(&mut old_contents).unwrap();
|
||||
|
||||
|
@ -146,28 +139,19 @@ pub fn replace_block(path: &Path, title: &str, new: &str) -> String {
|
|||
}
|
||||
|
||||
let start_offset = match &*starts {
|
||||
[] => panic!(
|
||||
"Coulnd't find start of block {title} in {p}",
|
||||
p = path.display()
|
||||
),
|
||||
[] => panic!("Coulnd't find start of block {title} in {p}", p = path.display()),
|
||||
[offset] => offset.end,
|
||||
[..] => panic!(),
|
||||
};
|
||||
|
||||
let end_offset = match &*ends {
|
||||
[] => panic!(
|
||||
"Coulnd't find end of block {title} in {p}",
|
||||
p = path.display()
|
||||
),
|
||||
[] => panic!("Coulnd't find end of block {title} in {p}", p = path.display()),
|
||||
[offset] => offset.start,
|
||||
[..] => panic!(),
|
||||
};
|
||||
|
||||
if end_offset < start_offset {
|
||||
panic!(
|
||||
"End of the {title} block is located before the start in {p}",
|
||||
p = path.display()
|
||||
);
|
||||
panic!("End of the {title} block is located before the start in {p}", p = path.display());
|
||||
}
|
||||
|
||||
format!("{}{}{}", &file[..start_offset], new, &file[end_offset..])
|
||||
|
|
|
@ -6,11 +6,7 @@ pub fn patch_schema(mut schema: Schema) -> Schema {
|
|||
}
|
||||
|
||||
schema.methods.iter_mut().for_each(|method| {
|
||||
method
|
||||
.params
|
||||
.iter_mut()
|
||||
.map(|p| &mut p.name)
|
||||
.for_each(escape_kw);
|
||||
method.params.iter_mut().map(|p| &mut p.name).for_each(escape_kw);
|
||||
|
||||
DOC_PATCHES.iter().for_each(|(key, patch)| match key {
|
||||
Target::Method(m) => {
|
||||
|
@ -18,10 +14,7 @@ pub fn patch_schema(mut schema: Schema) -> Schema {
|
|||
method.doc.patch(patch, *key);
|
||||
}
|
||||
}
|
||||
Target::Field {
|
||||
method_name: m,
|
||||
field_name: f,
|
||||
} => {
|
||||
Target::Field { method_name: m, field_name: f } => {
|
||||
if check(m, &method.names.0) {
|
||||
method
|
||||
.params
|
||||
|
@ -34,10 +27,7 @@ pub fn patch_schema(mut schema: Schema) -> Schema {
|
|||
if check(m, &method.names.0) {
|
||||
method.doc.patch(patch, *key);
|
||||
|
||||
method
|
||||
.params
|
||||
.iter_mut()
|
||||
.for_each(|p| p.descr.patch(patch, *key))
|
||||
method.params.iter_mut().for_each(|p| p.descr.patch(patch, *key))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -164,24 +154,18 @@ static DOC_PATCHES: &[(Target, Patch)] = &[
|
|||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Target<'a> {
|
||||
Any {
|
||||
method_name: Option<&'a str>,
|
||||
},
|
||||
Any { method_name: Option<&'a str> },
|
||||
Method(Option<&'a str>),
|
||||
Field {
|
||||
method_name: Option<&'a str>,
|
||||
field_name: Option<&'a str>,
|
||||
},
|
||||
Field { method_name: Option<&'a str>, field_name: Option<&'a str> },
|
||||
}
|
||||
|
||||
impl<'a> Target<'a> {
|
||||
fn is_exact(&self) -> bool {
|
||||
match self {
|
||||
Target::Method(m) => m.is_some(),
|
||||
Target::Field {
|
||||
method_name,
|
||||
field_name,
|
||||
} => method_name.is_some() && field_name.is_some(),
|
||||
Target::Field { method_name, field_name } => {
|
||||
method_name.is_some() && field_name.is_some()
|
||||
}
|
||||
Target::Any { method_name: _ } => false,
|
||||
}
|
||||
}
|
||||
|
@ -208,8 +192,7 @@ impl Doc {
|
|||
}
|
||||
}
|
||||
Patch::AddLink { name, value } => {
|
||||
self.md_links
|
||||
.insert((*name).to_owned(), (*value).to_owned());
|
||||
self.md_links.insert((*name).to_owned(), (*value).to_owned());
|
||||
}
|
||||
// Patch::RemoveLink { name } => drop(self.md_links.remove(*name)),
|
||||
// Patch::FullReplace { text, with } => {
|
||||
|
@ -253,9 +236,7 @@ fn intra_links(doc: &mut Doc) {
|
|||
|
||||
for repl in repls_t {
|
||||
if let Some(value) = doc.md_links.remove(repl.as_str()) {
|
||||
doc.md = doc
|
||||
.md
|
||||
.replace(format!("[{}]", repl).as_str(), &format!("[`{}`]", repl));
|
||||
doc.md = doc.md.replace(format!("[{}]", repl).as_str(), &format!("[`{}`]", repl));
|
||||
doc.md_links.insert(format!("`{}`", repl), value);
|
||||
}
|
||||
}
|
||||
|
@ -263,9 +244,7 @@ fn intra_links(doc: &mut Doc) {
|
|||
for repl in repls_m {
|
||||
if let Some(value) = doc.md_links.remove(repl.as_str()) {
|
||||
let repln = to_uppercase(&repl);
|
||||
doc.md = doc
|
||||
.md
|
||||
.replace(format!("[{}]", repl).as_str(), &format!("[`{}`]", repln));
|
||||
doc.md = doc.md.replace(format!("[{}]", repl).as_str(), &format!("[`{}`]", repln));
|
||||
doc.md_links.insert(format!("`{}`", repln), value);
|
||||
}
|
||||
}
|
||||
|
@ -284,21 +263,13 @@ fn to_uppercase(s: &str) -> String {
|
|||
|
||||
pub(crate) fn patch_ty(mut schema: Schema) -> Schema {
|
||||
// URLs
|
||||
patch_types(
|
||||
&mut schema,
|
||||
Type::String,
|
||||
Type::Url,
|
||||
&[("set_webhook", "url")],
|
||||
);
|
||||
patch_types(&mut schema, Type::String, Type::Url, &[("set_webhook", "url")]);
|
||||
|
||||
patch_types(
|
||||
&mut schema,
|
||||
Type::Option(Box::new(Type::String)),
|
||||
Type::Option(Box::new(Type::Url)),
|
||||
&[
|
||||
("answer_callback_query", "url"),
|
||||
("send_invoice", "photo_url"),
|
||||
],
|
||||
&[("answer_callback_query", "url"), ("send_invoice", "photo_url")],
|
||||
);
|
||||
|
||||
// Dates
|
||||
|
@ -317,10 +288,7 @@ pub(crate) fn patch_ty(mut schema: Schema) -> Schema {
|
|||
&mut schema,
|
||||
Type::Option(Box::new(Type::i64)),
|
||||
Type::Option(Box::new(Type::DateTime)),
|
||||
&[
|
||||
("create_chat_invite_link", "expire_date"),
|
||||
("edit_chat_invite_link", "expire_date"),
|
||||
],
|
||||
&[("create_chat_invite_link", "expire_date"), ("edit_chat_invite_link", "expire_date")],
|
||||
);
|
||||
|
||||
schema
|
||||
|
|
|
@ -110,10 +110,9 @@ pub enum ApiError {
|
|||
/// 1. [`EditMessageText`]
|
||||
///
|
||||
/// [`EditMessageText`]: crate::payloads::EditMessageText
|
||||
#[serde(
|
||||
rename = "Bad Request: message is not modified: specified new message content and reply \
|
||||
markup are exactly the same as a current content and reply markup of the message"
|
||||
)]
|
||||
#[serde(rename = "Bad Request: message is not modified: specified new message content and \
|
||||
reply markup are exactly the same as a current content and reply markup \
|
||||
of the message")]
|
||||
#[error(
|
||||
"Bad Request: message is not modified: specified new message content and reply markup are \
|
||||
exactly the same as a current content and reply markup of the message"
|
||||
|
@ -390,10 +389,8 @@ pub enum ApiError {
|
|||
/// 1. [`AnswerCallbackQuery`]
|
||||
///
|
||||
/// [`AnswerCallbackQuery`]: crate::payloads::AnswerCallbackQuery
|
||||
#[serde(
|
||||
rename = "Bad Request: query is too old and response timeout expired or query id is \
|
||||
invalid"
|
||||
)]
|
||||
#[serde(rename = "Bad Request: query is too old and response timeout expired or query id is \
|
||||
invalid")]
|
||||
#[error("Bad Request: query is too old and response timeout expired or query id is invalid")]
|
||||
InvalidQueryId,
|
||||
|
||||
|
@ -424,10 +421,8 @@ pub enum ApiError {
|
|||
/// 1. [`SendMessage`]
|
||||
///
|
||||
/// [`SendMessage`]: crate::payloads::SendMessage
|
||||
#[serde(
|
||||
rename = "Bad Request: can't parse inline keyboard button: Text buttons are unallowed in \
|
||||
the inline keyboard"
|
||||
)]
|
||||
#[serde(rename = "Bad Request: can't parse inline keyboard button: Text buttons are \
|
||||
unallowed in the inline keyboard")]
|
||||
#[error(
|
||||
"Bad Request: can't parse inline keyboard button: Text buttons are unallowed in the \
|
||||
inline keyboard"
|
||||
|
@ -614,10 +609,8 @@ pub enum ApiError {
|
|||
/// 1. [`SetWebhook`]
|
||||
///
|
||||
/// [`SetWebhook`]: crate::payloads::SetWebhook
|
||||
#[serde(
|
||||
rename = "Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or \
|
||||
8443"
|
||||
)]
|
||||
#[serde(rename = "Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 \
|
||||
or 8443")]
|
||||
#[error("Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443")]
|
||||
BadWebhookPort,
|
||||
|
||||
|
@ -627,9 +620,7 @@ pub enum ApiError {
|
|||
/// 1. [`SetWebhook`]
|
||||
///
|
||||
/// [`SetWebhook`]: crate::payloads::SetWebhook
|
||||
#[serde(
|
||||
rename = "Bad Request: bad webhook: Failed to resolve host: Name or service not known"
|
||||
)]
|
||||
#[serde(rename = "Bad Request: bad webhook: Failed to resolve host: Name or service not known")]
|
||||
#[error("Bad Request: bad webhook: Failed to resolve host: Name or service not known")]
|
||||
UnknownHost,
|
||||
|
||||
|
@ -732,10 +723,8 @@ pub enum ApiError {
|
|||
/// 1. [`GetUpdates`]
|
||||
///
|
||||
/// [`GetUpdates`]: crate::payloads::GetUpdates
|
||||
#[serde(
|
||||
rename = "Conflict: terminated by other getUpdates request; make sure that only one bot \
|
||||
instance is running"
|
||||
)]
|
||||
#[serde(rename = "Conflict: terminated by other getUpdates request; make sure that only one \
|
||||
bot instance is running")]
|
||||
#[error(
|
||||
"Conflict: terminated by other getUpdates request; make sure that only one bot instance \
|
||||
is running"
|
||||
|
|
|
@ -22,11 +22,7 @@
|
|||
//! let me = bot.get_me().await?;
|
||||
//!
|
||||
//! bot.send_dice(chat_id).emoji(DiceEmoji::Dice).await?;
|
||||
//! bot.send_message(
|
||||
//! chat_id,
|
||||
//! format!("Hi, my name is **{}** 👋", me.user.first_name),
|
||||
//! )
|
||||
//! .await?;
|
||||
//! bot.send_message(chat_id, format!("Hi, my name is **{}** 👋", me.user.first_name)).await?;
|
||||
//! # Ok::<_, Box<dyn std::error::Error>>(()) };
|
||||
//! ```
|
||||
//!
|
||||
|
|
|
@ -1293,11 +1293,9 @@ fn codegen_requester_forward() {
|
|||
.filter(|p| !matches!(p.ty, Type::Option(_)))
|
||||
.flat_map(|p| match convert_for(&p.ty) {
|
||||
Convert::Id(_) => None,
|
||||
Convert::Into(ty) => Some(format!(
|
||||
"{}: Into<{}>",
|
||||
&to_uppercase(prefixes[&*p.name]),
|
||||
ty
|
||||
)),
|
||||
Convert::Into(ty) => {
|
||||
Some(format!("{}: Into<{}>", &to_uppercase(prefixes[&*p.name]), ty))
|
||||
}
|
||||
Convert::Collect(ty) => Some(format!(
|
||||
"{}: IntoIterator<Item = {}>",
|
||||
&to_uppercase(prefixes[&*p.name]),
|
||||
|
@ -1306,11 +1304,8 @@ fn codegen_requester_forward() {
|
|||
})
|
||||
.join(",\n ");
|
||||
|
||||
let generics = if generics.is_empty() {
|
||||
String::from("")
|
||||
} else {
|
||||
format!("<{}>", generics)
|
||||
};
|
||||
let generics =
|
||||
if generics.is_empty() { String::from("") } else { format!("<{}>", generics) };
|
||||
|
||||
let where_clause = if where_clause.is_empty() {
|
||||
String::from("")
|
||||
|
|
|
@ -80,24 +80,16 @@ pub fn default_reqwest_settings() -> reqwest::ClientBuilder {
|
|||
///
|
||||
/// [Telegram documentation]: https://core.telegram.org/bots/api#making-requests
|
||||
fn method_url(base: reqwest::Url, token: &str, method_name: &str) -> reqwest::Url {
|
||||
base.join(&format!(
|
||||
"/bot{token}/{method}",
|
||||
token = token,
|
||||
method = method_name
|
||||
))
|
||||
.expect("failed to format url")
|
||||
base.join(&format!("/bot{token}/{method}", token = token, method = method_name))
|
||||
.expect("failed to format url")
|
||||
}
|
||||
|
||||
/// Creates URL for downloading a file. See the [Telegram documentation].
|
||||
///
|
||||
/// [Telegram documentation]: https://core.telegram.org/bots/api#file
|
||||
fn file_url(base: reqwest::Url, token: &str, file_path: &str) -> reqwest::Url {
|
||||
base.join(&format!(
|
||||
"file/bot{token}/{file}",
|
||||
token = token,
|
||||
file = file_path
|
||||
))
|
||||
.expect("failed to format url")
|
||||
base.join(&format!("file/bot{token}/{file}", token = token, file = file_path))
|
||||
.expect("failed to format url")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -94,18 +94,15 @@ pub fn download_file<'o, D>(
|
|||
where
|
||||
D: ?Sized + AsyncWrite + Unpin,
|
||||
{
|
||||
client
|
||||
.get(file_url(api_url, token, path))
|
||||
.send()
|
||||
.then(move |r| async move {
|
||||
let mut res = r?.error_for_status()?;
|
||||
client.get(file_url(api_url, token, path)).send().then(move |r| async move {
|
||||
let mut res = r?.error_for_status()?;
|
||||
|
||||
while let Some(chunk) = res.chunk().await? {
|
||||
dst.write_all(&chunk).await?;
|
||||
}
|
||||
while let Some(chunk) = res.chunk().await? {
|
||||
dst.write_all(&chunk).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Download a file from Telegram as [`Stream`].
|
||||
|
@ -119,11 +116,8 @@ pub fn download_file_stream(
|
|||
token: &str,
|
||||
path: &str,
|
||||
) -> impl Stream<Item = reqwest::Result<Bytes>> + 'static {
|
||||
client
|
||||
.get(file_url(api_url, token, path))
|
||||
.send()
|
||||
.into_stream()
|
||||
.flat_map(|res| match res.and_then(Response::error_for_status) {
|
||||
client.get(file_url(api_url, token, path)).send().into_stream().flat_map(|res| {
|
||||
match res.and_then(Response::error_for_status) {
|
||||
Ok(res) => Either::Left(unfold(res, |mut res| async {
|
||||
match res.chunk().await {
|
||||
Err(err) => Some((Err(err), res)),
|
||||
|
@ -132,5 +126,6 @@ pub fn download_file_stream(
|
|||
}
|
||||
})),
|
||||
Err(err) => Either::Right(once(ready(Err(err)))),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -100,9 +100,6 @@ where
|
|||
let text = response.text().await?;
|
||||
|
||||
serde_json::from_str::<TelegramResponse<T>>(&text)
|
||||
.map_err(|source| RequestError::InvalidJson {
|
||||
source,
|
||||
raw: text.into(),
|
||||
})?
|
||||
.map_err(|source| RequestError::InvalidJson { source, raw: text.into() })?
|
||||
.into()
|
||||
}
|
||||
|
|
|
@ -37,10 +37,7 @@ impl<R> From<TelegramResponse<R>> for ResponseResult<R> {
|
|||
fn from(this: TelegramResponse<R>) -> ResponseResult<R> {
|
||||
match this {
|
||||
TelegramResponse::Ok { response, .. } => Ok(response),
|
||||
TelegramResponse::Err {
|
||||
response_parameters: Some(params),
|
||||
..
|
||||
} => Err(match params {
|
||||
TelegramResponse::Err { response_parameters: Some(params), .. } => Err(match params {
|
||||
ResponseParameters::RetryAfter(i) => RequestError::RetryAfter(i),
|
||||
ResponseParameters::MigrateToChatId(to) => RequestError::MigrateToChatId(to),
|
||||
}),
|
||||
|
@ -61,10 +58,7 @@ mod tests {
|
|||
|
||||
assert!(matches!(
|
||||
val,
|
||||
TelegramResponse::Err {
|
||||
error: ApiError::TerminatedByOtherGetUpdates,
|
||||
..
|
||||
}
|
||||
TelegramResponse::Err { error: ApiError::TerminatedByOtherGetUpdates, .. }
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -237,10 +237,7 @@ fn codegen_payload_mods_and_reexports() {
|
|||
let schema = schema::get();
|
||||
let mut block = String::new();
|
||||
|
||||
schema
|
||||
.methods
|
||||
.iter()
|
||||
.for_each(|m| block.push_str(&format!("mod {};\n", m.names.2)));
|
||||
schema.methods.iter().for_each(|m| block.push_str(&format!("mod {};\n", m.names.2)));
|
||||
|
||||
block.push('\n');
|
||||
|
||||
|
|
|
@ -24,19 +24,12 @@ fn codegen_payloads() {
|
|||
let uses = uses(&method);
|
||||
|
||||
let method_doc = render_doc(&method.doc, method.sibling.as_deref());
|
||||
let eq_hash_derive = eq_hash_suitable(&method)
|
||||
.then(|| " Eq, Hash,")
|
||||
.unwrap_or("");
|
||||
let eq_hash_derive = eq_hash_suitable(&method).then(|| " Eq, Hash,").unwrap_or("");
|
||||
let default_derive = default_needed(&method).then(|| " Default,").unwrap_or("");
|
||||
|
||||
let return_ty = method.return_ty.to_string();
|
||||
|
||||
let required = params(
|
||||
method
|
||||
.params
|
||||
.iter()
|
||||
.filter(|p| !matches!(&p.ty, Type::Option(_))),
|
||||
);
|
||||
let required = params(method.params.iter().filter(|p| !matches!(&p.ty, Type::Option(_))));
|
||||
let required = match &*required {
|
||||
"" => "".to_owned(),
|
||||
_ => format!(" required {{\n{required}\n }}"),
|
||||
|
@ -155,10 +148,8 @@ fn render_doc(doc: &Doc, sibling: Option<&str>) -> String {
|
|||
let links = match &doc.md_links {
|
||||
links if links.is_empty() => String::new(),
|
||||
links => {
|
||||
let l: String = links
|
||||
.iter()
|
||||
.map(|(name, link)| format!("\n /// [{name}]: {link}"))
|
||||
.collect();
|
||||
let l: String =
|
||||
links.iter().map(|(name, link)| format!("\n /// [{name}]: {link}")).collect();
|
||||
|
||||
format!("\n ///{l}")
|
||||
}
|
||||
|
@ -173,13 +164,7 @@ fn render_doc(doc: &Doc, sibling: Option<&str>) -> String {
|
|||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
[
|
||||
" /// ",
|
||||
&doc.md.replace('\n', "\n /// "),
|
||||
&sibling_note,
|
||||
&links,
|
||||
]
|
||||
.concat()
|
||||
[" /// ", &doc.md.replace('\n', "\n /// "), &sibling_note, &links].concat()
|
||||
}
|
||||
|
||||
fn eq_hash_suitable(method: &Method) -> bool {
|
||||
|
@ -208,10 +193,7 @@ fn eq_hash_suitable(method: &Method) -> bool {
|
|||
}
|
||||
|
||||
fn default_needed(method: &Method) -> bool {
|
||||
method
|
||||
.params
|
||||
.iter()
|
||||
.all(|p| matches!(p.ty, Type::Option(_)))
|
||||
method.params.iter().all(|p| matches!(p.ty, Type::Option(_)))
|
||||
}
|
||||
|
||||
fn params(params: impl Iterator<Item = impl Borrow<Param>>) -> String {
|
||||
|
@ -258,12 +240,8 @@ fn params(params: impl Iterator<Item = impl Borrow<Param>>) -> String {
|
|||
}
|
||||
|
||||
fn multipart_input_file_fields(m: &Method) -> Option<Vec<&str>> {
|
||||
let fields: Vec<_> = m
|
||||
.params
|
||||
.iter()
|
||||
.filter(|&p| ty_is_multiparty(&p.ty))
|
||||
.map(|p| &*p.name)
|
||||
.collect();
|
||||
let fields: Vec<_> =
|
||||
m.params.iter().filter(|&p| ty_is_multiparty(&p.ty)).map(|p| &*p.name).collect();
|
||||
|
||||
if fields.is_empty() {
|
||||
None
|
||||
|
|
|
@ -14,17 +14,11 @@ pub trait MultipartPayload: Payload {
|
|||
|
||||
impl MultipartPayload for payloads::SendMediaGroup {
|
||||
fn copy_files(&self, into: &mut dyn FnMut(InputFile)) {
|
||||
self.media
|
||||
.iter()
|
||||
.flat_map(InputMedia::files)
|
||||
.for_each(|f| f.copy_into(into))
|
||||
self.media.iter().flat_map(InputMedia::files).for_each(|f| f.copy_into(into))
|
||||
}
|
||||
|
||||
fn move_files(&mut self, into: &mut dyn FnMut(InputFile)) {
|
||||
self.media
|
||||
.iter_mut()
|
||||
.flat_map(InputMedia::files_mut)
|
||||
.for_each(|f| f.move_into(into))
|
||||
self.media.iter_mut().flat_map(InputMedia::files_mut).for_each(|f| f.move_into(into))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,9 +72,7 @@ use crate::{
|
|||
/// bot.send_message(chat_id, "<b>Text</b>").await?;
|
||||
///
|
||||
/// // This will use `ParseMode::MarkdownV2`
|
||||
/// bot.send_message(chat_id, "**Text**")
|
||||
/// .parse_mode(ParseMode::MarkdownV2)
|
||||
/// .await?;
|
||||
/// bot.send_message(chat_id, "**Text**").parse_mode(ParseMode::MarkdownV2).await?;
|
||||
/// # Ok::<_, teloxide_core::RequestError>(())
|
||||
/// # };
|
||||
/// ```
|
||||
|
@ -1284,11 +1282,9 @@ fn codegen_requester_methods() {
|
|||
.filter(|p| !matches!(p.ty, Type::Option(_)))
|
||||
.flat_map(|p| match convert_for(&p.ty) {
|
||||
Convert::Id(_) => None,
|
||||
Convert::Into(ty) => Some(format!(
|
||||
"{}: Into<{}>",
|
||||
&to_uppercase(prefixes[&*p.name]),
|
||||
ty
|
||||
)),
|
||||
Convert::Into(ty) => {
|
||||
Some(format!("{}: Into<{}>", &to_uppercase(prefixes[&*p.name]), ty))
|
||||
}
|
||||
Convert::Collect(ty) => Some(format!(
|
||||
"{}: IntoIterator<Item = {}>",
|
||||
&to_uppercase(prefixes[&*p.name]),
|
||||
|
@ -1297,11 +1293,8 @@ fn codegen_requester_methods() {
|
|||
})
|
||||
.join(",\n ");
|
||||
|
||||
let generics = if generics.is_empty() {
|
||||
String::from("")
|
||||
} else {
|
||||
format!("<{}>", generics)
|
||||
};
|
||||
let generics =
|
||||
if generics.is_empty() { String::from("") } else { format!("<{}>", generics) };
|
||||
|
||||
let where_clause = if where_clause.is_empty() {
|
||||
String::from("")
|
||||
|
|
|
@ -99,11 +99,7 @@ mod tests {
|
|||
async fn issue_473() {
|
||||
to_form_ref(
|
||||
&payloads::SendPhoto::new(ChatId(0), InputFile::file_id("0")).caption_entities([
|
||||
MessageEntity {
|
||||
kind: MessageEntityKind::Url,
|
||||
offset: 0,
|
||||
length: 0,
|
||||
},
|
||||
MessageEntity { kind: MessageEntityKind::Url, offset: 0, length: 0 },
|
||||
]),
|
||||
)
|
||||
.unwrap()
|
||||
|
@ -131,9 +127,7 @@ mod tests {
|
|||
File::open("../../media/example.gif").await.unwrap(),
|
||||
))
|
||||
.thumb(InputFile::read(
|
||||
File::open("../../media/teloxide-core-logo.png")
|
||||
.await
|
||||
.unwrap(),
|
||||
File::open("../../media/teloxide-core-logo.png").await.unwrap(),
|
||||
))
|
||||
.duration(17),
|
||||
),
|
||||
|
@ -170,11 +164,7 @@ mod tests {
|
|||
InputFile::file("../../media/teloxide-core-logo.png"),
|
||||
)
|
||||
.caption_entities(entities())
|
||||
.thumb(InputFile::read(
|
||||
File::open("../../media/teloxide-core-logo.png")
|
||||
.await
|
||||
.unwrap(),
|
||||
))
|
||||
.thumb(InputFile::read(File::open("../../media/teloxide-core-logo.png").await.unwrap()))
|
||||
.allow_sending_without_reply(true),
|
||||
)
|
||||
.unwrap()
|
||||
|
@ -185,18 +175,10 @@ mod tests {
|
|||
<_>::into_iter([
|
||||
MessageEntity::new(MessageEntityKind::Url, 0, 0),
|
||||
MessageEntity::new(MessageEntityKind::Pre { language: None }, 0, 0),
|
||||
MessageEntity::new(
|
||||
MessageEntityKind::Pre {
|
||||
language: Some(String::new()),
|
||||
},
|
||||
0,
|
||||
0,
|
||||
),
|
||||
MessageEntity::new(MessageEntityKind::Pre { language: Some(String::new()) }, 0, 0),
|
||||
MessageEntity::new(MessageEntityKind::Url, 0, 0),
|
||||
MessageEntity::new(
|
||||
MessageEntityKind::TextLink {
|
||||
url: "https://example.com".parse().unwrap(),
|
||||
},
|
||||
MessageEntityKind::TextLink { url: "https://example.com".parse().unwrap() },
|
||||
0,
|
||||
0,
|
||||
),
|
||||
|
|
|
@ -62,10 +62,7 @@ impl Serializer for MultipartSerializer {
|
|||
type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
|
||||
|
||||
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
Ok(MultipartMapSerializer {
|
||||
form: Form::new(),
|
||||
key: None,
|
||||
})
|
||||
Ok(MultipartMapSerializer { form: Form::new(), key: None })
|
||||
}
|
||||
|
||||
fn serialize_struct(
|
||||
|
@ -266,10 +263,7 @@ impl SerializeMap for MultipartMapSerializer {
|
|||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let key = self
|
||||
.key
|
||||
.take()
|
||||
.expect("Value serialized before key or key is not string");
|
||||
let key = self.key.take().expect("Value serialized before key or key is not string");
|
||||
|
||||
let part = value.serialize(PartSerializer {})?;
|
||||
|
||||
|
@ -373,17 +367,11 @@ impl Serializer for PartSerializer {
|
|||
_: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
Ok(JsonPartSerializer {
|
||||
buf: String::new(),
|
||||
state: PartSerializerStructState::Empty,
|
||||
})
|
||||
Ok(JsonPartSerializer { buf: String::new(), state: PartSerializerStructState::Empty })
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
Ok(JsonPartSerializer {
|
||||
buf: String::new(),
|
||||
state: PartSerializerStructState::Empty,
|
||||
})
|
||||
Ok(JsonPartSerializer { buf: String::new(), state: PartSerializerStructState::Empty })
|
||||
}
|
||||
|
||||
// Unimplemented
|
||||
|
|
|
@ -303,10 +303,7 @@ pub(crate) mod serde_date_from_unix_timestamp {
|
|||
{
|
||||
let timestamp = i64::deserialize(deserializer)?;
|
||||
|
||||
Ok(DateTime::from_utc(
|
||||
NaiveDateTime::from_timestamp(timestamp, 0),
|
||||
Utc,
|
||||
))
|
||||
Ok(DateTime::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,10 +345,7 @@ pub(crate) mod option_url_from_string {
|
|||
|
||||
let json = r#"{"url":"https://github.com/token"}"#;
|
||||
let url: Struct = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(
|
||||
url.url,
|
||||
Some(Url::from_str("https://github.com/token").unwrap())
|
||||
);
|
||||
assert_eq!(url.url, Some(Url::from_str("https://github.com/token").unwrap()));
|
||||
assert_eq!(serde_json::to_string(&url).unwrap(), json.to_owned());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,20 +59,12 @@ mod tests {
|
|||
"mime_type":"video/gif",
|
||||
"file_size":6500}"#;
|
||||
let expected = Animation {
|
||||
file: FileMeta {
|
||||
id: "id".to_string(),
|
||||
unique_id: "".to_string(),
|
||||
size: 6500,
|
||||
},
|
||||
file: FileMeta { id: "id".to_string(), unique_id: "".to_string(), size: 6500 },
|
||||
width: 320,
|
||||
height: 320,
|
||||
duration: 59,
|
||||