diff --git a/src/commands/my_listings.rs b/src/commands/my_listings.rs index b621e4f..0cc4466 100644 --- a/src/commands/my_listings.rs +++ b/src/commands/my_listings.rs @@ -2,9 +2,7 @@ use crate::{ case, db::{Listing, ListingDAO, ListingId, User, UserDAO}, keyboard_buttons, - message_utils::{ - extract_callback_data, pluralize_with_count, send_message, HandleAndId, MessageTarget, - }, + message_utils::{extract_callback_data, pluralize_with_count, send_message, MessageTarget}, Command, DialogueRootState, HandlerResult, RootDialogue, }; use serde::{Deserialize, Serialize}; @@ -12,7 +10,7 @@ use sqlx::SqlitePool; use teloxide::{ dispatching::{DpHandlerDescription, UpdateFilterExt}, prelude::*, - types::{InlineKeyboardButton, Message, MessageId, ParseMode}, + types::{InlineKeyboardButton, Message}, Bot, }; @@ -183,7 +181,7 @@ async fn show_listing_details( ); send_message( - &bot, + bot, target, response, Some(ManageListingButtons::to_keyboard()), @@ -233,7 +231,7 @@ async fn get_user_and_listing( listing_id: ListingId, target: impl Into, ) -> HandlerResult<(User, Listing)> { - let user = match UserDAO::find_by_telegram_id(&db_pool, user_id).await? { + let user = match UserDAO::find_by_telegram_id(db_pool, user_id).await? { Some(user) => user, None => { send_message( @@ -247,7 +245,7 @@ async fn get_user_and_listing( } }; - let listing = match ListingDAO::find_by_id(&db_pool, listing_id).await? { + let listing = match ListingDAO::find_by_id(db_pool, listing_id).await? { Some(listing) => listing, None => { send_message(bot, target, "โŒ Listing not found.", None).await?; diff --git a/src/commands/new_listing/mod.rs b/src/commands/new_listing/mod.rs index 2041d4e..9348c9d 100644 --- a/src/commands/new_listing/mod.rs +++ b/src/commands/new_listing/mod.rs @@ -9,7 +9,6 @@ use crate::{ models::new_listing::{NewListing, NewListingBase, NewListingFields}, ListingDuration, NewUser, UserDAO, }, - keyboard_buttons, message_utils::*, DialogueRootState, HandlerResult, RootDialogue, }; @@ -35,8 +34,8 @@ fn create_back_button_keyboard_with_clear(field: &str) -> InlineKeyboardMarkup { create_single_row_keyboard(&[ ("๐Ÿ”™ Back", "edit_back"), ( - &format!("๐Ÿงน Clear {}", field), - &format!("edit_clear_{}", field), + &format!("๐Ÿงน Clear {field}"), + &format!("edit_clear_{field}"), ), ]) } @@ -190,7 +189,7 @@ async fn handle_description_callback( send_message(&bot, target, response, None).await?; } _ => { - error!("Unknown callback data: {}", data); + error!("Unknown callback data: {data}"); dialogue.exit().await?; } } @@ -205,7 +204,7 @@ async fn handle_awaiting_draft_field_callback( callback_query: CallbackQuery, ) -> HandlerResult { let (data, from, message_id) = extract_callback_data(&bot, callback_query).await?; - info!("User {:?} selected callback: {:?}", from, data); + info!("User {from:?} selected callback: {data:?}"); let target = (from, message_id); if data == "cancel" { @@ -214,17 +213,17 @@ async fn handle_awaiting_draft_field_callback( match field { ListingField::Title => { - error!("Unknown callback data: {}", data); + error!("Unknown callback data: {data}"); dialogue.exit().await?; - return Ok(()); + Ok(()) } ListingField::Description => { handle_description_callback(bot, dialogue, draft, data.as_str(), target).await } ListingField::Price => { - error!("Unknown callback data: {}", data); + error!("Unknown callback data: {data}"); dialogue.exit().await?; - return Ok(()); + Ok(()) } ListingField::Slots => { handle_slots_callback(bot, dialogue, draft, data.as_str(), target).await @@ -303,7 +302,7 @@ async fn process_slots_and_respond( ); send_message( - &bot, + bot, target, &response, Some(StartTimeKeyboardButtons::to_keyboard()), @@ -328,12 +327,12 @@ async fn handle_viewing_draft_callback( match button { ConfirmationKeyboardButtons::Create => { - info!("User {:?} confirmed listing creation", target); + info!("User {target:?} confirmed listing creation"); dialogue.exit().await?; create_listing(db_pool, bot, dialogue, from, message_id, draft.clone()).await?; } ConfirmationKeyboardButtons::Discard => { - info!("User {:?} discarded listing creation", from); + info!("User {from:?} discarded listing creation"); // Exit dialogue and send cancellation message dialogue.exit().await?; @@ -345,7 +344,7 @@ async fn handle_viewing_draft_callback( send_message(&bot, target, &response, None).await?; } ConfirmationKeyboardButtons::Edit => { - info!("User {:?} chose to edit listing", from); + info!("User {from:?} chose to edit listing"); // Go to editing state to allow user to modify specific fields dialogue @@ -379,18 +378,17 @@ async fn process_start_time_and_respond( .await?; // Generate response message - let start_msg = format!("in {}", duration); + let start_msg = format!("in {duration}"); let response = format!( - "โœ… Listing will start: {}\n\n\ + "โœ… Listing will start: {start_msg}\n\n\ Step 6 of 6: Duration\n\ How long should your listing run?\n\ - Enter duration in hours (minimum 1 hour, maximum 720 hours / 30 days):", - start_msg + Enter duration in hours (minimum 1 hour, maximum 720 hours / 30 days):" ); send_message( - &bot, + bot, target, &response, Some(DurationKeyboardButtons::to_keyboard()), @@ -606,7 +604,7 @@ async fn show_edit_screen( ); if let Some(flash_message) = flash_message { - response = format!("{}\n\n{}", flash_message, response); + response = format!("{flash_message}\n\n{response}"); } send_message( @@ -629,7 +627,7 @@ async fn handle_editing_field_input( let chat = msg.chat.clone(); let text = msg.text().unwrap_or("").trim(); - info!("User {:?} editing field {:?}", chat, field); + info!("User {chat:?} editing field {field:?}"); match field { ListingField::Title => { @@ -728,10 +726,9 @@ async fn handle_editing_draft_callback( // update the message to show the edit screen let response = format!( - "Editing {:?}\n\n\ - Previous value: {}\ - ", - field, value + "Editing {field:?}\n\n\ + Previous value: {value}\ + " ); send_message(&bot, target, response, Some(keyboard)).await?; @@ -751,7 +748,7 @@ async fn create_listing( let starts_at = now + Into::::into(draft.start_delay); let ends_at = starts_at + Into::::into(draft.duration); - let user = match UserDAO::find_by_telegram_id(&db_pool, from.id.clone()).await? { + let user = match UserDAO::find_by_telegram_id(&db_pool, from.id).await? { Some(user) => user, None => { UserDAO::insert_user( @@ -803,7 +800,7 @@ async fn create_listing( ); } Err(e) => { - log::error!("Failed to create listing for user {:?}: {}", from, e); + log::error!("Failed to create listing for user {from:?}: {e}"); send_message( &bot, (from, message_id), @@ -823,7 +820,7 @@ async fn cancel_wizard( target: impl Into, ) -> HandlerResult { let target = target.into(); - info!("{:?} cancelled new listing wizard", target); + info!("{target:?} cancelled new listing wizard"); dialogue.exit().await?; send_message(&bot, target, "โŒ Listing creation cancelled.", None).await?; Ok(()) @@ -838,7 +835,7 @@ async fn handle_edit_title( target: impl Into, ) -> HandlerResult { let target = target.into(); - info!("User {:?} editing title: '{}'", target, text); + info!("User {target:?} editing title: '{text}'"); draft.title = match validate_title(text) { Ok(title) => title, @@ -873,7 +870,7 @@ async fn handle_edit_description( target: impl Into, ) -> HandlerResult { let target = target.into(); - info!("User {:?} editing description: '{}'", target, text); + info!("User {target:?} editing description: '{text}'"); state.description = match validate_description(text) { Ok(description) => Some(description), @@ -903,7 +900,7 @@ async fn handle_edit_price( target: impl Into, ) -> HandlerResult { let target = target.into(); - info!("User {:?} editing price: '{}'", target, text); + info!("User {target:?} editing price: '{text}'"); state.buy_now_price = match validate_price(text) { Ok(price) => price, @@ -932,7 +929,7 @@ async fn handle_edit_slots( target: impl Into, ) -> HandlerResult { let target = target.into(); - info!("User {:?} editing slots: '{}'", target, text); + info!("User {target:?} editing slots: '{text}'"); state.slots_available = match validate_slots(text) { Ok(s) => s, @@ -962,7 +959,7 @@ async fn handle_edit_start_time( target: impl Into, ) -> HandlerResult { let target = target.into(); - info!("User {:?} editing start time: '{}'", target, text); + info!("User {target:?} editing start time: '{text}'"); state.start_delay = match validate_start_time(text) { Ok(h) => h, @@ -998,7 +995,7 @@ async fn handle_edit_duration( target: impl Into, ) -> HandlerResult { let target = target.into(); - info!("User {:?} editing duration: '{}'", target, text); + info!("User {target:?} editing duration: '{text}'"); state.duration = match validate_duration(text) { Ok(d) => d, diff --git a/src/commands/new_listing/validations.rs b/src/commands/new_listing/validations.rs index c50e162..ef63b93 100644 --- a/src/commands/new_listing/validations.rs +++ b/src/commands/new_listing/validations.rs @@ -41,7 +41,7 @@ pub fn validate_price(text: &str) -> Result { pub fn validate_slots(text: &str) -> Result { match text.parse::() { - Ok(slots) if slots >= 1 && slots <= 1000 => Ok(slots), + Ok(slots) if (1..=1000).contains(&slots) => Ok(slots), Ok(_) => Err( "โŒ Number of slots must be between 1 and 1000. Please enter a valid number:" .to_string(), @@ -52,7 +52,7 @@ pub fn validate_slots(text: &str) -> Result { pub fn validate_duration(text: &str) -> Result { match text.parse::() { - Ok(hours) if hours >= 1 && hours <= 720 => Ok(ListingDuration::hours(hours)), // 1 hour to 30 days + Ok(hours) if (1..=720).contains(&hours) => Ok(ListingDuration::hours(hours)), // 1 hour to 30 days Ok(_) => Err( "โŒ Duration must be between 1 and 720 hours. Please enter a valid number:".to_string(), ), @@ -62,7 +62,7 @@ pub fn validate_duration(text: &str) -> Result { pub fn validate_start_time(text: &str) -> Result { match text.parse::() { - Ok(hours) if hours >= 0 && hours <= 168 => Ok(ListingDuration::hours(hours)), // Max 1 week delay + Ok(hours) if (0..=168).contains(&hours) => Ok(ListingDuration::hours(hours)), // Max 1 week delay Ok(_) => Err( "โŒ Start time must be between 0 and 168 hours. Please enter a valid number:" .to_string(), diff --git a/src/config.rs b/src/config.rs index f39743b..1f328de 100644 --- a/src/config.rs +++ b/src/config.rs @@ -76,7 +76,7 @@ impl Config { log::info!(" Web Port: {}", self.web_port); if let Some(admin_id) = self.admin_user_id { - log::info!(" Admin User ID: {}", admin_id); + log::info!(" Admin User ID: {admin_id}"); } else { log::info!(" Admin User ID: Not set"); } diff --git a/src/db/dao/listing_dao.rs b/src/db/dao/listing_dao.rs index bc7e073..70613d2 100644 --- a/src/db/dao/listing_dao.rs +++ b/src/db/dao/listing_dao.rs @@ -114,7 +114,7 @@ impl ListingDAO { .fetch_optional(pool) .await?; - Ok(result.map(Self::row_to_listing).transpose()?) + result.map(Self::row_to_listing).transpose() } /// Find all listings by a seller @@ -125,10 +125,10 @@ impl ListingDAO { .fetch_all(pool) .await?; - Ok(rows + rows .into_iter() .map(Self::row_to_listing) - .collect::>>()?) + .collect::>>() } /// Delete a listing diff --git a/src/db/dao/user_dao.rs b/src/db/dao/user_dao.rs index 30185ed..9bb7026 100644 --- a/src/db/dao/user_dao.rs +++ b/src/db/dao/user_dao.rs @@ -13,6 +13,7 @@ use crate::db::{ /// Data Access Object for User operations pub struct UserDAO; +#[allow(unused)] impl UserDAO { /// Insert a new user into the database pub async fn insert_user(pool: &SqlitePool, new_user: &NewUser) -> Result { @@ -131,7 +132,7 @@ impl UserDAO { #[cfg(test)] mod tests { use super::*; - use crate::db::models::user::{NewUser, User}; + use crate::db::models::user::NewUser; use rstest::rstest; use sqlx::SqlitePool; use teloxide::types::UserId; diff --git a/src/db/models/listing.rs b/src/db/models/listing.rs index d4cb2e1..3df5274 100644 --- a/src/db/models/listing.rs +++ b/src/db/models/listing.rs @@ -15,6 +15,7 @@ use chrono::{DateTime, Utc}; /// Main listing/auction entity #[derive(Debug, Clone)] +#[allow(unused)] pub struct Listing { pub base: ListingBase, pub fields: ListingFields, @@ -22,6 +23,7 @@ pub struct Listing { /// Common fields shared by all listing types #[derive(Debug, Clone)] +#[allow(unused)] pub struct ListingBase { pub id: ListingId, pub seller_id: UserRowId, @@ -34,6 +36,7 @@ pub struct ListingBase { } #[derive(Debug, Clone)] +#[allow(unused)] pub enum ListingFields { BasicAuction { starting_bid: MoneyAmount, @@ -57,6 +60,7 @@ pub enum ListingFields { }, } +#[allow(unused)] impl Listing { /// Get the listing type as an enum value pub fn listing_type(&self) -> ListingType { diff --git a/src/db/models/mod.rs b/src/db/models/mod.rs index ab1adea..4c08a36 100644 --- a/src/db/models/mod.rs +++ b/src/db/models/mod.rs @@ -8,10 +8,6 @@ pub mod user; pub mod user_settings; // Re-export all types for easy access -pub use bid::*; pub use listing::*; -pub use listing_media::*; pub use listing_type::*; -pub use proxy_bid::*; pub use user::*; -pub use user_settings::*; diff --git a/src/db/models/new_listing.rs b/src/db/models/new_listing.rs index 48b31f5..e06ce61 100644 --- a/src/db/models/new_listing.rs +++ b/src/db/models/new_listing.rs @@ -29,6 +29,7 @@ pub struct NewListingBase { } #[derive(Debug, Clone)] +#[allow(unused)] pub enum NewListingFields { BasicAuction { starting_bid: MoneyAmount, @@ -52,6 +53,7 @@ pub enum NewListingFields { }, } +#[allow(unused)] impl NewListingBase { pub fn new( seller_id: UserRowId, diff --git a/src/db/models/proxy_bid.rs b/src/db/models/proxy_bid.rs index 830e9b9..82570e1 100644 --- a/src/db/models/proxy_bid.rs +++ b/src/db/models/proxy_bid.rs @@ -5,6 +5,7 @@ use crate::db::MoneyAmount; /// Proxy bid strategies (automatic bidding settings) #[derive(Debug, Clone, FromRow)] +#[allow(unused)] pub struct ProxyBid { pub id: i64, pub listing_id: i64, @@ -17,6 +18,7 @@ pub struct ProxyBid { /// New proxy bid data for insertion #[derive(Debug, Clone)] +#[allow(unused)] pub struct NewProxyBid { pub listing_id: i64, pub buyer_id: i64, diff --git a/src/db/models/user.rs b/src/db/models/user.rs index e12dd57..6340f46 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -5,6 +5,7 @@ use crate::db::{TelegramUserId, UserRowId}; /// Core user information #[derive(Debug, Clone, FromRow)] +#[allow(unused)] pub struct User { pub id: UserRowId, pub telegram_id: TelegramUserId, diff --git a/src/db/types/currency_type.rs b/src/db/types/currency_type.rs index a2a14d6..744f420 100644 --- a/src/db/types/currency_type.rs +++ b/src/db/types/currency_type.rs @@ -3,41 +3,38 @@ use sqlx::{ }; /// Currency types supported by the platform -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum CurrencyType { - USD, + #[default] + Usd, } +#[allow(unused)] impl CurrencyType { /// Get the currency code as a string pub fn as_str(&self) -> &'static str { match self { - CurrencyType::USD => "USD", + CurrencyType::Usd => "USD", } } /// Get the currency symbol pub fn symbol(&self) -> &'static str { match self { - CurrencyType::USD => "$", + CurrencyType::Usd => "$", } } /// Parse currency from string pub fn from_str(s: &str) -> Result { match s.to_uppercase().as_str() { - "USD" => Ok(CurrencyType::USD), - _ => Err(format!("Unsupported currency: {}", s)), + "USD" => Ok(CurrencyType::Usd), + _ => Err(format!("Unsupported currency: {s}")), } } } // Implement Default for CurrencyType (defaults to USD) -impl Default for CurrencyType { - fn default() -> Self { - CurrencyType::USD - } -} // Implement Display for CurrencyType impl std::fmt::Display for CurrencyType { @@ -83,7 +80,7 @@ mod tests { #[test] fn test_currency_type_display() { - let usd = CurrencyType::USD; + let usd = CurrencyType::Usd; assert_eq!(usd.to_string(), "USD"); assert_eq!(usd.symbol(), "$"); assert_eq!(usd.as_str(), "USD"); @@ -92,16 +89,16 @@ mod tests { #[test] fn test_currency_type_default() { let default_currency = CurrencyType::default(); - assert_eq!(default_currency, CurrencyType::USD); + assert_eq!(default_currency, CurrencyType::Usd); } #[test] fn test_currency_type_parsing() { let parsed_currency = CurrencyType::from_str("usd").unwrap(); // Case insensitive - assert_eq!(parsed_currency, CurrencyType::USD); + assert_eq!(parsed_currency, CurrencyType::Usd); let parsed_upper = CurrencyType::from_str("USD").unwrap(); - assert_eq!(parsed_upper, CurrencyType::USD); + assert_eq!(parsed_upper, CurrencyType::Usd); let invalid = CurrencyType::from_str("EUR"); assert!(invalid.is_err()); diff --git a/src/db/types/listing_duration.rs b/src/db/types/listing_duration.rs index aacafb0..330a897 100644 --- a/src/db/types/listing_duration.rs +++ b/src/db/types/listing_duration.rs @@ -11,6 +11,7 @@ use std::fmt::{self, Display}; use crate::message_utils::pluralize_with_count; #[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Default)] pub struct ListingDuration(i32); impl ListingDuration { pub fn hours(hours: i32) -> Self { @@ -23,11 +24,6 @@ impl ListingDuration { Default::default() } } -impl Default for ListingDuration { - fn default() -> Self { - Self(0) - } -} impl From for Duration { fn from(duration: ListingDuration) -> Self { Duration::hours(duration.0 as i64) diff --git a/src/db/types/mod.rs b/src/db/types/mod.rs index f61031e..b59137b 100644 --- a/src/db/types/mod.rs +++ b/src/db/types/mod.rs @@ -6,6 +6,7 @@ mod telegram_user_id; mod user_row_id; // Re-export all types for easy access +#[allow(unused)] pub use currency_type::*; pub use listing_duration::*; pub use listing_id::*; diff --git a/src/db/types/money_amount.rs b/src/db/types/money_amount.rs index 05c9ae0..2c7bc80 100644 --- a/src/db/types/money_amount.rs +++ b/src/db/types/money_amount.rs @@ -35,12 +35,12 @@ impl MoneyAmount { } /// Get the value in cents - pub fn cents(&self) -> i64 { + pub fn cents(self) -> i64 { self.0 } /// Get the value as a Decimal (for display/calculation purposes) - pub fn to_decimal(&self) -> Decimal { + pub fn to_decimal(self) -> Decimal { Decimal::new(self.0, 2) // 2 decimal places for cents } } @@ -204,7 +204,7 @@ mod tests { // Insert test data sqlx::query("INSERT INTO test_money (amount, currency) VALUES (?, ?)") .bind(&amount) - .bind(CurrencyType::USD) + .bind(CurrencyType::Usd) .execute(&pool) .await .expect("Failed to insert test data"); @@ -219,7 +219,7 @@ mod tests { let retrieved_currency: CurrencyType = row.get("currency"); assert_eq!(retrieved_amount, amount); - assert_eq!(retrieved_currency, CurrencyType::USD); + assert_eq!(retrieved_currency, CurrencyType::Usd); // Verify string representation matches expected format (cent-based precision) assert_eq!(retrieved_amount.to_string(), expected_str); @@ -234,7 +234,7 @@ mod tests { // Test with NULL (None) value sqlx::query("INSERT INTO test_money (amount, currency, optional_amount) VALUES (?, ?, ?)") .bind(MoneyAmount::from_str("50.00").unwrap()) - .bind(CurrencyType::USD) + .bind(CurrencyType::Usd) .bind(None::) .execute(&pool) .await @@ -244,7 +244,7 @@ mod tests { let optional_amount = Some(MoneyAmount::from_str("25.75").unwrap()); sqlx::query("INSERT INTO test_money (amount, currency, optional_amount) VALUES (?, ?, ?)") .bind(MoneyAmount::from_str("100.00").unwrap()) - .bind(CurrencyType::USD) + .bind(CurrencyType::Usd) .bind(&optional_amount) .execute(&pool) .await @@ -291,7 +291,7 @@ mod tests { // Insert into database sqlx::query("INSERT INTO test_money (amount, currency) VALUES (?, ?)") .bind(&amount) - .bind(CurrencyType::USD) + .bind(CurrencyType::Usd) .execute(&pool) .await .expect("Failed to insert precision test data"); diff --git a/src/db/types/user_row_id.rs b/src/db/types/user_row_id.rs index 4d4c055..226d799 100644 --- a/src/db/types/user_row_id.rs +++ b/src/db/types/user_row_id.rs @@ -7,7 +7,6 @@ use sqlx::{ encode::IsNull, error::BoxDynError, sqlite::SqliteTypeInfo, Decode, Encode, Sqlite, Type, }; use std::fmt; -use teloxide::types::ChatId; /// Type-safe wrapper for user IDs #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/src/keyboard_utils.rs b/src/keyboard_utils.rs index 00c0cb1..d8d5b24 100644 --- a/src/keyboard_utils.rs +++ b/src/keyboard_utils.rs @@ -35,10 +35,10 @@ macro_rules! keyboard_buttons { markup } } - impl Into for $name { - fn into(self) -> teloxide::types::InlineKeyboardButton { - match self { - $($(Self::$variant => teloxide::types::InlineKeyboardButton::callback($text, $callback_data)),*),* + impl From<$name> for teloxide::types::InlineKeyboardButton { + fn from(value: $name) -> Self { + match value { + $($($name::$variant => teloxide::types::InlineKeyboardButton::callback($text, $callback_data)),*),* } } } diff --git a/src/message_utils.rs b/src/message_utils.rs index e795fd5..4531d67 100644 --- a/src/message_utils.rs +++ b/src/message_utils.rs @@ -6,8 +6,8 @@ use teloxide::{ payloads::{EditMessageTextSetters as _, SendMessageSetters as _}, prelude::Requester as _, types::{ - CallbackQuery, Chat, ChatId, InlineKeyboardButton, InlineKeyboardMarkup, Message, - MessageId, ParseMode, User, + CallbackQuery, Chat, ChatId, InlineKeyboardButton, InlineKeyboardMarkup, MessageId, + ParseMode, User, }, Bot, }; @@ -39,14 +39,14 @@ impl<'s> HandleAndId<'s> { } } -impl<'s> Into> for &'s User { - fn into(self) -> HandleAndId<'s> { - HandleAndId::from_user(self) +impl<'s> From<&'s User> for HandleAndId<'s> { + fn from(val: &'s User) -> Self { + HandleAndId::from_user(val) } } -impl<'s> Into> for &'s Chat { - fn into(self) -> HandleAndId<'s> { - HandleAndId::from_chat(self) +impl<'s> From<&'s Chat> for HandleAndId<'s> { + fn from(val: &'s Chat) -> Self { + HandleAndId::from_chat(val) } } @@ -60,47 +60,47 @@ pub struct MessageTarget { pub message_id: Option, } -impl Into for ChatId { - fn into(self) -> MessageTarget { +impl From for MessageTarget { + fn from(val: ChatId) -> Self { MessageTarget { - chat_id: self, + chat_id: val, message_id: None, } } } -impl Into for Chat { - fn into(self) -> MessageTarget { +impl From for MessageTarget { + fn from(val: Chat) -> Self { MessageTarget { - chat_id: self.id, + chat_id: val.id, message_id: None, } } } -impl Into for User { - fn into(self) -> MessageTarget { +impl From for MessageTarget { + fn from(val: User) -> Self { MessageTarget { - chat_id: self.id.into(), + chat_id: val.id.into(), message_id: None, } } } -impl Into for (User, MessageId) { - fn into(self) -> MessageTarget { +impl From<(User, MessageId)> for MessageTarget { + fn from(val: (User, MessageId)) -> Self { MessageTarget { - chat_id: self.0.id.into(), - message_id: Some(self.1), + chat_id: val.0.id.into(), + message_id: Some(val.1), } } } -impl Into for (Chat, MessageId) { - fn into(self) -> MessageTarget { +impl From<(Chat, MessageId)> for MessageTarget { + fn from(val: (Chat, MessageId)) -> Self { MessageTarget { - chat_id: self.0.id.into(), - message_id: Some(self.1), + chat_id: val.0.id, + message_id: Some(val.1), } } } @@ -165,7 +165,7 @@ pub fn create_multi_row_keyboard(rows: &[&[(&str, &str)]]) -> InlineKeyboardMark } // Extract callback data and answer callback query -pub async fn extract_callback_data<'c>( +pub async fn extract_callback_data( bot: &Bot, callback_query: CallbackQuery, ) -> HandlerResult<(String, User, MessageId)> { @@ -184,7 +184,7 @@ pub async fn extract_callback_data<'c>( // Answer the callback query to remove loading state if let Err(e) = bot.answer_callback_query(callback_query.id.clone()).await { - log::warn!("Failed to answer callback query: {}", e); + log::warn!("Failed to answer callback query: {e}"); } Ok((data, from, message_id)) @@ -202,7 +202,7 @@ pub fn pluralize<'a, N: One + PartialEq>( } } -pub fn pluralize_with_count<'a, N: One + PartialEq + Display + Copy>( +pub fn pluralize_with_count + Display + Copy>( count: N, singular: &str, plural: &str,