fix: reply the edit-before-forward prompt to the post's own media message

One user message carrying several links opens one prompt per post; every
prompt used to reply to that shared link message, so they were
indistinguishable. The prompt now replies to the first media message it
edits, falling back to the link message when there is none.
This commit is contained in:
2026-10-31 18:53:29 +08:00
parent 8f6e78395b
commit 132fdd2999
3 changed files with 23 additions and 2 deletions
@@ -227,6 +227,8 @@ pub(crate) struct MockSender {
cursor: Mutex<usize>, cursor: Mutex<usize>,
calls: Mutex<Vec<&'static str>>, calls: Mutex<Vec<&'static str>>,
messages: Mutex<Vec<String>>, messages: Mutex<Vec<String>>,
/// The reply target of every `send_message`, in order.
message_replies: Mutex<Vec<Option<i64>>>,
captions: Mutex<Vec<String>>, captions: Mutex<Vec<String>>,
answers: Mutex<Vec<Option<String>>>, answers: Mutex<Vec<Option<String>>>,
/// `(chat, message, text)` of every text rewrite, in order. /// `(chat, message, text)` of every text rewrite, in order.
@@ -281,6 +283,7 @@ impl MockSender {
cursor: Mutex::new(0), cursor: Mutex::new(0),
calls: Mutex::new(Vec::new()), calls: Mutex::new(Vec::new()),
messages: Mutex::new(Vec::new()), messages: Mutex::new(Vec::new()),
message_replies: Mutex::new(Vec::new()),
captions: Mutex::new(Vec::new()), captions: Mutex::new(Vec::new()),
answers: Mutex::new(Vec::new()), answers: Mutex::new(Vec::new()),
edited_texts: Mutex::new(Vec::new()), edited_texts: Mutex::new(Vec::new()),
@@ -301,6 +304,12 @@ impl MockSender {
self.messages.lock().clone() self.messages.lock().clone()
} }
/// The reply target of every plain message sent, in order (`None` = no
/// reply).
pub(crate) fn message_replies(&self) -> Vec<Option<i64>> {
self.message_replies.lock().clone()
}
/// Captions passed to `edit_message_caption`, in order. /// Captions passed to `edit_message_caption`, in order.
pub(crate) fn captions(&self) -> Vec<String> { pub(crate) fn captions(&self) -> Vec<String> {
self.captions.lock().clone() self.captions.lock().clone()
@@ -415,11 +424,14 @@ impl MediaSender for MockSender {
&self, &self,
_chat_id: ChatId, _chat_id: ChatId,
text: String, text: String,
_reply_to: Option<MessageId>, reply_to: Option<MessageId>,
_reply_markup: Option<InlineKeyboardMarkup>, _reply_markup: Option<InlineKeyboardMarkup>,
) -> BoxFuture<'_, Result<i64, RequestError>> { ) -> BoxFuture<'_, Result<i64, RequestError>> {
Box::pin(async move { Box::pin(async move {
self.messages.lock().push(text); self.messages.lock().push(text);
self.message_replies
.lock()
.push(reply_to.map(|id| id.0 as i64));
match self.next("send_message") { match self.next("send_message") {
Outcome::MessageOk => Ok(MockSender::SENT_ID), Outcome::MessageOk => Ok(MockSender::SENT_ID),
Outcome::MessageErr => Err(self.error()), Outcome::MessageErr => Err(self.error()),
+3
View File
@@ -1646,6 +1646,9 @@ mod tests {
.expect("the prompt record must be stored"); .expect("the prompt record must be stored");
assert_eq!(record.url, "https://x.com/u/status/1"); assert_eq!(record.url, "https://x.com/u/status/1");
assert_eq!(record.forward_message_ids, vec![10, 11]); assert_eq!(record.forward_message_ids, vec![10, 11]);
// The prompt replies to the post's first media message, so several
// links in one user message still get distinguishable prompts.
assert_eq!(sender.message_replies(), vec![Some(10)]);
} }
#[tokio::test] #[tokio::test]
+7 -1
View File
@@ -301,12 +301,18 @@ pub(crate) async fn post_send_actions(ctx: &AppContext<'_>, task: &Task, message
"\n({hidden} more templates not shown — /remove_template to prune.)" "\n({hidden} more templates not shown — /remove_template to prune.)"
)); ));
} }
// Reply to this post's own first media message rather than the user's
// link message: one message carrying several links opens several
// prompts, and replying them all to that one message made each
// indistinguishable from the others. The media message is the thing
// the prompt actually edits and forwards.
let prompt_reply_to = message_ids.first().copied().unwrap_or(reply_to);
let prompt = ctx let prompt = ctx
.sender .sender
.send_message( .send_message(
ChatId(chat_id), ChatId(chat_id),
text, text,
Some(MessageId(reply_to as i32)), Some(MessageId(prompt_reply_to as i32)),
Some(keyboard), Some(keyboard),
) )
.await; .await;