Skip to content

ekollof/xepher

Repository files navigation

Xepher

Xepher logo

Xepher is a WeeChat plugin written in C++23 that adds full XMPP support to WeeChat. It targets XMPP Compliance Suite 2022 (XEP-0459) and implements a broad set of modern XEPs — including OMEMO encryption, Message Archive Management, HTTP file upload, microblogging via PubSub, and more.

Fork of bqv/weechat-xmpp
Original author: Tony Olagbaiye <bqv@fron.io>
Maintained at github.com/ekollof/xepher


Installation

Pre-built packages

Binary packages for v0.8.1 and later are published on GitHub Releases. Pick the file for your distribution:

Platform Package
Debian / Ubuntu xepher_*_amd64.deb
Fedora / RHEL xepher-*-fc*.x86_64.rpm
Arch Linux xepher-*-x86_64.pkg.tar.zst
Void Linux xepher-*_x86_64.xbps
Alpine Linux xepher-*-r0.apk

Note: Avoid the v0.8.0 Fedora RPM and Alpine APK — they were built with a packaging bug that produced ~1 GB artifacts. Use v0.8.1 or newer.

Install examples:

# Debian/Ubuntu
sudo dpkg -i xepher_0.8.1-1_amd64.deb

# Fedora
sudo dnf install ./xepher-0.8.1-1.fc44.x86_64.rpm

# Arch (as root or with sudo)
sudo pacman -U xepher-0.8.1-1-x86_64.pkg.tar.zst

After installing, restart WeeChat (or run /plugin load xmpp.so on first install).

Dependencies

Library Type Linux FreeBSD OpenBSD macOS (Homebrew)
libstrophe runtime ✅ package pkg install libstrophe pkg_add libstrophe brew install libstrophe
libxml2 runtime ✅ package pkg install libxml2 pkg_add libxml brew install libxml2
lmdb runtime ✅ package pkg install lmdb pkg_add lmdb brew install lmdb
libomemo-c runtime ✅ package pkg install libomemo-c pkg_add libomemo-c ⚠️ build from source
libsignal-protocol-c runtime ✅ package pkg install libsignal-protocol-c pkg_add libsignal-protocol-c ⚠️ build from source
gpgme runtime ✅ package pkg install gpgme pkg_add gpgme brew install gpgme
libfmt runtime ✅ package pkg install libfmt pkg_add fmt brew install fmt
clang/clang++ (C++23; ≥ 13) build ✅ package pkg install llvm ✅ base system / pkg_add brew install llvm
gmake build — (GNU make default) pkg install gmake pkg_add gmake brew install make
bison build ✅ package pkg install bison pkg_add bison brew install bison
flex build ✅ package pkg install flex pkg_add flex brew install flex
doctest (header-only) test ✅ vendored in deps/doctest/
WeeChat >= 3.0 runtime ✅ package pkg install weechat pkg_add weechat brew install weechat

On FreeBSD and OpenBSD, run ./install-deps.sh (or build from the port skeletons in packaging/freebsd/ and packaging/openbsd/). Use gmake instead of make.

Supported platforms

The plugin is developed and tested on Linux (Arch, Debian/Ubuntu, Fedora, Void, Alpine). CI builds packages for all five via GitHub Actions on each release tag.

macOS (Apple Silicon and Intel) receives best-effort support via Homebrew. The build system auto-detects the Homebrew prefix and sets PKG_CONFIG_PATH accordingly. See macOS build instructions below.

FreeBSD, OpenBSD, and NetBSD receive best-effort support: the build system and scripts have been ported to POSIX sh and BSD-compatible make, but these platforms are not routinely tested. Known considerations:

  • Use gmake instead of make on BSD (BSD make has different syntax).
  • Default toolchain: Clang/Clang++ (≥ 13). The makefile sets CC=clang and CXX=clang++ on all platforms (Homebrew LLVM on macOS). This matches OpenBSD/FreeBSD and catches Clang-only warnings under -Werror. NetBSD 9.x ships Clang 7 and cannot build — use NetBSD 10.x+ or a newer Clang from pkgsrc. Override with CC=gcc CXX=g++ gmake only for experiments.
  • libsignal-protocol-c and libomemo-c are packaged on FreeBSD and OpenBSD; on NetBSD they may still need to be built from pkgsrc source.
  • Default builds use -O2 -DNDEBUG. Use DEBUG=1 for unoptimized dev builds (-O0 -DDEBUG). Use ASAN=1 for AddressSanitizer (-fsanitize=address; -lasan -lrt on Linux only). Combine: gmake DEBUG=1 ASAN=1.
  • The .source ELF section embedding step (objcopy --add-section) is Linux-only, skipped on BSD, and skipped in distribution builds (PACKAGE_BUILD=1).

Build from source

git clone --depth 1 git@github.com:ekollof/xepher.git
cd xepher
make install-deps   # installs system packages (requires sudo)
make                # optimized plugin (no doctests)
make DEBUG=1        # dev build + 123 doctests
make test           # doctests only (handler slices, StanzaView, IQ builders, …)
make install        # installs to ~/.local/share/weechat/plugins/ — do NOT run as root

On BSD, replace make with gmake throughout.

Doctest is vendored under deps/doctest/ (v2.5.2). make DEBUG=1 or make test runs the full 109 handler-slice tests on every supported platform without a system package. Plain make skips doctests.

To build a distribution-style plugin locally (no .source embed, same as packages):

make PACKAGE_BUILD=1 weechat-xmpp

make install-deps automatically detects your distribution (Debian/Ubuntu, Fedora/RHEL, Arch, openSUSE, Void, Alpine, Gentoo, FreeBSD, OpenBSD, NetBSD, macOS) and installs the required packages.

macOS (Homebrew)

Note: libsignal-protocol-c and libomemo-c are not in Homebrew core and must be built from source before the plugin will compile.

Step 1 — Install Homebrew packages:

./install-deps.sh   # detects macOS and runs the brew install block

Or manually:

brew install llvm make bison flex libstrophe libxml2 lmdb gpgme fmt curl openssl weechat

Step 2 — Build libsignal-protocol-c from source:

git clone https://github.com/signalapp/libsignal-protocol-c
cd libsignal-protocol-c
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$(brew --prefix) .
make && make install
cd ..

Step 3 — Build libomemo-c from source:

git clone https://github.com/gkdr/libomemo-c
cd libomemo-c
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$(brew --prefix) .
make && make install
cd ..

Step 4 — Build Xepher:

git clone --depth 1 git@github.com:ekollof/xepher.git
cd xepher
git submodule update --init --recursive
make
make test
make install

The build system uses -dynamiclib instead of -shared and plain -g instead of -gdwarf-4 on macOS automatically. install-deps.sh installs Homebrew llvm; the makefile defaults to that Clang. No extra CXX= flags are needed.

