Generalize notification handling
This commit is contained in:
@ -75,12 +75,16 @@ fn get_twilio_config() -> Result<Option<TwilioWebHook>, String> {
|
|||||||
Ok(Some(config))
|
Ok(Some(config))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum NotificationType {
|
||||||
|
Discord(String),
|
||||||
|
Slack(String),
|
||||||
|
Telegram(TelegramWebHook),
|
||||||
|
Twilio(TwilioWebHook),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Notifier {
|
pub struct Notifier {
|
||||||
client: Client,
|
client: Client,
|
||||||
discord_webhook: Option<String>,
|
notifiers: Vec<NotificationType>,
|
||||||
slack_webhook: Option<String>,
|
|
||||||
telegram_webhook: Option<TelegramWebHook>,
|
|
||||||
twilio_webhook: Option<TwilioWebHook>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Notifier {
|
impl Notifier {
|
||||||
@ -91,99 +95,103 @@ impl Notifier {
|
|||||||
pub fn new(env_prefix: &str) -> Self {
|
pub fn new(env_prefix: &str) -> Self {
|
||||||
info!("Initializing {}Notifier", env_prefix);
|
info!("Initializing {}Notifier", env_prefix);
|
||||||
|
|
||||||
let discord_webhook = env::var(format!("{}DISCORD_WEBHOOK", env_prefix))
|
let mut notifiers = vec![];
|
||||||
.map_err(|_| {
|
|
||||||
info!("Discord notifications disabled");
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
let slack_webhook = env::var(format!("{}SLACK_WEBHOOK", env_prefix))
|
|
||||||
.map_err(|_| {
|
|
||||||
info!("Slack notifications disabled");
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
let telegram_webhook = if let (Ok(bot_token), Ok(chat_id)) = (
|
if let Ok(webhook) = env::var(format!("{}DISCORD_WEBHOOK", env_prefix)) {
|
||||||
|
notifiers.push(NotificationType::Discord(webhook));
|
||||||
|
}
|
||||||
|
if let Ok(webhook) = env::var(format!("{}SLACK_WEBHOOK", env_prefix)) {
|
||||||
|
notifiers.push(NotificationType::Slack(webhook));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (Ok(bot_token), Ok(chat_id)) = (
|
||||||
env::var(format!("{}TELEGRAM_BOT_TOKEN", env_prefix)),
|
env::var(format!("{}TELEGRAM_BOT_TOKEN", env_prefix)),
|
||||||
env::var(format!("{}TELEGRAM_CHAT_ID", env_prefix)),
|
env::var(format!("{}TELEGRAM_CHAT_ID", env_prefix)),
|
||||||
) {
|
) {
|
||||||
Some(TelegramWebHook { bot_token, chat_id })
|
notifiers.push(NotificationType::Telegram(TelegramWebHook {
|
||||||
} else {
|
bot_token,
|
||||||
info!("Telegram notifications disabled");
|
chat_id,
|
||||||
None
|
}));
|
||||||
};
|
}
|
||||||
let twilio_webhook = get_twilio_config()
|
|
||||||
.map_err(|err| panic!("Twilio config error: {}", err))
|
if let Ok(Some(webhook)) = get_twilio_config() {
|
||||||
.unwrap();
|
notifiers.push(NotificationType::Twilio(webhook));
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("{} notifiers", notifiers.len());
|
||||||
|
|
||||||
Notifier {
|
Notifier {
|
||||||
client: Client::new(),
|
client: Client::new(),
|
||||||
discord_webhook,
|
notifiers,
|
||||||
slack_webhook,
|
|
||||||
telegram_webhook,
|
|
||||||
twilio_webhook,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.notifiers.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn send(&self, msg: &str) {
|
pub fn send(&self, msg: &str) {
|
||||||
if let Some(webhook) = &self.discord_webhook {
|
for notifier in &self.notifiers {
|
||||||
for line in msg.split('\n') {
|
match notifier {
|
||||||
// Discord rate limiting is aggressive, limit to 1 message a second
|
NotificationType::Discord(webhook) => {
|
||||||
sleep(Duration::from_millis(1000));
|
for line in msg.split('\n') {
|
||||||
|
// Discord rate limiting is aggressive, limit to 1 message a second
|
||||||
|
sleep(Duration::from_millis(1000));
|
||||||
|
|
||||||
info!("Sending {}", line);
|
info!("Sending {}", line);
|
||||||
let data = json!({ "content": line });
|
let data = json!({ "content": line });
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let response = self.client.post(webhook).json(&data).send();
|
let response = self.client.post(webhook).json(&data).send();
|
||||||
|
|
||||||
if let Err(err) = response {
|
if let Err(err) = response {
|
||||||
warn!("Failed to send Discord message: \"{}\": {:?}", line, err);
|
warn!("Failed to send Discord message: \"{}\": {:?}", line, err);
|
||||||
break;
|
break;
|
||||||
} else if let Ok(response) = response {
|
} else if let Ok(response) = response {
|
||||||
info!("response status: {}", response.status());
|
info!("response status: {}", response.status());
|
||||||
if response.status() == StatusCode::TOO_MANY_REQUESTS {
|
if response.status() == StatusCode::TOO_MANY_REQUESTS {
|
||||||
warn!("rate limited!...");
|
warn!("rate limited!...");
|
||||||
warn!("response text: {:?}", response.text());
|
warn!("response text: {:?}", response.text());
|
||||||
sleep(Duration::from_secs(2));
|
sleep(Duration::from_secs(2));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NotificationType::Slack(webhook) => {
|
||||||
|
let data = json!({ "text": msg });
|
||||||
|
if let Err(err) = self.client.post(webhook).json(&data).send() {
|
||||||
|
warn!("Failed to send Slack message: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationType::Telegram(TelegramWebHook { chat_id, bot_token }) => {
|
||||||
|
let data = json!({ "chat_id": chat_id, "text": msg });
|
||||||
|
let url = format!("https://api.telegram.org/bot{}/sendMessage", bot_token);
|
||||||
|
|
||||||
|
if let Err(err) = self.client.post(&url).json(&data).send() {
|
||||||
|
warn!("Failed to send Telegram message: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationType::Twilio(TwilioWebHook {
|
||||||
|
account,
|
||||||
|
token,
|
||||||
|
to,
|
||||||
|
from,
|
||||||
|
}) => {
|
||||||
|
let url = format!(
|
||||||
|
"https://{}:{}@api.twilio.com/2010-04-01/Accounts/{}/Messages.json",
|
||||||
|
account, token, account
|
||||||
|
);
|
||||||
|
let params = [("To", to), ("From", from), ("Body", &msg.to_string())];
|
||||||
|
if let Err(err) = self.client.post(&url).form(¶ms).send() {
|
||||||
|
warn!("Failed to send Twilio message: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(webhook) = &self.slack_webhook {
|
|
||||||
let data = json!({ "text": msg });
|
|
||||||
if let Err(err) = self.client.post(webhook).json(&data).send() {
|
|
||||||
warn!("Failed to send Slack message: {:?}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(TelegramWebHook { chat_id, bot_token }) = &self.telegram_webhook {
|
|
||||||
let data = json!({ "chat_id": chat_id, "text": msg });
|
|
||||||
let url = format!("https://api.telegram.org/bot{}/sendMessage", bot_token);
|
|
||||||
|
|
||||||
if let Err(err) = self.client.post(&url).json(&data).send() {
|
|
||||||
warn!("Failed to send Telegram message: {:?}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(TwilioWebHook {
|
|
||||||
account,
|
|
||||||
token,
|
|
||||||
to,
|
|
||||||
from,
|
|
||||||
}) = &self.twilio_webhook
|
|
||||||
{
|
|
||||||
let url = format!(
|
|
||||||
"https://{}:{}@api.twilio.com/2010-04-01/Accounts/{}/Messages.json",
|
|
||||||
account, token, account
|
|
||||||
);
|
|
||||||
let params = [("To", to), ("From", from), ("Body", &msg.to_string())];
|
|
||||||
if let Err(err) = self.client.post(&url).form(¶ms).send() {
|
|
||||||
warn!("Failed to send Twilio message: {:?}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user