Added weather.

This commit is contained in:
2023-02-23 22:14:59 +00:00
parent cac238df97
commit d93d12e48a
6 changed files with 131 additions and 4 deletions

View File

@ -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()))
}
}

View File

@ -1,3 +1,4 @@
pub mod currency_converter;
pub mod get_chat_id;
pub mod help;
pub mod weather_forecaster;

View 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(())
}
}

View File

@ -1,3 +1,4 @@
pub mod blyaficator;
pub mod greeter;
pub mod repeator;
pub mod rotator;

View 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(())
}
}

View File

@ -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>>>,