diff options
| author | Franck Cuny <franck@fcuny.net> | 2022-11-19 18:48:12 -0800 |
|---|---|---|
| committer | Franck Cuny <franck@fcuny.net> | 2022-11-19 19:01:01 -0800 |
| commit | d78070d130c32227a2788591d3efd321da702658 (patch) | |
| tree | 55e34a15a8ff3b53714c55974bd738e48a5bbcb9 /src/message.rs | |
| parent | meta: ignore artifact created by `nix build` (diff) | |
| download | sendsms-d78070d130c32227a2788591d3efd321da702658.tar.gz | |
feat: a CLI to send sms via twilio's API
I want to get an SMS when some of my machines are rebooted. This tool
let me do just that. The CLI takes as argument the path to a
configuration file that contains credentials to the API. It also has a
number of sub commands, and each sub command is associated with a
specific action.
For each action, a section in the configuration file is expected. The
two actions currently supported are:
- `reboot`
- `hello`
`hello` is a simple one used for testing, it sends "hello world".
`reboot` is used to create a message that contains the host's name and
the IP address of the network interface specified in the configuration
file.
Diffstat (limited to 'src/message.rs')
| -rwxr-xr-x | src/message.rs | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/message.rs b/src/message.rs new file mode 100755 index 0000000..5fbd5fa --- /dev/null +++ b/src/message.rs @@ -0,0 +1,118 @@ +use clap::Parser; +use gethostname::gethostname; +use serde::Deserialize; +use std::net::IpAddr; + +#[derive(Parser, Debug)] +pub enum MessageKind { + Hello, + Reboot, +} + +#[derive(Deserialize, Debug)] +pub struct MessageBuilder { + pub from: Option<String>, + pub to: Option<String>, + pub body: Option<String>, +} + +impl MessageBuilder { + fn new() -> Self { + Self { + from: None, + to: None, + body: None, + } + } + + pub fn from(mut self, from: impl Into<String>) -> Self { + self.from = Some(from.into()); + self + } + + pub fn to(mut self, to: impl Into<String>) -> Self { + self.to = Some(to.into()); + self + } + + pub fn with_action(mut self, action: MessageKind, config: &crate::config::Config) -> Self { + let body = match action { + MessageKind::Reboot => reboot(&config.reboot), + MessageKind::Hello => hello(), + }; + self.body = Some(body); + self + } + + pub fn build(self) -> Message { + let Self { from, to, body } = self; + Message { from, to, body } + } +} + +#[derive(Deserialize, Debug)] +pub struct Message { + pub from: Option<String>, + pub to: Option<String>, + pub body: Option<String>, +} + +impl Message { + pub fn builder() -> MessageBuilder { + MessageBuilder::new() + } +} + +fn hello() -> String { + String::from("hello world") +} + +fn reboot(config: &crate::config::RebootConfig) -> String { + let ipaddr_v4 = if_addrs::get_if_addrs() + .unwrap_or_default() + .into_iter() + .find(|iface| iface.name == config.ifname) + .and_then(|iface| match iface.ip() { + IpAddr::V4(addr) => Some(addr), + IpAddr::V6(_) => None, + }) + .expect("there should be an ipv4 address"); + + let hostname = gethostname() + .into_string() + .expect("failed to get the hostname"); + + format!( + "{} has rebooted. The IP address for the interface {} is {}.", + hostname, config.ifname, ipaddr_v4 + ) +} + +#[cfg(test)] +mod test { + use crate::message::Message; + + #[test] + fn test_create_message() { + let from = "1".to_string(); + let to = "2".to_string(); + let account_sid = "test".to_string(); + let auth_token = "test".to_string(); + let cfg = crate::config::Config { + to, + from, + account_sid, + auth_token, + reboot: crate::config::RebootConfig { + ifname: "eth0".to_string(), + }, + hello: crate::config::HelloConfig {}, + }; + let msg = Message::builder() + .from("1") + .to("2") + .with_action(crate::message::MessageKind::Hello, &cfg) + .build(); + assert_eq!(msg.body, Some("hello world".to_string())); + } +} |
