Skip to content

Commit

Permalink
Improve error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Insprill committed May 25, 2023
1 parent 2e6d253 commit 886dc1b
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 13 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license = "Apache-2.0"
edition = "2021"

[dependencies]
anyhow = "1.0.71"
csv = "1.2.1"
itertools = "0.10.5"
log = "0.4.17"
Expand Down
46 changes: 33 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::Context;
use itertools::Itertools;
use log::{error, info, LevelFilter};
use reqwest::{
Expand Down Expand Up @@ -29,6 +30,13 @@ struct Config {
listmonk_overwrite: bool,
}

#[derive(Debug)]
struct Credentials {
square_api_token: String,
listmonk_username: String,
listmonk_password: String,
}

#[derive(Deserialize, Debug)]
struct SquareCustomer {
email_address: Option<String>,
Expand Down Expand Up @@ -81,8 +89,20 @@ async fn main() -> Result<(), Box<dyn Error>> {
env!("CARGO_PKG_VERSION")
);

let config_file = File::open("config.json")?;
let config: Config = serde_json::from_reader(config_file)?;
let config_file =
File::open("config.json").with_context(|| "Failed to open config.json! Does it exist?")?;
let config: Config = serde_json::from_reader(config_file).with_context(|| {
"Failed to deserialize config. Does it have syntax errors or missing fields?"
})?;

let creds = Credentials {
square_api_token: env::var("SQUARE_API_TOKEN")
.with_context(|| "Missing the SQUARE_API_TOKEN environment variable!")?,
listmonk_username: env::var("LISTMONK_USER")
.with_context(|| "Missing the LISTMONK_USER environment variable!")?,
listmonk_password: env::var("LISTMONK_PASSWORD")
.with_context(|| "Missing the LISTMONK_PASSWORD environment variable!")?,
};

let forever = task::spawn(async move {
let mut interval = time::interval(Duration::from_secs(config.run_every));
Expand All @@ -91,7 +111,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
loop {
interval.tick().await;
info!("Syncing...");
if let Err(err) = run(&config).await {
if let Err(err) = run(&config, &creds).await {
error!("Failed to sync! {:?}", err);
} else {
info!("Sync complete.")
Expand All @@ -102,8 +122,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
Ok(forever.await?)
}

async fn run(config: &Config) -> Result<(), Box<dyn Error>> {
let subscribers: Vec<ListmonkSubscriber> = get_square_customers()
async fn run(config: &Config, creds: &Credentials) -> Result<(), Box<dyn Error>> {
let subscribers: Vec<ListmonkSubscriber> = get_square_customers(creds)
.await?
.into_iter()
.filter(|c| c.email_address.is_some())
Expand Down Expand Up @@ -150,13 +170,13 @@ async fn run(config: &Config) -> Result<(), Box<dyn Error>> {
let csv = generate_import_csv(&subs)?;

info!("Uploading {} listmonk subscribers ({})", subs.len(), mode.0);
upload_subscribers(import, csv, &config.listmonk_domain).await?;
upload_subscribers(import, csv, &config.listmonk_domain, creds).await?;
}

Ok(())
}

async fn get_square_customers() -> Result<Vec<SquareCustomer>, Box<dyn Error>> {
async fn get_square_customers(creds: &Credentials) -> Result<Vec<SquareCustomer>, Box<dyn Error>> {
let mut cursor = String::new();
let mut customers = vec![];
let mut idx: u32 = 0;
Expand All @@ -167,7 +187,7 @@ async fn get_square_customers() -> Result<Vec<SquareCustomer>, Box<dyn Error>> {
.get("https://connect.squareup.com/v2/customers")
.header("Square-Version", SQUARE_VERSION)
.query(&[("cursor", cursor)])
.bearer_auth(env::var("SQUARE_API_TOKEN")?)
.bearer_auth(&creds.square_api_token)
.send()
.await?
.json::<SquareCustomersResponse>()
Expand Down Expand Up @@ -202,6 +222,7 @@ async fn upload_subscribers(
import: ListmonkImport,
csv: String,
domain: &str,
creds: &Credentials,
) -> Result<Response, Box<dyn Error>> {
let form = Form::new()
.text("params", serde_json::to_string(&import)?)
Expand All @@ -214,10 +235,9 @@ async fn upload_subscribers(
Ok(Client::new()
.post(format!("https://{domain}/api/import/subscribers"))
.multipart(form)
.basic_auth(
env::var("LISTMONK_USER")?,
Some(env::var("LISTMONK_PASSWORD")?),
)
.basic_auth(&creds.listmonk_username, Some(&creds.listmonk_password))
.send()
.await?)
.await?
.error_for_status()
.with_context(|| "Failed to upload subscribers to listmonk")?)
}

0 comments on commit 886dc1b

Please sign in to comment.