-
-
Notifications
You must be signed in to change notification settings - Fork 1
Microblogging
XMPP microblogging lets you publish short posts — analogous to Mastodon/Twitter
toots/tweets — directly over XMPP via PubSub nodes. Posts are Atom entries
stored on a PubSub service; contacts who subscribe to your
urn:xmpp:microblog:0 PEP node receive them in real-time.
Status: XEP-0277 is Deferred; XEP-0472 is Experimental. Both are implemented in this plugin for the write side (post, reply, repeat, retract, subscribe, unsubscribe, comments) and the receive side (incoming PEP push events are rendered automatically with deduplication).
- Posts live on a PubSub node (most commonly
urn:xmpp:microblog:0on a PEP service, or any XEP-0060 pubsub service). - Each post is an Atom entry (
<entry xmlns='http://www.w3.org/2005/Atom'>). - XEP-0472 requires the publish-option
pubsub#type=urn:xmpp:microblog:0and the capability stringurn:xmpp:pubsub-social-feed:1to be advertised — both are handled automatically by this plugin. - Threaded replies use RFC 4685
thr:in-reply-toinside the Atom entry. - Boosts/repeats use
<link rel='via'>(XEP-0472 §4.5). - Comments nodes are linked via
<link rel='replies'>(XEP-0277 §3).
| Software | Role |
|---|---|
| Movim | Full social feed — post, reply, retract, timeline |
| Libervia / Salut-à-Toi | Full implementation |
| ejabberd | PubSub mechanics work; no built-in social UI |
| Prosody + mod_pep | PubSub node creation/subscription works |
When you fetch a feed with /feed, each displayed item is assigned a short
#N alias shown in green before the title (e.g. #1, #2, #3). You can
use these aliases in place of the full item-id in any write command:
/feed reply #3 Nice post!
/feed repeat #3 Great content
/feed comments #3
/feed retract #3
Aliases are assigned per feed-buffer and reset when you reconnect or close WeeChat.
Long form (explicit service and node):
/feed post <service-jid> <node> [--open] [--title <title>] <text>
Short form (from a feed buffer — service/node inferred):
/feed post [--title <title>] <text>
/feed post --open <text>
/feed post -- <text> # use '--' when body starts with a JID-like word
/feed post --edit # open $EDITOR via feed_compose.py
The --open flag sets pubsub#access_model=open so the post is publicly
readable without a subscription.
The --title flag sets the Atom <title> element (the headline shown by
clients like Movim above the post body). If --title is omitted the
<title> element is not emitted at all — the entry is body-only. Use this
for microblog-style short posts that have no headline.
The --edit flag delegates to feed_compose.py: it opens your $EDITOR
with a YAML frontmatter template where you can fill in an optional title and
write a longer body. feed_compose.py must be loaded (see
Composing longer posts below).
Use -- as an explicit separator when the post body starts with a word
containing . or @ (e.g. a URL or username) to avoid the parser treating it
as a service JID:
/feed post -- hello@world.example is a great site
Examples:
# Post to your own PEP microblog
/feed post movim.eu urn:xmpp:microblog:0 Hello from WeeChat!
# Public post
/feed post movim.eu urn:xmpp:microblog:0 --open This is a public post
# Post with a headline title
/feed post --title My Weekend Project -- Spent the weekend hacking on XMPP…
# Short form from a feed buffer
/feed post Hello everyone!
# Short form with body starting with a URL
/feed post -- https://example.com check this out
# Compose a longer post in $EDITOR (requires feed_compose.py)
/feed post --edit
Failed publishes are reported in the buffer with the server error condition
(e.g. forbidden, item-not-found).
Long form:
/feed reply <service-jid> <node> <item-id|#N> [--open] <text>
Short form (from a feed buffer):
/feed reply #N [--open] <text>
/feed reply #N --edit # compose reply in $EDITOR (no title frontmatter)
The reply is a new Atom entry containing thr:in-reply-to ref="<atom-id>".
The ref attribute uses the Atom <id> URI of the original entry (cached from
the most recent fetch). Clients such as Movim render threaded conversations from
these references.
Note: Replies (comments) do not have titles — the
--titleflag is not available for/feed reply. When--editis used for a reply,feed_compose.pyopens the editor without a YAML frontmatter block.
When you run /feed post <text> from inside a comments buffer (a buffer
whose node starts with urn:xmpp:microblog:0:comments/), the post is
automatically treated as a reply to the parent article:
-
<thr:in-reply-to>is emitted pointing at the original article on theurn:xmpp:microblog:0blog node. - The post is published into the same comments node, not a new one.
This means /feed post and /feed reply are fully equivalent when run from a
comment buffer — you do not need to look up a #N alias.
Examples:
# Long form
/feed reply movim.eu urn:xmpp:microblog:0 abc-1234 That's a great point!
# Short form using alias
/feed reply #3 That's a great point!
# Compose reply in $EDITOR (requires feed_compose.py)
/feed reply #3 --edit
# Reply to a comments node item (XEP-0277)
/feed reply #3 Nice comment!
Long form:
/feed repeat <service-jid> <node> <item-id> [comment]
Short form (from a feed buffer):
/feed repeat #N [comment]
Publishes a new Atom entry with <link rel='via' href='xmpp:…' ref='atom-id'/>.
The ref attribute is set to the original entry's Atom <id> URI when known
(cached from the most recent fetch), enabling receiving clients to resolve the
full provenance chain.
An optional comment is included in the entry body.
Examples:
# Boost without comment
/feed repeat movim.eu urn:xmpp:microblog:0 abc-1234
# Boost with comment (long form)
/feed repeat movim.eu urn:xmpp:microblog:0 abc-1234 Great post, sharing this!
# Short form with alias
/feed repeat #3
# Short form with alias and comment
/feed repeat #3 Great content — everyone should read this
Long form:
/feed retract <service-jid> <node> <item-id>
Short form (from a feed buffer):
/feed retract #N
Sends a PubSub retract IQ with notify='true'. Subscribers receive a
retraction notification; supporting clients remove the post from their timeline.
Server errors (forbidden, item-not-found) are reported in the buffer.
Note: Retraction is best-effort. Contacts who already received the item may still have a local copy.
Examples:
/feed retract movim.eu urn:xmpp:microblog:0 abc-1234
/feed retract #3
/feed comments <service-jid> <node> <item-id|#N>
/feed comments #N # short form from a feed buffer
If the post carries a <link rel='replies'> element (XEP-0277 §3), this opens
a dedicated FEED buffer and fetches the comments node. The replies URI is cached
when the post is first fetched or received via push.
If no comments link was advertised the command reports that no cached link is
available — run /feed <service> <node> first to populate the cache.
When a post has a comments node, the feed buffer shows a hint:
Comments: /feed comments #3
Examples:
/feed comments movim.eu urn:xmpp:microblog:0 abc-1234
/feed comments #3
/feed subscribe <service-jid> <node>
/feed unsubscribe <service-jid> <node>
/feed subscriptions <service-jid>
Sends XEP-0060 subscribe/unsubscribe IQ stanzas to the service. Success and
error feedback is printed in the buffer where the command was run (not always
the account buffer). Errors include the XMPP error condition (e.g.
not-authorized, item-not-found).
/feed subscribe news.movim.eu Phoronix
/feed unsubscribe news.movim.eu Phoronix
/feed subscriptions news.movim.eu
Use the standard /feed read commands:
/feed movim.eu urn:xmpp:microblog:0 # fetch last 20 posts
/feed movim.eu urn:xmpp:microblog:0 --limit 5 # fetch last 5 posts
/feed movim.eu urn:xmpp:microblog:0 --before <item-id> # older page (RSM)
/feed movim.eu urn:xmpp:microblog:0 --latest # clear saved cursor, fetch newest page
Each node opens in its own dedicated WeeChat buffer. The RSM cursor is
persisted in LMDB so subsequent /feed calls automatically continue from where
you left off. Use --latest to go back to the newest page after paging back
through older items.
Items fetched via an explicit /feed command (IQ path) are always
rendered, even if they were seen before — so repeated /feed invocations
refresh the display. The seen-item set is still updated after each fetch.
Items delivered via a real-time PubSub push event are suppressed if the same
item-id was already rendered (e.g. fetched moments earlier by an explicit
/feed command). This prevents double-display of the same post when a server
both returns it in an IQ result and immediately pushes it.
When a contact publishes to their urn:xmpp:microblog:0 PEP node, the push
event is delivered automatically and rendered in the WeeChat buffer for that
contact. Each item displays:
- Author name and timestamp
- Title (bold) with
#Nalias in green - Body text
- Thread reference (
In reply to: #Nor the raw item UUID) - Reply quote prefix (
↪ <quoted text>) — the full text of the original message is shown when it is short (≤ 5 newlines and no line longer than 200 characters); longer originals are truncated to 40 characters with… - Boost provenance (
Repeated from: xmpp:…) - Comments hint (
Comments: /feed comments #N) when a replies link is present - Category tags
- Enclosure/attachment URLs
- Geolocation
- XHTML/HTML content rendered with WeeChat colors
Duplicate push-delivered items (already seen via an IQ fetch) are suppressed automatically.
The plugin advertises the following in its entity caps (XEP-0115) and
disco#info response so social-feed-aware servers and clients can discover
support:
-
urn:xmpp:microblog:0+notify— subscribe to contacts' microblog PEP nodes -
urn:xmpp:pubsub-social-feed:1— XEP-0472 social feed capability
The plugin's /feed post and /feed reply commands accept text inline on a
single line. For longer drafts — or when you simply prefer your editor — use
the --edit flag together with the feed_compose.py companion script.
# one-time install (script ships in scripts/ inside the repo)
cp /path/to/repo/scripts/feed_compose.py \
~/.local/share/weechat/python/autoload/Or load it without autoloading:
/script load /path/to/scripts/feed_compose.py
/feed post --edit # compose a new post in $EDITOR
/feed post --open --edit # compose a public post in $EDITOR
/feed reply #3 --edit # compose a reply in $EDITOR
When --edit is given, feed_compose.py is invoked automatically. A
temporary Markdown file is opened in your $EDITOR. For posts the file
starts with a YAML frontmatter block:
---
title:
---
Write your post body here.Fill in title: to add an Atom <title> headline; leave it blank (or delete
the frontmatter entirely) for a body-only post.
For replies the frontmatter is omitted entirely — comments have no titles.
Save and quit the editor — the content is placed in the WeeChat input bar as a
complete /feed post … or /feed reply … command ready to send.
The script also registers a /feed-compose command you can call directly:
/feed-compose [initial text]
Run it from inside a FEED buffer and the service JID and node are filled in automatically. Run it from any other buffer and you can add them before pressing Enter.
/alias add fc /feed-compose
/key bind meta-e /feed-compose
| Option | Default | Description |
|---|---|---|
editor |
"" |
Editor binary; falls back to $EDITOR, then vi
|
run_externally |
"false" |
Set to "true" for GUI or tmux-based editors (non-blocking) |
Set options with /set plugins.var.python.feed_compose.<option> <value>.
-
PubSub Feed Reader — general
/feedread commands -
Command Reference — full
/feedsub-command table