chore: remove Mastodon syndicator and related patches

Blog is now a native ActivityPub actor; Mastodon syndication via
troet.cafe is no longer needed. Removes the syndicator package,
config vars, patch script, and env example entries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sven
2026-03-14 22:31:37 +01:00
parent 296745fcf8
commit 3708dd92c3
5 changed files with 2 additions and 567 deletions
-6
View File
@@ -38,11 +38,5 @@ SYNDICATE_MOUNT_PATH=/syndicate
BLUESKY_HANDLE= BLUESKY_HANDLE=
BLUESKY_PASSWORD= BLUESKY_PASSWORD=
# Mastodon syndicator settings
# MASTODON_USER should be your username without @
MASTODON_URL=
MASTODON_USER=
MASTODON_ACCESS_TOKEN=
# Poll interval for webmention-sender (seconds). Long enough for deploys to complete. # Poll interval for webmention-sender (seconds). Long enough for deploys to complete.
WEBMENTION_SENDER_POLL_INTERVAL=600 WEBMENTION_SENDER_POLL_INTERVAL=600
-20
View File
@@ -84,14 +84,6 @@ const blueskyHandle = (process.env.BLUESKY_HANDLE || "")
.trim() .trim()
.replace(/^@+/, ""); .replace(/^@+/, "");
const blueskyPassword = process.env.BLUESKY_PASSWORD || ""; const blueskyPassword = process.env.BLUESKY_PASSWORD || "";
const mastodonUrl = process.env.MASTODON_URL || "https://troet.cafe";
const mastodonUser = (
process.env.MASTODON_USER || process.env.MASTODON_USERNAME || ""
)
.trim()
.replace(/^@+/, "");
const mastodonAccessToken =
process.env.MASTODON_ACCESS_TOKEN || process.env.MASTODON_TOKEN || "";
const syndicateMountPath = const syndicateMountPath =
process.env.SYNDICATE_MOUNT_PATH || "/syndicate"; process.env.SYNDICATE_MOUNT_PATH || "/syndicate";
const publicationBaseUrl = ( const publicationBaseUrl = (
@@ -327,7 +319,6 @@ export default {
"@indiekit/post-type-repost", "@indiekit/post-type-repost",
"@rmdes/indiekit-post-type-page", "@rmdes/indiekit-post-type-page",
"@rmdes/indiekit-syndicator-bluesky", "@rmdes/indiekit-syndicator-bluesky",
"@rmdes/indiekit-syndicator-mastodon",
"@rmdes/indiekit-syndicator-indienews", "@rmdes/indiekit-syndicator-indienews",
"@rmdes/indiekit-preset-eleventy", "@rmdes/indiekit-preset-eleventy",
"@rmdes/indiekit-endpoint-github", "@rmdes/indiekit-endpoint-github",
@@ -367,17 +358,6 @@ export default {
handle: blueskyHandle, handle: blueskyHandle,
password: blueskyPassword, password: blueskyPassword,
}, },
"@rmdes/indiekit-syndicator-mastodon": {
url: mastodonUrl,
user: mastodonUser,
accessToken: mastodonAccessToken,
// AP endpoint sends native Like/Announce activities; skip the redundant
// "❤️ URL" / "🔁 URL" status posts for external fediverse URLs.
// Native same-instance favourites/reblogs still work (needs write:favourites
// + write:statuses scope on the token).
syndicateExternalLikes: false,
syndicateExternalReposts: false,
},
"@indiekit/endpoint-syndicate": { "@indiekit/endpoint-syndicate": {
mountPath: syndicateMountPath, mountPath: syndicateMountPath,
}, },
-213
View File
@@ -33,7 +33,6 @@
"@rmdes/indiekit-preset-eleventy": "^1.0.0-beta.33", "@rmdes/indiekit-preset-eleventy": "^1.0.0-beta.33",
"@rmdes/indiekit-syndicator-bluesky": "^1.0.19", "@rmdes/indiekit-syndicator-bluesky": "^1.0.19",
"@rmdes/indiekit-syndicator-indienews": "^1.0.1", "@rmdes/indiekit-syndicator-indienews": "^1.0.1",
"@rmdes/indiekit-syndicator-mastodon": "^1.0.8",
"dotenv": "^17.3.1", "dotenv": "^17.3.1",
"mongodb": "^7.1.0", "mongodb": "^7.1.0",
"node-gyp": "^12.2.0" "node-gyp": "^12.2.0"
@@ -3106,21 +3105,6 @@
"node": ">=20" "node": ">=20"
} }
}, },
"node_modules/@rmdes/indiekit-syndicator-mastodon": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@rmdes/indiekit-syndicator-mastodon/-/indiekit-syndicator-mastodon-1.0.8.tgz",
"integrity": "sha512-5Ikq/YH1EH/7TwSiSrTCuJFanyZqf4j7sDyEJ/+/OAbiyDEpWSR1wZz2yzMoWzwI1XuPJu8pU+cQGbuB/fs6OA==",
"license": "MIT",
"dependencies": {
"html-to-text": "^9.0.0",
"masto": "^6.0.0"
},
"peerDependencies": {
"@indiekit/error": "^1.0.0-beta.25",
"@indiekit/indiekit": "1.x",
"@indiekit/util": "^1.0.0-beta.25"
}
},
"node_modules/@selderee/plugin-htmlparser2": { "node_modules/@selderee/plugin-htmlparser2": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
@@ -3563,16 +3547,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/camel-case": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
"integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
"license": "MIT",
"dependencies": {
"pascal-case": "^3.1.2",
"tslib": "^2.0.3"
}
},
"node_modules/camelcase": { "node_modules/camelcase": {
"version": "9.0.0", "version": "9.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-9.0.0.tgz", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-9.0.0.tgz",
@@ -3612,37 +3586,6 @@
"canonicalize": "bin/canonicalize.js" "canonicalize": "bin/canonicalize.js"
} }
}, },
"node_modules/capital-case": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz",
"integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==",
"license": "MIT",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3",
"upper-case-first": "^2.0.2"
}
},
"node_modules/change-case": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz",
"integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==",
"license": "MIT",
"dependencies": {
"camel-case": "^4.1.2",
"capital-case": "^1.0.4",
"constant-case": "^3.0.4",
"dot-case": "^3.0.4",
"header-case": "^2.0.4",
"no-case": "^3.0.4",
"param-case": "^3.0.4",
"pascal-case": "^3.1.2",
"path-case": "^3.0.4",
"sentence-case": "^3.0.4",
"snake-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/cheerio": { "node_modules/cheerio": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz",
@@ -3933,17 +3876,6 @@
"node": "^14.18.0 || >=16.10.0" "node": "^14.18.0 || >=16.10.0"
} }
}, },
"node_modules/constant-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz",
"integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==",
"license": "MIT",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3",
"upper-case": "^2.0.2"
}
},
"node_modules/content-disposition": { "node_modules/content-disposition": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
@@ -4358,16 +4290,6 @@
"url": "https://github.com/fb55/domutils?sponsor=1" "url": "https://github.com/fb55/domutils?sponsor=1"
} }
}, },
"node_modules/dot-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
"license": "MIT",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/dotenv": { "node_modules/dotenv": {
"version": "17.3.1", "version": "17.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
@@ -4597,12 +4519,6 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/events-to-async": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/events-to-async/-/events-to-async-2.0.2.tgz",
"integrity": "sha512-WzI6m/SU+F38t2tejHh6IQuQkNZ0dMOmSEmODJb9czaeMYtQ5FVZ+b6DOHr3hC6hNKNnn9CwDUN8mJiAkWSI9Q==",
"license": "MIT"
},
"node_modules/execa": { "node_modules/execa": {
"version": "8.0.1", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
@@ -5087,16 +5003,6 @@
"he": "bin/he" "he": "bin/he"
} }
}, },
"node_modules/header-case": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz",
"integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==",
"license": "MIT",
"dependencies": {
"capital-case": "^1.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/hono": { "node_modules/hono": {
"version": "4.12.7", "version": "4.12.7",
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz", "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz",
@@ -5572,15 +5478,6 @@
"integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==", "integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/isomorphic-ws": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz",
"integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==",
"license": "MIT",
"peerDependencies": {
"ws": "*"
}
},
"node_modules/jiti": { "node_modules/jiti": {
"version": "2.6.1", "version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
@@ -6169,15 +6066,6 @@
"integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.3"
}
},
"node_modules/lru-cache": { "node_modules/lru-cache": {
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
@@ -6316,19 +6204,6 @@
"node": ">= 12" "node": ">= 12"
} }
}, },
"node_modules/masto": {
"version": "6.10.4",
"resolved": "https://registry.npmjs.org/masto/-/masto-6.10.4.tgz",
"integrity": "sha512-TqIkWaZa884j9jik39efsv6mdpgalUElwiGLLPHevLlIuCSnGjapGC++VovlQvvVV6O5e4ce/gzWNy17cF6PHg==",
"license": "MIT",
"dependencies": {
"change-case": "^4.1.2",
"events-to-async": "^2.0.1",
"isomorphic-ws": "^5.0.0",
"ts-custom-error": "^3.3.1",
"ws": "^8.18.0"
}
},
"node_modules/math-interval-parser": { "node_modules/math-interval-parser": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz",
@@ -6745,16 +6620,6 @@
"resolved": "https://registry.npmjs.org/newbase60/-/newbase60-1.3.1.tgz", "resolved": "https://registry.npmjs.org/newbase60/-/newbase60-1.3.1.tgz",
"integrity": "sha512-2bjwvv8ytc4YQXXnV7lSz7yzQv01eYcdhhX/lo3OWkXgRSxfbbQb922s+6uiC4i5HbNlNu8Vtu9mSZ/xKRaTkg==" "integrity": "sha512-2bjwvv8ytc4YQXXnV7lSz7yzQv01eYcdhhX/lo3OWkXgRSxfbbQb922s+6uiC4i5HbNlNu8Vtu9mSZ/xKRaTkg=="
}, },
"node_modules/no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"license": "MIT",
"dependencies": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
},
"node_modules/node-addon-api": { "node_modules/node-addon-api": {
"version": "8.6.0", "version": "8.6.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.6.0.tgz", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.6.0.tgz",
@@ -7065,16 +6930,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
"integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
"license": "MIT",
"dependencies": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/parent-module": { "node_modules/parent-module": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -7182,26 +7037,6 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/pascal-case": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"license": "MIT",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/path-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz",
"integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==",
"license": "MIT",
"dependencies": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/path-key": { "node_modules/path-key": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -7775,17 +7610,6 @@
"url": "https://opencollective.com/express" "url": "https://opencollective.com/express"
} }
}, },
"node_modules/sentence-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz",
"integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==",
"license": "MIT",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3",
"upper-case-first": "^2.0.2"
}
},
"node_modules/serve-static": { "node_modules/serve-static": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
@@ -7991,16 +7815,6 @@
"npm": ">= 3.0.0" "npm": ">= 3.0.0"
} }
}, },
"node_modules/snake-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
"license": "MIT",
"dependencies": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/snakecase-keys": { "node_modules/snakecase-keys": {
"version": "9.0.2", "version": "9.0.2",
"resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-9.0.2.tgz", "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-9.0.2.tgz",
@@ -8340,15 +8154,6 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/ts-custom-error": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.3.1.tgz",
"integrity": "sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -8727,24 +8532,6 @@
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/upper-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz",
"integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.3"
}
},
"node_modules/upper-case-first": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz",
"integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.3"
}
},
"node_modules/uqr": { "node_modules/uqr": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/uqr/-/uqr-0.1.2.tgz", "resolved": "https://registry.npmjs.org/uqr/-/uqr-0.1.2.tgz",
+2 -3
View File
@@ -4,8 +4,8 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"postinstall": "xattr -w com.apple.fileprovider.ignore#P 1 node_modules 2>/dev/null || true && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-endpoint-activitypub-locales.mjs && node scripts/patch-endpoint-homepage-locales.mjs && node scripts/patch-endpoint-homepage-identity-defaults.mjs && node scripts/patch-federation-unlisted-guards.mjs && node scripts/patch-endpoint-micropub-where-note-visibility.mjs && node scripts/patch-endpoint-posts-ai-fields.mjs && node scripts/patch-endpoint-posts-ai-cleanup.mjs && node scripts/patch-endpoint-podroll-opml-upload.mjs && node scripts/patch-preset-eleventy-ai-frontmatter.mjs && node scripts/patch-micropub-ai-block-resync.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-endpoint-comments-locales.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-conversations-mastodon-disconnect.mjs && node scripts/patch-indiekit-routes-rate-limits.mjs && node scripts/patch-indiekit-error-production-stack.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-listening-endpoint-runtime-guards.mjs && node scripts/patch-endpoint-github-changelog-categories.mjs && node scripts/patch-microsub-reader-ap-dispatch.mjs && node scripts/patch-endpoint-blogroll-feeds-alias.mjs && node scripts/patch-endpoint-posts-uid-lookup.mjs && node scripts/patch-endpoint-posts-prefill-url.mjs && node scripts/patch-microsub-feed-discovery.mjs && node scripts/patch-conversations-bluesky-self-filter.mjs && node scripts/patch-conversations-bluesky-cursor-fix.mjs && node scripts/patch-inbox-ignore-view-activity.mjs && node scripts/patch-inbox-skip-view-activity-parse.mjs", "postinstall": "xattr -w com.apple.fileprovider.ignore#P 1 node_modules 2>/dev/null || true && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-endpoint-activitypub-locales.mjs && node scripts/patch-endpoint-homepage-locales.mjs && node scripts/patch-endpoint-homepage-identity-defaults.mjs && node scripts/patch-federation-unlisted-guards.mjs && node scripts/patch-endpoint-micropub-where-note-visibility.mjs && node scripts/patch-endpoint-posts-ai-fields.mjs && node scripts/patch-endpoint-posts-ai-cleanup.mjs && node scripts/patch-endpoint-podroll-opml-upload.mjs && node scripts/patch-preset-eleventy-ai-frontmatter.mjs && node scripts/patch-micropub-ai-block-resync.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-endpoint-comments-locales.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-indiekit-routes-rate-limits.mjs && node scripts/patch-indiekit-error-production-stack.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-listening-endpoint-runtime-guards.mjs && node scripts/patch-endpoint-github-changelog-categories.mjs && node scripts/patch-microsub-reader-ap-dispatch.mjs && node scripts/patch-endpoint-blogroll-feeds-alias.mjs && node scripts/patch-endpoint-posts-uid-lookup.mjs && node scripts/patch-endpoint-posts-prefill-url.mjs && node scripts/patch-microsub-feed-discovery.mjs && node scripts/patch-conversations-bluesky-self-filter.mjs && node scripts/patch-conversations-bluesky-cursor-fix.mjs && node scripts/patch-inbox-ignore-view-activity.mjs && node scripts/patch-inbox-skip-view-activity-parse.mjs",
"serve":"export NODE_ENV=${NODE_ENV:-production} INDIEKIT_DEBUG=${INDIEKIT_DEBUG:-0} && node scripts/preflight-production-security.mjs && node scripts/preflight-mongo-connection.mjs && node scripts/preflight-activitypub-rsa-key.mjs && node scripts/preflight-activitypub-profile-urls.mjs && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-endpoint-activitypub-locales.mjs && node scripts/patch-endpoint-homepage-locales.mjs && node scripts/patch-endpoint-homepage-identity-defaults.mjs && node scripts/patch-federation-unlisted-guards.mjs && node scripts/patch-endpoint-micropub-where-note-visibility.mjs && node scripts/patch-endpoint-posts-ai-fields.mjs && node scripts/patch-endpoint-posts-ai-cleanup.mjs && node scripts/patch-endpoint-podroll-opml-upload.mjs && node scripts/patch-preset-eleventy-ai-frontmatter.mjs && node scripts/patch-micropub-ai-block-resync.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-endpoint-comments-locales.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-conversations-mastodon-disconnect.mjs && node scripts/patch-indiekit-routes-rate-limits.mjs && node scripts/patch-indiekit-error-production-stack.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-listening-endpoint-runtime-guards.mjs && node scripts/patch-endpoint-github-changelog-categories.mjs && node scripts/patch-microsub-reader-ap-dispatch.mjs && node scripts/patch-endpoint-blogroll-feeds-alias.mjs && node scripts/patch-endpoint-posts-uid-lookup.mjs && node scripts/patch-endpoint-posts-prefill-url.mjs && node scripts/patch-microsub-feed-discovery.mjs && node scripts/patch-conversations-bluesky-self-filter.mjs && node scripts/patch-conversations-bluesky-cursor-fix.mjs && node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs", "serve": "export NODE_ENV=${NODE_ENV:-production} INDIEKIT_DEBUG=${INDIEKIT_DEBUG:-0} && node scripts/preflight-production-security.mjs && node scripts/preflight-mongo-connection.mjs && node scripts/preflight-activitypub-rsa-key.mjs && node scripts/preflight-activitypub-profile-urls.mjs && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-endpoint-activitypub-locales.mjs && node scripts/patch-endpoint-homepage-locales.mjs && node scripts/patch-endpoint-homepage-identity-defaults.mjs && node scripts/patch-federation-unlisted-guards.mjs && node scripts/patch-endpoint-micropub-where-note-visibility.mjs && node scripts/patch-endpoint-posts-ai-fields.mjs && node scripts/patch-endpoint-posts-ai-cleanup.mjs && node scripts/patch-endpoint-podroll-opml-upload.mjs && node scripts/patch-preset-eleventy-ai-frontmatter.mjs && node scripts/patch-micropub-ai-block-resync.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-endpoint-comments-locales.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-indiekit-routes-rate-limits.mjs && node scripts/patch-indiekit-error-production-stack.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-listening-endpoint-runtime-guards.mjs && node scripts/patch-endpoint-github-changelog-categories.mjs && node scripts/patch-microsub-reader-ap-dispatch.mjs && node scripts/patch-endpoint-blogroll-feeds-alias.mjs && node scripts/patch-endpoint-posts-uid-lookup.mjs && node scripts/patch-endpoint-posts-prefill-url.mjs && node scripts/patch-microsub-feed-discovery.mjs && node scripts/patch-conversations-bluesky-self-filter.mjs && node scripts/patch-conversations-bluesky-cursor-fix.mjs && node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"keywords": [], "keywords": [],
@@ -45,7 +45,6 @@
"@rmdes/indiekit-preset-eleventy": "^1.0.0-beta.33", "@rmdes/indiekit-preset-eleventy": "^1.0.0-beta.33",
"@rmdes/indiekit-syndicator-bluesky": "^1.0.19", "@rmdes/indiekit-syndicator-bluesky": "^1.0.19",
"@rmdes/indiekit-syndicator-indienews": "^1.0.1", "@rmdes/indiekit-syndicator-indienews": "^1.0.1",
"@rmdes/indiekit-syndicator-mastodon": "^1.0.8",
"dotenv": "^17.3.1", "dotenv": "^17.3.1",
"mongodb": "^7.1.0", "mongodb": "^7.1.0",
"node-gyp": "^12.2.0" "node-gyp": "^12.2.0"
@@ -1,325 +0,0 @@
import { access, readFile, writeFile } from "node:fs/promises";
const conversationsIndexCandidates = [
"node_modules/@rmdes/indiekit-endpoint-conversations/index.js",
"node_modules/@indiekit/indiekit/node_modules/@rmdes/indiekit-endpoint-conversations/index.js",
];
const conversationsControllerCandidates = [
"node_modules/@rmdes/indiekit-endpoint-conversations/lib/controllers/conversations.js",
"node_modules/@indiekit/indiekit/node_modules/@rmdes/indiekit-endpoint-conversations/lib/controllers/conversations.js",
];
const conversationsSchedulerCandidates = [
"node_modules/@rmdes/indiekit-endpoint-conversations/lib/polling/scheduler.js",
"node_modules/@indiekit/indiekit/node_modules/@rmdes/indiekit-endpoint-conversations/lib/polling/scheduler.js",
];
const conversationsViewCandidates = [
"node_modules/@rmdes/indiekit-endpoint-conversations/views/conversations.njk",
"node_modules/@indiekit/indiekit/node_modules/@rmdes/indiekit-endpoint-conversations/views/conversations.njk",
];
const patchSpecs = [
{
name: "conversations-index-mastodon-disconnect-routes",
candidates: conversationsIndexCandidates,
oldSnippet: ` // Manual poll trigger (admin only)
router.post("/poll", conversationsController.triggerPoll);
return router;`,
newSnippet: ` // Manual poll trigger (admin only)
router.post("/poll", conversationsController.triggerPoll);
router.post("/mastodon/logout", conversationsController.logoutMastodon);
router.post("/mastodon/reconnect", conversationsController.reconnectMastodon);
return router;`,
},
{
name: "conversations-dashboard-connection-state",
candidates: conversationsControllerCandidates,
marker: "const connectionState = {",
oldSnippet: ` // Get stats
const totalItems = await getConversationCount(application);`,
newSnippet: ` const connectionState = {
mastodonEnabled:
!!config.mastodonEnabled && !pollState?.mastodon_disabled,
blueskyEnabled: !!config.blueskyEnabled,
activitypubEnabled: !!config.activitypubEnabled,
};
// Get stats
const totalItems = await getConversationCount(application);`,
},
{
name: "conversations-dashboard-render-connection-state",
candidates: conversationsControllerCandidates,
oldSnippet: ` config,
pollState,
totalItems,`,
newSnippet: ` config,
pollState,
connectionState,
totalItems,`,
},
{
name: "conversations-dashboard-error-render-connection-state",
candidates: conversationsControllerCandidates,
oldSnippet: ` config: {},
totalItems: 0,`,
newSnippet: ` config: {},
connectionState: {
mastodonEnabled: false,
blueskyEnabled: false,
activitypubEnabled: false,
},
totalItems: 0,`,
},
{
name: "conversations-status-mastodon-disabled-flag",
candidates: conversationsControllerCandidates,
oldSnippet: ` const totalItems = await getConversationCount(application);
response.json({
status: "ok",
mastodon: {
enabled: !!config.mastodonEnabled,`,
newSnippet: ` const totalItems = await getConversationCount(application);
const mastodonEnabled =
!!config.mastodonEnabled && !pollState?.mastodon_disabled;
response.json({
status: "ok",
mastodon: {
enabled: mastodonEnabled,
disabledByAdmin: !!pollState?.mastodon_disabled,`,
},
{
name: "conversations-controller-mastodon-disconnect-handlers",
candidates: conversationsControllerCandidates,
marker: "async function logoutMastodon(request, response)",
oldSnippet: `/**
* Ingest a webmention`,
newSnippet: `/**
* Disable Mastodon polling (dashboard logout/disconnect action)
* POST /conversations/mastodon/logout
*/
async function logoutMastodon(request, response) {
const { application } = request.app.locals;
const config = application?.conversations || {};
const stateCollection = application?.collections?.get("conversation_state");
try {
if (stateCollection) {
await stateCollection.findOneAndUpdate(
{ _id: "poll_cursors" },
{
$set: {
mastodon_disabled: true,
mastodon_last_error: null,
mastodon_last_poll: new Date().toISOString(),
mastodon_last_disabled_at: new Date().toISOString(),
},
$unset: {
mastodon_since_id: "",
},
},
{ upsert: true },
);
}
response.redirect((config.mountPath || "/conversations") + "?mastodon=logged_out");
} catch (error) {
console.error("[Conversations] Mastodon logout error:", error.message);
response.redirect(
(config.mountPath || "/conversations") + "?error=mastodon_logout_failed",
);
}
}
/**
* Re-enable Mastodon polling after dashboard disconnect
* POST /conversations/mastodon/reconnect
*/
async function reconnectMastodon(request, response) {
const { application } = request.app.locals;
const config = application?.conversations || {};
const stateCollection = application?.collections?.get("conversation_state");
try {
if (stateCollection) {
await stateCollection.findOneAndUpdate(
{ _id: "poll_cursors" },
{
$unset: {
mastodon_disabled: "",
},
$set: {
mastodon_last_error: null,
mastodon_last_poll: new Date().toISOString(),
},
},
{ upsert: true },
);
}
response.redirect((config.mountPath || "/conversations") + "?mastodon=reconnected");
} catch (error) {
console.error("[Conversations] Mastodon reconnect error:", error.message);
response.redirect(
(config.mountPath || "/conversations") + "?error=mastodon_reconnect_failed",
);
}
}
/**
* Ingest a webmention`,
},
{
name: "conversations-controller-export-disconnect-handlers",
candidates: conversationsControllerCandidates,
oldSnippet: ` triggerPoll,
ingest,`,
newSnippet: ` triggerPoll,
logoutMastodon,
reconnectMastodon,
ingest,`,
},
{
name: "conversations-scheduler-mastodon-disabled-check",
candidates: conversationsSchedulerCandidates,
oldSnippet: ` const mastodonToken = process.env.MASTODON_ACCESS_TOKEN;
const hasMastodon = mastodonUrl && mastodonToken;`,
newSnippet: ` const mastodonToken = process.env.MASTODON_ACCESS_TOKEN;
const mastodonDisabled = state.mastodon_disabled === true;
const hasMastodon = !mastodonDisabled && mastodonUrl && mastodonToken;`,
},
{
name: "conversations-scheduler-mastodon-403-backoff",
candidates: conversationsSchedulerCandidates,
oldSnippet: ` if (error.status === 429 || error.status === 401) {`,
newSnippet: ` if (error.status === 429 || error.status === 401 || error.status === 403) {`,
},
{
name: "conversations-view-mastodon-connection-state",
candidates: conversationsViewCandidates,
oldSnippet: "config.mastodonEnabled",
newSnippet: "connectionState.mastodonEnabled",
replaceAll: true,
},
{
name: "conversations-view-bluesky-connection-state",
candidates: conversationsViewCandidates,
oldSnippet: "config.blueskyEnabled",
newSnippet: "connectionState.blueskyEnabled",
replaceAll: true,
},
{
name: "conversations-view-activitypub-connection-state",
candidates: conversationsViewCandidates,
oldSnippet: "config.activitypubEnabled",
newSnippet: "connectionState.activitypubEnabled",
replaceAll: true,
},
{
name: "conversations-view-mastodon-logout-button",
candidates: conversationsViewCandidates,
marker: "action=\"{{ baseUrl }}/mastodon/logout\"",
oldSnippet: ` <p style="font-size: 0.85em; margin: 0.25rem 0">
{{ platformCounts.mastodon or 0 }} {{ __("conversations.dashboard.itemsCollected") }}
</p>`,
newSnippet: ` <p style="font-size: 0.85em; margin: 0.25rem 0">
{{ platformCounts.mastodon or 0 }} {{ __("conversations.dashboard.itemsCollected") }}
</p>
<form method="post" action="{{ baseUrl }}/mastodon/logout" style="margin-top: 0.75rem">
<button type="submit" class="button">Logout Mastodon</button>
</form>`,
},
{
name: "conversations-view-mastodon-disabled-state",
candidates: conversationsViewCandidates,
marker: "Mastodon polling is disconnected for this dashboard.",
oldSnippet: ` {% else %}
<p style="font-size: 0.85em; color: #6b7280; margin: 0.25rem 0">
{{ __("conversations.dashboard.mastodonHint") }}
</p>
{% endif %}`,
newSnippet: ` {% else %}
{% if pollState and pollState.mastodon_disabled %}
<p style="font-size: 0.85em; color: #6b7280; margin: 0.25rem 0">
Mastodon polling is disconnected for this dashboard.
</p>
<form method="post" action="{{ baseUrl }}/mastodon/reconnect" style="margin-top: 0.75rem">
<button type="submit" class="button">Reconnect Mastodon</button>
</form>
{% else %}
<p style="font-size: 0.85em; color: #6b7280; margin: 0.25rem 0">
{{ __("conversations.dashboard.mastodonHint") }}
</p>
{% endif %}
{% endif %}`,
},
];
async function exists(filePath) {
try {
await access(filePath);
return true;
} catch {
return false;
}
}
const checkedFiles = new Set();
const patchedFiles = new Set();
for (const spec of patchSpecs) {
let foundAnyTarget = false;
for (const filePath of spec.candidates) {
if (!(await exists(filePath))) {
continue;
}
foundAnyTarget = true;
checkedFiles.add(filePath);
const source = await readFile(filePath, "utf8");
if (spec.marker && source.includes(spec.marker)) {
continue;
}
if (!source.includes(spec.oldSnippet)) {
continue;
}
let updated;
if (spec.replaceAll) {
updated = source.split(spec.oldSnippet).join(spec.newSnippet);
} else {
updated = source.replace(spec.oldSnippet, spec.newSnippet);
}
if (updated === source) {
continue;
}
await writeFile(filePath, updated, "utf8");
patchedFiles.add(filePath);
}
if (!foundAnyTarget) {
console.log(`[postinstall] ${spec.name}: no target files found`);
}
}
if (checkedFiles.size === 0) {
console.log("[postinstall] No conversations mastodon disconnect files found");
} else if (patchedFiles.size === 0) {
console.log("[postinstall] conversations mastodon disconnect patches already applied");
} else {
console.log(
`[postinstall] Patched conversations mastodon disconnect in ${patchedFiles.size}/${checkedFiles.size} file(s)`,
);
}