mastodon-notifier 0.1.0

Mastodon desktop notification daemon
Documentation
use std::time::Duration;

use crate::{
    auth,
    notification::{ActionResponse, NotificationManager},
    opts::Opts,
    util::open_browser,
    MastoClient, APP_NAME,
};

use anyhow::Result;
use futures::{StreamExt, TryStreamExt};
use tracing::{error, info};

pub async fn run(opts: Opts) -> Result<()> {
    let account = opts.account();

    let token = fetch_token(&account).await;

    info!("Found stored token for user {}", account);

    let icon = opts.icon.clone().unwrap_or_default();
    let timeout = opts.timeout;

    let client = MastoClient::with_token(opts, token);
    let mut notification_stream = client.notifications().await?;

    let notification_manager = NotificationManager::new().await?;
    let handle = notification_manager.handle();

    info!("Started mastodon notify daemon on account {}", account);

    tokio::task::spawn(async {
        let mut stream = handle.stream();
        while let Ok(response) = stream.try_next().await {
            if let Some(ActionResponse::Custom((noty, _))) = response {
                if let Some(url) = noty.url() {
                    let _ = open_browser(&url);
                }
            }
        }
    });

    while let Some(notification) = notification_stream.next().await {
        match notification {
            Ok(noty) => {
                notification_manager.send(noty, &icon, timeout).await?;
            }
            Err(error) => error!("Notification error {}", error),
        }
    }
    Ok(())
}

async fn fetch_token(account: &String) -> String {
    loop {
        match auth::get(APP_NAME, account) {
            Ok(token) => break token,
            Err(_) => {
                info!("Token for user not found {}. Please run the wizard with --config mode for configuring the authentication token", account);
                tokio::time::sleep(Duration::from_secs(5)).await;
            }
        }
    }
}