Files
AstralRinth/theseus_playground/src/main.rs
Wyatt Verchere f48959a816 Profile bindings (#55)
* basic framework. still has errors

* added functionality for main endpoints + some structuring

* formatting

* unused code

* mimicked CLI function with wait_for process

* made PR changes, added playground

* cargo fmt

* removed missed println

* misc tests fixes

* cargo fmt

* added windows support

* cargo fmt

* all OS use dunce

* restructured profile slightly; fixed mac bug

* profile changes, new main.rs

* fixed requested pr + canonicaliation bug

* fixed regressed bug in ui

* fixed regressed bugs

* fixed git error

* typo

* ran prettier

* clippy

* playground clippy

* ported profile loading fix

* profile change for real, url println and clippy

* PR changes

---------

Co-authored-by: Wyatt <wyatt@modrinth.com>
2023-03-31 11:00:43 -07:00

120 lines
3.8 KiB
Rust

#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
use dunce::canonicalize;
use std::path::Path;
use theseus::{prelude::*, profile_create::profile_create};
use tokio::process::Child;
use tokio::sync::{oneshot, RwLockWriteGuard};
// We use this function directly to call authentication procedure
// Note: "let url = match url" logic is handled differently, so that if there is a rate limit in the other set causing that one to end early,
// we can see the error message in this thread rather than a Recv error on 'rx' when the receiver is mysteriously droppped
pub async fn authenticate_run() -> theseus::Result<Credentials> {
println!("Adding new user account to Theseus");
println!("A browser window will now open, follow the login flow there.");
let (tx, rx) = oneshot::channel::<url::Url>();
let flow = tokio::spawn(auth::authenticate(tx));
let url = rx.await;
let url = match url {
Ok(url) => url,
Err(e) => {
flow.await.unwrap()?;
return Err(e.into());
}
};
println!("URL {}", url.as_str());
webbrowser::open(url.as_str())?;
let credentials = flow.await.unwrap()?;
State::sync().await?;
println!("Logged in user {}.", credentials.username);
Ok(credentials)
}
#[tokio::main]
async fn main() -> theseus::Result<()> {
println!("Starting.");
// Initialize state
let st = State::get().await?;
// Set max concurrent downloads to 10
st.settings.write().await.max_concurrent_downloads = 10;
// Example variables for simple project case
let name = "Example".to_string();
let game_version = "1.19.2".to_string();
let modloader = ModLoader::Vanilla;
let loader_version = "stable".to_string();
// let icon = Some(
// Path::new("../icon_test.png")
// .canonicalize()
// .expect("Icon could be not be found. If not using, set to None"),
// );
let icon = None;
// Clear profiles
println!("Clearing profiles.");
let h = profile::list().await?;
for (path, _) in h.into_iter() {
profile::remove(&path).await?;
}
println!("Creating/adding profile.");
// Attempt to create a profile. If that fails, try adding one from the same path.
// TODO: actually do a nested error check for the correct profile error.
let profile_path = profile_create(
name.clone(),
game_version,
modloader,
loader_version,
icon,
)
.await?;
State::sync().await?;
// async closure for testing any desired edits
// (ie: changing the java runtime of an added profile)
println!("Editing.");
profile::edit(&profile_path, |profile| {
// Eg: Java. TODO: hook up to jre.rs class to pick optimal java
profile.java = Some(JavaSettings {
install: Some(Path::new("/usr/bin/java").to_path_buf()),
extra_arguments: None,
});
async { Ok(()) }
})
.await?;
State::sync().await?;
println!("Authenticating.");
// Attempt to create credentials and run.
let proc_lock = match authenticate_run().await {
Ok(credentials) => {
println!("Running.");
profile::run(&canonicalize(&profile_path)?, &credentials).await
}
Err(e) => {
println!("Could not authenticate: {}.\nAttempting stored authentication.",e);
// Attempt to load credentials if Hydra is down/rate limit hit
let users = auth::users().await.unwrap();
let credentials = users.first().unwrap();
println!("Running.");
profile::run(&canonicalize(&profile_path)?, credentials).await
}
}?;
println!("Started. Waiting...");
let mut proc: RwLockWriteGuard<Child> = proc_lock.write().await;
profile::wait_for(&mut proc).await?;
// Run MC
Ok(())
}