Added weather.
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
use grammers_client::Update;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::utils::messages::get_message;
|
||||
|
||||
@ -31,9 +32,14 @@ pub struct ExcludedChatsFilter(pub Vec<i64>);
|
||||
#[derive(Clone)]
|
||||
pub struct MessageDirectionFilter(pub MessageDirection);
|
||||
|
||||
/// Filters text by predicate.
|
||||
#[derive(Clone)]
|
||||
pub struct TextFilter<'a>(pub &'a [&'a str], pub TextMatchMethod);
|
||||
|
||||
/// Filters using provided regex.
|
||||
#[derive(Clone)]
|
||||
pub struct RegexFilter(pub Regex);
|
||||
|
||||
impl Filter for ExcludedChatsFilter {
|
||||
fn filter(&self, update: &Update) -> anyhow::Result<bool> {
|
||||
let a = match update {
|
||||
@ -89,3 +95,10 @@ impl Filter for SilentFilter {
|
||||
Ok(!message.silent())
|
||||
}
|
||||
}
|
||||
|
||||
impl Filter for RegexFilter {
|
||||
fn filter(&self, update: &Update) -> anyhow::Result<bool> {
|
||||
let Some(message) = get_message(update) else {return Ok(false)};
|
||||
Ok(self.0.is_match(message.text()))
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod currency_converter;
|
||||
pub mod get_chat_id;
|
||||
pub mod help;
|
||||
pub mod weather_forecaster;
|
||||
|
84
src/bot/handlers/basic/weather_forecaster.rs
Normal file
84
src/bot/handlers/basic/weather_forecaster.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use grammers_client::{Client, InputMessage, Update};
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
use crate::{bot::handlers::Handler, utils::messages::get_message};
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WeatherForecaster {
|
||||
client: reqwest::Client,
|
||||
}
|
||||
|
||||
impl WeatherForecaster {
|
||||
pub fn new() -> anyhow::Result<Self> {
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.timeout(Duration::from_secs(2))
|
||||
.gzip(true)
|
||||
.build()?;
|
||||
Ok(Self { client })
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Handler for WeatherForecaster {
|
||||
async fn react(&self, _: &Client, update: &Update) -> anyhow::Result<()> {
|
||||
let Some(message) = get_message(update) else {
|
||||
return Ok(());
|
||||
};
|
||||
let Some(city) = message.text().strip_prefix(".w").map(str::trim) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let response = self
|
||||
.client
|
||||
.get(format!("https://wttr.in/{city}?0QT"))
|
||||
.header("user-agent", "curl/7.0")
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if response.status() == reqwest::StatusCode::NOT_FOUND {
|
||||
message
|
||||
.reply(
|
||||
[
|
||||
"Лол, ты сам-то понял что написал?",
|
||||
"Не, я хз где это.",
|
||||
"Если ты действительно тут живешь, то сочувствую.",
|
||||
]
|
||||
.choose(&mut OsRng)
|
||||
.copied()
|
||||
.unwrap(),
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if response.status() != reqwest::StatusCode::OK {
|
||||
message.reply("Сервис недоступен. Попробуй потом.").await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let forecast = response.text().await?;
|
||||
|
||||
message
|
||||
.reply(
|
||||
InputMessage::html(
|
||||
forecast
|
||||
// We need to wrap every line in pre tag.
|
||||
.split('\n')
|
||||
.filter(|line| !line.trim().is_empty())
|
||||
.map(|line| format!("<pre>{line}</pre>\n"))
|
||||
// Also we add a message at the end by chaining another
|
||||
// iterable.
|
||||
.chain([String::from("Ваш прогноз.")])
|
||||
// And collect interator to final HTML string.
|
||||
.collect::<String>(),
|
||||
)
|
||||
.silent(true),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
pub mod blyaficator;
|
||||
pub mod greeter;
|
||||
pub mod repeator;
|
||||
pub mod rotator;
|
||||
|
15
src/bot/handlers/fun/repeator.rs
Normal file
15
src/bot/handlers/fun/repeator.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use grammers_client::{Client, Update};
|
||||
|
||||
use crate::{bot::handlers::Handler, utils::messages::get_message};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Repeator;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Handler for Repeator {
|
||||
async fn react(&self, _: &Client, update: &Update) -> anyhow::Result<()> {
|
||||
let Some(message) = get_message(update) else { return Ok(()) };
|
||||
message.respond(message.text()).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -4,14 +4,15 @@ use crate::args::BotConfig;
|
||||
use grammers_client::{Client, Config, SignInError, Update};
|
||||
use grammers_session::Session;
|
||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||
use regex::Regex;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use super::{
|
||||
filters::{
|
||||
filtered_handler::FilteredHandler,
|
||||
message_fitlers::{
|
||||
ExcludedChatsFilter, MessageDirection, MessageDirectionFilter, SilentFilter,
|
||||
TextFilter, TextMatchMethod,
|
||||
ExcludedChatsFilter, MessageDirection, MessageDirectionFilter, RegexFilter,
|
||||
SilentFilter, TextFilter, TextMatchMethod,
|
||||
},
|
||||
},
|
||||
handlers::{
|
||||
@ -19,8 +20,9 @@ use super::{
|
||||
currency_converter::{CurrencyConverter, CurrencyTextFilter},
|
||||
get_chat_id::GetChatId,
|
||||
help::Help,
|
||||
weather_forecaster::WeatherForecaster,
|
||||
},
|
||||
fun::{blyaficator::Blyaficator, greeter::Greeter, rotator::Rotator},
|
||||
fun::{blyaficator::Blyaficator, greeter::Greeter, repeator::Repeator, rotator::Rotator},
|
||||
Handler,
|
||||
},
|
||||
};
|
||||
@ -90,11 +92,13 @@ async fn handle_with_log(handler: Box<dyn Handler>, client: Client, update_data:
|
||||
///
|
||||
/// Also, every available handler is defined here.
|
||||
async fn run(args: BotConfig, client: Client) -> anyhow::Result<()> {
|
||||
let me = client.get_me().await?;
|
||||
let handlers: Vec<FilteredHandler> = vec![
|
||||
// Printing help.
|
||||
FilteredHandler::new(Help).add_filter(TextFilter(&[".h"], TextMatchMethod::IMatches)),
|
||||
// Greeting my fellow humans.
|
||||
FilteredHandler::new(Greeter)
|
||||
.add_filter(ExcludedChatsFilter(vec![me.id()]))
|
||||
.add_filter(SilentFilter)
|
||||
.add_filter(MessageDirectionFilter(MessageDirection::Incoming))
|
||||
.add_filter(TextFilter(&["привет"], TextMatchMethod::IStartsWith))
|
||||
@ -115,6 +119,16 @@ async fn run(args: BotConfig, client: Client) -> anyhow::Result<()> {
|
||||
FilteredHandler::new(Rotator)
|
||||
.add_filter(SilentFilter)
|
||||
.add_filter(TextFilter(&[".rl"], TextMatchMethod::IStartsWith)),
|
||||
// Weather forecast.
|
||||
FilteredHandler::new(WeatherForecaster::new()?)
|
||||
.add_filter(SilentFilter)
|
||||
.add_filter(TextFilter(&[".w"], TextMatchMethod::IStartsWith)),
|
||||
// Smiley repeator.
|
||||
FilteredHandler::new(Repeator)
|
||||
.add_filter(ExcludedChatsFilter(vec![me.id()]))
|
||||
.add_filter(MessageDirectionFilter(MessageDirection::Incoming))
|
||||
.add_filter(SilentFilter)
|
||||
.add_filter(RegexFilter(Regex::new("^[)0]+$")?)),
|
||||
];
|
||||
|
||||
let mut errors_count = 0;
|
||||
@ -154,7 +168,6 @@ async fn run(args: BotConfig, client: Client) -> anyhow::Result<()> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn bot_life(
|
||||
args: BotConfig,
|
||||
web_code: Arc<RwLock<Option<String>>>,
|
||||
|
Reference in New Issue
Block a user