Initial commit

This commit is contained in:
2024-09-01 06:20:49 +03:00
parent bd61f5d591
commit 9263c396a1
81 changed files with 1494 additions and 1521 deletions

View File

@@ -4,13 +4,13 @@ CREATE TABLE settings (
max_concurrent_downloads INTEGER NOT NULL DEFAULT 10,
max_concurrent_writes INTEGER NOT NULL DEFAULT 10,
theme TEXT NOT NULL DEFAULT 'dark',
theme TEXT NOT NULL DEFAULT 'oled',
default_page TEXT NOT NULL DEFAULT 'home',
collapsed_navigation INTEGER NOT NULL DEFAULT TRUE,
advanced_rendering INTEGER NOT NULL DEFAULT TRUE,
native_decorations INTEGER NOT NULL DEFAULT FALSE,
telemetry INTEGER NOT NULL DEFAULT TRUE,
telemetry INTEGER NOT NULL DEFAULT FALSE,
discord_rpc INTEGER NOT NULL DEFAULT TRUE,
developer_mode INTEGER NOT NULL DEFAULT FALSE,

View File

@@ -0,0 +1,55 @@
use std::process::exit;
use reqwest;
use tokio::fs::File as AsyncFile;
use tokio::io::AsyncWriteExt;
use tokio::process::Command;
async fn download_file(download_url: &str, local_filename: &str, os_type: &str, auto_update_supported: bool) -> Result<(), Box<dyn std::error::Error>> {
let download_dir = dirs::download_dir().ok_or("[download_file] • Failed to determine download directory")?;
let full_path = download_dir.join(local_filename);
let response = reqwest::get(download_url).await?;
let bytes = response.bytes().await?;
let mut dest_file = AsyncFile::create(&full_path).await?;
dest_file.write_all(&bytes).await?;
println!("[download_file] • File downloaded to: {:?}", full_path);
if auto_update_supported {
let status;
if os_type.to_lowercase() == "Windows".to_lowercase() {
status = Command::new("explorer")
.arg(download_dir.display().to_string())
.status()
.await
.expect("[download_file] • Failed to open downloads folder");
} else if os_type.to_lowercase() == "MacOS".to_lowercase() {
status = Command::new("open")
.arg(full_path.to_str().unwrap_or_default())
.status()
.await
.expect("[download_file] • Failed to execute command");
} else {
status = Command::new(".")
.arg(full_path.to_str().unwrap_or_default())
.status()
.await
.expect("[download_file] • Failed to execute command");
}
if status.success() {
println!("[download_file] • File opened successfully!");
} else {
eprintln!("[download_file] • Failed to open the file. Exit code: {:?}", status.code());
}
}
Ok(())
}
pub async fn init_download(download_url: &str, local_filename: &str, os_type: &str, auto_update_supported: bool) {
println!("[init_download] • Initialize downloading from • {:?}", download_url);
println!("[init_download] • Save local file name • {:?}", local_filename);
if let Err(e) = download_file(download_url, local_filename, os_type, auto_update_supported).await {
eprintln!("[init_download] • An error occurred! Failed to download the file: {}", e);
} else {
println!("[init_download] • Code finishes without errors.");
exit(0)
}
}

View File

@@ -20,6 +20,14 @@ pub async fn finish_login(
crate::state::login_finish(code, flow, &state.pool).await
}
#[tracing::instrument]
pub async fn offline_auth(
name: &str
) -> crate::Result<Credentials> {
let state = State::get().await?;
crate::state::offline_auth(name, &state.pool).await
}
#[tracing::instrument]
pub async fn get_default_user() -> crate::Result<Option<uuid::Uuid>> {
let state = State::get().await?;

View File

@@ -11,6 +11,7 @@ pub mod process;
pub mod profile;
pub mod settings;
pub mod tags;
pub mod download;
pub mod data {
pub use crate::state::{

View File

@@ -16,6 +16,7 @@ use chrono::Utc;
use daedalus as d;
use daedalus::minecraft::{RuleAction, VersionInfo};
use daedalus::modded::LoaderVersion;
use rand::seq::SliceRandom;
use st::Profile;
use std::collections::HashMap;
use tokio::process::Command;
@@ -24,6 +25,8 @@ mod args;
pub mod download;
use crate::state::ACTIVE_STATE;
// All nones -> disallowed
// 1+ true -> allowed
// 1+ false -> disallowed
@@ -672,10 +675,11 @@ pub async fn launch_minecraft(
}
}
let _ = state
.discord_rpc
.set_activity(&format!("Playing {}", profile.name), true)
.await;
let selected_phrase = ACTIVE_STATE.choose(&mut rand::thread_rng()).unwrap();
let _ = state
.discord_rpc
.set_activity(&format!("{} {}", selected_phrase, profile.name), true)
.await;
// Create Minecraft child by inserting it into the state
// This also spawns the process and prepares the subsequent processes

View File

@@ -24,7 +24,7 @@ impl DirectoryInfo {
// init() is not needed for this function
pub fn get_initial_settings_dir() -> Option<PathBuf> {
Self::env_path("THESEUS_CONFIG_DIR")
.or_else(|| Some(dirs::data_dir()?.join("ModrinthApp")))
.or_else(|| Some(dirs::data_dir()?.join("AstralRinthApp")))
}
/// Get all paths needed for Theseus to operate properly

View File

@@ -1,12 +1,17 @@
use std::sync::{atomic::AtomicBool, Arc};
use std::{
sync::{atomic::AtomicBool, Arc},
time::{SystemTime, UNIX_EPOCH},
};
use discord_rich_presence::{
activity::{Activity, Assets},
activity::{Activity, Assets, Timestamps},
DiscordIpc, DiscordIpcClient,
};
use rand::seq::SliceRandom;
use tokio::sync::RwLock;
use crate::state::Profile;
// use crate::state::Profile;
use crate::util::utils;
use crate::State;
pub struct DiscordGuard {
@@ -14,12 +19,29 @@ pub struct DiscordGuard {
connected: Arc<AtomicBool>,
}
pub(crate) const ACTIVE_STATE: [&str; 6] = [
"Explores",
"Travels with",
"Pirating",
"Investigating the",
"Engaged in",
"Conducting",
];
pub(crate) const INACTIVE_STATE: [&str; 6] = [
"Idling...",
"Waiting for the pirate team...",
"Taking a break...",
"Resting...",
"On standby...",
"In a holding pattern...",
];
impl DiscordGuard {
/// Initialize discord IPC client, and attempt to connect to it
/// If it fails, it will still return a DiscordGuard, but the client will be unconnected
pub fn init() -> crate::Result<DiscordGuard> {
let dipc =
DiscordIpcClient::new("1123683254248148992").map_err(|e| {
DiscordIpcClient::new("1190718475832918136").map_err(|e| {
crate::ErrorKind::OtherError(format!(
"Could not create Discord client {}",
e,
@@ -77,11 +99,32 @@ impl DiscordGuard {
return Ok(());
}
let activity = Activity::new().state(msg).assets(
Assets::new()
.large_image("modrinth_simple")
.large_text("Modrinth Logo"),
);
// let activity = Activity::new().state(msg).assets(
// Assets::new()
// .large_image("modrinth_simple")
// .large_text("Modrinth Logo"),
// );
let launcher =
utils::read_package_json().expect("Failed to read package.json");
let build_info = format!("AR • v{}", launcher.version);
let build_download = "https://astralium.su/get/ar";
let time = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Failed to get system time")
.as_secs() as i64;
let activity = Activity::new()
.state(msg)
.assets(
Assets::new()
.large_image("astralrinth_logo")
.large_text(&build_info)
.small_image("astralrinth_logo")
.small_text(&build_download),
)
.timestamps(Timestamps::new().start(time));
// Attempt to set the activity
// If the existing connection fails, attempt to reconnect and try again
@@ -167,20 +210,10 @@ impl DiscordGuard {
return self.clear_activity(true).await;
}
let running_profiles = state.process_manager.get_all();
if let Some(existing_child) = running_profiles.first() {
let prof =
Profile::get(&existing_child.profile_path, &state.pool).await?;
if let Some(prof) = prof {
self.set_activity(
&format!("Playing {}", prof.name),
reconnect_if_fail,
)
.await?;
}
} else {
self.set_activity("Idling...", reconnect_if_fail).await?;
}
let selected_phrase =
INACTIVE_STATE.choose(&mut rand::thread_rng()).unwrap();
self.set_activity(&format!("{}", selected_phrase), reconnect_if_fail)
.await?;
Ok(())
}
}

View File

@@ -197,6 +197,29 @@ pub async fn login_finish(
Ok(credentials)
}
#[tracing::instrument]
pub async fn offline_auth(
name: &str,
exec: impl sqlx::Executor<'_, Database = sqlx::Sqlite> + Copy,
) -> crate::Result<Credentials> {
let random_uuid = Uuid::new_v4();
let access_token = "null".to_string();
let refresh_token = "null".to_string();
let credentials = Credentials {
id: random_uuid,
username: name.to_string(),
access_token: access_token,
refresh_token: refresh_token,
expires: Utc::now() + Duration::days(365 * 99),
active: true,
};
credentials.upsert(exec).await?;
Ok(credentials)
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Credentials {
pub id: Uuid,

View File

@@ -3,6 +3,7 @@ pub mod fetch;
pub mod io;
pub mod jre;
pub mod platform;
pub mod utils;
/// Wrap a builder which uses a mut reference into one which outputs an owned value
macro_rules! wrap_ref_builder {

View File

@@ -0,0 +1,18 @@
use serde::{Deserialize, Serialize};
use tokio::io;
const PACKAGE_JSON_CONTENT: &str =
include_str!("../../../../apps/app-frontend/package.json");
#[derive(Serialize, Deserialize)]
pub struct Launcher {
pub version: String,
pub development_build: bool,
}
pub fn read_package_json() -> io::Result<Launcher> {
// Deserialize the content of package.json into a Launcher struct
let launcher: Launcher = serde_json::from_str(PACKAGE_JSON_CONTENT)?;
Ok(launcher)
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="10mm" height="10mm" viewBox="0 0 10 10" version="1.1" id="svg26662" inkscape:version="1.2.2 (732a01da63, 2022-12-09)" sodipodi:docname="lic.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview id="namedview26664" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:showpageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#505050" inkscape:document-units="mm" showgrid="false" inkscape:zoom="14.638496" inkscape:cx="17.112414" inkscape:cy="34.258984" inkscape:window-width="1488" inkscape:window-height="1230" inkscape:window-x="2794" inkscape:window-y="123" inkscape:window-maximized="0" inkscape:current-layer="layer1" />
<defs id="defs26659" />
<g inkscape:label="Слой 1" inkscape:groupmode="layer" id="layer1">
<g id="g26657" transform="matrix(3.9940568,0,0,3.954914,-1082.6556,16143.384)">
<path id="path26649" style="fill:#05a6f0;fill-opacity:1;stroke-width:0.18168;stroke-miterlimit:5.8;paint-order:fill markers stroke" d="m 271.06666,-4080.4646 v 0.8986 c 0,0.1289 0.0997,0.2334 0.22634,0.2398 h 0.91261 v -1.1384 z" />
<path id="path26651" style="fill:#ffba08;fill-opacity:1;stroke-width:0.18168;stroke-miterlimit:5.8;paint-order:fill markers stroke" d="m 272.43195,-4080.4646 v 1.1384 h 0.89917 0.0124 c 0.12669,-0.01 0.22686,-0.1109 0.22686,-0.2398 v -0.8986 z" />
<path id="path26653" style="fill:#e25127;fill-opacity:1;stroke-width:0.18168;stroke-miterlimit:5.8;paint-order:fill markers stroke" d="m 271.3054,-4081.8547 c -0.13246,0 -0.23874,0.1073 -0.23874,0.2403 v 0.8955 h 1.13895 v -1.1358 z" />
<path id="path26655" style="fill:#81bc06;fill-opacity:1;stroke:none;stroke-width:0.184849;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:5.8;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" d="m 272.43195,-4081.8547 v 1.1358 h 1.13843 v -0.8955 c 0,-0.133 -0.1068,-0.2403 -0.23926,-0.2403 z" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<svg height="800px" width="800px" version="1.1" id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.672 511.672" xml:space="preserve">
<path style="fill:#ED5564;" d="M227.674,44.901c0,0,0.047-0.031,0.141-0.109c-0.031,0.031-3.342,2.437-9.088,3.514
c-7.745,1.437-16.208-0.109-25.14-4.591c-31.386-15.771-68.175-0.968-69.721-0.344l0.016,0.062c-3.88,1.593-6.621,5.403-6.621,9.869
c0,5.887,4.771,10.649,10.657,10.649c1.694,0,3.295-0.406,4.716-1.109c4.466-1.624,30.816-10.416,51.381-0.078
c10.954,5.497,20.706,7.371,28.919,7.371c17.028,0,27.42-8.073,28.044-8.573L227.674,44.901z"/>
<g>
<path style="fill:#7F4545;" d="M234.514,31.973c-5.887,0-10.657,4.778-10.657,10.665v351.704h21.322V42.638
C245.179,36.751,240.401,31.973,234.514,31.973z"/>
<path style="fill:#7F4545;" d="M511.672,319.655c0-5.887-4.777-10.665-10.648-10.665c-1.031,0-2.016,0.156-2.951,0.422l0,0
l-0.234,0.062l0,0l-108.213,31.073l5.871,20.487l108.463-31.137l0,0C508.408,328.618,511.672,324.512,511.672,319.655z"/>
</g>
<path style="fill:#A85D5D;" d="M10.689,308.99l99.725,33.385c0,0,39.116,41.239,124.1,41.239c85,0,106.611-29.138,106.611-29.138
l85.258-24.484c9.588,160.21-122.656,149.561-122.656,149.561H115.294c-86.171-5.996-73.633-88.568-73.633-88.568l-13.187-9.728
l-4.208-18.021L0,351.635L10.689,308.99z"/>
<path style="fill:#965353;" d="M426.664,335.317c-5.871,132.337-122.938,122.905-122.938,122.905H115.294
c-57.409-3.981-71.001-41.973-73.68-66.879c-0.765,5.84-9.205,82.432,73.68,88.209h188.433
C303.727,479.553,433.004,489.968,426.664,335.317z"/>
<g>
<path style="fill:#434A54;" d="M277.166,415.594c0,5.887,4.763,10.649,10.649,10.649c5.888,0,10.649-4.763,10.649-10.649
s-4.762-10.665-10.649-10.665C281.929,404.929,277.166,409.707,277.166,415.594z"/>
<path style="fill:#434A54;" d="M234.514,415.594c0,5.887,4.778,10.649,10.665,10.649s10.657-4.763,10.657-10.649
s-4.77-10.665-10.657-10.665S234.514,409.707,234.514,415.594z"/>
<path style="fill:#434A54;" d="M191.877,415.594c0,5.887,4.771,10.649,10.657,10.649s10.665-4.763,10.665-10.649
s-4.778-10.665-10.665-10.665S191.877,409.707,191.877,415.594z"/>
<path style="fill:#434A54;" d="M149.24,415.594c0,5.887,4.771,10.649,10.657,10.649s10.657-4.763,10.657-10.649
s-4.771-10.665-10.657-10.665S149.24,409.707,149.24,415.594z"/>
<path style="fill:#434A54;" d="M99.569,330.305C114.942,207.719,74.616,95.869,74.616,95.869h260.169
c80.105,93.783,24.953,234.561,24.953,234.561C262.832,285.849,99.569,330.305,99.569,330.305z"/>
</g>
<g style="opacity:0.1;">
<path style="fill:#FFFFFF;" d="M334.785,95.869h-21.314c69.206,81.026,37.445,197.147,27.529,227.222
c6.434,2.123,12.695,4.56,18.738,7.339C359.738,330.43,414.891,189.652,334.785,95.869z"/>
</g>
<path style="fill:#E6E9ED;" d="M170.555,196.477c0-35.321,28.638-63.959,63.959-63.959c35.329,0,63.951,28.638,63.951,63.959
c0,18.941-8.213,35.961-21.299,47.672v26.952h-85.289v-26.952C178.792,232.438,170.555,215.418,170.555,196.477z"/>
<g>
<path style="fill:#434A54;" d="M250.503,196.477c0,5.887,4.778,10.665,10.665,10.665c5.888,0,10.658-4.778,10.658-10.665
s-4.771-10.665-10.658-10.665C255.282,185.812,250.503,190.59,250.503,196.477z"/>
<path style="fill:#434A54;" d="M197.21,196.477c0,5.887,4.771,10.665,10.657,10.665s10.657-4.778,10.657-10.665
s-4.771-10.665-10.657-10.665S197.21,190.59,197.21,196.477z"/>
</g>
<g>
<path style="fill:#CCD1D9;" d="M277.166,271.085c-0.016-5.871-4.777-10.649-10.673-10.649c-5.887,0-10.657,4.778-10.657,10.665
h21.33V271.085z"/>
<path style="fill:#CCD1D9;" d="M255.836,271.085c0-5.871-4.77-10.649-10.657-10.649s-10.665,4.778-10.665,10.665h21.322V271.085z" />
<path style="fill:#CCD1D9;" d="M234.514,271.085c0-5.871-4.771-10.649-10.657-10.649s-10.657,4.778-10.657,10.665h21.314V271.085z" />
<path style="fill:#CCD1D9;" d="M213.199,271.085c-0.008-5.871-4.778-10.649-10.665-10.649s-10.657,4.778-10.657,10.665h21.322
L213.199,271.085L213.199,271.085z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="10mm" height="10mm" viewBox="0 0 10 10" version="1.1" id="svg26662" inkscape:version="1.2.2 (732a01da63, 2022-12-09)" sodipodi:docname="pir.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview id="namedview26664" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:showpageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#505050" inkscape:document-units="mm" showgrid="false" inkscape:zoom="10.35098" inkscape:cx="16.375261" inkscape:cy="42.073312" inkscape:window-width="1488" inkscape:window-height="1230" inkscape:window-x="2794" inkscape:window-y="123" inkscape:window-maximized="0" inkscape:current-layer="layer1" />
<defs id="defs26659" />
<g inkscape:label="Слой 1" inkscape:groupmode="layer" id="layer1">
<path id="path26647" style="fill:#e7f9fb;fill-opacity:1;stroke:none;stroke-width:0.734686;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:5.8;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" d="M 0.953646,0 C 0.4245958,0 0,0.42377 0,0.950056 V 9.051658 C 0,9.577943 0.4245958,9.9999995 0.953646,9.9999995 H 9.044545 C 9.573595,9.9999995 10,9.577943 10,9.051658 V 0.950056 C 10,0.42377 9.573595,0 9.044545,0 Z m 4.0319653,0.680202 c 0.7122257,0 1.1971907,0.171336 1.6235677,0.587681 C 7.149602,1.795597 7.303455,2.529484 7.076165,3.503527 6.954393,4.024672 6.743646,4.411034 6.384675,4.767983 6.046182,5.105514 5.7597,5.274565 5.369942,5.364516 4.7470347,5.510152 4.177518,5.313116 3.618915,4.763985 3.260174,4.411034 3.0504322,4.028385 2.9274247,3.503527 2.6985267,2.5272 2.8504547,1.797596 3.392573,1.267883 3.8051351,0.866387 4.2970505,0.680202 4.9856113,0.680202 Z M 4.1253339,2.785916 C 3.7727965,2.786202 3.5578276,2.980097 3.5578276,3.29821 c 0,0.197035 0.074385,0.320683 0.2711164,0.455467 C 4.0618628,3.91359 4.4444125,3.833637 4.5886441,3.596619 4.6788251,3.450984 4.6839941,3.154002 4.6001321,3.01265 4.5082281,2.855593 4.3583101,2.784203 4.1277751,2.784203 Z m 1.7295441,0 c -0.20506,0 -0.404923,0.09423 -0.493868,0.26557 C 5.226026,3.311345 5.34091,3.641452 5.60714,3.779948 5.859588,3.90845 6.185962,3.822778 6.372268,3.574345 6.463308,3.45441 6.469338,3.164568 6.383758,3.033211 6.273759,2.864731 6.062581,2.784774 5.85752,2.784774 Z M 1.8659927,5.307119 c 0.00862,-5.71e-4 0.020104,0 0.03073,0 0.2179844,2.86e-4 0.5876389,0.16848 1.6846262,0.695051 C 4.3488321,6.369399 4.9972712,6.669808 5.018122,6.669808 5.038222,6.669237 5.68049,6.371113 6.440564,6.008738 7.200522,5.64465 7.88377,5.323396 7.958155,5.323396 8.14742,5.283416 8.403142,5.409066 8.509492,5.577544 8.663431,5.82598 8.604552,6.167795 8.374795,6.361404 8.316205,6.409954 6.898963,7.091579 5.226428,7.875439 2.6791977,9.069933 2.1554033,9.312944 1.9972712,9.312944 c -0.2153996,0 -0.2679571,0 -0.3915391,-0.114223 C 1.3150575,8.936006 1.3506989,8.509952 1.6827021,8.264656 1.7519171,8.213256 2.1996325,7.990519 2.6777048,7.764356 3.1557197,7.54162 3.5582872,7.334304 3.5756915,7.334304 c 0.01436,0 -0.3826933,-0.217025 -0.8872167,-0.448042 C 2.1839513,6.654959 1.7142365,6.421657 1.646802,6.369971 1.4819495,6.24718 1.4026824,6.080128 1.4026824,5.863103 c 0,-0.219881 0.09535,-0.394643 0.2731268,-0.491448 0.063758,-0.03141 0.1203366,-0.05711 0.1901261,-0.06282 z M 7.094115,7.62329 7.661622,7.905994 c 0.784456,0.383506 0.930354,0.522573 0.930354,0.881807 0,0.219881 -0.105403,0.397498 -0.280307,0.480311 -0.151641,0.06568 -0.331859,0.06853 -0.513628,0 C 7.59815,9.193862 5.819639,8.388875 5.788334,8.354036 c -0.01436,0 0.273414,-0.182758 0.639363,-0.378651 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -175,6 +175,18 @@ import _Heading3Icon from './icons/heading-3.svg?component'
import './omorphia.scss'
// AstralRinth Icons
import _PirateIcon from './icons/pirate.svg?component'
import _MicrosoftIcon from './icons/microsoft.svg?component'
import _PirateShipIcon from './icons/pirate-ship.svg?component'
// AstralRinth Exports
export const PirateIcon = _PirateIcon
export const MicrosoftIcon = _MicrosoftIcon
export const PirateShipIcon = _PirateShipIcon
export const ModrinthIcon = _ModrinthIcon
export const FourOhFourNotFound = _FourOhFourNotFound
export const ModrinthPlusIcon = _ModrinthPlusIcon