use std::path::{Path, PathBuf}; use std::sync::Mutex; use crate::consts::*; static LAST_SETTING_ID: Mutex = Mutex::new(0); pub fn filename(id: u128, ext: &str) -> String { format!("{}.{}", id, ext) } pub fn setting_path_by_id(root: impl AsRef, id: u128, ext: &str) -> PathBuf { root.as_ref() .join(SETTING_FOLDER) .join(ID_FOLDER) .join(filename(id, ext)) } pub fn setting_folder_by_app_id(root: impl AsRef, steam_app_id: u32) -> PathBuf { root.as_ref() .join(SETTING_FOLDER) .join(APP_ID_FOLDER) .join(steam_app_id.to_string()) } pub fn setting_tag_folder_by_app_id(root: impl AsRef, steam_app_id: u32) -> PathBuf { root.as_ref() .join(SETTING_FOLDER) .join(APP_ID_FOLDER) .join(steam_app_id.to_string()) .join(TAG_FOLDER) } pub fn setting_folder_by_app_id_tag(root: impl AsRef, steam_app_id: u32, tag: &str) -> PathBuf { root.as_ref() .join(SETTING_FOLDER) .join(APP_ID_FOLDER) .join(steam_app_id.to_string()) .join(TAG_FOLDER) .join(tag) } pub fn setting_folder_by_user_id(root: impl AsRef, steam_user_id: u64) -> PathBuf { root.as_ref() .join(SETTING_FOLDER) .join(USER_ID_FOLDER) .join(steam_user_id.to_string()) } pub fn setting_tag_folder_by_user_id(root: impl AsRef, steam_user_id: u64) -> PathBuf { root.as_ref() .join(SETTING_FOLDER) .join(USER_ID_FOLDER) .join(steam_user_id.to_string()) .join(TAG_FOLDER) } pub fn setting_folder_by_user_id_tag(root: impl AsRef, steam_user_id: u64, tag: &str) -> PathBuf { root.as_ref() .join(SETTING_FOLDER) .join(USER_ID_FOLDER) .join(steam_user_id.to_string()) .join(TAG_FOLDER) .join(tag) } pub fn setting_folder_by_tag(root: impl AsRef, tag: &str) -> PathBuf { root.as_ref() .join(SETTING_FOLDER) .join(TAG_FOLDER) .join(tag) } pub fn next_setting_id(root: impl AsRef) -> u128 { let mut lock = LAST_SETTING_ID.lock().unwrap(); let mut last_id = *lock; if last_id == 0 { // needs init last_id = 1; let mut path = setting_path_by_id(root.as_ref(), last_id, RON_EXTENSION); while path.exists() { last_id += 1; path = setting_path_by_id(root.as_ref(), last_id, RON_EXTENSION); } *lock = last_id - 1; log::info!("setting id initialized to {}", last_id); } *lock += 1; *lock } pub struct ToSymlink { pub ron: Vec, pub json: Vec, } pub fn symlinks(root: impl AsRef, meta: &community_settings_core::v1::Metadata) -> std::io::Result { let mut symlink_locations = ToSymlink { ron: Vec::new(), json: Vec::new() }; let filename_ron = filename(meta.get_id(), crate::consts::RON_EXTENSION); let filename_json = filename(meta.get_id(), crate::consts::JSON_EXTENSION); // build symlinks to app id folder let app_id_folder = setting_folder_by_app_id(&root, meta.steam_app_id); log::debug!("App id folder {}", app_id_folder.display()); if !app_id_folder.exists() { std::fs::create_dir(&app_id_folder)?; std::fs::create_dir(setting_tag_folder_by_app_id(&root, meta.steam_app_id))?; } symlink_locations.ron.push(app_id_folder.join(&filename_ron)); symlink_locations.json.push(app_id_folder.join(&filename_json)); // create symlinks for user id folder let user_id_folder = setting_folder_by_user_id(&root, meta.steam_user_id); if !user_id_folder.exists() { std::fs::create_dir(&user_id_folder)?; std::fs::create_dir(setting_tag_folder_by_user_id(&root, meta.steam_user_id))?; } symlink_locations.ron.push(user_id_folder.join(&filename_ron)); symlink_locations.json.push(user_id_folder.join(&filename_json)); // create symlinks for each tag for tag in meta.tags.iter() { if !str_is_alphanumeric_or_space(&tag){ continue; } // create symlinks for general tag folder let tag_folder = setting_folder_by_tag(&root, tag); if !tag_folder.exists() { std::fs::create_dir(&tag_folder)?; } symlink_locations.ron.push(tag_folder.join(&filename_ron)); symlink_locations.json.push(tag_folder.join(&filename_json)); // create symlinks for app id tag folder let app_tag_folder = setting_folder_by_app_id_tag(&root, meta.steam_app_id, tag); if !app_tag_folder.exists() { std::fs::create_dir(&app_tag_folder)?; } symlink_locations.ron.push(app_tag_folder.join(&filename_ron)); symlink_locations.json.push(app_tag_folder.join(&filename_json)); // create symlinks for user id tag folder let user_tag_folder = setting_folder_by_user_id_tag(&root, meta.steam_user_id, tag); if !user_tag_folder.exists() { std::fs::create_dir(&user_tag_folder)?; } symlink_locations.ron.push(user_tag_folder.join(&filename_ron)); symlink_locations.json.push(user_tag_folder.join(&filename_json)); } Ok(symlink_locations) } fn str_is_alphanumeric_or_space(s: &str) -> bool { let mut result = true; for ch in s.chars() { result &= ch.is_ascii_alphanumeric() || ch == ' '; } result }