nathan-sain / foundry-world-tools

A Python CLI for managing Foundry VTT assets on the file system
MIT License
10 stars 5 forks source link

Foundry World Tools (FWT)

[!WARNING]
This utility is currently only compatable with Foundry 7,8,9

A Python CLI for working with Foundry VTT project assets on the file system. FWT generally does two things when run; 1st it moves files and 2nd it updates the foundry databases with the new location of the file using a search and replace. In the case of duplicate files FWT does not delete files, only move them to a trash directory at the root of the world directory, if files are to be deleted that must be done manually. FWT makes a backup copy of any database files it rewrites using the original name with a .bak.X at the end. Regular expressions are used as patterns when preforming file renaming and preferred file matching. FWT was created to help me clean up adventure modules exported from other VTTs, and I hope it can help you.

fwt --help and fwt CMD --help will give brief usage information for the CLI and supported commands.

Installation

Install using pip python3 -m pip install git+https://github.com/nathan-sain/foundry-world-tools.git or if FWT is already installed use python3 -m pip install -U git+https://github.com/nathan-sain/foundry-world-tools.git to upgrade to the latest version.

On windows the cli command isn't installed in a directory that is in the binary path. In this case you have three options:

  1. use python3 -m foundryWorldTools instead of fwt to execute the cli
  2. find the fwt cli command and put it in your path. It's usually in an AppData/Local/Packages/Python3X/Scripts
  3. create a PowerShell function to run the python module with the fwt command Function fwt {python3 -m foundryWorldTools @Args}

Notes

Foundry User Data Directory

When fwt changes the name or location of files it must update the database files of a Foundry project. Foundry databases store file paths relative to the Foundry user data directory (fudd). Therefore in order for fwt to correctly update file paths in the database it must know the location of the fudd. If the configuration file does not have the fudd set or the --dataDir option is not set fwt will attempt to auto detect the fudd path. This is usually pretty easy if fwt is used interactively in a project directory. But if fwt run from outside of the fudd it will be necessary to set the dataDir in the config file or by using the --dataDir option. fwt --dataDir=e:\Data renameall --replace=/_/-/ e:\Data\worlds\lmop

File paths

fwt is intended to be use interactively on the command line. Where files and directories are required as arguments you can specify them as you would with any command-line to work with files, e.g. fwt rename token.png ../../characters/wizard/

Config file and presets

A JSON formatted config file can be used to store the location of the Foundry user data directory, dataDir, as well as presets. It is possible to see the config file default location and to open the config file in the default editor using fwt --edit. It is also possible to manually set the config file path using fwt --config= option. A config file must exist in order to be loaded. If an empty config file is detected it will be populated with the default configuration. To create a new file with the default configuration use the --mkconfig flag. When the --mkconfig flag is present, file exists, and isn't empty it will be left as is and a warning will be logged.

fwt supports storing presets for commands which allow consistent application of options across multiple uses and prevent the need to type long commands repeatedly. fwt ships with some default presets setup in the config file.

Logging

fwt can be configured to log messages to the console or to a file. To specify a file for logging use the --logfile option with a path for the log file. File logging is always at the debug level. To change the console logging level use the --loglevel option with any of INFO,WARNING,ERROR,DEBUG,QUIET.

Deleting files

fwt doesn't delete any files. When file paths are removed from the the database the corresponding files are moved to a trash directory located in the root of the project directory. Additionally when databases are to be modified, before changes are made, a unmodified version of the database file is stored in the trash directory. fwt uses a incrementing trash directory scheme. The first trash directory is trash/session.0 and on consecutive runs new trash directories will be created: trash/session.1, trash/session.2 etc. This makes it possible to preserve files and databases across multiple runs as well as easily removing all of the trash files by deleting the trash folder.

Usage

Commands

Complete Example

This example shows how to remove duplicate PNG files, replace all PNG images with WEBP images using the cwebp command, and then remove undesirable characters from the remaining files. The adventure1 world has many duplicate images. Some of the duplicates are stored in a folder called images/misc and it is preferred for images to be stored in the characters, journal, and scenes directories. On windows don't use -rf with the rm command

### Dedup by content to find extra files
fwt dedup --bycontent --ext ".png" --preferred="<project_dir>/characters.*token.*" --preferred="<project_dir>/characters" --preferred="<project_dir>/journal" --preferred="<project_dir>/scenes" /fvtt/Data/worlds/adventure1 

# Load the adventure in Foundry and check to make sure everything loads properly then delete Trash and backups
rm -rf /fvtt/Data/worlds/adventure1/trash

# if files remain in the images/misc directory copy the individual files from images/misc to other preferred directories and rerun dedup
fwt dedup --bycontent --ext ".png" --preferred="<project_dir>/characters.*token.*" --preferred="<project_dir>/characters" --preferred="<project_dir>/journal" --preferred="<project_dir>/scenes" /fvtt/Data/worlds/adventure1
# repeat testing and detete Trash and backups...
### shell script to preform webp image conversion and then remove extra files with FWT
###### On Unix
for file in $(find /fvtt/Data/worlds/adventure1 -iname '*png'); do cwebp -preset drawing -sharp_yuv -mt -psnr 45 "$file" -o "${file%*png}webp";done
###### On Windows
gci \fvtt\Data\worlds\adventure1 -R -include *.png | Foreach-Object { c:\bin\cwebp -preset drawing -sharp_yuv -mt -psnr 45 -o "$($_.FullName.split('.')[0]).webp" $_.FullName }
# Dedup by name to remove the PNG files
fwt dedup --ext=".png" --ext=".webp" --byname --preferred=".*webp" /fvtt/Data/worlds/adventure1
# Load the adventure in Foundry and check to make sure everything loads properly then delete Trash and backups
### Use replaceall to remove or replace undesirable characters from files and convert path to lower case
fwt renameall --remove="[0-9]{3}_-_" --replace="/_+/-/" --lower worlds/adventure
# Load the adventure in Foundry and check to make sure everything loads properly then delete Trash and backups"

Config file example

{   
    "dataDir":"/fvtt/Data",
    "presets":{
        "imgDedup":{
            "description":"Find duplicate image files and chooses files from the characters,journal,scenes directories to keep",
            "command":"dedup",
            "bycontent":true,
            "ext": [".png",".jpg",".jpeg",".gif",".webp"],
            "preferred":["<project_dir>/characters.*token.*","<project_dir>/characters","<project_dir>/journal.*token.*","<project_dir>/journal","<project_dir>/scenes"]
        }
    }
}

Git diff utilities

nedb2yaml

With git configured to use nedb2yaml as a textconv filter it is possible to view human readable diffs of nedb files presented in YAML format. Add the following git config snippets to configure git diff to use nedb2yaml.

.git/config

[diff "nedb"]
        textconv = python3 -m foundryWorldTools.nedb2yaml
        cachetextconv = true

.gitattributes

*.db diff=nedb

Note for Windows OS: If python is installed through the windows store git may not have permission to execute python. Also python3 may not be in your path so you may need to use py instead of python3.

yaml2nedb

It is also possible to convert nedb files to yaml with nedb2yaml make edits and then convert them back to nedb with the utility yaml2nedb.

Examples:

view a YAML formatted git diff: screenshot of VSCode diff and git diff

git diff HEAD^:./data/actors.db :./data/actors.db

Create a YAML version of a Foundry db

python3 -m foundryWorldTools.nedb2yaml data/actors.db > actors.yaml

Create a Foundry db from a YAML file

python3 -m foundryWorldTools.yaml2nedb actors.yaml > actors.db

Contribution

If you notice a bug or would like to request a feature please the open an issue. Better yet fork the repository and make a pull request!