105 lines
3.8 KiB
Rust
105 lines
3.8 KiB
Rust
//! Message types and conversion methods.
|
|
|
|
use kuska_ssb::api::dto::content::TypedMessage;
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::Value;
|
|
use std::fmt::Debug;
|
|
|
|
use crate::error::GolgiError;
|
|
|
|
/// `SsbMessageContent` is a type alias for `TypedMessage` from the `kuska_ssb` library.
|
|
/// It is aliased in golgi to fit the naming convention of the other message
|
|
/// types: `SsbMessageKVT` and `SsbMessageValue`.
|
|
///
|
|
/// See the [kuska source code](https://github.com/Kuska-ssb/ssb/blob/master/src/api/dto/content.rs#L103) for the type definition of `TypedMessage`.
|
|
pub type SsbMessageContent = TypedMessage;
|
|
|
|
/// The `value` of an SSB message (the `V` in `KVT`).
|
|
///
|
|
/// More information concerning the data model can be found in the
|
|
/// [`Metadata` documentation](https://spec.scuttlebutt.nz/feed/messages.html#metadata).
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
#[serde(deny_unknown_fields)]
|
|
#[allow(missing_docs)]
|
|
pub struct SsbMessageValue {
|
|
pub previous: Option<String>,
|
|
pub author: String,
|
|
pub sequence: u64,
|
|
pub timestamp: f64,
|
|
pub hash: String,
|
|
pub content: Value,
|
|
pub signature: String,
|
|
}
|
|
|
|
/// Message content types.
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
#[allow(missing_docs)]
|
|
pub enum SsbMessageContentType {
|
|
About,
|
|
Vote,
|
|
Post,
|
|
Contact,
|
|
Unrecognized,
|
|
}
|
|
|
|
impl SsbMessageValue {
|
|
/// Get the type field of the message content as an enum, if found.
|
|
///
|
|
/// If no `type` field is found or the `type` field is not a string,
|
|
/// it returns an `Err(GolgiError::ContentType)`.
|
|
///
|
|
/// If a `type` field is found but with an unknown string,
|
|
/// it returns an `Ok(SsbMessageContentType::Unrecognized)`.
|
|
pub fn get_message_type(&self) -> Result<SsbMessageContentType, GolgiError> {
|
|
let msg_type = self
|
|
.content
|
|
.get("type")
|
|
.ok_or_else(|| GolgiError::ContentType("type field not found".to_string()))?;
|
|
let mtype_str: &str = msg_type.as_str().ok_or_else(|| {
|
|
GolgiError::ContentType("type field value is not a string as expected".to_string())
|
|
})?;
|
|
let enum_type = match mtype_str {
|
|
"about" => SsbMessageContentType::About,
|
|
"post" => SsbMessageContentType::Post,
|
|
"vote" => SsbMessageContentType::Vote,
|
|
"contact" => SsbMessageContentType::Contact,
|
|
_ => SsbMessageContentType::Unrecognized,
|
|
};
|
|
Ok(enum_type)
|
|
}
|
|
|
|
/// Helper function which returns `true` if this message is of the given type,
|
|
/// and `false` if the type does not match or is not found.
|
|
pub fn is_message_type(&self, message_type: SsbMessageContentType) -> bool {
|
|
let self_message_type = self.get_message_type();
|
|
match self_message_type {
|
|
Ok(mtype) => mtype == message_type,
|
|
Err(_err) => false,
|
|
}
|
|
}
|
|
|
|
/// Convert the content JSON value into an `SsbMessageContent` `enum`,
|
|
/// using the `type` field as a tag to select which variant of the `enum`
|
|
/// to deserialize into.
|
|
///
|
|
/// See the [Serde docs on internally-tagged enum representations](https://serde.rs/enum-representations.html#internally-tagged) for further details.
|
|
pub fn into_ssb_message_content(self) -> Result<SsbMessageContent, GolgiError> {
|
|
let m: SsbMessageContent = serde_json::from_value(self.content)?;
|
|
Ok(m)
|
|
}
|
|
}
|
|
|
|
/// An SSB message represented as a key-value-timestamp (`KVT`).
|
|
///
|
|
/// More information concerning the data model can be found in the
|
|
/// [`Metadata` documentation](https://spec.scuttlebutt.nz/feed/messages.html#metadata).
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
#[serde(deny_unknown_fields)]
|
|
#[allow(missing_docs)]
|
|
pub struct SsbMessageKVT {
|
|
pub key: String,
|
|
pub value: SsbMessageValue,
|
|
pub timestamp: Option<f64>,
|
|
pub rts: Option<f64>,
|
|
}
|