Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions src-tauri/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use keyring::Entry;
use serde::Deserialize;
use tokio::sync::Mutex as AsyncMutex;

use crate::config::{
AppConfig, DetectedService, KEYRING_ACCESS, KEYRING_SERVICE, KEYRING_SESSION,
};
use crate::config::{AppConfig, DetectedService, KEYRING_ACCESS, KEYRING_SERVICE, KEYRING_SESSION};
use crate::device;
use crate::oauth_loopback::REDIRECT_URI;
use crate::pkce;
Expand Down Expand Up @@ -195,10 +193,7 @@ pub async fn detect_and_apply(cfg: &mut AppConfig) -> Result<String, String> {
if !res.status().is_success() {
return Err(format!("health HTTP {}", res.status()));
}
let body: HealthBody = res
.json()
.await
.map_err(|e| format!("health JSON: {e}"))?;
let body: HealthBody = res.json().await.map_err(|e| format!("health JSON: {e}"))?;
if !body.ok {
return Err("health ok=false".into());
}
Expand Down Expand Up @@ -349,10 +344,8 @@ mod tests {

#[test]
fn parses_code_callback() {
let (c, s) = parse_callback_code(
"http://127.0.0.1:58473/callback?code=abc&state=xyz",
)
.unwrap();
let (c, s) =
parse_callback_code("http://127.0.0.1:58473/callback?code=abc&state=xyz").unwrap();
assert_eq!(c, "abc");
assert_eq!(s, "xyz");
}
Expand Down
3 changes: 1 addition & 2 deletions src-tauri/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ pub const OAUTH_REVOKE_PATH: &str = "/oauth/qmonitor/revoke";
pub const KEYRING_SERVICE: &str = "qmonitor";
pub const KEYRING_ACCESS: &str = "access_token";
pub const KEYRING_SESSION: &str = "session_token";
pub const DEFAULT_DETECTABLE_URL: &str =
"https://discord.com/api/v10/applications/detectable";
pub const DEFAULT_DETECTABLE_URL: &str = "https://discord.com/api/v10/applications/detectable";

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
Expand Down
20 changes: 16 additions & 4 deletions src-tauri/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,10 @@ mod tests {
let path = dir.path().join("test.db");
let db = TursoDb::open(&path).await.expect("open");
db.ping().await.expect("ping");
let row = db.open_session_at(&sample_identity(), Utc::now()).await.unwrap();
let row = db
.open_session_at(&sample_identity(), Utc::now())
.await
.unwrap();
assert_eq!(row.push_status, PushStatus::Active);
let ended = db.end_session_at(&row.id, Utc::now()).await.unwrap();
assert_eq!(ended.push_status, PushStatus::Pending);
Expand All @@ -678,8 +681,14 @@ mod tests {
let dir = tempdir().unwrap();
let path = dir.path().join("dup.db");
let db = TursoDb::open(&path).await.expect("open");
let a = db.open_session_at(&sample_identity(), Utc::now()).await.unwrap();
let b = db.open_session_at(&sample_identity(), Utc::now()).await.unwrap();
let a = db
.open_session_at(&sample_identity(), Utc::now())
.await
.unwrap();
let b = db
.open_session_at(&sample_identity(), Utc::now())
.await
.unwrap();
assert_eq!(a.id, b.id);
assert_eq!(db.list_active().await.unwrap().len(), 1);
}
Expand All @@ -689,7 +698,10 @@ mod tests {
let dir = tempdir().unwrap();
let path = dir.path().join("discard.db");
let db = TursoDb::open(&path).await.expect("open");
let row = db.open_session_at(&sample_identity(), Utc::now()).await.unwrap();
let row = db
.open_session_at(&sample_identity(), Utc::now())
.await
.unwrap();
db.discard_session(&row.id).await.unwrap();
assert!(db.list_active().await.unwrap().is_empty());
assert!(db.list_due_pushes().await.unwrap().is_empty());
Expand Down
13 changes: 7 additions & 6 deletions src-tauri/src/detect/platform/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ pub fn is_proton_wrapper(process_name: &str) -> bool {
}

#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
pub fn detect_steam(
processes: &[ProcessSnapshot],
steam: &SteamLibraryIndex,
) -> Vec<GameIdentity> {
pub fn detect_steam(processes: &[ProcessSnapshot], steam: &SteamLibraryIndex) -> Vec<GameIdentity> {
let mut identities = steamlaunch_identities(processes, steam);
for proc in processes {
if is_denied(&proc.name) || is_proton_wrapper(&proc.name) {
Expand Down Expand Up @@ -87,7 +84,9 @@ mod tests {
SteamGame {
app_id: 730,
title: "CS2".into(),
install_path: PathBuf::from("/games/steamapps/common/Counter-Strike Global Offensive"),
install_path: PathBuf::from(
"/games/steamapps/common/Counter-Strike Global Offensive",
),
},
);
let procs = vec![ProcessSnapshot {
Expand Down Expand Up @@ -118,7 +117,9 @@ mod tests {
let procs = vec![ProcessSnapshot {
pid: 1,
name: "dota2".into(),
exe_path: Some("/games/steamapps/common/dota 2 beta/game/bin/linuxsteamrt64/dota2".into()),
exe_path: Some(
"/games/steamapps/common/dota 2 beta/game/bin/linuxsteamrt64/dota2".into(),
),
cmdline: None,
}];
let ids = detect_steam(&procs, &dota_index());
Expand Down
7 changes: 2 additions & 5 deletions src-tauri/src/detect/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
pub mod linux;
pub mod windows;

use crate::identity::{GameIdentity, ProcessSnapshot};
use crate::identity::steam_library::SteamLibraryIndex;
use crate::identity::{GameIdentity, ProcessSnapshot};

/// Dispatch to the host OS detector.
pub fn detect_steam(
processes: &[ProcessSnapshot],
steam: &SteamLibraryIndex,
) -> Vec<GameIdentity> {
pub fn detect_steam(processes: &[ProcessSnapshot], steam: &SteamLibraryIndex) -> Vec<GameIdentity> {
#[cfg(target_os = "windows")]
{
windows::detect_steam(processes, steam)
Expand Down
12 changes: 2 additions & 10 deletions src-tauri/src/detect/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,12 @@ pub fn is_install_sidecar(proc: &ProcessSnapshot) -> bool {
.unwrap_or("")
.replace('\\', "/")
.to_ascii_lowercase();
const SEGMENTS: &[&str] = &[
"/easyanticheat/",
"/battleye/",
"/eossdk/",
"/eosoverlay",
];
const SEGMENTS: &[&str] = &["/easyanticheat/", "/battleye/", "/eossdk/", "/eosoverlay"];
SEGMENTS.iter().any(|s| path.contains(s))
}

#[cfg_attr(not(target_os = "windows"), allow(dead_code))]
pub fn detect_steam(
processes: &[ProcessSnapshot],
steam: &SteamLibraryIndex,
) -> Vec<GameIdentity> {
pub fn detect_steam(processes: &[ProcessSnapshot], steam: &SteamLibraryIndex) -> Vec<GameIdentity> {
let mut identities = steamlaunch_identities(processes, steam);
for proc in processes {
if is_denied(&proc.name) || is_install_sidecar(proc) {
Expand Down
14 changes: 5 additions & 9 deletions src-tauri/src/health.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,12 @@ pub fn init_tracing() {
FILE_ON.store(level.file_enabled(), Ordering::Relaxed);
prune_now(level);

let (filter, reload_handle) =
reload::Layer::new(EnvFilter::new(level.env_filter()));
let (filter, reload_handle) = reload::Layer::new(EnvFilter::new(level.env_filter()));
let _ = FILTER_RELOAD.set(reload_handle);

tracing_subscriber::registry()
.with(filter)
.with(
tracing_subscriber::fmt::layer()
.with_writer(std::io::stderr.and(GatedMakeWriter)),
)
.with(tracing_subscriber::fmt::layer().with_writer(std::io::stderr.and(GatedMakeWriter)))
.init();

if level.file_enabled() {
Expand Down Expand Up @@ -369,9 +365,9 @@ mod tests {
}
let _reset = ResetSink;

let active = dir.path().join(
active_daily_log_name().expect("sink is active"),
);
let active = dir
.path()
.join(active_daily_log_name().expect("sink is active"));
fs::write(&active, vec![b'x'; LOG_MAX_BYTES as usize + 64]).unwrap();
let other = dir.path().join("qmonitor.log.2020-01-01");
fs::write(&other, vec![b'y'; 200]).unwrap();
Expand Down
6 changes: 1 addition & 5 deletions src-tauri/src/identity/catalog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@ impl LocalCatalog {
pub fn match_process(&self, proc: &ProcessSnapshot) -> Option<GameIdentity> {
let os = current_os_label();
let pname = proc.name.to_ascii_lowercase();
let path_l = proc
.exe_path
.as_deref()
.unwrap_or("")
.to_ascii_lowercase();
let path_l = proc.exe_path.as_deref().unwrap_or("").to_ascii_lowercase();
let cmd = proc.cmdline.as_deref().unwrap_or("").to_ascii_lowercase();

let mut best: Option<(Confidence, &CatalogEntry)> = None;
Expand Down
6 changes: 6 additions & 0 deletions src-tauri/src/identity/deny.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub fn is_denied(process_name: &str) -> bool {
|| stem.contains("crashhandler")
|| stem.contains("crashreporter")
|| stem.contains("webview")
|| stem.contains("subprocess")
|| stem.contains("unrealcef")
|| stem.contains("crashpad")
|| stem.starts_with("qtwebengine")
|| name.contains("easyanticheat")
|| name.contains("battleye")
Expand All @@ -83,6 +86,7 @@ mod tests {
assert!(is_denied("UnityCrashHandler64.exe"));
assert!(!is_denied("dota2.exe"));
assert!(!is_denied("Hades.exe"));
assert!(!is_denied("Caffeine.exe"));
}

#[test]
Expand All @@ -91,5 +95,7 @@ mod tests {
assert!(is_denied("QtWebEngineProcess.exe"));
assert!(is_denied("obs-browser-page.exe"));
assert!(is_denied("NVIDIA Broadcast.exe"));
assert!(is_denied("UnrealCEFSubProcess.exe"));
assert!(!is_denied("Caffeine.exe"));
}
}
6 changes: 1 addition & 5 deletions src-tauri/src/identity/detectable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,7 @@ fn normalize_path(s: &str) -> String {
}

fn pattern_basename(pattern: &str) -> String {
pattern
.rsplit('/')
.next()
.unwrap_or(pattern)
.to_string()
pattern.rsplit('/').next().unwrap_or(pattern).to_string()
}

fn current_discord_os() -> &'static str {
Expand Down
57 changes: 42 additions & 15 deletions src-tauri/src/identity/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,7 @@ pub fn crash_report_client() -> ProcessSnapshot {
proc(
1,
"CrashReportClient.exe",
Some(
r"D:\Steam\steamapps\common\Apex Legends\Engine\Binaries\Win64\CrashReportClient.exe",
),
Some(r"D:\Steam\steamapps\common\Apex Legends\Engine\Binaries\Win64\CrashReportClient.exe"),
None,
)
}
Expand All @@ -131,20 +129,13 @@ pub fn r5apex_under_install() -> ProcessSnapshot {
proc(
1,
name,
Some(&format!(
r"D:\Steam\steamapps\common\Apex Legends\{name}"
)),
Some(&format!(r"D:\Steam\steamapps\common\Apex Legends\{name}")),
None,
)
}

pub fn reaper_dota() -> ProcessSnapshot {
proc(
9,
"reaper",
None,
Some("reaper SteamLaunch AppId=570 --"),
)
proc(9, "reaper", None, Some("reaper SteamLaunch AppId=570 --"))
}

pub fn wineserver_under_dota() -> ProcessSnapshot {
Expand Down Expand Up @@ -227,11 +218,47 @@ mod tests {
}

#[test]
fn path_only_game_exe_is_not_auto_tracked_without_discord() {
fn path_only_mismatched_exe_goes_pending() {
let pipeline = pipeline_with(apex_steam(), DetectableCatalog::default(), Vec::new());
let (ids, pending) = pipeline.resolve_running(&[r5apex_under_install()]);
assert!(ids.is_empty(), "path-only Low must not auto-track: {ids:?}");
assert!(pending.is_empty());
assert!(
ids.is_empty(),
"mismatched exe must not auto-track: {ids:?}"
);
assert_eq!(pending.len(), 1);
assert_eq!(pending[0].suggested_title, "Apex Legends");
assert_eq!(pending[0].identity_id.as_deref(), Some("steam:1172470"));
}

#[test]
fn steam_path_title_like_exe_auto_tracks_without_discord() {
let mut steam = SteamLibraryIndex::default();
steam.games.insert(
3321460,
SteamGame {
app_id: 3321460,
title: "Crimson Desert Enhanced".into(),
install_path: PathBuf::from(r"D:\SteamLibrary\steamapps\common\Crimson Desert"),
},
);
let pipeline = pipeline_with(steam, DetectableCatalog::default(), Vec::new());
let name = if cfg!(target_os = "windows") {
"CrimsonDesert.exe"
} else {
"CrimsonDesert"
};
let procs = vec![proc(
1,
name,
Some(r"D:\SteamLibrary\steamapps\common\Crimson Desert\bin64\CrimsonDesert.exe"),
None,
)];
let (ids, pending) = pipeline.resolve_running(&procs);
assert!(pending.is_empty(), "pending: {pending:?}");
assert_eq!(ids.len(), 1);
assert_eq!(ids[0].steam_app_id, Some(3321460));
assert_eq!(ids[0].confidence, Confidence::Medium);
assert_eq!(ids[0].title, "Crimson Desert Enhanced");
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/identity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod detectable;
pub mod fingerprint;
pub mod resolver;
pub mod steam_library;
pub mod steam_path;

#[cfg(test)]
pub mod fixtures;
Expand Down
Loading