- C 91.8%
- CSS 2.5%
- Makefile 2%
- JavaScript 1.6%
- HTML 1.4%
- Other 0.7%
| .forgejo/workflows | ||
| .github/workflows | ||
| migrations | ||
| public | ||
| src | ||
| tools | ||
| vendor/stb | ||
| .clang-format | ||
| .clangd | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| 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)
for the top image, users can paste any https url or pick "use discord avatar with
the ring frame", which serves public/images/ring.png composited over their
discord avatar from a stable url (swap that file to restyle the frame).
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 (text) |
guild |
guild name, or "no guild" (text) |
alliance |
alliance name, or "no alliance" (text) |
region |
americas, europe, or asia (text) |
kill_fame |
lifetime pvp kill fame |
death_fame |
lifetime pvp death fame |
fame_ratio |
kill/death fame ratio (text) |
kills_tracked |
kills counted since linking |
total_fame |
lifetime total fame (pvp + pve + gathering + crafting + fishing + farming + crystal) |
pve_fame |
total pve fame |
pve_royal / pve_outlands / pve_avalon / pve_hellgate / pve_corrupted / pve_mists |
pve fame per zone |
gather_fame |
total gathering fame |
gather_fiber / gather_hide / gather_ore / gather_stone / gather_wood |
gathering fame per resource |
crafting_fame |
crafting fame |
fishing_fame |
fishing fame |
farming_fame |
farming fame |
crystal_fame |
crystal league fame |
all of this comes from the same albion gameinfo player call (no third-party
service). text-slot numbers are sent compactly (e.g. 5.2M); number-slot values
are sent raw. 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.