1use std::fs;
2
3use anyhow::Result;
4use apple_apns::{
5 Alert, Authentication, CertificateAuthority, ClientBuilder, InterruptionLevel, Request, Sound,
6};
7use clap::Parser;
8
9mod cli;
10
11pub use cli::*;
12
13#[allow(unused_assignments)]
14pub async fn main() -> Result<()> {
15 dotenvy::dotenv().ok();
16
17 let cli = Cli::parse();
18
19 let mut builder = ClientBuilder::new();
20
21 if let Some(endpoint) = cli.endpoint {
22 builder.endpoint = endpoint;
23 }
24
25 if let Some(user_agent) = &cli.user_agent {
26 builder.user_agent = user_agent;
27 }
28
29 let mut ca_pem = None;
30 if let Some(ca_pem_file) = &cli.ca_pem_file {
31 ca_pem = Some(fs::read(ca_pem_file)?);
32 builder.ca = Some(CertificateAuthority::Pem(ca_pem.as_ref().unwrap()))
33 }
34
35 let mut client_pem = None;
36 let mut key_pem = None;
37 if let Some(client_pem_file) = &cli.client_pem_file {
38 client_pem = Some(fs::read(client_pem_file)?);
39 builder.authentication = Some(Authentication::Certificate {
40 client_pem: client_pem.as_ref().unwrap(),
41 })
42 } else if let (Some(key_id), Some(key_pem_file), Some(team_id)) =
43 (&cli.key_id, &cli.key_pem_file, &cli.team_id)
44 {
45 key_pem = Some(fs::read(key_pem_file)?);
46 builder.authentication = Some(Authentication::Token {
47 key_id,
48 key_pem: key_pem.as_ref().unwrap(),
49 team_id,
50 });
51 }
52
53 let client = builder.build()?;
54
55 let sound = cli.sound.map(|name| {
56 let critical = cli.interruption_level == Some(InterruptionLevel::Critical);
57 let mut sound = Sound {
58 critical,
59 name,
60 ..Default::default()
61 };
62 if let Some(volume) = cli.volume {
63 sound.volume = volume;
64 }
65 sound
66 });
67
68 let request = Request {
69 device_token: cli.device_token,
70 push_type: cli.push_type,
71 id: cli.id,
72 expiration: cli.expiration,
73 priority: cli.priority,
74 topic: cli.topic,
75 collapse_id: cli.collapse_id,
76 alert: Some(Alert {
77 title: cli.title.map(Into::into),
78 subtitle: cli.subtitle.map(Into::into),
79 body: cli.body.map(Into::into),
80 launch_image: cli.launch_image,
81 ..Default::default()
82 }),
83 badge: cli.badge,
84 sound,
85 thread_id: cli.thread_id,
86 category: cli.category,
87 content_available: cli.content_available,
88 mutable_content: cli.mutable_content,
89 target_content_id: cli.target_content_id,
90 interruption_level: cli.interruption_level,
91 relevance_score: cli.relevance_score,
92 user_info: cli.user_info,
93 };
94
95 let apns_id = client.post(request).await?;
96 println!("{}", apns_id.as_hyphenated());
97
98 Ok(())
99}