Skip to content

Commit

Permalink
Server overlay as HTTP (#71)
Browse files Browse the repository at this point in the history
* Add simple http

* Add simple http

* Web server implmentation

* Finish the server hosting

* Add sentry config

* Update actions

* Fix main

* Fix getting data from the store

* Plugin load changes

* Final cleanup
  • Loading branch information
petrvecera authored Feb 26, 2024
1 parent 952b56b commit 2510c23
Show file tree
Hide file tree
Showing 15 changed files with 299 additions and 68 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ jobs:
publish-tauri:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 18

- name: Cache node modules
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: cache-node-modules-v1
with:
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ jobs:
cancel-in-progress: true

steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18

- name: Cache node modules
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: cache-node-modules-v1
with:
Expand All @@ -44,14 +44,14 @@ jobs:
cancel-in-progress: true

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 18

- name: Cache node modules
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: cache-node-modules-v1
with:
Expand Down
26 changes: 26 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ reqwest = { version = "0.11", features = ["json", "multipart"] }
rev_lines = "0.3"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2", features = [ "window-all", "path-all", "dialog-all", "shell-open", "clipboard-write-text", "http-all", "fs-all", "updater"] }
tauri = { version = "1.2", features = [ "process-all", "window-all", "path-all", "dialog-all", "shell-open", "clipboard-write-text", "http-all", "fs-all", "updater"] }
tauri-plugin-deep-link = "0.1"
tauri-plugin-fs-watch = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
Expand All @@ -38,6 +38,8 @@ vault = "8"
window-shadows = "0.2"
# monitoring by sentry
sentry = "0.32.2"
# For the OBS interface we need to expose webserver
tiny_http = "0.11"

[dev-dependencies]
criterion = { version = "0.4", features = ["html_reports"] }
Expand Down
31 changes: 31 additions & 0 deletions src-tauri/src/dp_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use serde::de::DeserializeOwned;
// COH3 Desktop App Utils
use tauri_plugin_store::{StoreCollection, with_store};
use log::{error};
use tauri::{AppHandle, Manager, Runtime};

pub fn load_from_store<R: Runtime, T: DeserializeOwned>(handle: AppHandle<R>, key: &str) -> Option<T> {
let stores = handle.state::<StoreCollection<R>>();
let path = handle
.path_resolver()
.app_data_dir()
.unwrap()
.join("config.dat");

match with_store(handle.clone(), stores, path, |store| {
Ok(store.get(key).cloned())
}) {
Ok(Some(value)) => match serde_json::from_value(value.clone()) {
Ok(result) => Some(result),
Err(err) => {
error!("error deserializing store value at {key}: {err}");
None
}
},
Ok(None) => None,
Err(err) => {
error!("error retrieving store value at {key}: {err}");
None
}
}
}
2 changes: 2 additions & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod parse_log_file;
pub mod plugins;
pub mod overlay_server;
pub mod dp_utils;
31 changes: 27 additions & 4 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

extern crate machine_uid;

use coh3_stats_desktop_app::{parse_log_file, plugins::cohdb};
use log::error;
use coh3_stats_desktop_app::dp_utils::load_from_store;
use coh3_stats_desktop_app::{parse_log_file, plugins::cohdb, overlay_server::run_http_server};
use log::{error, info};
use std::path::Path;
use std::thread;
use tauri::Manager;
use tauri_plugin_log::LogTarget;
use window_shadows::set_shadow;
Expand Down Expand Up @@ -62,8 +64,10 @@ fn main() {
))
.plugin(coh3_stats_desktop_app::plugins::cohdb::sync::init())
.setup(setup)
.setup(setup_web_server)
.run(tauri::generate_context!())
.expect("error while running tauri application");

}

fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
Expand All @@ -90,11 +94,30 @@ fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}

fn setup_web_server(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
let app_handle = app.handle();

if load_from_store(app_handle.clone(), "streamerOverlayEnabled").unwrap_or(false) {
info!("Streamer overlay is enabled");
let mut file_path = app_handle.path_resolver().app_data_dir().unwrap();
file_path.push("streamerOverlay.html");
info!("Expecting the streamerOverlay at {:?}", file_path);

let _handle = thread::spawn(|| {
run_http_server(file_path);
});
} else {
info!("Streamer overlay is disabled");
}

Ok(())
}

