diff options
-rw-r--r-- | src-tauri/bindings/ParsedLogResults.ts | 4 | ||||
-rw-r--r-- | src-tauri/bindings/ParsedModFromLog.ts | 3 | ||||
-rw-r--r-- | src-tauri/src/main.rs | 3 | ||||
-rw-r--r-- | src-tauri/src/repair_and_verify/log_handling.rs | 117 | ||||
-rw-r--r-- | src-tauri/src/repair_and_verify/mod.rs | 2 | ||||
-rw-r--r-- | src-vue/src/views/DeveloperView.vue | 63 |
6 files changed, 192 insertions, 0 deletions
diff --git a/src-tauri/bindings/ParsedLogResults.ts b/src-tauri/bindings/ParsedLogResults.ts new file mode 100644 index 00000000..6ae3c0ad --- /dev/null +++ b/src-tauri/bindings/ParsedLogResults.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ParsedModFromLog } from "./ParsedModFromLog"; + +export interface ParsedLogResults { northstar_launcher_version: string, installed_mods: Array<ParsedModFromLog>, has_northstar_crashed: boolean, }
\ No newline at end of file diff --git a/src-tauri/bindings/ParsedModFromLog.ts b/src-tauri/bindings/ParsedModFromLog.ts new file mode 100644 index 00000000..f71ed83d --- /dev/null +++ b/src-tauri/bindings/ParsedModFromLog.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export interface ParsedModFromLog { mod_name: string, enabled: boolean, }
\ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c7451763..2ad1d9fe 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -41,6 +41,8 @@ use tauri::Manager; use tauri_plugin_store::PluginBuilder; use tokio::time::sleep; +use crate::repair_and_verify::log_handling::parse_given_log_text; + #[derive(Default)] struct Counter(Arc<Mutex<i32>>); @@ -115,6 +117,7 @@ fn main() { delete_northstar_mod, get_server_player_count, delete_thunderstore_mod, + parse_given_log_text, query_thunderstore_packages_api, get_pull_requests_wrapper, apply_launcher_pr, diff --git a/src-tauri/src/repair_and_verify/log_handling.rs b/src-tauri/src/repair_and_verify/log_handling.rs new file mode 100644 index 00000000..2cbc4ae6 --- /dev/null +++ b/src-tauri/src/repair_and_verify/log_handling.rs @@ -0,0 +1,117 @@ +use regex::Regex; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +#[derive(Serialize, Deserialize, Debug, Clone, TS)] +#[ts(export)] +pub struct ParsedModFromLog { + mod_name: String, + enabled: bool, +} + +#[derive(Serialize, Deserialize, Debug, Clone, TS)] +#[ts(export)] +pub struct ParsedLogResults { + northstar_launcher_version: String, + installed_mods: Vec<ParsedModFromLog>, + has_northstar_crashed: bool, +} + +/// Parse logs for installed mods +fn parse_given_log_text_for_installed_mods( + log_text: String, +) -> Result<Vec<ParsedModFromLog>, String> { + // Regex to capture mod loading and whether enabled/disabled + let regex = Regex::new(r"(?m)Loaded mod (.*) successfully\n.*\[NORTHSTAR\] \[info\] Mod (.*) is (enabled|disabled)\n").unwrap(); + + // Run regex, result will be an iterator over tuples containing the start and end indices for each match in the string + let result = regex.captures_iter(&log_text); + + let mut mods = Vec::new(); + for mat in result { + // Get the captured string, which is the first and only capturing group in the regex + let mod_name = match mat.get(1) { + Some(mod_name) => mod_name.as_str().to_string(), + None => { + println!("Failed parsing {:?}", mat); // log on failure + continue; + } + }; + let mod_name_copy = match mat.get(2) { + Some(mod_name) => mod_name.as_str().to_string(), + None => { + println!("Failed parsing {:?}", mat); // log on failure + continue; + } + }; + let enabled_disabled = match mat.get(3) { + Some(mod_name) => mod_name.as_str().to_string(), + None => { + println!("Failed parsing {:?}", mat); // log on failure + continue; + } + }; + println!("{}, {}, {}", mod_name, mod_name_copy, enabled_disabled); + if mod_name != mod_name_copy { + return Err("Mod names don't match up".to_string()); + } + + // TODO improve checking + let mod_enabled; + if enabled_disabled == "enabled" { + mod_enabled = true; + } else { + mod_enabled = false; + } + + let parsed_mod_from_log = ParsedModFromLog { + mod_name, + enabled: mod_enabled, + }; + + // Add mod to list + mods.push(parsed_mod_from_log); + } + + // Return the captured mod names + return Ok(mods); +} + +/// Parse logs for Northstar launcher version +fn parse_for_northstar_launcher_version(log_text: String) -> Result<String, String> { + let regex = Regex::new(r"(?m)NorthstarLauncher version: (.*)\n").unwrap(); + + // result will be an iterator over tuples containing the start and end indices for each match in the string + let mut result = regex.captures_iter(&log_text); + + // Return found Northstar launcher version number + match result.next() { + None => Err("Couldn't parse Northstar launcher version".to_string()), + Some(mat) => match mat.get(1) { + None => Err("Couldn't parse Northstar launcher version".to_string()), + Some(mod_name) => Ok(mod_name.as_str().to_string()), + }, + } +} + +fn parse_log_for_crash(log_text: String) -> bool { + let pattern = Regex::new(r"(?m)Northstar has crashed!").unwrap(); + pattern.is_match(&log_text) +} + +/// Parse logs for installed mods +#[tauri::command] +pub async fn parse_given_log_text(log_text: String) -> Result<ParsedLogResults, String> { + let installed_mods = parse_given_log_text_for_installed_mods(log_text.clone())?; + let northstar_launcher_version = parse_for_northstar_launcher_version(log_text.clone())?; + let has_northstar_crashed = parse_log_for_crash(log_text); + + let parsed_log_results = ParsedLogResults { + northstar_launcher_version, + installed_mods, + has_northstar_crashed, + }; + + // Return the parsed results + return Ok(parsed_log_results); +} diff --git a/src-tauri/src/repair_and_verify/mod.rs b/src-tauri/src/repair_and_verify/mod.rs index 9d020f15..c53759af 100644 --- a/src-tauri/src/repair_and_verify/mod.rs +++ b/src-tauri/src/repair_and_verify/mod.rs @@ -1,3 +1,5 @@ +pub mod log_handling; + use crate::mod_management::{rebuild_enabled_mods_json, set_mod_enabled_status}; use anyhow::anyhow; /// Contains various functions to repair common issues and verifying installation diff --git a/src-vue/src/views/DeveloperView.vue b/src-vue/src/views/DeveloperView.vue index 11cb4f5d..c73aef6a 100644 --- a/src-vue/src/views/DeveloperView.vue +++ b/src-vue/src/views/DeveloperView.vue @@ -55,6 +55,42 @@ <el-button type="primary" @click="clearFlightCorePersistentStore"> Delete FlightCore persistent store </el-button> + <h3>Tech support</h3> + + <el-button type="primary" @click="parseGivenLogTextForMods"> + Parse logs + </el-button> + <el-input + v-model="log_content" + type="textarea" + :rows="5" + placeholder="Paste log content here" + + /> + <div> + <el-table :data="logResults"> + <el-table-column prop="northstar_launcher_version" + label="Northstar Launcher Version"></el-table-column> + <el-table-column prop="installed_mods" label="Installed and enabled/disabled Mods"> + <template v-slot="{ row }"> + <ul> + <li v-for="mod in row.installed_mods"> + <el-icon class="no-inherit"> + <Select v-if="mod.enabled" /> + <Close v-else /> + </el-icon> + {{ mod.mod_name }} + </li> + </ul> + </template> + </el-table-column> + <el-table-column prop="has_northstar_crashed" label="Northstar Crashed"> + <template v-slot="{ row }"> + {{ row.has_northstar_crashed }} + </template> + </el-table-column> + </el-table> + </div> <h3>Testing</h3> <pull-requests-selector /> @@ -70,6 +106,8 @@ import { GameInstall } from "../utils/GameInstall"; import { Store } from 'tauri-plugin-store-api'; import { ReleaseCanal } from "../utils/ReleaseCanal"; import PullRequestsSelector from "../components/PullRequestsSelector.vue"; +import { ParsedLogResults } from "../../../src-tauri/bindings/ParsedLogResults"; +import { ParsedModFromLog } from "../../../src-tauri/bindings/ParsedModFromLog"; const persistentStore = new Store('flight-core-settings.json'); export default defineComponent({ @@ -80,6 +118,8 @@ export default defineComponent({ data() { return { mod_to_install_field_string : "", + log_content : "", + logResults: [] as ParsedLogResults[] } }, methods: { @@ -261,6 +301,29 @@ export default defineComponent({ notification.close(); }); }, + async parseGivenLogTextForMods() { + let current_log_content = this.log_content; + await invoke<[ParsedLogResults]>("parse_given_log_text", { logText: current_log_content }) + .then((message) => { + console.log(message); // TODO present better here + this.logResults.push(message); + // Show user notification if task completed. + ElNotification({ + title: `Done`, + message: `${message}`, + type: 'success', + position: 'bottom-right' + }); + }) + .catch((error) => { + ElNotification({ + title: 'Error', + message: error, + type: 'error', + position: 'bottom-right' + }); + }); + }, } }); </script> |