- C 91.3%
- CSS 2.8%
- Makefile 2%
- JavaScript 1.7%
- HTML 1.5%
- Other 0.7%
| .github/workflows | ||
| migrations | ||
| public | ||
| src | ||
| tools | ||
| .clang-format | ||
| .clangd | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| Makefile | ||
| OPTIONS.md | ||
| README.md | ||
albwidget
shows your albion online pvp stats as a widget on your discord profile: character, guild, kill fame, death fame, fame ratio, and kills tracked since you linked. multi-user, self-hosted, written in c.
each user connects their discord account, runs /link to pick their albion
character, and a background service keeps their profile widget up to date.
how it works
- authorize: a user opens
/login, approves discord oauth (scopesidentify openid sdk.social_layer), and lands on the web dashboard. tokens are stored encrypted. - link: the user picks their character either on the web dashboard or with
the
/link character:<name> [region:<americas|europe|asia>]slash command in discord. the app finds the character via the albion gameinfo api. - poll: a background worker reads the character's kill/death fame and recent kills and writes them to the user's discord game profile.
- add the widget: on desktop or web the user opens edit profile, profile widgets, add widget, and adds the albion online widget. this last step is manual in the discord client; apps cannot add it for you.
configure from either the web dashboard (/dashboard) or the slash commands
/link, /unlink, /status.
what you need
- a discord application with social sdk access and a published profile-widget layout (this is a gated, experimental discord feature). the layout's field names must match the table below.
- a public https url (a real domain with tls, or a tunnel like cloudflared or ngrok). discord requires https.
- postgresql.
- docker, or a c17 compiler with libcurl, libjson-c, libmicrohttpd, libpq, and openssl.
setup
order matters: discord checks the urls by calling your running server, so deploy first, then set the urls.
- in the discord developer portal, create the app. get social sdk access and build + publish a widget layout whose fields match the table below.
- copy
.env.exampleto.envand fill it in. setDISCORD_PUBLIC_KEYbefore you save the interactions url, and generateTOKEN_ENC_KEYandSESSION_SECRETwithopenssl rand -hex 32.cp .env.example .env - put a public https url in front and set
PUBLIC_BASE_URLto it (no trailing slash). start the service and confirm it answers:docker compose up --build curl https://<your-host>/health # -> ok - in the portal, set oauth2 redirect to
${PUBLIC_BASE_URL}/oauth/callbackand interactions endpoint url to${PUBLIC_BASE_URL}/interactions. - install the app so the commands appear: open
${PUBLIC_BASE_URL}/installto add it to a server, or${PUBLIC_BASE_URL}/install?user=1to add it to your own account. - a user authorizes at
${PUBLIC_BASE_URL}/login, runs/linkin discord, then adds the widget on their profile (edit profile, profile widgets, add widget).
widget fields
albwidget fills a generic, slot-based layout, so each user picks what their widget shows from the web dashboard. build your published widget layout in the portal with user-data fields named exactly:
- widget bottom:
stat_1_label..stat_6_label(text) andstat_1_value..stat_6_value- always sent. the value's presentation type is fixed by your layout:stat_1_value..stat_4_valueare numbers,stat_5_valueandstat_6_valueare text. - mini profile:
mini_label(text),mini_text(number),mini_image(image) - widget top:
top_title(text) andtop_image(image)
labels are always text. number fields only accept numeric data (kill fame, death
fame, kills, total fame) and are sent as the raw number; text fields accept any
data and numbers are formatted compactly (e.g. 5.2M). the six widget-bottom
stats are a fixed, required part of the layout, so the app always sends all six.
each user maps the slots to the data they want at /dashboard. available data
points:
| metric | shows |
|---|---|
character |
character name |
guild |
guild name, or "no guild" |
region |
americas, europe, or asia |
kill_fame |
lifetime kill fame |
death_fame |
lifetime death fame |
fame_ratio |
kill/death fame ratio |
kills_tracked |
kills counted since linking |
total_fame |
kill fame plus death fame |
values are sent as compact text (e.g. 5.2M). a label and its value are separate
fields, so each label is whatever the user types. slots left unset show the
layout's fallback.
build from source
make # build build/albwidget
sudo make install
albwidget run # run the server and poller (default)
albwidget register # register the slash commands, then exit
albwidget check-config # validate the environment, then exit
albwidget --help
troubleshooting
- the albion online widget is not in the add-widget menu: the profile data isn't
set, or the app's widget layout isn't published. confirm
/linksucceeded and the logs show nopatch profile failed. profile widgets are desktop/web only. - interactions endpoint url won't validate: the server isn't reachable over https,
or
DISCORD_PUBLIC_KEYis wrong. - commands don't appear: the app isn't installed (step 5), or global commands are still propagating (can take up to an hour; restart your discord client).
/linksays not found: names must match exactly; pick the right region.
notes
kills_trackedis best-effort: more than ~50 kills between polls can undercount (a warning is logged).- tuning lives in env vars:
POLL_INTERVAL,POLL_CONCURRENCY. see OPTIONS.md for all configuration, endpoints, and build targets.
license
agpl-3.0-or-later. see LICENSE.