- TypeScript 95%
- CSS 4%
- Nix 1%
- HTML <1%
Orianna #
Source, issues and pull requests live on Tangled.
git clone zekurio.me@knot.zekurio.me:did:plc:c5tl5gu27hssisgzp4x3mmvq/orianna
Orianna is a bot for servers on a self-hosted Fluxer instance. Invite it to as many servers as you like. Each one gets its own settings, which start at the defaults.
- Members propose emojis and stickers, the server votes with reactions, and the bot adds what passes. The image can be an attachment, a link or a 7TV emote, and a wide image turns into a row of emojis.
!pollstarts a poll that shows its results while people vote.- Role menus give a role to whoever reacts to a message.
- Members give each other karma by reacting to messages, as on shinpuru. Rules can hand out roles at a value.
- Permission rules decide who may run which command.
- Members sign in to a web interface with their Fluxer account. They can browse the karma scoreboard and see the commands they're allowed to run, and admins change the settings there.
Fluxer has no slash commands or buttons yet, so commands start with a prefix,
! by default, and every vote is a reaction.
The code is the documentation. src/config.ts describes
every key of the config file and every bot setting, the permission rules
included. !help and the web interface's commands page list the commands a
member may run, with their options.
Running it #
The config file says how to reach Fluxer, where the database goes, where to
serve the web interface, and how much to log. Everything else is a per-server
setting. A server's owner and members with Administrator change those on the
web interface's Admin tab, or with !settings export and !settings import
in chat.
The web interface signs people in through the bot's application. Add
<publicUrl>/auth/callback to the application's redirect URIs and give the
bot its client secret.
On NixOS #
{
inputs.orianna.url = "git+https://knot.zekurio.me/did:plc:c5tl5gu27hssisgzp4x3mmvq/orianna";
outputs = { nixpkgs, orianna, ... }: {
nixosConfigurations.host = nixpkgs.lib.nixosSystem {
modules = [
orianna.nixosModules.default
{
services.orianna = {
enable = true;
tokenFile = "/run/secrets/orianna-token";
settings.instance = "https://chat.example.org";
};
}
];
};
};
}
The module writes settings to /etc/orianna/config.json and keeps the
database in /var/lib/orianna. It hands the token to the service as a systemd
credential, so the file can stay readable by root only. For the web
interface, add web to settings and set clientSecretFile.
Anywhere else #
bun install --production
bun run build
That gives you dist/orianna, one executable with the web interface and the
Bun runtime inside. It runs on the same kind of machine that built it and
needs ImageMagick 7 next to it. To start it:
cp config.example.json config.json # fill in the instance, and `web` or remove it
echo 'FLUXER_BOT_TOKEN=...' > .env # and FLUXER_CLIENT_SECRET for the web interface
./dist/orianna
The bot reads the config from ORIANNA_CONFIG, or ./config.json, and
creates its database on the first start.
What the bot needs in Fluxer #
Give the bot's role these permissions. Skip the rows for features a server leaves off.
| Feature | Where | Permissions |
|---|---|---|
| Commands | Where members run them | View Channel, Send Messages, Embed Links, Add Reactions, Manage Messages |
!settings export |
Where admins run it | Attach Files |
| Proposals | The server | Manage Expressions |
| Proposals | The polls channel | Send Messages, Attach Files, Add Reactions, Manage Messages, Read Message History, Mention Everyone |
!poll |
Where members run it | Send Messages, Embed Links, Add Reactions, Manage Messages, Read Message History |
| Role menus | The server | Manage Roles, with the bot's highest role above every menu role |
| Role menus | The menu channels | Send Messages, Embed Links, Add Reactions, Manage Messages, Read Message History |
| Karma | Where members react | View Channel, Read Message History |
| Karma rules | The server | Manage Roles, with the bot's highest role above every rule role; Kick Members and Ban Members for those rules |
Manage Messages lets the bot move a vote when someone picks another answer,
clear reactions that don't belong, and delete the !poll message once the
poll is up. In command channels it's only for the ⬅️ and ➡️ arrows on long
lists. Mention Everyone is for the @here on each proposal.
Development #
The flake's dev shell provides Bun, SQLite and ImageMagick from the same
nixpkgs as the package build. Enter it with nix develop, or run
direnv allow to load it automatically through .envrc.
nix develop
bun install --frozen-lockfile
cp config.example.json config.json
echo 'FLUXER_BOT_TOKEN=...' > .env
bun run dev
Bun reads the token and client secret from .env; the shell doesn't export
them. Run bun install --frozen-lockfile again after bun.lock changes.
bun run dev restarts the bot when a file changes and reloads open pages of
the web interface. bun run typecheck is the only check there is, so run it
before every commit.
The bot creates its database when it's missing and applies the migration in
drizzle/ whenever it starts. The db:* scripts run drizzle-kit on the
database named in the config file, the same one the bot opens:
| Script | What it does |
|---|---|
bun db:generate |
Replaces drizzle/ with a fresh <timestamp>_init migration from src/db/schema.ts |
bun db:push |
Changes the database to match src/db/schema.ts, without a migration |
bun db:studio |
Opens it in Drizzle Studio |
There are no migrations while the bot is in early development, so after
changing src/db/schema.ts, run bun db:generate, delete the database and
its -wal and -shm files, and start the bot, which creates it again.
AGENTS.md covers commit style, branch names and pull requests.