From 51d00add2287210d82a6b12efdbdefc7fedd447e Mon Sep 17 00:00:00 2001 From: Brian Bowman Date: Mon, 11 Jul 2022 04:06:05 -0500 Subject: [PATCH 1/8] Set up CI for backend --- .github/workflows/backend-checks.yml | 51 ++++++++++++++++++++++++++++ src-tauri/src/file_helpers.rs | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/backend-checks.yml diff --git a/.github/workflows/backend-checks.yml b/.github/workflows/backend-checks.yml new file mode 100644 index 0000000..f0d6d46 --- /dev/null +++ b/.github/workflows/backend-checks.yml @@ -0,0 +1,51 @@ +name: Check backend + +on: + push: + paths: + - ".github/workflows/backend-checks.yml" + - "src-tauri/**" + pull_request: + paths: + - ".github/workflows/backend-checks.yml" + - "src-tauri/**" + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + clippy: + runs-on: ${{ matrix.platform }} + + strategy: + fail-fast: false + matrix: + platform: [windows-latest, ubuntu-latest, macos-latest] + + steps: + - uses: actions/checkout@v3 + + - name: Install Linux dependencies + if: matrix.platform == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y libwebkit2gtk-4.0-dev \ + build-essential \ + curl \ + wget \ + libssl-dev \ + libgtk-3-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev + + - uses: Swatinem/rust-cache@v1 + with: + working-directory: src-tauri + + - uses: actions-rs/clippy-check@v1 + with: + name: clippy (${{ runner.os }}) + token: ${{ secrets.GITHUB_TOKEN }} + args: --manifest-path ./src-tauri/Cargo.toml --no-default-features -- -D warnings + diff --git a/src-tauri/src/file_helpers.rs b/src-tauri/src/file_helpers.rs index d27f354..c63cda4 100644 --- a/src-tauri/src/file_helpers.rs +++ b/src-tauri/src/file_helpers.rs @@ -36,7 +36,7 @@ pub fn dir_delete(path: &str) { #[tauri::command] pub fn copy_file(path: String, new_path: String) -> bool { - let filename = &path.split("/").last().unwrap(); + let filename = &path.split('/').last().unwrap(); let mut new_path_buf = std::path::PathBuf::from(&new_path); // If the new path doesn't exist, create it. From 53e2b0cbed01d636003d7960fe2fee39d52d2ab1 Mon Sep 17 00:00:00 2001 From: Brian Bowman Date: Mon, 11 Jul 2022 01:17:59 -0500 Subject: [PATCH 2/8] Fix tsc and ESLint warnings --- .eslintrc.json | 21 +++++++ src/ui/App.tsx | 2 +- src/ui/Debug.tsx | 2 +- src/ui/components/ServerLaunchSection.tsx | 8 +-- src/ui/components/TopBar.tsx | 1 - src/ui/components/common/BigButton.tsx | 4 +- src/ui/components/common/TextInput.tsx | 4 +- src/ui/components/menu/Downloads.tsx | 4 +- src/ui/components/news/NewsSection.tsx | 71 +++++++++++++++-------- src/utils/configuration.ts | 10 ++-- 10 files changed, 82 insertions(+), 45 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 638c08f..a683c1e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -33,6 +33,27 @@ "semi": [ "error", "never" + ], + "@typescript-eslint/ban-types": [ + "warn", + { + "extendDefaults": true, + "types": { + "{}": false + } + } + ], + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_" + } ] + }, + "settings": { + "react": { + "version": "detect" + } } } diff --git a/src/ui/App.tsx b/src/ui/App.tsx index 92277a4..49e87ef 100644 --- a/src/ui/App.tsx +++ b/src/ui/App.tsx @@ -56,7 +56,7 @@ class App extends React.Component { console.log(payload) }) - listen('jar_extracted', ({ payload }) => { + listen('jar_extracted', ({ payload }: { payload: string}) => { setConfigOption('grasscutter_path', payload) }) diff --git a/src/ui/Debug.tsx b/src/ui/Debug.tsx index e70c7df..4846541 100644 --- a/src/ui/Debug.tsx +++ b/src/ui/Debug.tsx @@ -40,7 +40,7 @@ function none() { alert('none') } -class Debug extends React.Component{ +class Debug extends React.Component{ render() { return (
diff --git a/src/ui/components/ServerLaunchSection.tsx b/src/ui/components/ServerLaunchSection.tsx index 3644310..1cf5495 100644 --- a/src/ui/components/ServerLaunchSection.tsx +++ b/src/ui/components/ServerLaunchSection.tsx @@ -11,10 +11,6 @@ import Server from '../../resources/icons/server.svg' import './ServerLaunchSection.css' import {dataDir} from '@tauri-apps/api/path' -interface IProps { - [key: string]: any -} - interface IState { grasscutterEnabled: boolean; buttonLabel: string; @@ -31,8 +27,8 @@ interface IState { httpsEnabled: boolean; } -export default class ServerLaunchSection extends React.Component { - constructor(props: IProps) { +export default class ServerLaunchSection extends React.Component<{}, IState> { + constructor(props: {}) { super(props) this.state = { diff --git a/src/ui/components/TopBar.tsx b/src/ui/components/TopBar.tsx index f1fac63..aeb6ae6 100644 --- a/src/ui/components/TopBar.tsx +++ b/src/ui/components/TopBar.tsx @@ -5,7 +5,6 @@ import closeIcon from '../../resources/icons/close.svg' import minIcon from '../../resources/icons/min.svg' import cogBtn from '../../resources/icons/cog.svg' import downBtn from '../../resources/icons/download.svg' -import gameBtn from '../../resources/icons/game.svg' import Tr from '../../utils/language' diff --git a/src/ui/components/common/BigButton.tsx b/src/ui/components/common/BigButton.tsx index 997e773..5b6cbe7 100644 --- a/src/ui/components/common/BigButton.tsx +++ b/src/ui/components/common/BigButton.tsx @@ -3,7 +3,7 @@ import './BigButton.css' interface IProps { children: React.ReactNode; - onClick: () => any; + onClick: () => unknown; id: string; disabled?: boolean; } @@ -23,7 +23,7 @@ export default class BigButton extends React.Component { this.handleClick = this.handleClick.bind(this) } - static getDerivedStateFromProps(props: IProps, state: IState) { + static getDerivedStateFromProps(props: IProps, _state: IState) { return { disabled: props.disabled } diff --git a/src/ui/components/common/TextInput.tsx b/src/ui/components/common/TextInput.tsx index e2009ea..1efac23 100644 --- a/src/ui/components/common/TextInput.tsx +++ b/src/ui/components/common/TextInput.tsx @@ -12,9 +12,7 @@ interface IProps { id?: string; clearable?: boolean; customClearBehaviour?: () => void; - style?: { - [key: string]: any; - } + style?: React.CSSProperties; } interface IState { diff --git a/src/ui/components/menu/Downloads.tsx b/src/ui/components/menu/Downloads.tsx index 0368a46..59d484e 100644 --- a/src/ui/components/menu/Downloads.tsx +++ b/src/ui/components/menu/Downloads.tsx @@ -8,7 +8,7 @@ import { dataDir } from '@tauri-apps/api/path' import './Downloads.css' import Divider from './Divider' -import { getConfigOption, setConfigOption } from '../../../utils/configuration' +import { getConfigOption } from '../../../utils/configuration' import { invoke } from '@tauri-apps/api' import { listen } from '@tauri-apps/api/event' import HelpButton from '../common/HelpButton' @@ -183,7 +183,7 @@ export default class Downloads extends React.Component { grasscutter_downloading: this.props.downloadManager.downloadingJar(), resources_downloading: this.props.downloadManager.downloadingResources(), repo_downloading: this.props.downloadManager.downloadingRepo(), - grasscutter_set: gc_path && gc_path !== '', + grasscutter_set: gc_path !== '', }) } diff --git a/src/ui/components/news/NewsSection.tsx b/src/ui/components/news/NewsSection.tsx index 3b4638b..861b8c1 100644 --- a/src/ui/components/news/NewsSection.tsx +++ b/src/ui/components/news/NewsSection.tsx @@ -11,8 +11,28 @@ interface IProps { interface IState { selected: string; - news: any; - commitList: any; + news?: JSX.Element; + commitList?: JSX.Element[]; +} + +interface GrasscutterAPIResponse { + commits: { + gc_stable: CommitResponse[]; + gc_dev: CommitResponse[]; + cultivation: CommitResponse[]; + } +} + +interface CommitResponse { + sha: string; + commit: Commit; +} + +interface Commit { + author: { + name: string; + }; + message: string; } export default class NewsSection extends React.Component { @@ -21,8 +41,6 @@ export default class NewsSection extends React.Component { this.state = { selected: props.selected || 'commits', - news: null, - commitList: null } this.setSelected = this.setSelected.bind(this) @@ -42,40 +60,41 @@ export default class NewsSection extends React.Component { async showLatestCommits() { if (!this.state.commitList) { - const commits: string = await invoke('req_get', { url: 'https://api.grasscutter.io/cultivation/query' }) - let obj + const response: string = await invoke('req_get', { url: 'https://api.grasscutter.io/cultivation/query' }) + let grasscutterApiResponse: GrasscutterAPIResponse | null = null try { - obj = JSON.parse(commits) + grasscutterApiResponse = JSON.parse(response) } catch(e) { - obj = {} + grasscutterApiResponse = null } - // If it didn't work, use official API - if (!obj.commits) { - const commits: string = await invoke('req_get', { url: 'https://api.github.com/repos/Grasscutters/Grasscutter/commits' }) - obj = JSON.parse(commits) + let commits: CommitResponse[] + if (grasscutterApiResponse?.commits == null) { + // If it didn't work, use official API + const response: string = await invoke('req_get', { url: 'https://api.github.com/repos/Grasscutters/Grasscutter/commits' }) + commits = JSON.parse(response) } else { - obj = obj.commits.gc_stable + commits = grasscutterApiResponse.commits.gc_stable } // Probably rate-limited - if (!Array.isArray(obj)) return + if (!Array.isArray(commits)) return // Get only first 5 - const commitsList = obj.slice(0, 10) - const commitsListHtml = commitsList.map((commit: any) => { + const commitsList = commits.slice(0, 10) + const commitsListHtml = commitsList.map((commitResponse: CommitResponse) => { return ( - - {commit.commit.author.name} - {commit.commit.message} + + {commitResponse.commit.author.name} + {commitResponse.commit.message} ) }) this.setState({ commitList: commitsListHtml, - news: commitsListHtml + news: <>{commitsListHtml} }) } @@ -83,12 +102,16 @@ export default class NewsSection extends React.Component { } async showNews() { - let news = + let news: JSX.Element | JSX.Element[] = switch(this.state.selected) { - case 'commits': - news = await this.showLatestCommits() + case 'commits': { + const commits = await this.showLatestCommits() + if (commits != null) { + news = commits + } break + } case 'latest_version': news = Latest version @@ -100,7 +123,7 @@ export default class NewsSection extends React.Component { } this.setState({ - news + news: <>{news} }) } diff --git a/src/utils/configuration.ts b/src/utils/configuration.ts index 5ce8863..65aa91e 100644 --- a/src/utils/configuration.ts +++ b/src/utils/configuration.ts @@ -45,16 +45,16 @@ export interface Configuration { debug_enabled: boolean } -export async function setConfigOption(key: string, value: any): Promise { - const config: any = await getConfig() +export async function setConfigOption(key: K, value: Configuration[K]): Promise { + const config = await getConfig() config[key] = value await saveConfig( config) } -export async function getConfigOption(key: string): Promise { - const config: any = await getConfig() - const defaults: any = defaultConfig +export async function getConfigOption(key: K): Promise { + const config = await getConfig() + const defaults = defaultConfig return config[key] || defaults[key] } From 4d05063b6197a65f1af9496cff25de13eb955c16 Mon Sep 17 00:00:00 2001 From: Brian Bowman Date: Mon, 11 Jul 2022 01:18:09 -0500 Subject: [PATCH 3/8] Set up CI for frontend --- .github/workflows/frontend-checks.yml | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/frontend-checks.yml diff --git a/.github/workflows/frontend-checks.yml b/.github/workflows/frontend-checks.yml new file mode 100644 index 0000000..4535d49 --- /dev/null +++ b/.github/workflows/frontend-checks.yml @@ -0,0 +1,37 @@ +name: Check frontend + +on: + push: + paths: + - ".github/workflows/frontend-checks.yml" + - "src/**" + - ".eslintrc.json" + - "package.json" + - "tsconfig.json" + - "yarn.lock" + pull_request: + paths: + - ".github/workflows/frontend-checks.yml" + - "src/**" + - ".eslintrc.json" + - "package.json" + - "tsconfig.json" + - "yarn.lock" + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + tsc-eslint-checks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install modules + run: yarn + - name: Run tsc + run: yarn tsc --noEmit + - name: Run ESLint + run: yarn eslint src + From e41a89b26cd0ff7a7e606959546a84d7e944b8c3 Mon Sep 17 00:00:00 2001 From: Brian Bowman Date: Mon, 11 Jul 2022 04:40:28 -0500 Subject: [PATCH 4/8] Configure and run rustfmt --- .editorconfig | 2 + src-tauri/rustfmt.toml | 3 + src-tauri/src/downloader.rs | 45 +++---------- src-tauri/src/lang.rs | 13 ++-- src-tauri/src/main.rs | 18 ++--- src-tauri/src/proxy.rs | 112 +++++++++++++++++++++++--------- src-tauri/src/structs.rs | 2 +- src-tauri/src/system_helpers.rs | 9 +-- src-tauri/src/unzip.rs | 21 +++--- src-tauri/src/web.rs | 16 ++++- 10 files changed, 139 insertions(+), 102 deletions(-) create mode 100644 src-tauri/rustfmt.toml diff --git a/.editorconfig b/.editorconfig index 2acebee..813f40d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,6 +13,8 @@ trim_trailing_whitespace = false [*.rs] max_line_length = 100 indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true [{*.ats,*.cts,*.mts,*.ts}] indent_size = 2 diff --git a/src-tauri/rustfmt.toml b/src-tauri/rustfmt.toml new file mode 100644 index 0000000..2f9c1b2 --- /dev/null +++ b/src-tauri/rustfmt.toml @@ -0,0 +1,3 @@ +tab_spaces = 2 +use_field_init_shorthand = true +use_try_shorthand = true diff --git a/src-tauri/src/downloader.rs b/src-tauri/src/downloader.rs index 1b567ce..ebf6301 100644 --- a/src-tauri/src/downloader.rs +++ b/src-tauri/src/downloader.rs @@ -1,9 +1,9 @@ use once_cell::sync::Lazy; -use std::sync::Mutex; use std::cmp::min; use std::fs::File; use std::io::Write; +use std::sync::Mutex; use futures_util::StreamExt; @@ -15,17 +15,14 @@ static DOWNLOADS: Lazy>> = Lazy::new(|| Mutex::new(Vec::new()) #[tauri::command] pub async fn download_file(window: tauri::Window, url: &str, path: &str) -> Result<(), String> { // Reqwest setup - let res = match reqwest::get(url) - .await { + let res = match reqwest::get(url).await { Ok(r) => r, Err(_e) => { emit_download_err(window, format!("Failed to request {}", url), path); return Err(format!("Failed to request {}", url)); } }; - let total_size = res - .content_length() - .unwrap_or(0); + let total_size = res.content_length().unwrap_or(0); // Create file path let mut file = match File::create(path) { @@ -77,25 +74,10 @@ pub async fn download_file(window: tauri::Window, url: &str, path: &str) -> Resu let mut res_hash = std::collections::HashMap::new(); - res_hash.insert( - "downloaded".to_string(), - downloaded.to_string(), - ); - - res_hash.insert( - "total".to_string(), - total_size.to_string(), - ); - - res_hash.insert( - "path".to_string(), - path.to_string(), - ); - - res_hash.insert( - "total_downloaded".to_string(), - total_downloaded.to_string(), - ); + res_hash.insert("downloaded".to_string(), downloaded.to_string()); + res_hash.insert("total".to_string(), total_size.to_string()); + res_hash.insert("path".to_string(), path.to_string()); + res_hash.insert("total_downloaded".to_string(), total_downloaded.to_string()); // Create event to send to frontend window.emit("download_progress", &res_hash).unwrap(); @@ -111,15 +93,8 @@ pub async fn download_file(window: tauri::Window, url: &str, path: &str) -> Resu pub fn emit_download_err(window: tauri::Window, msg: String, path: &str) { let mut res_hash = std::collections::HashMap::new(); - res_hash.insert( - "error".to_string(), - msg, - ); - - res_hash.insert( - "path".to_string(), - path.to_string(), - ); + res_hash.insert("error".to_string(), msg); + res_hash.insert("path".to_string(), path.to_string()); window.emit("download_error", &res_hash).unwrap(); } @@ -139,4 +114,4 @@ pub fn stop_download(path: String) { if let Err(_e) = std::fs::remove_file(&path) { // Do nothing } -} \ No newline at end of file +} diff --git a/src-tauri/src/lang.rs b/src-tauri/src/lang.rs index e797996..2ec452f 100644 --- a/src-tauri/src/lang.rs +++ b/src-tauri/src/lang.rs @@ -1,12 +1,14 @@ -use std::path::{Path, PathBuf}; use crate::system_helpers::*; +use std::path::{Path, PathBuf}; #[tauri::command] pub async fn get_lang(window: tauri::Window, lang: String) -> String { let lang = lang.to_lowercase(); // Send contents of language file back - let lang_path: PathBuf = [&install_location(), "lang", &format!("{}.json", lang)].iter().collect(); + let lang_path: PathBuf = [&install_location(), "lang", &format!("{}.json", lang)] + .iter() + .collect(); match std::fs::read_to_string(&lang_path) { Ok(x) => x, Err(e) => { @@ -45,10 +47,7 @@ pub async fn get_languages() -> std::collections::HashMap { pub fn emit_lang_err(window: tauri::Window, msg: String) { let mut res_hash = std::collections::HashMap::new(); - res_hash.insert( - "error".to_string(), - msg, - ); + res_hash.insert("error".to_string(), msg); window.emit("lang_error", &res_hash).unwrap(); -} \ No newline at end of file +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 3bbf69a..525558d 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,22 +1,22 @@ #![cfg_attr( -all(not(debug_assertions), target_os = "windows"), -windows_subsystem = "windows" + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" )] use once_cell::sync::Lazy; -use std::{sync::Mutex, collections::HashMap}; +use std::{collections::HashMap, sync::Mutex}; use std::thread; +use structs::APIQuery; use sysinfo::{System, SystemExt}; -use structs::{APIQuery}; -mod structs; -mod system_helpers; -mod file_helpers; -mod unzip; mod downloader; +mod file_helpers; mod lang; mod proxy; +mod structs; +mod system_helpers; +mod unzip; mod web; static WATCH_GAME_PROCESS: Lazy> = Lazy::new(|| Mutex::new(String::new())); @@ -155,7 +155,7 @@ async fn get_theme_list(data_dir: String) -> Vec> { map.insert("json".to_string(), theme_json); map.insert("path".to_string(), path.to_str().unwrap().to_string()); - + // Push key-value pair containing "json" and "path" themes.push(map); } diff --git a/src-tauri/src/proxy.rs b/src-tauri/src/proxy.rs index 415bc43..ec29d69 100644 --- a/src-tauri/src/proxy.rs +++ b/src-tauri/src/proxy.rs @@ -4,15 +4,15 @@ */ use once_cell::sync::Lazy; -use std::{sync::Mutex, str::FromStr}; +use std::{str::FromStr, sync::Mutex}; -use rcgen::*; use hudsucker::{ async_trait::async_trait, certificate_authority::RcgenAuthority, hyper::{Body, Request, Response}, *, }; +use rcgen::*; use std::fs; use std::net::SocketAddr; @@ -22,10 +22,11 @@ use rustls_pemfile as pemfile; use tauri::http::Uri; #[cfg(windows)] -use registry::{Hive, Data, Security}; +use registry::{Data, Hive, Security}; async fn shutdown_signal() { - tokio::signal::ctrl_c().await + tokio::signal::ctrl_c() + .await .expect("Failed to install CTRL+C signal handler"); } @@ -42,16 +43,18 @@ pub fn set_proxy_addr(addr: String) { #[async_trait] impl HttpHandler for ProxyHandler { - async fn handle_request(&mut self, - _context: &HttpContext, - mut request: Request, + async fn handle_request( + &mut self, + _context: &HttpContext, + mut request: Request, ) -> RequestOrResponse { let uri = request.uri().to_string(); let uri_path = request.uri().path(); - + if uri.contains("hoyoverse.com") || uri.contains("mihoyo.com") || uri.contains("yuanshen.com") { // Create new URI. - let new_uri = Uri::from_str(format!("{}{}", SERVER.lock().unwrap(), uri_path).as_str()).unwrap(); + let new_uri = + Uri::from_str(format!("{}{}", SERVER.lock().unwrap(), uri_path).as_str()).unwrap(); // Set request URI to the new one. *request.uri_mut() = new_uri; } @@ -59,10 +62,13 @@ impl HttpHandler for ProxyHandler { RequestOrResponse::Request(request) } - async fn handle_response(&mut self, - _context: &HttpContext, - response: Response, - ) -> Response { response } + async fn handle_response( + &mut self, + _context: &HttpContext, + response: Response, + ) -> Response { + response + } } /** @@ -70,20 +76,22 @@ impl HttpHandler for ProxyHandler { */ pub async fn create_proxy(proxy_port: u16, certificate_path: String) { // Get the certificate and private key. - let mut private_key_bytes: &[u8] = &fs::read(format!("{}\\private.key", certificate_path)).expect("Could not read private key"); - let mut ca_cert_bytes: &[u8] = &fs::read(format!("{}\\cert.crt", certificate_path)).expect("Could not read certificate"); + let mut private_key_bytes: &[u8] = + &fs::read(format!("{}\\private.key", certificate_path)).expect("Could not read private key"); + let mut ca_cert_bytes: &[u8] = + &fs::read(format!("{}\\cert.crt", certificate_path)).expect("Could not read certificate"); // Parse the private key and certificate. let private_key = rustls::PrivateKey( pemfile::pkcs8_private_keys(&mut private_key_bytes) .expect("Failed to parse private key") - .remove(0) + .remove(0), ); let ca_cert = rustls::Certificate( pemfile::certs(&mut ca_cert_bytes) .expect("Failed to parse CA certificate") - .remove(0) + .remove(0), ); // Create the certificate authority. @@ -108,13 +116,23 @@ pub async fn create_proxy(proxy_port: u16, certificate_path: String) { #[cfg(windows)] pub fn connect_to_proxy(proxy_port: u16) { // Create 'ProxyServer' string. - let server_string: String = format!("http=127.0.0.1:{};https=127.0.0.1:{}", proxy_port, proxy_port); + let server_string: String = format!( + "http=127.0.0.1:{};https=127.0.0.1:{}", + proxy_port, proxy_port + ); // Fetch the 'Internet Settings' registry key. - let settings = Hive::CurrentUser.open(r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", Security::Write).unwrap(); + let settings = Hive::CurrentUser + .open( + r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", + Security::Write, + ) + .unwrap(); // Set registry values. - settings.set_value("ProxyServer", &Data::String(server_string.parse().unwrap())).unwrap(); + settings + .set_value("ProxyServer", &Data::String(server_string.parse().unwrap())) + .unwrap(); settings.set_value("ProxyEnable", &Data::U32(1)).unwrap(); println!("Connected to the proxy."); @@ -131,7 +149,12 @@ pub fn connect_to_proxy(_proxy_port: u16) { #[cfg(windows)] pub fn disconnect_from_proxy() { // Fetch the 'Internet Settings' registry key. - let settings = Hive::CurrentUser.open(r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", Security::Write).unwrap(); + let settings = Hive::CurrentUser + .open( + r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", + Security::Write, + ) + .unwrap(); // Set registry values. settings.set_value("ProxyEnable", &Data::U32(0)).unwrap(); @@ -157,7 +180,7 @@ pub fn generate_ca_files(path: &Path) { details.push(DnType::OrganizationName, "Grasscutters"); details.push(DnType::CountryName, "CN"); details.push(DnType::LocalityName, "CN"); - + // Set details in the parameter. params.distinguished_name = details; // Set other properties. @@ -165,9 +188,9 @@ pub fn generate_ca_files(path: &Path) { params.key_usages = vec![ KeyUsagePurpose::DigitalSignature, KeyUsagePurpose::KeyCertSign, - KeyUsagePurpose::CrlSign + KeyUsagePurpose::CrlSign, ]; - + // Create certificate. let cert = Certificate::from_params(params).unwrap(); let cert_crt = cert.serialize_pem().unwrap(); @@ -176,26 +199,37 @@ pub fn generate_ca_files(path: &Path) { // Make certificate directory. let cert_dir = path.join("ca"); match fs::create_dir(&cert_dir) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { println!("{}", e); } }; - + // Write the certificate to a file. let cert_path = cert_dir.join("cert.crt"); match fs::write(&cert_path, cert_crt) { Ok(_) => println!("Wrote certificate to {}", cert_path.to_str().unwrap()), - Err(e) => println!("Error writing certificate to {}: {}", cert_path.to_str().unwrap(), e), + Err(e) => println!( + "Error writing certificate to {}: {}", + cert_path.to_str().unwrap(), + e + ), } // Write the private key to a file. let private_key_path = cert_dir.join("private.key"); match fs::write(&private_key_path, private_key) { - Ok(_) => println!("Wrote private key to {}", private_key_path.to_str().unwrap()), - Err(e) => println!("Error writing private key to {}: {}", private_key_path.to_str().unwrap(), e), + Ok(_) => println!( + "Wrote private key to {}", + private_key_path.to_str().unwrap() + ), + Err(e) => println!( + "Error writing private key to {}: {}", + private_key_path.to_str().unwrap(), + e + ), } - + // Install certificate into the system's Root CA store. install_ca_files(&cert_path); } @@ -205,13 +239,27 @@ pub fn generate_ca_files(path: &Path) { */ #[cfg(windows)] pub fn install_ca_files(cert_path: &Path) { - crate::system_helpers::run_command("certutil", vec!["-user", "-addstore", "Root", cert_path.to_str().unwrap()]); + crate::system_helpers::run_command( + "certutil", + vec!["-user", "-addstore", "Root", cert_path.to_str().unwrap()], + ); println!("Installed certificate."); } #[cfg(target_os = "macos")] pub fn install_ca_files(cert_path: &Path) { - crate::system_helpers::run_command("security", vec!["add-trusted-cert", "-d", "-r", "trustRoot", "-k", "/Library/Keychains/System.keychain", cert_path.to_str().unwrap()]); + crate::system_helpers::run_command( + "security", + vec![ + "add-trusted-cert", + "-d", + "-r", + "trustRoot", + "-k", + "/Library/Keychains/System.keychain", + cert_path.to_str().unwrap(), + ], + ); println!("Installed certificate."); } diff --git a/src-tauri/src/structs.rs b/src-tauri/src/structs.rs index e2d0710..406083e 100644 --- a/src-tauri/src/structs.rs +++ b/src-tauri/src/structs.rs @@ -5,4 +5,4 @@ use serde::Deserialize; #[derive(Deserialize)] pub(crate) struct APIQuery { pub bg_file: String, -} \ No newline at end of file +} diff --git a/src-tauri/src/system_helpers.rs b/src-tauri/src/system_helpers.rs index 2eb3f39..2cb49bc 100644 --- a/src-tauri/src/system_helpers.rs +++ b/src-tauri/src/system_helpers.rs @@ -10,8 +10,7 @@ pub fn run_program(path: String) { #[tauri::command] pub fn run_command(program: &str, args: Vec<&str>) { - cmd(program, args).run() - .expect("Failed to run command"); + cmd(program, args).run().expect("Failed to run command"); } #[tauri::command] @@ -23,7 +22,10 @@ pub fn run_jar(path: String, execute_in: String, java_path: String) { }; // Open the program from the specified path. - match open::with(format!("/k cd /D \"{}\" & {}", &execute_in, &command), "C:\\Windows\\System32\\cmd.exe") { + match open::with( + format!("/k cd /D \"{}\" & {}", &execute_in, &command), + "C:\\Windows\\System32\\cmd.exe", + ) { Ok(_) => (), Err(e) => println!("Failed to open jar ({} from {}): {}", &path, &execute_in, e), }; @@ -38,7 +40,6 @@ pub fn open_in_browser(url: String) { }; } - #[tauri::command] pub fn install_location() -> String { let mut exe_path = std::env::current_exe().unwrap(); diff --git a/src-tauri/src/unzip.rs b/src-tauri/src/unzip.rs index dcfe084..310b7c4 100644 --- a/src-tauri/src/unzip.rs +++ b/src-tauri/src/unzip.rs @@ -23,21 +23,18 @@ pub fn unzip(window: tauri::Window, zipfile: String, destpath: String) { match zip_extract::extract(&f, &full_path, true) { Ok(_) => { - println!("Extracted zip file to: {}", full_path.to_str().unwrap_or("Error")); + println!( + "Extracted zip file to: {}", + full_path.to_str().unwrap_or("Error") + ); } Err(e) => { println!("Failed to extract zip file: {}", e); let mut res_hash = std::collections::HashMap::new(); - res_hash.insert( - "error".to_string(), - e.to_string(), - ); + res_hash.insert("error".to_string(), e.to_string()); - res_hash.insert( - "path".to_string(), - zipfile.to_string(), - ); + res_hash.insert("path".to_string(), zipfile.to_string()); window.emit("download_error", &res_hash).unwrap(); } @@ -50,7 +47,9 @@ pub fn unzip(window: tauri::Window, zipfile: String, destpath: String) { // If the contents is a jar file, emit that we have extracted a new jar file if name.ends_with(".jar") { - window.emit("jar_extracted", destpath.to_string() + name).unwrap(); + window + .emit("jar_extracted", destpath.to_string() + name) + .unwrap(); } // Delete zip file @@ -65,4 +64,4 @@ pub fn unzip(window: tauri::Window, zipfile: String, destpath: String) { window.emit("extract_end", &zipfile).unwrap(); }); -} \ No newline at end of file +} diff --git a/src-tauri/src/web.rs b/src-tauri/src/web.rs index af5864d..9650124 100644 --- a/src-tauri/src/web.rs +++ b/src-tauri/src/web.rs @@ -3,7 +3,12 @@ use reqwest::header::USER_AGENT; pub(crate) async fn query(site: &str) -> String { let client = reqwest::Client::new(); - let response = client.get(site).header(USER_AGENT, "cultivation").send().await.unwrap(); + let response = client + .get(site) + .header(USER_AGENT, "cultivation") + .send() + .await + .unwrap(); response.text().await.unwrap() } @@ -12,7 +17,12 @@ pub(crate) async fn valid_url(url: String) -> bool { // Check if we get a 200 response let client = reqwest::Client::new(); - let response = client.get(url).header(USER_AGENT, "cultivation").send().await.unwrap(); + let response = client + .get(url) + .header(USER_AGENT, "cultivation") + .send() + .await + .unwrap(); response.status().as_str() == "200" -} \ No newline at end of file +} From cd5c2985e5d68586b76c30adac7a7dbfb7ce8e8d Mon Sep 17 00:00:00 2001 From: Brian Bowman Date: Mon, 11 Jul 2022 04:42:03 -0500 Subject: [PATCH 5/8] Add rustfmt CI check --- .github/workflows/backend-checks.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/backend-checks.yml b/.github/workflows/backend-checks.yml index f0d6d46..a66b210 100644 --- a/.github/workflows/backend-checks.yml +++ b/.github/workflows/backend-checks.yml @@ -15,6 +15,17 @@ concurrency: cancel-in-progress: true jobs: + rustfmt: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: actions-rs/cargo@v1 + with: + command: fmt + args: --manifest-path ./src-tauri/Cargo.toml --all -- --check + clippy: runs-on: ${{ matrix.platform }} From 58e683c669e5d1c63c3690dbd9c85bf0feee1721 Mon Sep 17 00:00:00 2001 From: Brian Bowman Date: Mon, 11 Jul 2022 18:50:51 -0500 Subject: [PATCH 6/8] Add format and lint scripts --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index cc5729e..897563a 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,9 @@ "test": "react-scripts test", "eject": "react-scripts eject", "tauri": "tauri", - "start:dev": "tauri dev" + "start:dev": "tauri dev", + "format": "cargo fmt --manifest-path ./src-tauri/Cargo.toml --all", + "lint": "cargo clippy --manifest-path ./src-tauri/Cargo.toml --no-default-features && yarn tsc --noEmit && yarn eslint src" }, "eslintConfig": { "extends": [ From be633eeea55eaee64c1f024527ba431a50b17514 Mon Sep 17 00:00:00 2001 From: Brian Bowman Date: Tue, 12 Jul 2022 23:19:59 -0500 Subject: [PATCH 7/8] Document how to run formatting and linting scripts --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index da10500..c9e9cda 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,10 @@ Once downloaded, extract somewhere and open as administrator. Add `--release` or `--debug` depending on what release you are creating. This defaults to `--release` +### Code Formatting and Linting + +Format the code with `yarn format`. Run the lints with `yarn lint`. + ### Updating * Add the `TAURI_PRIVATE_KEY` as an environment variable with a path to your private key. * Add the `TAURI_KEY_PASSWORD` as an environment variable with the password for your private key. From 5bf70194824cc01062529cf206a7e28a95f422c4 Mon Sep 17 00:00:00 2001 From: Brian Bowman Date: Tue, 12 Jul 2022 23:30:43 -0500 Subject: [PATCH 8/8] Also list npm command for running formatting and linting scripts --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c9e9cda..b8d3af6 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Add `--release` or `--debug` depending on what release you are creating. This de ### Code Formatting and Linting -Format the code with `yarn format`. Run the lints with `yarn lint`. +Format the code with `npm format` or `yarn format`. Run the lints with `npm lint` or `yarn lint`. ### Updating * Add the `TAURI_PRIVATE_KEY` as an environment variable with a path to your private key.