mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-03 17:52:12 +01:00
Add ThreadId
newtype
This commit is contained in:
parent
9b9c1509b1
commit
693121a6f6
3 changed files with 84 additions and 0 deletions
|
@ -15,8 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `Update::from`, a replacement for `Update::user` ([#850][pr850])
|
||||
- `Seconds` type, which represents a duration is seconds ([#859][pr859])
|
||||
- `VideoChatEnded::duration` field that was previously missed ([#859][pr859])
|
||||
- `ThreadId` newtype over `MessageId`, used for identifying reply threads ([#887][pr887])
|
||||
|
||||
[pr851]: https://github.com/teloxide/teloxide/pull/851
|
||||
[pr887]: https://github.com/teloxide/teloxide/pull/887
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ pub use sticker::*;
|
|||
pub use sticker_set::*;
|
||||
pub use successful_payment::*;
|
||||
pub use target_message::*;
|
||||
pub use thread_id::*;
|
||||
pub use unit_false::*;
|
||||
pub use unit_true::*;
|
||||
pub use update::*;
|
||||
|
@ -191,6 +192,7 @@ mod sticker;
|
|||
mod sticker_set;
|
||||
mod successful_payment;
|
||||
mod target_message;
|
||||
mod thread_id;
|
||||
mod unit_false;
|
||||
mod unit_true;
|
||||
mod update;
|
||||
|
|
80
crates/teloxide-core/src/types/thread_id.rs
Normal file
80
crates/teloxide-core/src/types/thread_id.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use crate::types::MessageId;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Reply thread identifier.
|
||||
///
|
||||
/// A message that isn't a reply and other messages that reply to it directly or
|
||||
/// indirectly through a reply chain constitute a reply thread. All messages
|
||||
/// except the initial root message have an additional [`thread_id`] field that
|
||||
/// is equal to the root message's id.
|
||||
///
|
||||
/// In other words a thread id can be found recursively following
|
||||
/// `reply_to_message_id`, until you find a message which does not reply to
|
||||
/// anything, it's id is the thread id.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```text
|
||||
/// lizard: Hi {id:17} <-------------+--------------+----+--------------+---------------------+
|
||||
/// | | | | |
|
||||
/// wizard: hewwo {id:18, reply: 17 -+, thread: 17 -+} | | |
|
||||
/// | | |
|
||||
/// lizard: I've been wondering [...] {id:19, reply: 17 -+, thread: 17 -+} <---+ |
|
||||
/// | |
|
||||
/// neushoorn: wait, did y'all know that [...] {id:20} <-----------------------)--------------)--+-----+
|
||||
/// | | | |
|
||||
/// wizard: so this is not an easy question, actually [...] {id:21, reply: 19 -+, thread: 17 -+} | |
|
||||
/// +--------+ |
|
||||
/// | |
|
||||
/// wizard: everyone knows that, how did you not know that before?... {id:22, reply:20 -+, thread: 20 -+}
|
||||
/// ```
|
||||
///
|
||||
/// Note that channel comments and forum topics, reuse threads for different
|
||||
/// meanings. For channel comments every comment (indirectly) replies to the
|
||||
/// channel post forwarded to the linked chat (i.e. the forwarded channel post
|
||||
/// is the root of the comments thread). For forum topics every message in a
|
||||
/// topic is in the same thread too (i.e. they (indirectly) reply to the start
|
||||
/// of the topic).
|
||||
///
|
||||
/// [`thread_id`]: crate::types::Message::thread_id
|
||||
#[derive(Clone, Copy, Debug, derive_more::Display, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(from = "ThreadIdRaw", into = "ThreadIdRaw")]
|
||||
pub struct ThreadId(/** Identifier of the root message in a reply thread. */ pub MessageId);
|
||||
|
||||
// N.B. this is a hack to [de]serialize `ThreadId` as just a number
|
||||
// we need this since `MessageId` is [de]serialized as `{"message_id":n}`.
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct ThreadIdRaw(i32);
|
||||
|
||||
impl From<ThreadIdRaw> for ThreadId {
|
||||
fn from(ThreadIdRaw(message_id): ThreadIdRaw) -> Self {
|
||||
ThreadId(MessageId(message_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ThreadId> for ThreadIdRaw {
|
||||
fn from(ThreadId(MessageId(message_id)): ThreadId) -> Self {
|
||||
ThreadIdRaw(message_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::{MessageId, ThreadId};
|
||||
|
||||
#[test]
|
||||
fn smoke_deser() {
|
||||
let json = r#"123"#;
|
||||
let mid: ThreadId = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(mid, ThreadId(MessageId(123)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_ser() {
|
||||
let mid: ThreadId = ThreadId(MessageId(123));
|
||||
let json = serde_json::to_string(&mid).unwrap();
|
||||
assert_eq!(json, r#"123"#);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue