Python utility that listens to the Elite Dangerous Data Network (EDDN) Journal feed, filters messages with user-defined criteria, and forwards grouped notifications to a Discord webhook and/or the terminal.
- Python 3.9 or newer.
- The dependencies listed in
requirements.txt(pip install -r requirements.txt). - A Discord webhook URL (optional if you only want terminal output).
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp config.example.yaml config.yamlEdit config.yaml to set your Discord webhook, disable outputs you do not need, and tailor the filters you want to run.
eddn.relay: Relay endpoint to subscribe to (defaults to the public EDDN relay).logging.level: Log verbosity (INFO,DEBUG,WARNING, ...).debug.terminal_output: Defaulttrue; force terminal output whentrue, suppress it entirely whenfalse; remove the key if you want to defer tooutput.terminal.enabled.formatting.normalize_station_placeholders: Converts placeholder station names such as$EXT_PANEL_ColonisationShipinto user-friendly labels (e.g.,Colonization Ship) before they appear in captures, terminal output, and messages.output.terminal.enabled: Prints matched events to the terminal with a readable block layout.output.discord.*: Controls batching behaviour for webhook delivery. Messages are grouped according tobatch_interval_secondsandmax_batch_size, deduplicated across all filters withindedupe_window_seconds, and dispatched to respect Discord limits.watchlists.systems/watchlists.stations: Lists of watched locations. Each entry can be a string or a mapping withnameand optionalalias; aliases feed the human-readable names used in terminal output, friendly messages, and Discord summaries.filters: A list of match rules. Each rule is evaluated against the decoded EDDN payload. Usepathvalues such asmessage.eventorheader.uploaderID, setopto one ofeq,in,contains,regex,exists,gt, orlt, and providevaluewhen the operator requires it. Optionalcaptureslet you listlabel/pathpairs whose extracted values appear alongside matches,send_to_discordtoggles whether matches for that filter are queued for the webhook,send_full_msg_to_terminal: trueprints the entire Journal payload only when the log level isDEBUG(otherwise a note indicates full message output is disabled), andmessage_templatecan produce a friendly sentence using capture labels or built-in fields ({filter},{event},{system},{body},{commander},{timestamp}), with timestamps rendered to minute-level UTC. To reuse a watchlist inside a condition, setvalueto{"watchlist": "systems"}(orstations). Leaving a condition’svalueempty (for example an empty list for events) causes that condition to be ignored. When logging is set toDEBUG, the composed notification message, any captured fields, and each Discord batch payload are summarised to the terminal before the detailed block.
Filters are evaluated against the original payload, so the full message is still available in the Discord notifications or terminal logs if you want to add more context.
python eddn_listener.py --config config.yamlThe listener runs until interrupted. Press Ctrl+C to stop it gracefully.
- The script defaults to the Journal schema, but you can listen for other schemas by adjusting the
schemasubstring in each filter. - Discord notifications are skipped entirely if no webhook URL is configured or if
enabledis set tofalse. - The ZeroMQ socket polls in one-second intervals by default; you can tweak this via
eddn.poll_timeout_msif you need faster flushing at the expense of slightly higher CPU usage.