use std::{env, net::Ipv4Addr, sync::Arc};
use actix_web::{
middleware::Logger,
web::{self, Data},
App, HttpServer,
};
use anthill_di::*;
use anthill_di_derive::constructor;
use async_lock::RwLock;
use botx_api::{
api::{
context::BotXApiContext,
v4::notification::internal::{
api::internal_notification,
models::{
InternalNotificationRequestBuilder,
InternalNotificationRequest,
},
},
},
extensions::botx_api_context::IBotXApiContextExt,
};
use botx_api_framework::{
contexts::{BotXApiFrameworkContext, RequestContext},
extensions::actix::IActixHandlersExt,
handlers::message::IMessageHandler,
results::{CommandOk, CommandResult},
};
use env_logger::Env;
use serde::Serialize;
#[derive(Serialize, Clone)]
pub struct InternalBotMessageData {
pub message: String
}
#[derive(Serialize, Clone)]
pub struct InternalBotMessageOption {
pub internal_data: String
}
#[derive(constructor)]
pub struct MessageHandler {
#[resolve]
api: Arc<RwLock<BotXApiContext>>,
}
#[async_trait_with_sync::async_trait]
impl IMessageHandler for MessageHandler {
async fn handle(&mut self, _message: String, request: RequestContext) -> CommandResult {
let request: InternalNotificationRequest<InternalBotMessageData, InternalBotMessageOption> = InternalNotificationRequestBuilder::default()
.with_group_chat_id(request.from.group_chat_id.unwrap())
.with_data(InternalBotMessageData { message: "test message data".to_string() })
.with_opts(InternalBotMessageOption { internal_data: "internal message option".to_string() })
.build()
.unwrap();
internal_notification(&self.api, &request).await.unwrap();
Ok(CommandOk::default())
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let (ip, port) = get_address();
let ioc_ctx = DependencyContext::new_root();
ioc_ctx
.register_type::<BotXApiFrameworkContext>(LifeCycle::Transient)
.await?;
ioc_ctx
.register_type::<MessageHandler>(LifeCycle::Transient)
.await?
.map_as::<dyn IMessageHandler>()
.await?;
ioc_ctx.register_botx_api_context().await?;
HttpServer::new(move || {
App::new()
.wrap(Logger::default())
.app_data(web::PayloadConfig::new(usize::MAX))
.app_data(web::JsonConfig::default().limit(usize::MAX))
.app_data(Data::new(ioc_ctx.clone()))
.add_botx_api_handlers()
})
.bind((ip.to_string(), port))?
.run()
.await?;
Ok(())
}
const BOT_HOST_ENV: &str = "BOT_HOST";
const BOT_PORT_ENV: &str = "BOT_PORT";
fn get_address() -> (Ipv4Addr, u16) {
let ip = env::var(BOT_HOST_ENV)
.expect(&*format!("Env {BOT_HOST_ENV} not found"))
.parse::<Ipv4Addr>()
.expect(&*format!("Env {BOT_HOST_ENV} must be valid ipv4"));
let port = env::var(BOT_PORT_ENV)
.expect(&*format!("Env {BOT_PORT_ENV} not found"))
.parse::<u16>()
.expect(&*format!("Env {BOT_PORT_ENV} must be valid u32"));
(ip, port)
}