diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8e3e66e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 + +# 3 space indentation +[*.js] +indent_style = space +indent_size = 3 diff --git a/.env.sample b/.env.sample index f64d1a1..f7a197b 100644 --- a/.env.sample +++ b/.env.sample @@ -1,3 +1,3 @@ PLEX_TOKEN= PLEX_IP= -USERNAME= \ No newline at end of file +PLEX_USER= diff --git a/README.md b/README.md index 34d5f7a..059196c 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,49 @@ # plex-letterboxd + Syncs your letterboxd watchlist with movies on you plex ## Installation -1. `git clone https://github.com/slgoetz/plex-letterboxd-sync.git` -2. `cd plex-letterboxd-sync` -3. `yarn install` +```bash +git clone https://github.com/slgoetz/plex-letterboxd-sync.git +cd plex-letterboxd-sync +yarn install +``` -## Usage -If you want this to run in the background and sync once a day you can add it as a launch script on your mac. To do so you will need to fill in the blanks (`{path-for-your-file}` and `{username}`) in `launched.plexletterboxdsync.plist`. Then check to see if you have a directory at `~/Library/LaunchAgents`. If not, create one and copy the launch file there. This should run at midnight every day and output a log file for synced movies as well as errors. +## Setup -*Make sure the `PATH` set the start.sh file is replaced with your `PATH`* +Copy `.env.sample` to `.env` and fill in the environment variables. + +* `$PLEX_TOKEN` - See [this Plex support article](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/) +* `$PLEX_IP` - Can be an IP address (e.g., `192.168.1.2`) or a hostname (e.g., `plex.example.com`) +* `$PLEX_USER` - Your username with Plex (e.g., how you log in to plex.tv) + +## Usage ### Run Once -If you would like to run this once, you can run with `node ./index.js` + +If you would like to run this once: + +```bash +cd plex-letterboxd-sync +./start.sh +``` + +### Run On A Schedule + +If you want this to run in the background on a regular interval (e.g., once a day), you can add it as a launchd script on your Mac. + +1. Edit `com.slgoetz.plexletterboxdsync.plist` and replace `/path/to/plex-letterboxd-sync` with the absolute path to where you cloned this repository. E.g., `/Users/username/plex-letterboxd-sync` +2. *Make sure the `PATH` set in `~/Library/LaunchAgents/com.slgoetz.plexletterboxdsync.plist` is valid for your user,* it should ensure that `node` is available to launchd to run the script. + * E.g., if `node` is at `/usr/local/bin` or `/opt/homebrew/bin` (the default locations for Homebrew-installed Node.js, depending on if you have an Intel or Apple Silicon Mac), you should be good with the default value. +3. Check if you have a directory at `~/Library/LaunchAgents`. If not, create it. +4. Copy the launchd plist file, `com.slgoetz.plexletterboxdsync.plist`, to `~/Library/LaunchAgents` + +This will enable the script to run at midnight every day and output a log file for synced movies as well as errors to the `WorkingDirectory` you set in step 1 above. + +If you’d like to run it on a different schedule, the `StartCalendarInterval` stanza can be modified. You can do this by hand, or using a utility application like [LaunchControl](https://www.soma-zone.com/LaunchControl/). ## Roadmap + - [ ] Sync ratings - [ ] Sync Watched - diff --git a/com.slgoetz.plexletterboxdsync.plist b/com.slgoetz.plexletterboxdsync.plist new file mode 100644 index 0000000..2af6661 --- /dev/null +++ b/com.slgoetz.plexletterboxdsync.plist @@ -0,0 +1,26 @@ + + + + + EnvironmentVariables + + PATH + /opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin + + Label + com.slgoetz.plexletterboxdsync + Program + start.sh + StandardErrorPath + plex-letterboxd-sync-error.log + StandardOutPath + plex-letterboxd-sync.log + StartCalendarInterval + + Minute + 0 + + WorkingDirectory + /path/to/plex-letterboxd-sync + + diff --git a/index.js b/index.js index 372146d..468c2d4 100644 --- a/index.js +++ b/index.js @@ -53,7 +53,7 @@ const getAllLibraries = async () => { }; const letterboxd = async () => { - return await fetch(`https://letterboxd.com/${process.env.USERNAME}/watchlist/`) + return await fetch(`https://letterboxd.com/${process.env.PLEX_USER}/watchlist/`) .then((response) => response.text()) .then((html) => { let $ = cheerio.load(html); @@ -67,7 +67,7 @@ const letterboxd = async () => { }; const getLbMovieInfo = async (movies) => { const getFilm = async ({ filmId, filmSlug }) => { - return await fetch(`https://letterboxd.com${filmSlug}`) + return await fetch(`https://letterboxd.com/${filmSlug}`) .then((response) => response.text()) .then((html) => { let $ = cheerio.load(html); diff --git a/launched.plexletterboxdsync.plist b/launched.plexletterboxdsync.plist deleted file mode 100644 index 12963dc..0000000 --- a/launched.plexletterboxdsync.plist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - Label - launched.plexletterboxdsync - ProgramArguments - - sh - start.sh - - StandardErrorPath - /{path-for-your-file}/plex-letterboxd-sync/logger-error.text - StandardOutPath - /{path-for-your-file}/plex-letterboxd-sync/logger.text - StartCalendarInterval - - Minute - 0 - - StartInterval - 0 - UserName - {username} - WorkingDirectory - /{path-for-your-file}/plex-letterboxd-sync - - diff --git a/package.json b/package.json index e261f4c..0f204c1 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Sync your Letterboxd watchlist with your Plex media server.", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "sync": "node index.js" }, "author": "", "type": "module", @@ -19,6 +20,6 @@ "node-schedule": "^2.1.1", "plex-api": "^5.3.2", "url-join": "^5.0.0", - "xml2js": "^0.4.23" + "xml2js": "^0.6.2" } } diff --git a/start.sh b/start.sh old mode 100644 new mode 100755 index 2567310..52b31e6 --- a/start.sh +++ b/start.sh @@ -1,4 +1,4 @@ -export PATH=/opt/homebrew/opt/node@14/bin:/opt/homebrew/opt/node@14/bin:/opt/homebrew/opt/node@16/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin +#!/usr/bin/env bash yarn install -node ./index.js +yarn sync diff --git a/yarn.lock b/yarn.lock index bac314e..0d1dad2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -377,9 +377,9 @@ domutils@^3.0.1: domhandler "^5.0.1" dotenv@^16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + version "16.6.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" + integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== duplexer@~0.1.1: version "0.1.2" @@ -967,9 +967,9 @@ node-domexception@^1.0.0: integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== node-fetch@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.0.tgz#37e71db4ecc257057af828d523a7243d651d91e4" - integrity sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA== + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== dependencies: data-uri-to-buffer "^4.0.0" fetch-blob "^3.1.4" @@ -1252,9 +1252,9 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@>=0.6.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + version "1.5.0" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.5.0.tgz#b5549b671069b7aa392df55ec7574cf411179eb8" + integrity sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA== set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" @@ -1493,9 +1493,9 @@ verror@1.10.0: extsprintf "^1.2.0" web-streams-polyfill@^3.0.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" - integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== xml2js@0.4.16: version "0.4.16" @@ -1513,10 +1513,10 @@ xml2js@0.4.19: sax ">=0.6.0" xmlbuilder "~9.0.1" -xml2js@^0.4.23: - version "0.4.23" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" - integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== +xml2js@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0"