706 Commits
Author SHA1 Message Date
renovate[bot] 555b134644 chore(deps): update vitest monorepo to v5 (#625) 2026-09-29 18:16:45 +02:00
renovate[bot] 3042a10979 chore(deps): update postgres docker tag to v18 (#659) 2026-09-29 18:09:37 +02:00
renovate[bot] 3d942cb463 chore(deps): update dependency undici to v8.11.2 (#658) 2026-09-29 18:09:08 +02:00
renovate[bot] 7552fa86b2 chore(deps): update typescript-projects (#655) 2026-09-29 18:06:02 +02:00
renovate[bot] aeddf905f6 chore(deps): update dependency unplugin-swc to v2 (#656) 2026-09-29 18:05:15 +02:00
bo0tzz d259b74498 fix: omit the body from renovate PR notifications (#657) 2026-09-29 10:28:46 +02:00
Zack Pollard a7d8276bdb feat: configure zulip github expansion per stream by command (#654) 2026-09-24 16:54:34 +01:00
renovate[bot] d939ccef5e chore(deps): update node (#632) 2026-09-24 16:23:00 +02:00
renovate[bot] 0a0384e3a2 chore(deps): update typescript-projects (#633) 2026-09-24 16:22:44 +02:00
renovate[bot] 17d316c146 fix(deps): update dependency dotenv to v18 (#640) 2026-09-24 16:22:29 +02:00
Zack Pollard 9d9ee3b680 fix: mirror review follow-ups (#653) 2026-09-24 12:23:50 +01:00
Zack Pollard 49f0661baa feat: backfill the discord history of a mirrored conversation into zulip (#652) 2026-09-24 09:37:24 +01:00
Zack Pollard 4ed72292b5 feat: mirror improvements (#651) 2026-09-24 00:02:35 +01:00
Zack PollardandClaude b70e207962 chore: add a local dev environment for the dev discord server (#455)
Co-authored-by: Claude <noreply@anthropic.com>
2026-09-23 19:22:29 +00:00
Zack Pollard 88de64b545 feat: link mirrored channels and accounts with commands (#650) 2026-09-23 20:20:01 +01:00
Zack Pollard 26dffb00a1 feat: mirror the discord dev channels to zulip (#646) 2026-09-23 14:22:18 +01:00
Zack Pollard acd5ee4064 fix: report errors thrown in discord event handlers (#649) 2026-09-23 13:58:03 +01:00
Zack Pollard 39c7cc3bfc fix: suffix emotes named like zulip built-in emoji (#647) 2026-09-23 11:05:04 +01:00
Zack Pollard e3919a6870 fix: send bot startup and error messages to zulip immich-alerts (#648) 2026-09-23 11:01:42 +01:00
Zack Pollard bfb68a8179 feat: scheduled messages and rss feeds on zulip (#644) 2026-09-23 09:17:26 +01:00
Zack Pollard 8494ad8243 fix: zulip issues found testing against a real server (#645)
* fix: reference every bracket in zulip link labels

* fix: acknowledge backfill-pull-requests all before listing the pull requests

* fix: fail emote-sync on an unreadable discord server and count the uploads

* fix: skip emotes mattermost already has instead of failing them

* fix: stop the zulip side of emote-sync once zulip refuses the user account

* fix: write pull request actions as words in notifications

* fix: shorten the unknown zulip command echo

* fix: keep the full pull request title in its zulip topic

* fix: fail fourthwall update with a clear error when the order is not returned
2026-09-23 02:24:17 +01:00
Zack Pollard a286e32ae7 fix: expand zulip references in #immich and every team stream (#643) 2026-09-23 00:47:44 +00:00
Zack Pollard fb0dea13a1 feat: zulip @-mention command router (#641)
zulip has no slash commands, modals, buttons, autocomplete or ephemeral
replies, so the bot is driven by mentioning it at the start of a message in a
team stream and it answers in the topic. help, emote-sync,
backfill-pull-requests, fourthwall update and similar are ported; the community
commands stay on discord.

commands are accepted only in the private team streams, because membership of
those is the only authorization signal zulip offers a bot, and the stream is
checked to actually be private rather than assumed. every reply is public in
the topic, which is a real downgrade from the discord commands that answer
ephemerally.

fixes a pre-existing bug the port uncovered: /backfill-pull-requests has never
done anything. getOpenPullRequests overwrote the graphql node id with the
numeric database id and never set node_id, which is the key both team paths
look a pull request up by, so every lookup missed and the command reported
success regardless. it now backfills only what a pull request is missing,
leaves existing threads and topics alone, and reports what it created, skipped
and failed.
2026-09-23 01:19:55 +01:00
Zack Pollard 40c840d105 feat: zulip event queue and passive expanders (#639)
the bot can now hear zulip. a long-poll event queue feeds github reference
expansion, github permalink snippets and the x.com mirror into the team
channels, reusing the same methods discord and mattermost already use.

the loop is the point of this change. zulip garbage-collects idle queues and
drops them on restart, so a dead queue is normal operation, and zulip-js
answered that by re-polling the dead queue once a second forever, silently. this
loop re-registers on a dead queue, backs off exponentially on anything else,
treats a long poll that outlives the server timeout as an empty poll, keeps a
floor between polls so a fast server cannot be hammered, says so when it has
been unhealthy for a while, and on shutdown aborts the poll and deletes the
queue.

expanders run only in an allowlist of private team streams. they pass
isPrivileged, so they would expose private repository titles and code if a
public stream were ever added to that list. the server tells us which streams
are private when the queue is registered, so that is now enforced rather than
assumed, and a stream whose privacy is unknown is treated as public.
2026-09-23 01:19:54 +01:00
Zack Pollard 0fcde16476 feat: one zulip topic per pull request (#638)
mirrors the discord team pull-request forum in zulip stream 112: a topic per
public immich pull request, a notice on close, reopen and draft, and the topic
resolved with a checkmark when the pull request is merged or closed.

zulip topics are mutable strings with no id, so the bot stores the id of its
first message and reads the topic back before every rename. a human who renames
or resolves a topic is respected, instead of the bot silently creating a second
empty topic beside the real conversation.

realm settings can refuse an edit, a rename or a resolve: pull requests outlive
message_content_edit_limit_seconds and move_messages_within_stream_limit_seconds,
and resolving needs can_resolve_topics_group. every one of those degrades — it is
logged, a plain message is posted where the information would otherwise be lost,
and the webhook still succeeds.

the discord and zulip paths no longer depend on each other. discord's failure
used to skip the zulip topic entirely, which would have left topics missing and
permanently stale after any discord outage. discord still runs first and its
error still surfaces unchanged.

emote names are normalised for zulip, which lowercases names and treats
underscores as spaces, so colliding names get a numeric suffix and a second sync
is a no-op. the bot warns at boot when it is not subscribed to a stream it posts
to.
2026-09-23 01:19:54 +01:00
Zack Pollard 59ea289350 feat: send team notifications to zulip (#637)
adds a zulip renderer and zulip routes for the eight team destinations, so
github feeds, purchases, reports and release alerts reach zulip alongside
discord and mattermost. webhook.service and schedule.service are untouched,
which is what the phase 1 seam was for.

zulip has no embeds or colour, so the renderer flattens a notification into
markdown and maps each accent to an emoji by meaning. untrusted github titles,
bodies and the customer-written merch order message are contained: bodies go in
a tilde quote fence sized to outrun any fence inside them, mentions are
neutralised, and link labels cannot be broken out of.

delivery is now isolated per platform. previously a platform failure stopped the
ones after it, and because community.* destinations are discord-only and the
handlers post community then team in sequence, a discord outage also silenced
zulip. notify now logs failures and never rejects; a webhook reports success
even when every post failed, so the log is the signal.

fhs pull requests and releases stay on mattermost only, as agreed.
2026-09-23 01:19:54 +01:00
Zack Pollard f7cea83fb2 feat: typed zulip client on openapi-fetch (#636) 2026-09-22 23:50:36 +01:00
Zack Pollard 12f4bbfddd refactor: route notifications through a platform-neutral seam (#635) 2026-09-22 17:17:49 +01:00
renovate[bot] 6eddedf34e chore(deps): update github-actions (#634) 2026-09-22 14:21:39 +02:00
renovate[bot] a91446326a chore(deps): update typescript-projects (#630) 2026-09-15 12:59:27 +02:00
renovate[bot] 2a0abe0799 chore(deps): update node (#629) 2026-09-15 12:58:59 +02:00
renovate[bot] d67b1545ab chore(deps): update node.js to v24.21.0 (#631) 2026-09-15 12:49:20 +02:00
Daniel Dietzler 733a2a0d72 feat: mattermost modals (#621) 2026-09-11 21:22:05 +02:00
Daniel Dietzler ddda30b019 fix: mattermost suppress embeds (#628) 2026-09-11 15:14:39 -04:00
Daniel Dietzler 386b8c1bef fix: purchases notifications (#627) 2026-09-10 15:37:48 +02:00
Daniel Dietzlerandrenovate[bot] daf053b537 feat: fhs mattermost (#626)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-10 15:29:24 +02:00
renovate[bot] d884b56c8a chore(deps): update typescript-projects (#622) 2026-09-08 12:12:57 +02:00
Daniel Dietzler 85ab8cba24 feat: silent mattermost messages (#624) 2026-09-08 11:07:32 +02:00
Daniel Dietzler 3780764a02 fix: do not send purchase notifications to discord (#623) 2026-09-08 07:48:32 +00:00
Daniel Dietzler affa006cdb fix: undefined field access (#620) 2026-09-07 15:49:02 +02:00
Daniel Dietzler 87e5cdf368 feat: suppress mattermost embeds (#619) 2026-09-07 15:35:47 +02:00
Daniel Dietzler 001d9a8686 chore: notifications design tweaks (#618) 2026-09-07 15:10:48 +02:00
Daniel Dietzler 6c20dfa28d fix: stray parens (#617) 2026-09-07 12:23:18 +00:00
Daniel Dietzler 666786901d feat: more notifications on mattermost (#616) 2026-09-07 13:37:45 +02:00
Daniel Dietzler 2ae01af5a8 fix: guard against rss feeds with lengthy descriptions (#615) 2026-09-07 11:22:55 +02:00
Daniel Dietzler 6650c674e5 fix: mattermost webhooks (#614) 2026-09-04 15:41:06 +00:00
Daniel Dietzler 2db7a8221f feat: mattermost merch notifications (#613) 2026-09-03 11:22:56 +02:00
Daniel Dietzler a2e0d28f76 feat: mattermost commands (#610) 2026-09-02 12:53:37 +02:00
renovate[bot] b765d5625d chore(deps): update node.js to v24.20.0 (#612) 2026-09-02 11:24:46 +02:00
Daniel Dietzler c77014b52c fix: new mattermost ids (#611) 2026-09-01 20:01:48 +00:00