Skip to content

Commit

Permalink
[GUI/CORE] Better Analytics On Update
Browse files Browse the repository at this point in the history
  • Loading branch information
Bwc9876 committed Jul 20, 2023
1 parent 392748c commit df8a3bc
Show file tree
Hide file tree
Showing 13 changed files with 77 additions and 22 deletions.
2 changes: 1 addition & 1 deletion owmods_core/src/analytics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl AnalyticsPayload {
// Note how this function doesn't return a result, it shouldn't. We want to simply move on if we can't
// send an event because it's not the end of the world.

/// Send an analytics event with the given `event_name` for the given mod's `unique_name`
/// Send an analytics event with the given [AnalyticsEventName] for the given mod's `unique_name`
///
/// **Please note that unless an `ANALYTICS_API_KEY` env variable is specified at build time this function does nothing.**
pub async fn send_analytics_event(event_name: AnalyticsEventName, unique_name: &str) {
Expand Down
3 changes: 2 additions & 1 deletion owmods_core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl Config {
}

/// Set that a specific mod's warning was shown.
/// (Doesn't save the config, you have to do that yourself)
pub fn set_warning_shown(&mut self, unique_name: &str) {
self.viewed_alerts.push(unique_name.to_string());
}
Expand All @@ -98,7 +99,7 @@ impl Config {
///
/// ## Returns
///
/// The newly created or loaded config.
/// The newly created or loaded [Config].
///
/// ## Errors
///
Expand Down
24 changes: 17 additions & 7 deletions owmods_core/src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ fn extract_mod_zip(
}
}

/// Downloads and install OWML to the path specified in config.owml_path
/// Downloads and installs OWML to the path specified in `config.owml_path`
///
/// ## Errors
///
Expand Down Expand Up @@ -249,7 +249,7 @@ pub async fn download_and_install_owml(
///
/// ## Returns
///
/// The newly installed LocalMod
/// The newly installed [LocalMod]
///
/// ## Errors
///
Expand Down Expand Up @@ -320,7 +320,7 @@ pub fn install_mod_from_zip(
///
/// ## Returns
///
/// The newly installed local mod
/// The newly installed [LocalMod]
///
/// ## Errors
///
Expand Down Expand Up @@ -357,7 +357,7 @@ pub async fn install_mod_from_url(
///
/// ## Errors
///
/// If __any__ mod fails to install from the list
/// If **any** mod fails to install from the list
///
pub async fn install_mods_parallel(
unique_names: Vec<String>,
Expand Down Expand Up @@ -396,7 +396,7 @@ pub async fn install_mods_parallel(
///
/// - If you requested a prerelease and the mod doesn't have one.
/// - If we can't install the target mod for any reason.
/// - If we can't install __any__ dependencies for any reason.
/// - If we can't install **any** dependencies for any reason.
///
pub async fn install_mod_from_db(
unique_name: &String,
Expand All @@ -406,7 +406,13 @@ pub async fn install_mod_from_db(
recursive: bool,
prerelease: bool,
) -> Result<()> {
let already_installed = local_db.get_mod(unique_name).is_some();
let existing_mod = local_db.get_mod(unique_name);

let already_installed = existing_mod.is_some();
let existing_version = existing_mod
.as_ref()
.map(|m| m.manifest.version.clone())
.unwrap_or_default();

let remote_mod = remote_db
.get_mod(unique_name)
Expand Down Expand Up @@ -489,7 +495,11 @@ pub async fn install_mod_from_db(
let mod_event = if prerelease {
AnalyticsEventName::ModPrereleaseInstall
} else if already_installed {
AnalyticsEventName::ModReinstall
if existing_version == new_mod.manifest.version {
AnalyticsEventName::ModReinstall
} else {
AnalyticsEventName::ModUpdate
}
} else {
AnalyticsEventName::ModInstall
};
Expand Down
5 changes: 5 additions & 0 deletions owmods_core/src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ use crate::{config::Config, constants::OWML_EXE_NAME, owml::OWMLConfig};
/// If no port is given, the output of OWML.Launcher.exe will be written to stdout.
/// You can set `open_in_new_window` to `true` to make the command open in a new cmd window (**Windows Only**).
/// On Linux there's no reliable way to open a new terminal window, so it's recommended you disallow that arg to be false on linux.
///
/// ## Errors
///
/// If we can't launch the game/OWML, if we can't start a log server, or if we can't read the config.
///
pub async fn launch_game(
config: &Config,
open_in_new_window: bool,
Expand Down
4 changes: 2 additions & 2 deletions owmods_core/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ pub fn export_mods(db: &LocalDatabase) -> Result<String> {
Ok(result)
}

/// Import mods from a JSON file that contains an array or unique name (like the one exported by `export_mods`).
/// Import mods from a JSON file that contains an array or unique name (like the one exported by [export_mods]).
/// Mods that aren't in the remote database will be ignored and will only log a warning.
/// Optionally this can also disable all current mods not found in this list as well.
/// Optionally, this can also disable all current mods not found in this list.
///
/// ## Errors
///
Expand Down
1 change: 1 addition & 0 deletions owmods_core/src/mods/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ impl UnsafeLocalMod {
}

/// Gets the path for a mod
/// This is the same for [UnsafeLocalMod::Valid] and [UnsafeLocalMod::Invalid]
pub fn get_path(&self) -> &str {
match self {
Self::Invalid(m) => &m.mod_path,
Expand Down
2 changes: 1 addition & 1 deletion owmods_core/src/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn open_shortcut(identifier: &str, conf: &Config, local_db: &LocalDatabase)
///
/// ## Errors
///
/// If the unique name provided is not an installed mod
/// If the unique name provided is not an installed mod or we can't open the browser.
///
pub fn open_readme(unique_name: &str, db: &RemoteDatabase) -> Result<()> {
let remote_mod = db
Expand Down
14 changes: 13 additions & 1 deletion owmods_core/src/owml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
#[typeshare]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(non_snake_case)] // Have to allow non_snake_case here because OWML's config uses incrementalGC, which isn't proper camelCase
#[allow(non_snake_case)] // Have to allow non_snake_case here because OWML's config uses "incrementalGC", which isn't proper camelCase
pub struct OWMLConfig {
pub game_path: String,
debug_mode: bool,
Expand Down Expand Up @@ -65,6 +65,12 @@ impl OWMLConfig {
serialize_to_json(self, path, true)
}

/// Get the default OWML config (OWML.DefaultConfig.json)
///
/// ## Errors
///
/// If we can't read the default config or can't get the user data dir. (Linux only)
///
#[cfg(not(windows))]
pub fn default(config: &Config) -> Result<OWMLConfig> {
use anyhow::anyhow;
Expand All @@ -84,6 +90,12 @@ impl OWMLConfig {
Ok(conf)
}

/// Get the default OWML config (OWML.DefaultConfig.json)
///
/// ## Errors
///
/// If we can't read the default config or can't get the user data dir. (Linux only)
///
#[cfg(windows)]
pub fn default(config: &Config) -> Result<OWMLConfig> {
deserialize_from_json(&Path::new(&config.owml_path).join(OWML_DEFAULT_CONFIG_NAME))
Expand Down
12 changes: 10 additions & 2 deletions owmods_core/src/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use crate::{
///
/// ## Returns
///
/// A `Vec<String>` of mods that have pre-patchers and need to have a warning shown to the user
/// A `Vec<String>` of mods that have pre-patchers
/// and thus **should have a warning shown to the user telling them to check the mod's README for instructions**
///
/// ## Errors
///
Expand Down Expand Up @@ -55,14 +56,21 @@ pub fn remove_mod(
///
/// ## Errors
///
/// If we can't delete the folder
/// If we can't delete the folder the mod was in.
///
pub fn remove_failed_mod(failed_mod: &FailedMod) -> Result<()> {
remove_dir_all(PathBuf::from(&failed_mod.mod_path))?;
Ok(())
}

/// Removes all files not specified in `pathsToPreserve`
///
/// See [get_paths_to_preserve] to see implicit paths to preserve
///
/// ## Errors
///
/// If we can't delete the files
///
pub fn remove_old_mod_files(local_mod: &LocalMod) -> Result<()> {
let glob_matches = glob(
PathBuf::from(&local_mod.mod_path)
Expand Down
11 changes: 11 additions & 0 deletions owmods_core/src/search.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
/// Represents an object that can be searched
pub trait Searchable {
/// Get the values that can be searched
/// Each value will be weighted based on its position in the list (first is most important)
fn get_values(&self) -> Vec<String>;
}

/// Search a list of [Searchable] for a string
/// This will return a list of the items that match the search, sorted by relevance
/// Relevance is determined like so:
/// - If the search is an exact match for a value, that value will be weighted 2x
/// - If the search is contained in a value, that value will be weighted 1x
/// - If the search is not contained in a value, that value will be weighted 0x
/// The score is then also weighted by the position of the value in the list the [Searchable] (first is most important)
/// These scores are then summed and the list is sorted by the total score of each item
pub fn search_list<'a, T>(source_list: Vec<&'a T>, filter: &str) -> Vec<&'a T>
where
T: Searchable,
Expand Down
4 changes: 2 additions & 2 deletions owmods_core/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl LogServer {
///
/// ## Returns
///
/// A new log server that's bound to the given port, **but not ready to listen to logs**.
/// A new log server that's bound to the given port, **but not ready to listen to** logs.
///
/// ## Errors
///
Expand Down Expand Up @@ -156,7 +156,7 @@ impl LogServer {

// Loop that runs on start, listens for clients to connect
// Makes a new client_loop for each client
pub async fn server_loop(
async fn server_loop(
&self,
tx: &LogServerSender,
shutdown_sender: mpsc::Sender<()>,
Expand Down
6 changes: 2 additions & 4 deletions owmods_core/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,8 @@ fn check_mod_conflicts(local_mod: &LocalMod, db: &LocalDatabase) -> Vec<ModValid
errors
}

/// Check a local mod for issues such as:
/// - Missing/Disabled Dependencies
/// - Conflicting Mods
/// - Missing DLL File
/// Check a local mod for issues described in [ModValidationError]
/// (except for [ModValidationError::InvalidManifest], [ModValidationError::DuplicateMod], and [ModValidationError::Outdated])
///
/// ## Returns
///
Expand Down
11 changes: 10 additions & 1 deletion owmods_gui/backend/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::{

use anyhow::anyhow;
use log::error;
use owmods_core::analytics::{send_analytics_event, AnalyticsEventName};
use owmods_core::mods::local::LocalMod;
use owmods_core::{
alerts::{fetch_alert, Alert},
Expand Down Expand Up @@ -589,7 +590,8 @@ pub async fn update_all_mods(
}
drop(busy_mods);
handle.typed_emit_all(&Event::ModBusy(())).ok();
install_mods_parallel(unique_names.clone(), &config, &remote_db, &local_db).await?;
let updated_mods =
install_mods_parallel(unique_names.clone(), &config, &remote_db, &local_db).await?;
if owml_in_list {
download_and_install_owml(
&config,
Expand All @@ -603,6 +605,13 @@ pub async fn update_all_mods(
let mut busy_mods = state.mods_in_progress.write().await;
busy_mods.retain(|m| !unique_names.contains(m) && (!owml_in_list || m != OWML_UNIQUE_NAME));
handle.typed_emit_all(&Event::ModBusy(())).ok();
for updated_mod in updated_mods {
send_analytics_event(
AnalyticsEventName::ModUpdate,
&updated_mod.manifest.unique_name,
)
.await;
}
Ok(())
}

Expand Down

0 comments on commit df8a3bc

Please sign in to comment.