diff --git a/README.md b/README.md index b311eb3..a9c763c 100644 --- a/README.md +++ b/README.md @@ -144,9 +144,24 @@ example: additional_sync_args=--onedrive-av-override ``` +### Custom sync root + +By default the sync root is `/` for simplicity. If having it causes issues, you can change it to another place and create symlinks. Set `plugin.properties` value `sync_root` to be whatever you wish (e.g. `/home/deck/`). **IMPORTANT: This path must be absolute, and must end with a trailing `/`** + +Example, where 2 symlinks are created: + +```bash +cd /home/deck/syncs +ln -s /run/media/mmcblk0p1/Emulation/saves/ "$(pwd)/emulation-saves" +ln -s "/home/deck/homebrew/settings/decky-cloud-save/" "$(pwd)/dcs-config" +``` + +In `plugin.properties`, when root is set to `/home/deck`, we can sync the folder `syncs`, and it would show up as `emulation-saves`, and `dcs-config` on the configured cloud provider. + ## Acknowledgments Thank you to: * [Emiliopg91](https://github.com/Emiliopg91), [NL-TCH](https://github.com/NL-TCH) for bi-sync support! +* [AkazaRenn](https://github.com/AkazaRenn), for various support! * [Decky Homebrew Community](https://github.com/SteamDeckHomebrew) for assistance with development! * [rclone](https://rclone.org/) for making this plugin possible! diff --git a/package.json b/package.json index 936f662..b2966f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "decky-cloud-save", - "version": "1.4.1", + "version": "1.4.2", "description": "Manage cloud saves for games that do not support it in [current year].", "scripts": { "build": "shx rm -rf dist && rollup -c", diff --git a/py_modules/plugin_config.py b/py_modules/plugin_config.py index dc2f2a2..579107e 100644 --- a/py_modules/plugin_config.py +++ b/py_modules/plugin_config.py @@ -110,3 +110,5 @@ def migrate(): set_config("toast_auto_sync", "true") if not any(e[0] == "additional_sync_args" for e in config): set_config("additional_sync_args", "") + if not any(e[0] == "sync_root" for e in config): + set_config("sync_root", "/") diff --git a/py_modules/rclone_setup_manager.py b/py_modules/rclone_setup_manager.py index 2d22b87..7eb0f10 100644 --- a/py_modules/rclone_setup_manager.py +++ b/py_modules/rclone_setup_manager.py @@ -124,6 +124,9 @@ async def test_syncpath(self, path: str): Returns: int | str: The number of files if it's a directory, '9000+' if it exceeds the limit, or 0 if it's a file. """ + if not path.startswith(plugin_config.get_config_item("sync_root", "/")): + raise Exception("Selection is outside of sync root.") + if path.endswith("/**"): scan_single_dir = False path = path[:-3] @@ -154,6 +157,9 @@ async def add_syncpath(self, path: str, file: str): """ decky_plugin.logger.info("Adding Path to Sync: '%s', %s", path, file) + # Replace the beginning of path to replace the root. + path = path.replace(plugin_config.get_config_item("sync_root", "/"), "/", 1) + file = plugin_config.cfg_syncpath_excludes_file if file == "excludes" else plugin_config.cfg_syncpath_includes_file with open(file, "r") as f: diff --git a/py_modules/rclone_sync_manager.py b/py_modules/rclone_sync_manager.py index 5899af2..5de02f5 100644 --- a/py_modules/rclone_sync_manager.py +++ b/py_modules/rclone_sync_manager.py @@ -32,6 +32,7 @@ async def sync_now(self, winner: str, resync: bool): bisync_enabled = plugin_config.get_config_item("bisync_enabled", "false") == "true" destination_path = plugin_config.get_config_item("destination_directory", "decky-cloud-save") + sync_root = plugin_config.get_config_item("sync_root", "/") additional_args = [x for x in plugin_config.get_config_item("additional_sync_args", "").split(' ') if x] @@ -42,7 +43,7 @@ async def sync_now(self, winner: str, resync: bool): args.extend(["copy"]) decky_plugin.logger.debug("Using copy") - args.extend(["/", f"backend:{destination_path}", "--filter-from", + args.extend([sync_root, f"backend:{destination_path}", "--filter-from", plugin_config.cfg_syncpath_filter_file, "--copy-links"]) if bisync_enabled: if resync: diff --git a/src/components/AddNewPathButton.tsx b/src/components/AddNewPathButton.tsx index 0612446..8fca4cb 100644 --- a/src/components/AddNewPathButton.tsx +++ b/src/components/AddNewPathButton.tsx @@ -2,7 +2,7 @@ import { ButtonItem, showContextMenu, Menu, MenuItem, FilePickerRes, showModal, import { useState } from "react"; import { PageProps } from "../helpers/types"; import { Toast } from "../helpers/toast"; -import { Translator } from "../helpers/translator" +import { Translator } from "../helpers/translator"; export default function AddNewPathButton({ serverApi, onPathAdded, file }: PageProps<{ onPathAdded?: () => void; file: "includes" | "excludes" }>) { const [buttonDisabled, setButtonDisabled] = useState(false); diff --git a/src/index.tsx b/src/index.tsx index 663200e..0dc1fe3 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -76,18 +76,12 @@ function syncGame(e: LifetimeNotification) { } function shouldSync(gameInfo: any) { - // Steam Games == 1 - if (gameInfo?.app_type === 1) { - // Steam Cloud Enabled - if (gameInfo?.local_per_client_data?.cloud_status === 1) { - Logger.info("Steam game without Steam Cloud, proceeding"); - return true; - } else { - Logger.info("Steam game with Steam Cloud, skipping"); - return false; - } + if (gameInfo?.store_category.includes(23)) { + // 23 - Cloud Save + Logger.info("Steam game with Steam Cloud, skipping"); + return false; } else { - Logger.info("Non Steam game, proceeding"); + Logger.info("Non Steam game, or game without Steam Cloud, proceeding"); return true; } }