Skip to content

Commit

Permalink
feat: support lark bot push message
Browse files Browse the repository at this point in the history
  • Loading branch information
fan-tastic-z committed Jun 1, 2024
1 parent edce0b6 commit 4217c82
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 36 deletions.
4 changes: 4 additions & 0 deletions config/development.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ tg_bot:
ding_bot:
access_token: {{ get_env(name="DING_ACCESS_TOKEN", default="") }}
secret_token: {{ get_env(name="DING_SECRET_TOKEN", default="") }}

lark_bot:
access_token: {{ get_env(name="LARK_ACCESS_TOKEN", default="") }}
secret_token: {{ get_env(name="LARK_SECRET_TOKEN", default="") }}
7 changes: 7 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct Config {
pub logger: Logger,
pub tg_bot: TgBot,
pub ding_bot: DingBot,
pub lark_bot: LarkBot,
}

impl Config {
Expand Down Expand Up @@ -108,3 +109,9 @@ pub struct DingBot {
pub access_token: String,
pub secret_token: String,
}

#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct LarkBot {
pub access_token: String,
pub secret_token: String,
}
7 changes: 5 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::num::ParseIntError;
use std::{num::ParseIntError, time::SystemTimeError};

use hmac::digest::crypto_common;
use migration::sea_orm;
Expand Down Expand Up @@ -66,7 +66,10 @@ pub enum Error {
IO(#[from] std::io::Error),

#[error(transparent)]
DataParse(#[from] chrono::ParseError),
DateParse(#[from] chrono::ParseError),

#[error(transparent)]
SystemTime(#[from] SystemTimeError),

#[error(transparent)]
Any(#[from] Box<dyn std::error::Error + Send + Sync>),
Expand Down
52 changes: 19 additions & 33 deletions src/push/dingding.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::time::SystemTime;

use crate::{
error::{Error, Result},
utils::{calc_hmac_sha256, http_client::Help},
Expand Down Expand Up @@ -74,42 +72,30 @@ impl DingDing {
Help::new(headers)
}
pub fn generate_sign(&self) -> Result<Sign> {
let sign = if !self.secret_token.is_empty() {
let timestamp = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_millis();
let timestamp_and_secret = &format!("{}\n{}", timestamp, self.secret_token);
let hmac_sha256 = calc_hmac_sha256(
self.secret_token.as_bytes(),
timestamp_and_secret.as_bytes(),
)?;
let sign = BASE64_STANDARD.encode(hmac_sha256);
Sign {
access_token: self.access_token.clone(),
timestamp: Some(timestamp),
sign: Some(sign),
}
} else {
Sign {
access_token: self.access_token.clone(),
timestamp: None,
sign: None,
}
};
Ok(sign)
let now = chrono::Local::now().timestamp();
let timestamp_and_secret = &format!("{}\n{}", now, self.secret_token);
let hmac_sha256 = calc_hmac_sha256(
self.secret_token.as_bytes(),
timestamp_and_secret.as_bytes(),
)?;
let sign = BASE64_STANDARD.encode(hmac_sha256);
Ok(Sign {
access_token: self.access_token.clone(),
timestamp: now,
sign,
})
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Sign {
pub access_token: String,
pub timestamp: Option<u128>,
pub sign: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DingResponse {
pub errmsg: String,
pub errcode: i64,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Sign {
pub access_token: String,
pub timestamp: i64,
pub sign: String,
}
108 changes: 108 additions & 0 deletions src/push/lark.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use async_trait::async_trait;
use base64::prelude::*;
use hmac::{Hmac, Mac};
use reqwest::header;
use serde::{Deserialize, Serialize};
use serde_json::json;
use sha2::Sha256;
use tracing::warn;

use crate::error::{Error, Result};
use crate::utils::http_client::Help;

use super::MessageBot;

const LARK_HOOK_URL: &str = "https://open.feishu.cn/open-apis/bot/v2/hook";
const MSG_TYPE: &str = "interactive";

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Lark {
pub access_token: String,
pub secret_token: String,
}

#[async_trait]
impl MessageBot for Lark {
async fn push_markdown(&self, title: String, msg: String) -> Result<()> {
let help = self.get_help();
let message = self.generate_lark_card(title, msg)?;
let url = format!("{}/{}", LARK_HOOK_URL, self.access_token);
let res: LarkResponse = help
.http_client
.post(url)
.json(&message)
.send()
.await?
.json()
.await?;
if res.code != 0 {
warn!("lark push markdown message error, err msg is {}", res.msg);
return Err(Error::Message(
"lark push markdown message response errorcode not eq 0".to_owned(),
));
}
Ok(())
}
}

impl Lark {
pub fn new(access_token: String, secret_token: String) -> Self {
Lark {
access_token,
secret_token,
}
}

pub fn get_help(&self) -> Help {
let mut headers = header::HeaderMap::new();
headers.insert("Accept-Charset", header::HeaderValue::from_static("utf8"));
Help::new(headers)
}

pub fn generate_sign(&self, timestamp: i64) -> Result<String> {
let timestamp_and_secret = format!("{}\n{}", timestamp, self.secret_token);
let hmac: Hmac<Sha256> = Hmac::new_from_slice(timestamp_and_secret.as_bytes())?;
let hmac_code = hmac.finalize().into_bytes();
let sign = BASE64_STANDARD.encode(hmac_code);
Ok(sign)
}

pub fn generate_lark_card(&self, title: String, message: String) -> Result<serde_json::Value> {
println!("{}", title);
println!("{}", message);
let message = message.replace("&nbsp", "");
let now = chrono::Local::now().timestamp();
let sign = self.generate_sign(now)?;
let card = json!({
"msg_type": MSG_TYPE,
"card": {
"elements": [
{
"tag": "div",
"text": {
"content": message,
"tag": "lark_md"
}

},
],
"header": {
"title": {
"content": title,
"tag": "plain_text"
}
}
},
"timestamp":now,
"sign": sign,
});
Ok(card)
}
}

// LarkResponse ignore data
#[derive(Debug, Serialize, Deserialize)]
pub struct LarkResponse {
pub msg: String,
pub code: i32,
}
12 changes: 11 additions & 1 deletion src/push/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use crate::{config::Config, error::Result};
use async_trait::async_trait;
use dingding::DingDing;
use lark::Lark;
use std::sync::Arc;
use telegram::Telegram;

pub mod dingding;
pub mod lark;
pub mod msg_template;
pub mod telegram;

Expand Down Expand Up @@ -34,9 +36,17 @@ pub fn init(config: Config) -> BotManager {
let tg_bot = Telegram::new(config.tg_bot.token, config.tg_bot.chat_id);
bots.add_bot(tg_bot)
}
if !config.ding_bot.access_token.trim().is_empty() {
if !config.ding_bot.access_token.trim().is_empty()
&& !config.ding_bot.secret_token.trim().is_empty()
{
let ding_bot = DingDing::new(config.ding_bot.access_token, config.ding_bot.secret_token);
bots.add_bot(ding_bot);
}
if !config.lark_bot.access_token.trim().is_empty()
&& !config.lark_bot.secret_token.trim().is_empty()
{
let lark_bot = Lark::new(config.lark_bot.access_token, config.lark_bot.secret_token);
bots.add_bot(lark_bot);
}
bots
}

0 comments on commit 4217c82

Please sign in to comment.