/// returns the default expected log file path
#[tauri::command]
fn default_log_file_path() -> String {
let mut path = tauri::api::path::document_dir().unwrap();
path.push("My Games");
path.push("My Games"); // TODO: Is this "my games" also on non-English Windows?
path.push("Company of Heroes 3");
path.push("warnings.log");
path.display().to_string()
Expand All @@ -103,7 +126,7 @@ fn default_log_file_path() -> String {
#[tauri::command]
fn default_playback_path() -> String {
let mut path = tauri::api::path::document_dir().unwrap();
path.push("My Games");
path.push("My Games"); // TODO: Is this "my games" also on non-English Windows?
path.push("Company of Heroes 3");
path.push("playback");
path.display().to_string()
Expand Down
37 changes: 37 additions & 0 deletions src-tauri/src/overlay_server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::fs::File;
use std::panic;
use log::{error, info};
use std::path::PathBuf;

use tiny_http::{Server, Response, StatusCode};

pub fn run_http_server(streamer_overlay_path: PathBuf) {

let result = panic::catch_unwind(|| {

// Ideally we would allow setting up port in the settings
info!("Starting streamer overlay server on port 47824");
let server = Server::http("127.0.0.1:47824").unwrap();

for request in server.incoming_requests() {

let file = match File::open(&streamer_overlay_path) {
Ok(file) => file,
Err(_) => {
let response = Response::new_empty(StatusCode(404));
let _ = request.respond(response);
continue;
}
};

let response = Response::from_file(file);
let _ = request.respond(response);
}

});

if let Err(err) = result {
error!("Couldn't start the streamer overlay server: {:?}", err);
}

}
30 changes: 2 additions & 28 deletions src-tauri/src/plugins/cohdb/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ use std::{path::PathBuf, sync::Mutex};
use auth::responses::User;
use log::{debug, error, info, warn};
use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Watcher};
use serde::de::DeserializeOwned;
use tauri::{
plugin::{Builder, TauriPlugin},
AppHandle, EventHandler, Manager, Runtime,
};
use tauri_plugin_store::{with_store, StoreCollection};
use vault::{GameType, Replay};

use crate::dp_utils::load_from_store;

use super::auth;

#[derive(Debug, Default)]
Expand Down Expand Up @@ -135,32 +135,6 @@ fn includes_user(replay: &Replay, user: &User) -> bool {
.any(|player| player.profile_id().is_some() && player.profile_id() == user.profile_id)
}

fn load_from_store<R: Runtime, T: DeserializeOwned>(handle: AppHandle<R>, key: &str) -> Option<T> {
let stores = handle.state::<StoreCollection<R>>();
let path = handle
.path_resolver()
.app_data_dir()
.unwrap()
.join("config.dat");

match with_store(handle.clone(), stores, path, |store| {
Ok(store.get(key).cloned())
}) {
Ok(Some(value)) => match serde_json::from_value(value.clone()) {
Ok(result) => Some(result),
Err(err) => {
error!("error deserializing store value at {key}: {err}");
None
}
},
Ok(None) => None,
Err(err) => {
error!("error retrieving store value at {key}: {err}");
None
}
}
}

fn load_playback_path<R: Runtime>(handle: AppHandle<R>) -> String {
if let Some(path) = load_from_store::<R, String>(handle, "playbackPath") {
path
Expand Down
3 changes: 3 additions & 0 deletions src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
},
"window": {
"all": true
},
"process": {
"all": true
}
},
"bundle": {
Expand Down
13 changes: 10 additions & 3 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@ info("Start frontend")
Sentry.init({
dsn: "https://88e8a309f91b8b5bb9a41dd14ff775b9@o4504995920543744.ingest.sentry.io/4506752563019776",
integrations: [Sentry.browserTracingIntegration()],
// Performance Monitoring
tracesSampleRate: 0.1, // Capture 100% of the transactions
// Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
tracesSampleRate: 0.1,
tracePropagationTargets: ["localhost"],
beforeSend(event, hint) {
// On macOS we do only development, we can ignore all development errors
if (event.contexts?.os?.name === "macOS") {
// Ignore the event
return null
}
// Otherwise, return the event as is
return event
},
})

events.init()
Expand Down
5 changes: 5 additions & 0 deletions src/streamer-overlay/configValues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ const [getShowFlagsOverlay, useShowFlagsOverlay] = configValueFactory<boolean>(
const [getAlwaysShowOverlay, useAlwaysShowOverlay] =
configValueFactory<boolean>("alwaysShowOverlay", async () => false)

const [getStreamerOverlayEnabled, useStreamerOverlayEnabled] =
configValueFactory<boolean>("streamerOverlayEnabled", async () => false)

export {
getShowFlagsOverlay,
useShowFlagsOverlay,
getAlwaysShowOverlay,
useAlwaysShowOverlay,
getStreamerOverlayEnabled,
useStreamerOverlayEnabled,
}
10 changes: 10 additions & 0 deletions src/views/About.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getVersion } from "@tauri-apps/api/app"
import { appDataDir } from "@tauri-apps/api/path"
import { open } from "@tauri-apps/api/shell"
import { useState, useEffect } from "react"
import {
Expand All @@ -21,9 +22,12 @@ import events from "../mixpanel/mixpanel"

export const About: React.FC = () => {
const [appVersion, setAppVersion] = useState<string>()
const [pathToLogs, setPathToLogs] = useState<string>()

useEffect(() => {
getVersion().then((version) => setAppVersion(version))
events.open_about()
appDataDir().then((path) => setPathToLogs(path))
}, [])

return (
Expand Down Expand Up @@ -80,6 +84,12 @@ export const About: React.FC = () => {
C:\Users\Username\Documents\My Games\Company of Heroes
3\warnings.log
</Code>
<br />
<br />
You can also provide the logs from the COH3 Stats Desktop app which
are located here:
<br />
<Code>{pathToLogs}logs</Code>
</Text>
<Button onClick={() => open("https://ko-fi.com/cohstats")}>
<Group spacing="xs">
Expand Down
Loading

0 comments on commit 2510c23

Please sign in to comment.