macltok request, custom emote and sticker packs (MSC2545)
Problem
Malice is adding an emoji picker for reactions that should also offer the user’s custom emotes and stickers. Those live in MSC2545 image packs, spread over three places.
im.ponies.user_emotesglobal account data, the user’s personal packim.ponies.room_emotesroom state, one pack per state key, in the current roomim.ponies.emote_roomsglobal account data, which names other rooms (and state keys) whose packs the user enabled everywhere
Merging those, resolving pack vs image usage, and following emote_rooms into rooms the client may not have state for is protocol work every consumer would repeat, so it belongs in macltok. Malice can’t do it today anyway. global_account_data covers 1 and 3, but there is no room state getter for 2.
ruma-events 0.34 already has the types behind unstable-msc2545 (image_pack.rs, RoomImagePackEventContent, AccountImagePackEventContent, ImagePackRoomsEventContent, PackUsage), including the stable m.image_pack aliases.
Request
A normalised query for the packs usable in a given room.
impl ClientHandle {
/// user pack, then the room's own packs, then emote_rooms packs, deduplicated
pub async fn image_packs(&self, room_id: Option<OwnedRoomId>) -> Result<Vec<ImagePack>, Error>;
}
pub struct ImagePack {
pub id: String,
pub display_name: String,
pub avatar_url: Option<OwnedMxcUri>,
pub source: ImagePackSource,
pub images: Vec<PackImage>,
}
pub enum ImagePackSource {
User,
Room { room_id: OwnedRoomId, state_key: String },
}
pub struct PackImage {
pub shortcode: String,
pub url: OwnedMxcUri,
pub body: Option<String>,
/// image usage if set, else the pack's, else both
pub usage: Vec<PackUsage>,
}id only needs to be stable for a pack across calls, e.g. user or room:<room_id>:<state_key>. Serialised field names should match the rest of macltok’s normalised types. Malice’s web client already has the matching TypeScript shape in web/src/lib/types.ts (ImagePack, PackImage).
It would also help to get a change event when any of the three sources updates, so the picker doesn’t go stale, either a dedicated event or folding it into the existing room/account mirror.
Related, reactions with custom emotes (MSC4027)
A custom emote reaction uses the image’s mxc URI as the m.annotation key, with the shortcode in com.beeper.reaction.shortcode so clients without the pack can show a label.
toggle_reactiononly takes a key. An optional shortcode would let malice send the label.normalise::timeline::reactionsdrops the shortcode on receipt.Reactioncould carryshortcode: Option<String>, taken from any sender’s annotation for that key.
Malice relaxed its own 32-char key limit for mxc:// keys, so sending already works without the shortcode.