avam-client and oauth2
This commit is contained in:
180
avam-client/src/main.rs
Normal file
180
avam-client/src/main.rs
Normal file
@@ -0,0 +1,180 @@
|
||||
#![allow(clippy::needless_return)]
|
||||
|
||||
mod app;
|
||||
mod config;
|
||||
mod dirs;
|
||||
mod icon;
|
||||
mod lock;
|
||||
mod models;
|
||||
mod oauth;
|
||||
mod pipe;
|
||||
mod state_machine;
|
||||
|
||||
use crate::config::Config;
|
||||
use clap::Parser;
|
||||
use lock::Lock;
|
||||
use oauth::{start_code_listener, start_code_to_token};
|
||||
use pipe::Pipe;
|
||||
use state_machine::Event;
|
||||
use tokio::task::JoinSet;
|
||||
|
||||
pub static BASE_URL: &str = "https://avam.avii.nl";
|
||||
pub static PROJECT_NAME: &str = "Avii's Virtual Airline Manager";
|
||||
pub static COPYRIGHT: &str = "Avii's Virtual Airline Manager © 2024";
|
||||
pub static CLIENT_ID: uuid::Uuid = uuid::uuid!("f9525060-0a34-4233-87e2-0f9990b7c6db");
|
||||
pub static REDIRECT_URI: &str = "avam:token";
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct Arguments {
|
||||
#[arg(short, long)]
|
||||
code: Option<String>,
|
||||
#[arg(short, long, action)]
|
||||
force: bool,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), anyhow::Error> {
|
||||
let (event_sender, event_receiver) = tokio::sync::broadcast::channel(1);
|
||||
let args = Arguments::parse();
|
||||
|
||||
if handle_single_instance(&args).await? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
register_url_scheme()?;
|
||||
|
||||
let config = Config::new()?;
|
||||
|
||||
let mut futures = JoinSet::new();
|
||||
|
||||
// Register Quit handler
|
||||
let sender = event_sender.clone();
|
||||
let mut ctrl_c_counter = 0;
|
||||
ctrlc::set_handler(move || {
|
||||
println!("CTRL_C: Quit singal sent");
|
||||
ctrl_c_counter += 1;
|
||||
if ctrl_c_counter >= 3 {
|
||||
let _ = unregister_url_scheme();
|
||||
Lock::unlock();
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if let Err(e) = sender.send(Event::Quit) {
|
||||
println!("{:#?}", e)
|
||||
};
|
||||
})?;
|
||||
|
||||
// Start the State Machine
|
||||
let c = config.clone();
|
||||
let sender = event_sender.clone();
|
||||
let receiver = event_receiver.resubscribe();
|
||||
futures.spawn(state_machine::start(c, sender, receiver));
|
||||
|
||||
// // Start the code listener
|
||||
let receiver = event_receiver.resubscribe();
|
||||
let (pipe_sender, pipe_receiver) = tokio::sync::broadcast::channel(100);
|
||||
futures.spawn(start_code_listener(pipe_sender, receiver));
|
||||
|
||||
// Start token listener
|
||||
let c = config.clone();
|
||||
let sender = event_sender.clone();
|
||||
let receiver = event_receiver.resubscribe();
|
||||
futures.spawn(start_code_to_token(c, pipe_receiver, sender, receiver));
|
||||
|
||||
// Start the Tray Icon
|
||||
let c = config.clone();
|
||||
let sender = event_sender.clone();
|
||||
let receiver = event_receiver.resubscribe();
|
||||
start_tray_icon(c, sender, receiver).await?;
|
||||
|
||||
// Wait for everything to finish
|
||||
while let Some(result) = futures.join_next().await {
|
||||
if let Ok(Err(e)) = result {
|
||||
panic!("{:#?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
unregister_url_scheme()?;
|
||||
Lock::unlock();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
use app::App;
|
||||
use tokio::sync::broadcast::{Receiver, Sender};
|
||||
use winit::event_loop::EventLoop;
|
||||
async fn start_tray_icon(
|
||||
config: Config,
|
||||
sender: Sender<Event>,
|
||||
receiver: Receiver<Event>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let mut app = App::new(config, sender, receiver)?;
|
||||
let event_loop = EventLoop::new()?;
|
||||
|
||||
event_loop.run_app(&mut app)?;
|
||||
println!("EventLoop Shutdonw");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
/// returns `Ok(true)` if we need to quit gracefully
|
||||
/// returns `Err(e)` if we're already running
|
||||
async fn handle_single_instance(args: &Arguments) -> Result<bool, anyhow::Error> {
|
||||
let lock = Lock::new(args.force)?;
|
||||
|
||||
if lock.is_locked() && args.code.is_none() {
|
||||
return Err(anyhow::anyhow!("Lockfile exists, exiting."));
|
||||
}
|
||||
|
||||
if let Some(code) = &args.code {
|
||||
Pipe::send(code).await?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Lock::lock();
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn register_url_scheme() -> Result<(), anyhow::Error> {
|
||||
use winreg::enums::*;
|
||||
use winreg::RegKey;
|
||||
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
let avam_schema_root = hkcu.create_subkey("Software\\Classes\\avam")?;
|
||||
avam_schema_root.0.set_value("URL Protocol", &"")?;
|
||||
let command = avam_schema_root.0.create_subkey("shell\\open\\command")?;
|
||||
|
||||
let current_exec = std::env::current_exe()?;
|
||||
|
||||
command.0.set_value(
|
||||
"",
|
||||
&format!("\"{}\" -c \"%1\"", current_exec.to_str().unwrap()),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unregister_url_scheme() -> Result<(), anyhow::Error> {
|
||||
use winreg::enums::*;
|
||||
use winreg::RegKey;
|
||||
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
hkcu.delete_subkey_all("Software\\Classes\\avam").ok();
|
||||
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user