Debugger: On macOS the make debug target uses lldb with DYLD_INSERT_LIBRARIES instead of gdb/LD_PRELOAD.

WeeChat version compatibility

WeeChat 4.3.0 (May 2024) changed the base64 API. This fork defaults to >= 4.3.0. If you get a compilation error like invalid conversion from 'int' to 'const char*', open omemo.cpp, find this block near line 42, and change #if 1 to #if 0:

#if 1  // Set to 0 for WeeChat < 4.3.0
    #define WEECHAT_BASE64 "64"
#else
    #define WEECHAT_BASE64 64
#endif

Then rebuild with make clean && make.


Usage

Quick start

/account add work user@example.com mypassword
/account connect work

Use /help account for full details.

Encryption status indicator

Add the xmpp_encryption bar item to your status bar to see the current buffer's encryption mode (🔒OMEMO / 🔒PGP / empty for plaintext). In MUCs it may show "🔒OMEMO (pending)" while fetching occupant bundles.

/set weechat.bar.status.items "[time],[buffer_last_number],[buffer_plugin],buffer_number+:+buffer_name+(buffer_modes)+{buffer_nicklist_count}+buffer_zoom+buffer_filter,xmpp_encryption,[lag],[hotlist],completion"

Typing indicator

  1. Enable typing in WeeChat:

    /set typing.look.enabled_nicks on
    /set typing.look.enabled_self on
    /set typing.look.input_min_chars 2
    /save typing
    
  2. Add the typing bar item:

    /set weechat.bar.typing.items "typing"
    /save
    

Message status glyphs

