atagen

macltok

public
Star0
Watch0

Commit 924b7c011591

tarball

atagen <boss@atagen.co>2026-10-25 10:28 UTC

4 files changed+29-11
packs: send stickers to a timeline, threads included

A sticker sent from a thread view landed in the main timeline, because SendSticker only knew the room. It now takes a TimelineId like AttachmentUpload, so a thread target gets the thread relation and the pinned timeline refuses it.
Modified file: src/engine/packs.rs+23 additions−5 deletions
@@ -18,6 +18,7 @@ use super::{
1818 };
1919 use crate::{
2020 CommandOutput, Error, ErrorKind, ImagePackSource, PackCommand, PackImageInfo, PackUsage, Patch,
21+ TimelineId,
2122 normalise::{
2223 ENABLED_ROOMS, ROOM_PACKS, USER_PACK, effective_usage, resolve_pack_id, stored_pack,
2324 },
@@ -223,10 +224,10 @@ pub(super) async fn run_detached(
223224 }
224225 match command {
225226 PackCommand::SendSticker {
226- room_id,
227+ timeline_id,
227228 pack_id,
228229 shortcode,
229- } => send_sticker(&client, room_id, &pack_id, &shortcode)
230+ } => send_sticker(&client, &timeline_id, &pack_id, &shortcode)
230231 .await
231232 .map(|()| CommandOutput::Done),
232233 PackCommand::Rehost(mxc) => rehost(&client, mxc, None, max_bytes)
@@ -365,21 +366,38 @@ async fn insert(
365366
366367 async fn send_sticker(
367368 client: &Client,
368- room_id: OwnedRoomId,
369+ timeline_id: &TimelineId,
369370 pack_id: &str,
370371 shortcode: &str,
371372 ) -> Result<(), Error> {
372- let room = client.get_room(&room_id).ok_or_else(Error::room_unknown)?;
373+ if matches!(timeline_id, TimelineId::Pinned(_)) {
374+ return Err(Error::new(
375+ ErrorKind::Invalid,
376+ "the pinned timeline can't send or paginate",
377+ ));
378+ }
379+ let room = client
380+ .get_room(timeline_id.room_id())
381+ .ok_or_else(Error::room_unknown)?;
373382 let image = pack_image(client, pack_id, shortcode).await?;
374383 let url = image
375384 .get("url")
376385 .and_then(mxc)
377386 .ok_or_else(|| Error::new(ErrorKind::Invalid, "that image has no usable url"))?;
378- let content = json!({
387+ let mut content = json!({
379388 "body": sticker_body(&image, shortcode),
380389 "url": url,
381390 "info": image.get("info").cloned().unwrap_or_else(|| json!({})),
382391 });
392+ // the same fallback the send queue gives a threaded attachment with no reply
393+ if let Some(root) = timeline_id.thread_root() {
394+ content["m.relates_to"] = json!({
395+ "rel_type": "m.thread",
396+ "event_id": root,
397+ "is_falling_back": true,
398+ "m.in_reply_to": { "event_id": root },
399+ });
400+ }
383401 room.send_queue()
384402 .send_raw(raw(&object(content)), "m.sticker".to_owned())
385403 .await
Modified file: src/engine/repair.rs+2 additions−3 deletions
@@ -309,9 +309,8 @@ async fn fill_gap(
309309 };
310310 // the sdk answers an already unavailable gap without asking the server, and a joined
311311 // one with NotFound. an empty first page that hits the end looks the same, uncounted
312- let settled_before = report.pages == 0
313- && events == 0
314- && gap.status == HistoryGapStatus::Unavailable;
312+ let settled_before =
313+ report.pages == 0 && events == 0 && gap.status == HistoryGapStatus::Unavailable;
315314 if !settled_before {
316315 report.pages += 1;
317316 committed = true;
Modified file: src/model.rs+2 additions−1 deletions
@@ -409,8 +409,9 @@ pub enum MediaCommand {
409409 #[non_exhaustive]
410410 pub enum PackCommand {
411411 /// body defaults to the shortcode
412+ /// into a thread with the thread relation. the pinned timeline refuses it
412413 SendSticker {
413- room_id: OwnedRoomId,
414+ timeline_id: TimelineId,
414415 pack_id: String,
415416 shortcode: String,
416417 },
Modified file: src/transport.rs+2 additions−2 deletions
@@ -934,12 +934,12 @@ impl ClientHandle {
934934 /// body defaults to the shortcode
935935 pub async fn send_sticker(
936936 &self,
937- room_id: OwnedRoomId,
937+ timeline_id: TimelineId,
938938 pack_id: String,
939939 shortcode: String,
940940 ) -> Result<(), Error> {
941941 self.run(Command::Pack(PackCommand::SendSticker {
942- room_id,
942+ timeline_id,
943943 pack_id,
944944 shortcode,
945945 }))