Skip to content

Contributing

Emiel Kollof edited this page Apr 2, 2026 · 4 revisions

Contributing

Contributions are welcome — bug reports, fixes, and new features alike. Please keep changes minimal and targeted; avoid unnecessary refactoring of working code.


Getting the source

git clone https://github.com/ekollof/xepher.git
cd xepher
git submodule update --init --recursive

Building

make            # build xmpp.so
make test       # run doctest suite
make clean      # remove build artifacts
make install    # install to ~/.local/share/weechat/plugins/

On BSD use gmake instead of make.

The compiler must support C++23 (-std=c++23). GCC 12 or later is required. Clang is not tested but may work.


Code style

General rules

  • Follow the existing style in the file you are editing.
  • C++23 throughout — use std::string_view, std::optional, std::expected, structured bindings, ranges, etc.
  • Use nullptr, not NULL.
  • Prefer std::string / std::string_view over const char * for read-only strings.
  • RAII everywhere — malloc/free/new/delete are forbidden.

Memory management

Pattern What to use
Strophe-allocated strings (e.g. xmpp_jid_bare) xmpp_string_guard
Heap byte buffers heap_buf / make_heap_buf (see src/omemo.hh)
LMDB key strings std::string + fmt::format
WeeChat string_dyn weechat_string_dyn_free(ptr, 1) and own the raw pointer
Fixed-size arrays std::make_unique<T[]>(N)

Never let an LMDB transaction go out of scope without committing or aborting it.

WeeChat conventions

  • All WeeChat API calls start with weechat_.
  • Handler functions return int: 1 = keep handler, 0 = remove.
  • Never use weechat_buffer_merge() — it merges display history and causes unexpected behaviour.
  • Buffer display: use "1" (don't auto-switch), not "auto".

XMPP / Strophe conventions

  • Create stanzas with xmpp_stanza_new() / xmpp_iq_new() etc.
  • Always set the namespace with xmpp_stanza_set_ns().
  • Use xmpp_uuid_gen() for IDs; guard with xmpp_string_guard.
  • Release with xmpp_stanza_release(), free strophe strings with xmpp_free().

Commit message format

<type>: <short description>

[optional body — explain the why, not the what]

Types: feat, fix, docs, refactor, test, chore.

Examples:

fix: MUC occupant display_name was always set to full JID due to pointer comparison
feat: add /feed command for on-demand PubSub item fetch (XEP-0060)
docs: document MUC nicklist role/affiliation prefix symbols

Keep commits atomic — one logical change per commit.


Architecture overview

Key source files

File Responsibility
src/connection.cpp XMPP connection lifecycle; dispatches to .inl handlers
src/connection/message_handler.inl Incoming message processing
src/connection/presence_handler.inl Presence and MUC join/leave
src/connection/iq_handler.inl IQ stanza handling (MAM, caps, vCard, …)
src/account.cpp Account management, LMDB cache, caps cache
src/channel.cpp Chat buffer management (MUC and PM)
src/command.cpp WeeChat /xmpp command implementations
src/user.cpp User objects — display name, color, nicklist
src/omemo.cpp OMEMO encryption/decryption
src/pgp.cpp PGP encryption
src/config.cpp Plugin configuration

Channel types

channel::chat_type::MUC   — multi-user chat room
channel::chat_type::PM    — private (1-on-1) message
channel::chat_type::FEED  — PubSub feed buffer

Check the channel type before any operation that behaves differently in MUC vs PM (typing indicators, nick display, encryption, etc.).

MAM timestamp sentinels (important!)

The LMDB MAM cache stores a timestamp per channel:

Value Meaning
0 Brand new — fetch 7 days of history
-1 User deliberately closed — skip MAM; do not auto-recreate
> 0 Existing channel — fetch only messages newer than this timestamp

Every code path that creates or re-opens a channel must respect the -1 sentinel.

LMDB database

  • Location: ~/.local/share/weechat/xmpp/<account>.db
  • Tables: messages, timestamps, capabilities
  • Load on account connect; flush after updates.
  • Always commit or abort every transaction — never let one go out of scope without doing one of those two.

Testing

There is no automated integration test suite (WeeChat plugin APIs are hard to mock, and XMPP requires live servers). Testing is manual:

  1. Build and install: make && make install
  2. Close WeeChat and reopen it.
  3. Connect an account and exercise the changed feature.
  4. Check the account log and raw XML log for unexpected errors.

The doctest suite (make test) covers utility functions and data structures that do not require WeeChat or XMPP:

make test

Manual regression checklist

Before submitting a pull request, verify these basics still work:

  • PM buffers do not reappear after /close
  • Typing indicators show nick (not full JID) in MUC
  • MUC nicks show resource only (not full JID) in messages
  • OMEMO encrypts/decrypts in a PM
  • /retract picker opens and sends retraction
  • /bookmark lists bookmarks; autojoin works on reconnect
  • Plugin loads without errors (/plugin list shows xmpp)

Submitting changes

  1. Fork the repository on GitHub.
  2. Create a branch: git checkout -b fix/my-bug or feat/my-feature.
  3. Make focused, atomic commits.
  4. Test manually (see above).
  5. Open a pull request against master on github.com/ekollof/xepher.

Please describe what the change does and why in the PR description. Referencing a related issue number is helpful.


Cutting a release

See the Releasing wiki page for the full release, packaging, and publishing workflow.


Related specifications

Clone this wiki locally