Sent PM messages show delivery and encryption status as aligned prefixes at the start of the message text (WeeChat's private tag hides the nick column for your own lines). Examples: ⌛ hello, ✓ 🔒 hello. Status updates automatically when the recipient acknowledges the message:

Glyph Meaning
Pending — sent, no receipt yet
Delivered — recipient's client received it (XEP-0184)
✓✓ Read — recipient marked it displayed (XEP-0333)

Avatar badges in PM

A colored Unicode symbol (for example ) may appear before a contact's bare JID in PM buffers. That is a deterministic avatar badge derived from their XEP-0084 PEP avatar image — not an OMEMO device ID. Contacts without a published avatar show only the colored JID.

Highlight words

The account nickname is automatically added as a highlight word to PM and FEED buffers so messages containing it trigger a notification. MUC rooms use WeeChat's native nick-based highlighting instead.

To disable this behaviour (e.g. if your short nickname causes false highlights):

/set xmpp.look.highlight_words off
/save

XHTML-IM rendering (XEP-0071)

When a message contains an <html> body, the plugin renders it with WeeChat color/attribute support instead of raw markup.

Element Rendered as
<b>, <strong> Bold
<i>, <em> Italic
<u> Underline
<del>, <s>, <strike> Darkgray
<code>, <tt> Gray monospace
<pre> Gray-wrapped preformatted block
<a href="...">text</a> text (blue URL)
<img alt="..."/> [alt] placeholder
<br> Newline
<blockquote> Green > prefix
<span style="color:..."> Terminal color (16 named + #rgb hex)

Link previews (XEP-0511)

Incoming: When a message contains <rdf:Description> (XEP-0511) carrying OpenGraph metadata, a compact preview is rendered in darkgray:

alice: Check this out! https://example.com/article
        The Best Webpage  This is a great webpage and you will really like it  https://example.com/canonical-url [img]

To disable incoming previews:

/set xmpp.look.incoming_link_preview off

Outgoing: URLs in your messages automatically trigger a background fetch; a metadata stanza is sent as a follow-up so the recipient can render a preview even without server-side injection. To disable:

/set xmpp.look.outgoing_link_preview off

Message Correction — /edit and /edit-to (XEP-0308)

Opens an interactive picker showing your last 20 non-retracted sent messages so you can select which one to correct, then pre-fills the input bar with the original text ready for editing.

/edit                   # open interactive picker — select message, edit in input bar
/edit-to <id> <text>    # correct a specific message by ID (used internally by picker)

How it works:

  1. Type /edit with no arguments to open the interactive picker.
  2. Navigate with / and press Enter to select the message you want to correct.
  3. The picker closes and the input bar is pre-filled with /edit-to <id> <original text>. Edit the text and press Enter to send.
  4. A correction stanza is sent referencing the original message ID. The local buffer updates the line with an [edit] prefix.

Notes:

  • In MUC rooms, correction uses the server-assigned stanza-id (XEP-0359) when available, falling back to the origin-id.
  • Recipients who do not support XEP-0308 will receive the correction as a new message with a [CORRECTION] fallback body.
  • You must be connected and inside a chat buffer (PM or MUC) to use /edit.

Example:

you: Hello eweryone!
/edit
[interactive picker opens — select the message, press Enter]
> input bar is pre-filled: /edit-to abc123 Hello eweryone!
> edit to: /edit-to abc123 Hello everyone!   [Enter]
you: [edit] Hello everyone!

Message Retraction — /retract (XEP-0424)

Deletes one of your own messages from the current buffer.

/retract

Takes no arguments. Opens an interactive picker showing your last 20 non-retracted messages. Navigate with /, press Enter to retract the selected message, or q/Esc to cancel.

How it works:

  1. An interactive picker opens listing your last 20 sent messages (most recent at the top).
  2. Select the message to retract and press Enter.
  3. A retraction stanza is sent referencing that message's ID. In MUC rooms the server-assigned stanza-id (XEP-0359) is used, which is required by the spec.
  4. Supporting clients replace the original message with a tombstone. The local buffer shows [Message deleted] in place of the original text.
  5. A store hint (XEP-0334) is included so MAM archives record the retraction, and other devices that sync history will also see the tombstone.

Notes:

  • Retraction is not a guarantee: recipients who already received the message keep it. Clients that do not support XEP-0424 will instead display the fallback body: [user] retracted a previous message, but it's unsupported by your client.
  • You cannot retract another user's message with /retract. Use /moderate (XEP-0425) for that (requires MUC moderator role).
  • You must be connected and inside a chat buffer (PM or MUC) to use /retract.

Example:

you: I should not have said that
/retract
[interactive picker opens — select the message, press Enter]
-- xmpp: message retraction sent
you: [Message deleted]

Message Reactions — /react (XEP-0444)

Sends an emoji reaction to the last received message in the current buffer.

/react <emoji>

How it works:

  1. Type /react followed by one or more emoji (the entire argument after /react is used as the reaction string).
  2. The plugin finds the most recent message in the buffer that was not sent by you (identified by having an id_ tag and no self_msg tag).
  3. A reaction stanza is sent referencing that message's ID.

Notes:

  • Reactions target the last incoming message, not your own messages.
  • In MUC rooms, the stanza-id (XEP-0359) is used when available.
  • Multiple emoji in a single argument are sent as one reaction (e.g., /react 👍❤️ sends the two-emoji string as a single reaction).
  • Clients that do not support XEP-0444 ignore the reaction stanza silently.
  • You must be connected and inside a chat buffer to use /react.

Examples:

/react 👍
/react ❤️
/react 😂
/react 🎉

Message Replies — /reply and /reply-to (XEP-0461)

Sends a reply with a message reference so supporting clients can display a quoted preview.

/reply                  # open interactive picker to choose which message to reply to
/reply <text>           # reply immediately to the last received message
/reply-to <id> <text>   # reply to a specific message by ID (used internally by picker)

How /reply works (no arguments — interactive picker):

  1. An interactive picker opens listing the last 20 messages received from others (non-own, non-retracted).
  2. Navigate with / and press Enter to select.
  3. The picker closes and the input bar is pre-filled with /reply-to <id> .
  4. Type your reply text and press Enter to send.

How /reply <text> works (with text):

The plugin finds the most recent non-own message and sends a reply directly, without opening the picker. Useful for quick replies.

Notes:

  • Clients that do not support XEP-0461 will display the plain message text without the quoted context.
  • In MUC rooms, the MUC-assigned stanza-id (XEP-0359) is used when present, as required by the spec for rooms with stanza-id support.
  • You must be connected and inside a chat buffer to use /reply.

Examples:

/reply                        # opens picker
/reply Thanks, that helped!   # immediate reply to last received message

Message Moderation — /moderate (XEP-0425)

Removes another user's message from a MUC room (requires moderator role).

/moderate [reason]

Opens an interactive picker showing the last 20 non-retracted messages in the room. Navigate with /, press Enter to moderate the selected message, or q/Esc to cancel. The optional reason is forwarded in the moderation stanza.

How it works:

  1. An interactive picker opens listing the last 20 messages in the MUC buffer (both own and others', excluding already-retracted messages).
  2. Select the message to moderate and press Enter.
  3. A moderation stanza is sent referencing the server-assigned stanza-id (XEP-0359), which is required by XEP-0425 for MUC moderation.
  4. Supporting clients replace the original message with a moderation tombstone.

Notes:

  • Requires MUC moderator role. The server will reject the request otherwise.
  • Use /retract to delete your own messages instead.
  • Moderation is not a guarantee: clients that do not support XEP-0425 may still show the original message.
  • Must be used inside a MUC buffer (not a PM channel).

Examples:

/moderate
/moderate Spam message
/moderate Violates community guidelines

Microblogging — /feed (XEP-0277 / XEP-0472)

Publish and interact with microblog posts on PubSub services such as Movim and Libervia/Salut-à-Toi. XMPP microblogging is XMPP's equivalent of a federated social timeline — posts are Atom entries stored on PubSub nodes; contacts who subscribe to your urn:xmpp:microblog:0 PEP node receive your posts in real-time.

Feed content is rendered with full visual formatting: XHTML via the XEP-0071 renderer, HTML stripped to plain text, and plain-text entries processed through a lightweight Markdown renderer (headings, bold, italic, inline code, fenced blocks, blockquotes, lists, links, images, strikethrough, horizontal rules).

Note: XEP-0277 is Deferred and XEP-0472 is Experimental. Server support varies. Movim and Libervia implement the full stack; ejabberd supports the underlying XEP-0060 mechanics.

Short aliases (#N):

When you fetch a feed, each item is assigned a short #N alias shown in green. Use it in place of the full item-id in any write command:

/feed reply #3 That's a great point!
/feed repeat #3 Great content
/feed comments #3
/feed retract #3

Publishing a post:

# Long form
/feed post movim.eu urn:xmpp:microblog:0 Hello from WeeChat!
/feed post movim.eu myblog --open My public post     # --open = public node
/feed post movim.eu myblog --title My Headline -- Body text   # with Atom title

# Short form from a feed buffer (service/node inferred)
/feed post Hello everyone!
/feed post -- https://example.com check this out     # '--' avoids JID-like parse

# Compose in $EDITOR (requires feed_compose.py)
/feed post --edit

Sends an Atom <entry> to the PubSub node with pubsub#type=urn:xmpp:microblog:0 and the urn:xmpp:pubsub-social-feed:1 publish-option required by XEP-0472. Failed publishes are reported in the buffer with the server error condition.

Embedding media in a post (XEP-0363 + XEP-0447):

Top-level microblog posts (not comments) support Jinja2-style embed tags that upload files via HTTP File Upload and insert XEP-0447 <file-sharing> children into the Atom entry:

{{ embed "photo.jpg" }}                  # inline image → ![photo.jpg](url)
{{ embed "photo.jpg" alt="sunset" }}     # with alt text
{{ attach "paper.pdf" }}                 # download link → [paper.pdf](url)
{{ attach "paper.pdf" alt="My Paper" }}
{{ video "demo.mp4" }}                   # inline video → ![demo.mp4](url)
{{ video "demo.mp4" alt="Demo" }}
  • embed and video set disposition='inline'; attach sets disposition='attachment'
  • Files are uploaded one at a time (async); the Atom entry is published only when all uploads have completed
  • On any upload failure the post is aborted and a draft is saved to $weechat_data_dir/xmpp/drafts/<account>-<timestamp>.md with YAML frontmatter; the draft path is printed in the feed buffer
  • Embed tags are not supported in comments nodes; attempting them prints an error

Receiving clients that support XEP-0447 (Conversations, Dino, Gajim) render the media natively. Xepher displays a summary line for each attachment:

[Image: photo.jpg (image/jpeg, 1.2 MB) https://…]
[File:  paper.pdf (application/pdf, 340 KB) https://…]

Replying to a post (threaded):

/feed reply movim.eu urn:xmpp:microblog:0 abc123 That's a great point!
/feed reply #3 That's a great point!    # short form using alias
/feed reply #3 --edit                   # compose reply in $EDITOR

Adds a thr:in-reply-to element (RFC 4685) referencing the original item. Clients such as Movim render threaded conversations from these references.

Boosting / repeating a post (XEP-0472 §4.5):

/feed repeat movim.eu urn:xmpp:microblog:0 abc123
/feed repeat movim.eu urn:xmpp:microblog:0 abc123 Great post!
/feed repeat #3                         # short form using alias
/feed repeat #3 Great content!          # short form with comment

Publishes a new entry with <link rel='via'> pointing to the original item. An optional comment is included in the entry body.

Retracting (deleting) a post:

/feed retract movim.eu urn:xmpp:microblog:0 abc123
/feed retract #3    # short form using alias

Sends a PubSub retract IQ. Server errors are reported in the buffer.

Fetching comments for a post:

/feed comments movim.eu urn:xmpp:microblog:0 abc123
/feed comments #3   # short form using alias

If the post carried a <link rel='replies'> element (XEP-0277 §4.1), this fetches the linked comments node into a dedicated FEED buffer. The hint is shown in the feed buffer as Comments: /feed comments #N. Run /feed movim.eu urn:xmpp:microblog:0 first if no hint is shown.

Subscribing and unsubscribing:

/feed subscribe news.movim.eu Phoronix
/feed unsubscribe news.movim.eu Phoronix
/feed subscriptions news.movim.eu

Sends XEP-0060 subscribe/unsubscribe IQ stanzas. Feedback (success or error condition) is printed in the originating buffer.

Receiving posts from contacts:

Incoming PEP pushes from contacts' urn:xmpp:microblog:0 nodes are automatically rendered in the WeeChat buffer for that contact, showing the author name, timestamp, content body, and — when present — threaded reply references (thr:in-reply-to), boost/repeat provenance (Repeated from:), comments links (Comments: /feed comments #N), category tags, enclosure URLs, and geolocation. XHTML and HTML content is rendered with WeeChat formatting. Duplicate items (already seen via IQ fetch) are suppressed via LMDB deduplication.

Reading a microblog feed:

/feed movim.eu urn:xmpp:microblog:0
/feed movim.eu urn:xmpp:microblog:0 --limit 5
/feed movim.eu urn:xmpp:microblog:0 --before <item-id>   # older page (RSM)
/feed movim.eu urn:xmpp:microblog:0 --latest             # reset cursor; newest page

The RSM cursor is persisted in LMDB. Use --latest to go back to the newest page after paging back through older items.

Auto-discovering your server's PubSub services:

At connect time the plugin queries your server's disco#items (XEP-0030) to find all components, then queries disco#info on each one. Any component reporting identity category='pubsub' is remembered. You can then use:

/feed                        # fetch subscriptions from all discovered services
/feed discover               # list discovered services without fetching
/feed discover --all         # fetch every node from every discovered service
/feed close                  # close all open feed buffers (does not unsubscribe)

Closing feed buffers:

/feed close dismisses every open FEED buffer without unsubscribing from PubSub nodes. Closed feeds do not receive pubsub push updates until opened again via /feed.

Disabling feeds entirely:

If you do not use microblogging and want to prevent feed buffers from appearing:

/set xmpp.look.feeds off

When off: no feed buffers are created or restored on connect, pubsub pushes for feed nodes are ignored, and /feed is disabled (except /feed close to dismiss buffers that were already open). Default is on. Re-enable with /set xmpp.look.feeds on.

Legacy OMEMO PEP nodes (eu.siacs.conversations.axolotl.*) are never misclassified as feeds; this option is for users who want no PubSub timeline buffers at all.


Ad-hoc Commands and Data Forms (XEP-0050 / XEP-0004)

/adhoc example.com                          # list available commands
/adhoc example.com announce                 # execute a command (form rendered inline)
/adhoc example.com announce <id> subject=Hello body=World

Required fields are marked with *. Multi-step sessions are supported.


Command reference

Account management

/account list
/account add <name> <jid> <password>
/account connect <account>
/account disconnect <account>
/account reconnect <account>
/account delete <account>
/account register <name> <jid> <password>   # create account on server (XEP-0077)
/account unregister <account>               # cancel account on server (XEP-0077)
/account password <account> <new-password>  # change password in-band (XEP-0077)

Messaging

Command Description
/enter <jid> Join a MUC room
/join <jid> Alias for /enter
/open <jid> Open a direct chat (PM)
/query <jid> [msg] Alias for /open
/msg <text> Send a message to the current buffer
/me <text> Send a /me action (XEP-0245)
/ephemeral <seconds> <text> Send an ephemeral message that disappears after N seconds (XEP-0466)
/notify [<jid>] [always|on-mention|never] Get or set per-chat notification preference (XEP-0492)
/invite [--mediated] <jid> [reason] Invite a user to the current MUC (XEP-0249 direct by default; --mediated for XEP-0045 §7.8.2)
/decline [room inviter [reason]] Decline a pending mediated MUC invitation (XEP-0045 §7.8.2; account buffer)
/selfping Verify MUC membership (XEP-0410)
/edit Picker: choose a sent message to correct (XEP-0308)
/edit-to <id> <text> Correct a specific message by ID — used by the /edit picker
/retract Picker: choose a sent message to delete (XEP-0424)
/moderate [reason] Picker: choose a MUC message to moderate (XEP-0425)
/react <emoji> React to the last received message (XEP-0444)
/reply Picker: choose a message to reply to (XEP-0461)
/reply <text> Reply to the last received message (XEP-0461)
/reply-to <id> <text> Reply to a specific message by ID (XEP-0461)
/spoiler [hint:] <text> Send a spoiler message (XEP-0382)
/buzz Send attention request to current PM contact (XEP-0224)
/whois [jid] Retrieve vCard information (XEP-0054)
/setvcard <field> <value> Publish a vCard field (XEP-0054)
/setavatar <filepath> Publish avatar image (XEP-0084)

MUC room management

Command Description
/enter <jid> Join a MUC room (creates it if it doesn't exist on the server)
/join <jid> Alias for /enter
/create <room@server> [nick] [--reserved] Create a new MUC room (XEP-0045 §10.1). With --reserved the room is created locked so the owner can configure it via /setmodes / /affiliation / /destroy before letting anyone in. Without --reserved the room is unlocked with server defaults (instant room) as soon as the server signals status 201
/kick <nick> [reason] Kick a user from the MUC (requires moderator role)
/ban <jid> [reason] Ban a user by JID (requires admin/owner role)
/voice <nick> [reason] Grant voice in a moderated room (role=participant; moderator)
/devoice <nick> [reason] Revoke voice (role=visitor; moderator)
/op <nick> [reason] Grant moderator role (admin/owner)
/deop <nick> [reason] Revoke moderator role back to participant (not a kick)
/affiliation list [owner|admin|member|outcast] Query affiliation list (default: member)
/affiliation set <jid> <aff> [--nick <nick>] [reason] [--confirm] Change affiliation; --nick sets or unsets (empty) reserved member nick
/mucregister query Show room registration / reserved-nick info (XEP-0045 §15)
/mucregister [nick] Register with the room using the given nick
/invite [--mediated] <jid> [reason] Invite a user (direct XEP-0249 by default; --mediated for XEP-0045 §7.8.2)
/decline [room inviter [reason]] Decline a pending mediated MUC invitation (XEP-0045 §7.8.2)
/topic [text] Set or clear the room topic
/nick [newnick] Change your nickname in the current MUC
/names List all known occupants in the current MUC with IRC-style role/affiliation prefixes (same symbols as the nicklist; sorted by rank then nick)
/modes Display the MUC room modes and metadata (XEP-0045 §6.4/6.5). The mode flags alone also appear in the buffer's status-bar modes slot IRC-style (e.g. +miP for a moderated, members-only, persistent room) — automatically updated on join and on status-104 config-change notifications
/setmodes [+/-][m][i][k][p][P][N][S] [secret] [--confirm] Set/clear room mode flags (XEP-0045 §10.2, owner-only). Without --confirm prints the planned diff
/destroy [<reason> [<alt-jid> [<alt-password>]]] [--confirm] Destroy the current MUC room (XEP-0045 §10.7, owner-only). Irreversible — use --confirm to apply

MUC nicklist prefixes

Each nick in a MUC room displays a prefix indicating their role or affiliation (XEP-0045). Affiliation takes precedence over role when both apply.

Prefix XEP-0045 role/affiliation Meaning
~ affiliation: owner Room owner — full control
& affiliation: admin Administrator — can grant/revoke roles
@ role: moderator Can kick and mute participants
% affiliation: member Registered member (voice in members-only rooms)
+ role: participant Can send messages (standard occupant)
? role: visitor Read-only in a moderated room
! affiliation: outcast Banned from the room
. (none) No role or affiliation set yet

Privacy & blocking

Command Description
/block <jid> [...] Block one or more JIDs (XEP-0191)
/unblock [jid ...] Unblock JIDs, or all if no argument given
/blocklist List all blocked JIDs

Encryption

Note: OMEMO for non-anonymous MUC rooms (XEP-0384 §5.8 multi-recipient) is implemented but experimental and lightly tested. Use at your own risk. See docs/planning-muc-omemo.md for architecture and status. PM OMEMO remains the primary tested path.

MUC requirements: The room must be non-anonymous — every occupant's real bare JID must be visible (check with /modes; N in the mode string). OMEMO is refused in semi-anonymous or fully anonymous rooms.

MUC prefetch: When OMEMO is enabled in an eligible MUC, device lists and bundles for occupants are fetched in the background so the first encrypted message can be sent once the bar leaves 🔒OMEMO (pending). Passive prefetch establishes Signal sessions quietly; it does not send key-transport groupchat stanzas into the room (avoiding spurious undecryptable messages for strangers). Key-transport is sent only when explicitly needed — e.g. /omemo kex or decrypt recovery after you have exchanged encrypted traffic with that contact.

Trust model: This plugin uses Blind Trust Before Verification (BTBV) TOFU, matching Gajim's default behaviour. Trust levels are stored per {jid, device_id} in LMDB:

Level Name Meaning
BLIND Auto-trusted First device seen for this JID (default)
VERIFIED Manually verified User ran /omemo trust <jid> [device-id]
UNTRUSTED Explicitly distrusted User ran /omemo distrust <jid> [device-id]; device is excluded from encryption
UNDECIDED New device A new device for a JID that already has VERIFIED or UNTRUSTED keys

Only BLIND and VERIFIED devices receive encrypted key material. UNTRUSTED devices are silently skipped. When you enable OMEMO in a MUC, all occupant devices default to BLIND trust — verify important contacts with /omemo trust if desired.

Command Description
/omemo Enable OMEMO for the current buffer. Works for both PMs and non-anonymous MUCs (MUC OMEMO support is experimental and untested — see planning doc).
/omemo check Verify OMEMO bundle is published
/omemo republish Republish legacy OMEMO bundle nodes (axolotl namespace)
/omemo status Show device ID and status
/omemo reset-keys Reset key database (forces renegotiation)
/omemo fetch [jid] [device-id] Force devicelist/bundle refresh
/omemo kex [jid] [device-id] Force key transport now
/omemo fingerprint [jid] Show colon-hex fingerprint(s) with BTBV trust status ([BLIND]/[VERIFIED]/[UNTRUSTED]/[UNDECIDED])
/omemo devices <jid> List known OMEMO devices for a JID
/omemo trust <jid> [device-id] Mark key(s) as VERIFIED (manual trust)
/omemo distrust <jid> [device-id] Mark key(s) as UNTRUSTED (blocks encryption to that device)
/pgp [keyid|status|reset] Manage PGP encryption
/plain Disable encryption (use plaintext)

File sharing

/upload [filename]   # interactive picker if no filename given

Uploads a file via HTTP File Upload (XEP-0363) and announces it in the current channel using a three-layer stanza for maximum client compatibility (implemented with the fluent stanza builder per project rules for XEP support):

  1. XEP-0447 Stateless File Sharing (urn:xmpp:sfs:0, disposition='inline') — used by Conversations ≥ 2.10, Dino, and Gajim to display inline image previews without the user having to click a link. Includes XEP-0446 <file> (media-type, name, size, sha-256 hash, width/height for images) + sources.
  2. XEP-0385 SIMS (urn:xmpp:sims:1) — older inline media sharing, understood by clients that pre-date XEP-0447.
  3. XEP-0066 OOB (jabber:x:oob) — plain URL fallback; renders as a clickable link in any client that does not understand the above.

For OMEMO-enabled channels the file is AES-256-GCM encrypted before upload (XEP-0448 ESFS); the stanza carries the <encrypted> block with b64 key/iv + cipher hash and the visible body uses the aesgcm://...#ivkey convention so supporting clients can decrypt. The outer <file> metadata always describes the original plaintext.

For JPEG and PNG images the plugin automatically detects <width> and <height> from the file's binary headers (JPEG SOF markers, PNG IHDR chunk) and includes them in the XEP-0446 <file> element so receiving clients can pre-size preview boxes before the image finishes downloading.

Incoming XEP-0447 file-sharing stanzas sent by other clients are also parsed and displayed, deduplicated against any SIMS or OOB element for the same URL so the file appears only once per message.

XEP-0231 Bits of Binary (small images, plaintext only): On channels without OMEMO, /upload on an image/* file of 8 KiB or less is sent as BoB instead of HTTP upload (Movim sticker interop). The message carries XHTML-IM <img src='cid:sha1+…@bob.xmpp.org'/>; payloads of 1 KiB or less also include inline <data xmlns='urn:xmpp:bob'/>, and larger ones are IQ-hosted from bob_hosted when peers fetch the cid. The plugin advertises urn:xmpp:bob in entity capabilities. OMEMO-enabled channels still use HTTP upload with XEP-0448 ESFS for images — outbound BoB inside encrypted messages is not implemented.

Inline image display (weechat-icat)

The weechat-icat script is vendored in scripts/icat.py (built from https://github.com/trygveaa/weechat-icat). Enabling xmpp.look.icat causes the plugin to automatically display received images inline using the Kitty graphics protocol:

  • Outgoing uploads — the local file is shown via /icat immediately after the upload completes and the sharing link is posted (HTTP upload or XEP-0231 BoB).
  • Incoming SFS / SIMS / OOB — unencrypted image URLs are passed to /icat when the message is received (including MAM replay).
  • Incoming encrypted uploads (XEP-0448 ESFS) — after the file is decrypted and saved to ~/Downloads/xmpp/<jid>/<date>/, /icat is invoked on the local path.
  • XEP-0449 stickers<sticker xmlns='urn:xmpp:stickers:0'/> with sibling SFS image payloads; the [File: …] suffix is suppressed when icat displays the image.
  • XEP-0514 custom emoji<emoji xmlns='urn:xmpp:markup:emoji:0'/> spans in XEP-0394 markup resolved against sibling SFS/SIMS file hashes.
  • XEP-0231 BoB (Movim stickers) — XHTML-IM <img src='cid:…@bob.xmpp.org'/> references are IQ-fetched from the sender, cached under ~/.local/share/weechat/xmpp/bob_cache/<account>/, and displayed inline (the [Sticker] placeholder is not shown when icat is enabled).

Only image MIME types (image/*) trigger icat. Other file types are announced normally without inline display.

Note: The plugin passes -print_immediately to icat so placeholder lines are printed synchronously, directly under the message that shared the image. Kitty terminals correctly scroll these image cells together with the buffer text.

During MAM replay, image URLs are never passed directly to icat (async HTTP downloads would land out of order). Instead the plugin resolves each image to a local file first — LMDB cache hit, synchronous download, or synchronous ESFS decrypt — then invokes icat on that path immediately after the message line. Live delivery still uses icat's async URL fetch, but also caches downloaded paths for faster MAM replay on reconnect.

Setup:

cp scripts/icat.py ~/.local/share/weechat/python/autoload/

Inside WeeChat:

/script load icat.py
/set xmpp.look.icat on

Requires a terminal that supports the Kitty graphics protocol (e.g. Kitty, WezTerm, or foot). Also requires Python PIL/Pillow (pip install Pillow or python-pillow package).

Archive & history

/mam [days]                          # fetch history (default: 7 days)
/mam prefs                           # show MAM preferences (XEP-0441)
/mam prefs default <always|never|roster>  # set default archiving policy
/mam prefs always <jid>              # add JID to always-archive list
/mam prefs never <jid>               # add JID to never-archive list

Service discovery & roster

Command Description
/disco [jid] Discover services and features (XEP-0030)
/adhoc <jid> [node] [id] [field=value ...] Execute ad-hoc commands (XEP-0050)
/roster Display contact list
/roster add <jid> [name] Add a contact
/roster del <jid> Remove a contact
/list [keywords] Search public MUC rooms (XEP-0433)
/feed Fetch subscriptions from all auto-discovered PubSub services (XEP-0060)
/feed close Close all open feed buffers (does not unsubscribe)
/feed discover List auto-discovered PubSub services
/feed discover --all Fetch every node from every discovered service
/feed <service-jid> Fetch all subscribed nodes on a service
/feed <service-jid> --all Discover and fetch all nodes via disco#items
/feed <service-jid> <node> Fetch a specific node into a dedicated buffer
/feed ... --limit N Override the per-node item limit (default: 20)
/feed ... --before <id> Fetch items older than <id> (XEP-0059 RSM paging)
/feed ... --latest Clear saved RSM cursor; return to the newest page
/feed subscribe <service> <node> Subscribe to a PubSub node
/feed unsubscribe <service> <node> Unsubscribe from a PubSub node
/feed subscriptions <service> List subscribed nodes on a service
/feed post <service> <node> [--open] [--title <t>] <text> Publish a microblog Atom entry (XEP-0472); --title sets Atom <title>
/feed post [--open] [--title <t>] <text> Short form: post from a feed buffer (service/node inferred)
/feed post --edit Open $EDITOR via feed_compose.py; YAML frontmatter for optional title
/feed post -- <text> -- separator: body starts with JID-like word or URL
/feed reply <service> <node> <item-id|#N> <text> Reply with thr:in-reply-to threading (no title)
/feed reply #N <text> Short form reply using item alias
/feed reply #N --edit Compose reply in $EDITOR via feed_compose.py (no frontmatter)
/feed repeat <service> <node> <item-id> [comment] Boost/repeat a post (XEP-0472 §4.5)
/feed repeat #N [comment] Short form boost using item alias
/feed retract <service> <node> <item-id> Retract (delete) a published post
/feed retract #N Short form retract using item alias
/feed comments <service> <node> <item-id|#N> Fetch comments node for a post (XEP-0277)
/feed comments #N Short form fetch comments using item alias
/bookmark List bookmarks
/bookmark add [jid] [name] Add a bookmark
/bookmark del <jid> Remove a bookmark
/bookmark autojoin <jid> <on|off> Toggle autojoin

Rooms with autojoin enabled are joined in the background on connect (no buffer switch). Use /enter or /join manually to join and switch to the room buffer.

Network & status

Command Description
/ping [jid] Send XMPP ping (XEP-0199)
/mood [mood [text]] Publish mood via PEP (XEP-0107)
/activity [category[/specific] [text]] Publish activity via PEP (XEP-0108)
/xml <stanza> Send raw XML (advanced/debug)
/xmpp Show plugin version
/trap Trigger debug breakpoint (developers only)

Interactive picker UI

Several commands open an in-buffer interactive picker when invoked without arguments. Picker key bindings:

Key Action
/ Navigate up/down
Enter Confirm selection
q / Esc Cancel and return to previous buffer

Debugging

Three complementary mechanisms are available for diagnosing protocol issues. All are opt-in and off by default so normal users see no extra noise.

Verbose protocol log — xmpp.look.debug

Routes internal protocol messages (PEP events, avatar updates, vCard auto-fetches, OMEMO device lists and session bootstrap, stream management, client state, upload service discovery) to a dedicated xmpp.debug buffer (xmpp.debug in WeeChat buffer notation) instead of cluttering account buffers.

/set xmpp.look.debug on

The buffer is created lazily on first use. Each line carries a dim [file:line] source prefix so you can trace back to the exact code path.

To jump to the debug buffer:

/buffer xmpp.debug

To turn it off again (messages stop appearing; buffer remains open):

/set xmpp.look.debug off

Raw XML stanza log — xmpp.look.raw_xml_log

Appends every inbound (RECV) and outbound (SEND) XML stanza to a per-account log file on disk. Useful when you need the full wire-level picture for protocol analysis or when filing bug reports.

/set xmpp.look.raw_xml_log on

Log files are written to:

~/.local/share/weechat/xmpp/raw_xml_<account>.log

Each entry is formatted as:

[YYYY-MM-DD HH:MM:SS] SEND|RECV <stanza-name>
<full xml text>

Turn off to stop writing (existing log file is kept):

/set xmpp.look.raw_xml_log off

PubSub feeds — xmpp.look.feeds

Controls whether PubSub microblog feed buffers (/feed, XEP-0060 / XEP-0472) are enabled. On by default.

/set xmpp.look.feeds off   # disable feed buffers and /feed (except /feed close)
/set xmpp.look.feeds on    # re-enable (default)

See Microblogging — /feed for details.

OMEMO log correlation helper

When diagnosing OMEMO key transport or session bootstrap issues, the correlate_omemo_xml.sh helper cross-references WeeChat log events with raw XML stanzas so you can see what the plugin received at the exact moment an error occurred:

tools/correlate_omemo_xml.sh --account <account>

This is most useful when xmpp.look.raw_xml_log is also enabled, since the helper reads from raw_xml_<account>.log.


Companion scripts

Optional Python scripts live in scripts/. They are not loaded automatically — install the ones you want by hand.

feed_compose.py — compose posts in $EDITOR

Opens a temporary Markdown file in your editor. For posts the file includes a YAML frontmatter block with an optional title: field — fill it in to set the Atom <title> headline, or leave it blank for a body-only post. For replies and when run from a comments buffer the frontmatter is omitted automatically (comments carry no Atom title). On save the content is placed in the WeeChat input bar as a /feed post … or /feed reply … command ready to review and send.

The easiest way to invoke it is with the --edit flag:

/feed post --edit          # new post in $EDITOR
/feed reply #3 --edit      # reply in $EDITOR

Or install and invoke directly:

cp scripts/feed_compose.py ~/.local/share/weechat/python/autoload/

Inside WeeChat:

/alias add fc /feed-compose
/key bind meta-e /feed-compose

See scripts/README.md for full configuration options.

icat.py — inline image display (vendored weechat-icat)

Displays shared images inline using the Kitty graphics protocol. Vendored from https://github.com/trygveaa/weechat-icat (MIT license). Used automatically when xmpp.look.icat is enabled.

Requires Python PIL/Pillow (pip install Pillow or python-pillow package).

cp scripts/icat.py ~/.local/share/weechat/python/autoload/

Contributing

Pull requests and issues are welcome. See the Contributing wiki page and AGENTS.md for architecture and style guidance.

  • C++23 throughout — match existing style in the file you edit.
  • Port abstraction — use xmpp::StanzaView for inbound stanzas, fluent stanza::spec builders for outbound stanzas, and weechat::UiPort / BufferPort / LineStorePort for WeeChat output. Raw xmpp_stanza_get_* and weechat_printf belong only in hook/adapter glue.
  • Tests — run make DEBUG=1 or make test (123 doctests) after changes; manual WeeChat testing for integration behaviour.
  • Releases — see Releasing wiki; pushing a v* tag triggers GitHub Actions to build and attach packages.

Community

The official Xepher MUC is the place to ask questions, report usage issues that don't belong in the GitHub issue tracker, share tips, and follow announcements:

You can join with the plugin itself once any account is connected:

/xmpp enter xepher@conference.hackerheaven.org

Or from any other XMPP client (Conversations, Gajim, Dino, Monal, etc.) using the JID above.


XMPP Compliance (XEP-0459: CCS2022)

Core IM

  • ✅ XEP-0030: Service Discovery
  • ✅ XEP-0045: Multi-User Chat — /create, IRC-style admin (/kick, /ban, /voice, /devoice, /op, /deop), owner config (/setmodes, /affiliation, /destroy), registration (/mucregister), direct and mediated invites (/invite, /decline); no full interactive roomconfig UI
  • ✅ XEP-0054: vcard-temp (retrieval via /whois, publishing via /setvcard)
  • ✅ XEP-0077: In-Band Registration (/account register, unregister, password)
  • ✅ XEP-0115: Entity Capabilities (persistent caching)
  • ✅ XEP-0163: Personal Eventing Protocol
  • ✅ XEP-0191: Blocking Command
  • ✅ XEP-0198: Stream Management — negotiates SM before application stanzas; session resume with stanza retransmit; resume failure falls back to fresh <enable/>; on resume skips redundant roster/presence/MAM/feed fetches; honors server <enabled location='…'/> for reconnect; closes stream on invalid peer ack (handled-count-too-high); graceful final ack before disconnect

Advanced IM

  • ✅ XEP-0245: The /me Command
  • ✅ XEP-0249: Direct MUC Invitations
  • ✅ XEP-0308: Last Message Correction
  • ✅ XEP-0363: HTTP File Upload
  • ✅ XEP-0393: Message Styling
  • ✅ XEP-0410: MUC Self-Ping
  • ✅ XEP-0424: Message Retraction
  • ✅ XEP-0425: Message Moderation
  • ✅ XEP-0444: Message Reactions
  • ✅ XEP-0461: Message Replies

Additional implemented XEPs

  • ✅ XEP-0004: Data Forms (rendered in-buffer for Ad-Hoc Commands)
  • ✅ XEP-0048: Bookmark Storage (Private XML)
  • ✅ XEP-0049: Private XML Storage
  • ✅ XEP-0050: Ad-Hoc Commands
  • ✅ XEP-0059: Result Set Management (MAM paging)
  • ✅ XEP-0066: Out of Band Data
  • ✅ XEP-0071: XHTML-IM (bold, italic, underline, code, blockquotes, links, CSS colors)
  • ✅ XEP-0085: Chat State Notifications (all 5 states)
  • ✅ XEP-0092: Software Version
  • ✅ XEP-0107: User Mood
  • ✅ XEP-0108: User Activity
  • ✅ XEP-0153: vCard-Based Avatars (receive; publishing not yet implemented)
  • ✅ XEP-0172: User Nickname
  • ✅ XEP-0184: Message Delivery Receipts
  • ✅ XEP-0199: XMPP Ping
  • ✅ XEP-0202: Entity Time
  • ✅ XEP-0203: Delayed Delivery
  • ✅ XEP-0223: Persistent Storage of Private Data via PubSub
  • ✅ XEP-0224: Attention
  • ✅ XEP-0280: Message Carbons
  • ✅ XEP-0283: Moved (account migration notices)
  • ✅ XEP-0292: vCard4 Over XMPP (fetch via /whois; no publish support yet)
  • ✅ XEP-0297: Forwarded Messages
  • ✅ XEP-0300: Cryptographic Hash Functions
  • ✅ XEP-0313: Message Archive Management (with LMDB caching)
  • ✅ XEP-0319: Last User Interaction in Presence
  • ✅ XEP-0333: Chat Markers
  • ✅ XEP-0334: Message Processing Hints
  • ✅ XEP-0352: Client State Indication
  • ✅ XEP-0359: Unique and Stable Stanza IDs
  • ✅ XEP-0372: References
  • ✅ XEP-0380: Explicit Message Encryption
  • ✅ XEP-0382: Spoiler Messages
  • ✅ XEP-0384: OMEMO Encryption (legacy axolotl namespace eu.siacs.conversations.axolotl only — OMEMO:2 / urn:xmpp:omemo:2 is not supported; BTBV trust model with per-device LMDB trust store; random pre-key selection; own-device encryption for carbon-copy and self-message decryption; pre-key ID continuity across signed pre-key rotation; stale-session recovery via MAM bundle re-fetch)
  • ✅ XEP-0385: Stateless Inline Media Sharing (SIMS <reference uri> extraction fixed for urn:xmpp:reference:0 sources)
  • ✅ XEP-0392: Consistent Color Generation
  • ✅ XEP-0402: PEP Native Bookmarks
  • ✅ XEP-0422: Message Fastening
  • ✅ XEP-0428: Fallback Indication
  • ✅ XEP-0437: Room Activity Indicators (Deferred — subscribe via <rai xmlns='urn:xmpp:rai:0'/> presence to own bare JID on connect; incoming <activity> notifications displayed in account buffer)
  • ✅ XEP-0446: File Metadata Element (image dimensions sent with uploads)
  • ✅ XEP-0447: Stateless File Sharing (inline previews for Conversations/Dino/Gajim)
  • ⚡ XEP-0231: Bits of Binary (Experimental — receive: inline <data xmlns='urn:xmpp:bob'/> and XHTML-IM cid:…@bob.xmpp.org image refs; IQ-fetch uncached payloads; local cache + weechat-icat; send: plaintext /upload of images ≤8 KiB as BoB + XHTML-IM with sha1 cid, inline data ≤1 KiB, IQ-get hosting; urn:xmpp:bob in caps; OMEMO outbound BoB not implemented)
  • ⚡ XEP-0449: Stickers (Experimental — receive: <sticker xmlns='urn:xmpp:stickers:0'/> with SFS images; inline via weechat-icat; sticker pack pubsub not implemented)
  • ⚡ XEP-0514: Emoji Markup (Experimental — receive: custom emoji spans in XEP-0394 markup resolved against sibling SFS/SIMS hashes; inline via weechat-icat)
  • ✅ XEP-0490: Message Displayed Synchronization
  • ✅ XEP-0511: Link Metadata (incoming previews + outgoing OpenGraph)
  • ⚡ XEP-0277: Microblogging over XMPP (Deferred — publish/reply/retract via /feed post|reply|retract; receive PEP microblog push events; Atom metadata: title, author, categories, enclosures, geolocation, replies links; /feed comments fetches comments nodes)
  • ⚡ XEP-0394: Message Markup (Experimental — receive-only: <markup xmlns='urn:xmpp:markup:0'> parsed and rendered to WeeChat colour codes; <span emphasis> → italic, <span strong> → bold, <span code> → cyan, <span deleted> → grey, <bcode> → grey block, <bquote> → green-prefixed lines, <list>/<li> → bullet markers; takes precedence over XEP-0393 when present; advertised in caps)
  • ⚡ XEP-0413: Order-By for MAM (Experimental — urn:xmpp:order-by:1 field='creation-date' included in XEP-0442 pubsub MAM queries for newest-first ordering; advertised in caps)
  • ⚡ XEP-0442: Pubsub MAM (Experimental — on reconnect, disco#info probes each pubsub service; if urn:xmpp:mam:2 is supported, fetches feed history via MAM with node= filter and XEP-0413 Order-By; falls back to XEP-0060 max_items for servers without pubsub MAM support; Atom entries extracted from forwarded MAM result messages and rendered to the feed buffer with dedup and alias assignment; RSM cursor persisted to LMDB)
  • ⚡ XEP-0452: MUC Mention Notifications (Experimental — receive side: <addresses type='mentioned'> notification messages from MUC service detected and forwarded message body rendered to the MUC buffer with highlight, so missed @mentions surface even when not present in the room)
  • ⚡ XEP-0441: MAM Preferences (Experimental — /mam prefs displays current server default policy and always/never JID lists; /mam prefs default <always|never|roster> sets default; /mam prefs always <jid> / /mam prefs never <jid> add JIDs to the respective list)
  • ⚡ XEP-0466: Ephemeral Messages (Experimental — send: /ephemeral <seconds> <message> attaches <ephemeral timer='N'/> + <no-permanent-store/> hint; receive: timer value displayed as [⏱ Ns] prefix, message automatically tombstoned after N seconds; urn:xmpp:ephemeral:0 advertised in caps)
  • ⚡ XEP-0492: Chat Notification Settings (Experimental — per-chat notification preference (always/on-mention/never) stored in XEP-0402 bookmark <extensions><notify>; /notify [<jid>] [always|on-mention|never] gets or sets the preference and re-publishes the bookmark)
  • ⚡ XEP-0448: Encrypted File Sharing (Experimental — send: when /upload-ing a file to an OMEMO-enabled channel, the file is AES-256-GCM encrypted before HTTP PUT; the XMPP message carries <file-sharing> with <encrypted xmlns='urn:xmpp:esfs:0' cipher='urn:xmpp:ciphers:aes-256-gcm-nopadding:0'> containing the base64 key/IV/hash; receive: <encrypted xmlns='urn:xmpp:esfs:0'> detected inside SFS <sources>, cipher attribute validated against urn:xmpp:ciphers:aes-256-gcm-nopadding:0 (other ciphers skipped per §4), ciphertext downloaded in a background thread, decrypted with AES-256-GCM, saved to ~/Downloads/<filename>; urn:xmpp:esfs:0 advertised in caps)
  • ⚡ XEP-0472: Pubsub Social Feed (Experimental — publishes pubsub#type=urn:xmpp:microblog:0, advertises urn:xmpp:pubsub-social-feed:1 in caps; thr:in-reply-to@ref uses real Atom entry IRI; feed-level <feed> metadata items rendered; XHTML/HTML Atom content properly rendered)
  • ⚡ XEP-0433: Extended Channel Search (Searcher role; Search Service role not implemented)

Planned

  • ⏳ XEP-0153: vCard-Based Avatars (publishing own avatar)
  • ⏳ XEP-0398: Avatar Conversion

Known limitation: Plugin reload while WeeChat is running is not supported due to fundamental race conditions with timer hooks. Always restart WeeChat instead of reloading the plugin.


License

Licensed under the Mozilla Public License 2.0.
See LICENSE or https://www.mozilla.org/en-US/MPL/2.0/

Original project © Tony Olagbaiye — https://github.com/bqv/weechat-xmpp

About

Fork of weechat-xmpp with many improvements and fixes

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors