diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..b43ed4d --- /dev/null +++ b/.npmignore @@ -0,0 +1,3 @@ +node_modules/ +.env +yarn.lock diff --git a/README.md b/README.md index 5c506f6..6c09694 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,64 @@ # syncthing-hooks -Very early experiment for running event hooks when SyncThing detects changes in a folder. +Run shell scripts via event hook files (similar to Git hooks) when changes are detected in a [Syncthing](https://syncthing.net/) folder. ## Prerequisites -A somewhat recent version of Node.js. +[Node.js >= 10](https://nodejs.org/en/) ## Installation -None yet, there's no point installing this as a daemon right now. But you'll need to install the dependencies to make it run: - ```sh -npm i -# or -yarn +npm i -g syncthing-hooks ``` ## Usage -You can experiment with it by just running it via Node.js and monitoring the output. +You can simply run the watcher process via: ```sh -API_KEY=mykey node index.js +API_KEY=mykey syncthing-hooks ``` -Then change some files in one of your monitored folders. +Don't forget to substitute `mykey` with your syncthing API key, which can be found in the settings in the GUI. + +If Syncthing runs on another host or listens to a non-default port, you can specify an URL by using `ST_URL`. +Note that this URL has to include the protocol, hostname, port and path, e.g.: + +``` +ST_URL=http://:8384/rest/events +``` + +It won't install itself as a daemon by default, however. In order to run it as a service, it is recommended to install [pm2](https://pm2.keymetrics.io/): + +```sh +npm i -g pm2 +``` + +You can then register it as a daemon via: + +```sh +pm2 start "API_KEY=mykey syncthing-hooks" --name sthooks +``` + +To create the daemon automatically on startup, consult [this documentation](https://pm2.keymetrics.io/docs/usage/startup/). + +You can follow the output of your hooks by using: + +```sh +pm2 logs +``` + +## Hooks + +Create a folder in your home directory called `.syncthing-hooks`. +A different directory can be set using `ST_HOOK_ROOT`. +Each hook is a file with the following naming scheme: + +`folder-name-delay` + +The folder name is the 11 character unique string found in the syncthing GUI. The delay is a string (anything parseable by the [ms module](https://github.com/zeit/ms)) indicating the idle time after an event, so that hooks aren't executed multiple times on successive changes in a short interval. + +An example: a script at the location `~/.syncthing-hooks/night-owlzz-5m` will be executed five minutes after the most recent event in the folder with the identifier `night-owlzz`. + +Don't forget to `chmod +x` the script. diff --git a/api.js b/api.js index 7caf844..5219d25 100644 --- a/api.js +++ b/api.js @@ -1,9 +1,10 @@ const got = require('got'); +const { getEnvVar } = require('./env.js'); const fetchEvents = () => - got('http://localhost:8384/rest/events', { + got(getEnvVar('ST_URL','http://localhost:8384/rest/events'), { headers: { - 'X-API-Key': process.env.API_KEY, + 'X-API-Key': getEnvVar('API_KEY','invalid') }, }).json(); diff --git a/env.js b/env.js new file mode 100644 index 0000000..8999dd4 --- /dev/null +++ b/env.js @@ -0,0 +1,9 @@ +module.exports = { + getEnvVar: function (varname, defaultvalue){ + var result = process.env[varname]; + if(result!=undefined) + return result; + else + return defaultvalue; + } +}; diff --git a/hooks.js b/hooks.js index 512d6c2..19c0531 100644 --- a/hooks.js +++ b/hooks.js @@ -3,8 +3,9 @@ const ms = require('ms'); const os = require('os'); const path = require('path'); const { spawn } = require('child_process'); +const { getEnvVar } = require('./env.js'); -const getHooksRoot = () => path.join(os.homedir(), '/.syncthing-hooks'); +const getHooksRoot = () => getEnvVar('ST_HOOK_ROOT', path.join(os.homedir(), '/.syncthing-hooks')) const readHooksRoot = async root => { try { @@ -20,7 +21,7 @@ const parseHooks = (root, hooks) => hooks .map(x => ({ path: path.join(root, x), - match: x.match(/(?.{11})-(?