atagen

malice

public
Star0
Watch0
06339d2de37a2adbd7c9697702da5360fad61c36
2
ssh://brewery@pls.lobotomise.me:33/atagen/malice.git
MACLTOK_URL_PREVIEW.mdMarkdown49 lines2.6 KB

macltok request, URL previews via the homeserver

Problem

Malice’s link cards only show the URL’s host and path. It wants the page’s title, description and image, the way other Matrix clients do. The client can’t scrape pages itself. Browsers block it with CORS, and fetching from the malice server would leak its IP to every linked site.

Matrix already solves this with GET /_matrix/client/v1/media/preview_url?url=...&ts=... (ruma authenticated_media::get_media_preview). The homeserver fetches the page, parses OpenGraph, re-hosts og:image as an mxc, and returns the og:* keys as a loose JSON map. Knowing that endpoint, which keys matter, and that og:image is an mxc is protocol work every consumer would repeat, so it belongs in macltok. Nothing in ClientHandle reaches it today.

Request

impl ClientHandle {
    /// None when the server has no preview for the url (404, empty body, or no usable keys)
    pub async fn url_preview(&self, url: &str) -> Result<Option<UrlPreview>, Error>;
}

pub struct UrlPreview {
    pub url: String,
    pub title: Option<String>,
    pub description: Option<String>,
    pub site_name: Option<String>,
    pub image: Option<UrlPreviewImage>,
}

pub struct UrlPreviewImage {
    /// og:image, already re-hosted by the server, usable with `media` / `media_source`
    pub media_id: MediaId,
    pub width: Option<u32>,
    pub height: Option<u32>,
    pub mimetype: Option<String>,
    pub size: Option<u64>,
}

Things that would help beyond the bare call.

  1. Fall back to the legacy /_matrix/media/v3/preview_url when the server lacks authenticated media, the same way media does.
  2. Cache results per url for a while, including negative ones. Synapse rate-limits this endpoint and a busy timeline repeats links.
  3. Clamp string lengths, since the server passes page text through unfiltered. Something like 256 chars for title and site name, 1024 for description.
  4. Treat og:image that isn’t an mxc:// uri as absent.
  5. Map 429 and 5xx to a distinct error, so hosts can tell “try later” from “no preview”.

Optional, room level opt-out

Element honours org.matrix.room.preview_urls room state ({"disable": true}, set by room admins) and the per-user org.matrix.preview_urls room account data. If macltok exposed those on RoomSummary, or as url_previews_allowed(room_id) -> bool, malice wouldn’t need to know the event types.

Malice side, for context

Malice will call this only in unencrypted rooms by default, with a user setting to also allow it in encrypted ones, because the homeserver sees every previewed url. The image goes through malice’s existing bounded media endpoint by media_id.