Slidge v0.4.0beta "Spaces"

Hear, hear, a new slidge is out! The full changelog is available on the codeberg release page, but here are the main highlights, in a more legible format.

Main new feature: server-side spaces (XEP-0503)

This is the main new user-facing feature. Slidge supports collection of rooms in so-called server-side spaces. This support is "read-only" at the moment, meaning you cannot administrate a space through slidge yet; this will be part of the 0.5 series.

Support for slidcord servers and mattermost teams has already been merged but is still unreleased. Releases and support for Matrix spaces (matrix, you copycats! wait), along with WhatsApp communities and Steam chat groups should follow relatively soon. Stay tuned!

Movim is the only XMPP client that has a dedicated UI for spaces so far, but as usual, we target the largest possible compatibility, so fallbacks in the form of chatbot or adhoc commands was also implemented. This mean you can list rooms by spaces from any XMPP client, no matter how old or simplistic it is (as long as it can send and receive text messages).

Refactoring and breaking changes

The implementation of spaces per se was actually a relatively small change to the codebase. But we are in for the long run, and we did not want to pile in technical debt, so adding this feature was an opportunity to improve some internals. This lead to public API breaking changes, not only for the exhilarating pleasure of sabotaging stuff, but to attempt to make various things more sane.

XMPP event hooks relocation and shorter function signatures

Slidge-powered gateways implement handlers for actions made by the user from their XMPP client by subclassing abstract methods. Up until now, most of these methods were declared on BaseSession. It typically looked like that:

class Session(slidge.BaseSession):
    async def on_text(
        self,
        chat: Contact | MUC,
        text: str,
        reply_to_msg_id: str | None = None,
        thread: str | None | None = None,
        mentions: list[Mentions] | None = None,
        **kwargs,  # some stuff that the concrete implementation did not use
    ) -> str:
        # in practice, the body was longer than that, to handle mentions and
        # stuff like that.
        if chat.is_group:
            msg = await self.legacy_client.send_group_message(
                text=text,
                group_id=chat.legacy_id,
                reply_to=reply_to_msg_id,
            )
        else:
            msg = await self.legacy_client.send_direct_message(
                text=text,
                contact_id=chat.legacy_id,
                reply_to=reply_to_msg_id,
            )
        return msg.id

A lot of these methods took chat as their first argument. This was poorly designed, it makes much more sense to have these event handlers as part of the MUC and Contact subclasses directly, so we changed that. Since this is relatively big breaking change for gateways based on slidge, we also took this opportunity to reduce the uglyly large number of arguments in these methods by grouping most other arguments in a XMPPMessage dataclass.

This lead to unifying the on_text(), on_file() and on_correct() handlers thanks to the XMPPMessage.body, .attachments, and .replace attributes. For now, a XMPPMessage either has a body (=text) or a single attachment, but this paves the way for a feature that some XMPP clients should implement at some point: single messages with multiple attachments and some text to come along with.

After relocation, methods now look like this:

class Contact(slidge.LegacyContact):
    async def on_message(self, message: XMPPMessage) -> str:
        msg = await self.session.legacy_client.send_direct_message(
            text=text,
            group_id=chat.legacy_id,
            reply_to=message.reply.msg_id if message.reply else None,
        )

class MUC(slidge.LegacyMUC):
    async def on_message(self, message: XMPPMessage) -> str:
        ...

In practice, it often is a little more complex than that, but we are happy with the changes as it makes code organisation cleaner and factorization easier. Have a look a slidgram's 0.4 migration commit for a fuller picture.

No more "legacy ID" type conversions in slidge core

Up until now, if the legacy (=bridged) network used something else than strings as identifiers (for messages, users, groups, …), this was handled in a generic way in slidge core. While this sounded like a good idea, it was poorly implemented, leading to a lot of complexity in the codebase and overuse/misuse of generics. Combined with the fact that most networks actually use strings that can be usable as-is on the XMPP side, it sounded very reasonable to ditch support for that conversion in slidge core all along.

As a result, it is now the responsibility of slidge-powered gateways to handle string-to-something (usually integers) conversions for identifiers. This required some work for slidcord, sleamdge and slidgram, which all use integers as identifiers; the added conversion burden was very reasonable though. Work has already merged and it seems that all hell did not break lose for the audacious running the containers tagged main (or via other ways to get the latest unreleased changes).

As a nice consequence, mostly because we are not misusing typing generics as much as before, coverage of the static type checking of the codebase has been vastly improved. This is not only an internal change because gateways based on slidge will also benefit from this. Thanks to that, migrating the gateways to this breaking change was not as tedious as expected so far.

What's next?

Besides 0.4.x (beta or not) releases of all slidge-powered gateways that should follow soon(ish) and usual bugfixes, the main feature that we plan to add in the 0.4 series is support for spaces avatars, which require serving them as out of the XMPP stream. The 0.5.x series will support administration of "legacy spaces" via your XMPP client and some more internal cleaning up, most likely ending up in public API breakage for the greater good.

Slidge needs YOU

Slidge development all happens in the open. We would love to welcome new contributions in the form of code of pull request reviews. It may be a bit scary to dive into "slidge the lib", but several issues are labelled are "good first issue" and should be good starting points for the brave who want to give it a try. On the contrary, slidge-based gateways are small codebases, use a similar label in their issue tracker, see for instance the slidge-whatsapp tracker. Maybe give it a try if you are not allergic to python?

Acknowledgments

We are immensely grateful for all the testing, bug reporting, feature requesting and mutual user support that already take place. A lot of ♥♥♥ to you all nerds.

Slidge development now receives support from nlnet. Many thanks to that awesome organisation for supporting a better, human-centered internet.

NGI0 core logo


You can read and comment this article using a pubsub capable XMPP client such as movim.


Published:

Category: misc