Deserialize TypedSsbMessageValue
This commit is contained in:
parent
0952ad9220
commit
1b2b1db95f
|
@ -4,6 +4,7 @@ use kuska_ssb::api::dto::content::{SubsetQuery, TypedMessage, Post};
|
||||||
|
|
||||||
use golgi::error::GolgiError;
|
use golgi::error::GolgiError;
|
||||||
use golgi::sbot::Sbot;
|
use golgi::sbot::Sbot;
|
||||||
|
use golgi::utils::{SsbMessageValue, TypedSsbMessageValue};
|
||||||
|
|
||||||
async fn run() -> Result<(), GolgiError> {
|
async fn run() -> Result<(), GolgiError> {
|
||||||
let mut sbot_client = Sbot::init(None, None).await?;
|
let mut sbot_client = Sbot::init(None, None).await?;
|
||||||
|
@ -14,13 +15,12 @@ async fn run() -> Result<(), GolgiError> {
|
||||||
let author = "@L/z54cbc8V1kL1/MiBhpEKuN3QJkSoZYNaukny3ghIs=.ed25519".to_string();
|
let author = "@L/z54cbc8V1kL1/MiBhpEKuN3QJkSoZYNaukny3ghIs=.ed25519".to_string();
|
||||||
|
|
||||||
println!("Calling create_history");
|
println!("Calling create_history");
|
||||||
let hist_response = sbot_client.create_history_stream(author).await?;
|
let messages : Vec<SsbMessageValue> = sbot_client.create_history_stream(author).await?;
|
||||||
println!("hist: {:?}", hist_response);
|
println!("hist: {:?}", messages);
|
||||||
|
|
||||||
let posts: Vec<Post> = hist_response.iter().flat_map(|msg| msg.into_post()).collect();
|
for message in messages {
|
||||||
|
let t: TypedSsbMessageValue = message.into_typed_message_value()?;
|
||||||
for post in posts {
|
println!("t: {:?}", t);
|
||||||
println!("post: {:?}", post);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -35,6 +35,8 @@ pub enum GolgiError {
|
||||||
Sbot(String),
|
Sbot(String),
|
||||||
/// JSON serialization or deserialization error.
|
/// JSON serialization or deserialization error.
|
||||||
SerdeJson(JsonError),
|
SerdeJson(JsonError),
|
||||||
|
/// Error decoding typed ssb message from content.
|
||||||
|
ContentTypeDecode(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for GolgiError {
|
impl std::error::Error for GolgiError {
|
||||||
|
@ -48,6 +50,7 @@ impl std::error::Error for GolgiError {
|
||||||
GolgiError::Rpc(ref err) => Some(err),
|
GolgiError::Rpc(ref err) => Some(err),
|
||||||
GolgiError::Sbot(_) => None,
|
GolgiError::Sbot(_) => None,
|
||||||
GolgiError::SerdeJson(ref err) => Some(err),
|
GolgiError::SerdeJson(ref err) => Some(err),
|
||||||
|
GolgiError::ContentTypeDecode(ref err) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +70,7 @@ impl std::fmt::Display for GolgiError {
|
||||||
GolgiError::Sbot(ref err) => write!(f, "Sbot returned an error response: {}", err),
|
GolgiError::Sbot(ref err) => write!(f, "Sbot returned an error response: {}", err),
|
||||||
GolgiError::SerdeJson(_) => write!(f, "Failed to serialize JSON slice"),
|
GolgiError::SerdeJson(_) => write!(f, "Failed to serialize JSON slice"),
|
||||||
//GolgiError::WhoAmI(ref err) => write!(f, "{}", err),
|
//GolgiError::WhoAmI(ref err) => write!(f, "{}", err),
|
||||||
|
GolgiError::ContentTypeDecode(ref err) => write!(f, "Failed to decode typed message from ssb message content: {}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,6 @@
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod sbot;
|
pub mod sbot;
|
||||||
mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
pub use crate::error::GolgiError;
|
pub use crate::error::GolgiError;
|
||||||
|
|
76
src/utils.rs
76
src/utils.rs
|
@ -6,7 +6,6 @@ use serde::{Serialize, Deserialize};
|
||||||
use kuska_ssb::api::dto::WhoAmIOut;
|
use kuska_ssb::api::dto::WhoAmIOut;
|
||||||
use kuska_ssb::feed::{Feed, Message};
|
use kuska_ssb::feed::{Feed, Message};
|
||||||
use kuska_ssb::rpc::{RecvMsg, RequestNo, RpcReader};
|
use kuska_ssb::rpc::{RecvMsg, RequestNo, RpcReader};
|
||||||
use kuska_ssb::api::dto::content::{Post, Vote};
|
|
||||||
use kuska_ssb::api::dto::content::TypedMessage;
|
use kuska_ssb::api::dto::content::TypedMessage;
|
||||||
|
|
||||||
use ssb_legacy_msg_data::LegacyF64;
|
use ssb_legacy_msg_data::LegacyF64;
|
||||||
|
@ -36,37 +35,58 @@ impl SsbMessageValue {
|
||||||
msg_type
|
msg_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_post(self) -> Result<Post, GolgiError> {
|
pub fn into_typed_message(self) -> Result<TypedMessage, GolgiError> {
|
||||||
let p: Post = serde_json::from_value(self.content)?;
|
let t: TypedMessage = serde_json::from_value(self.content)?;
|
||||||
Ok(p)
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_vote(self) -> Result<Vote, GolgiError> {
|
pub fn into_typed_message_value(self) -> Result<TypedSsbMessageValue, GolgiError> {
|
||||||
let p: Vote = serde_json::from_value(self.content)?;
|
let typed_message: TypedMessage = get_typed_message_from_value(self.content.clone())?;
|
||||||
Ok(p)
|
let typed_message_value = TypedSsbMessageValue {
|
||||||
|
previous: self.previous,
|
||||||
|
author: self.author,
|
||||||
|
sequence: self.sequence,
|
||||||
|
timestamp: self.timestamp,
|
||||||
|
hash: self.hash,
|
||||||
|
content: self.content,
|
||||||
|
typed_message,
|
||||||
|
signature: self.signature,
|
||||||
|
};
|
||||||
|
Ok(typed_message_value)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: this doesnt work, because the arms return two different types
|
|
||||||
// but maybe there is a way to do type inheritance?
|
/// Function to parse a TypedMessage from an ssb message content field.
|
||||||
// this SO post says you dont deserialize directly into enum variants
|
/// TypedMessage has a tag field, named "type", which instructs serde to choose which variant
|
||||||
// https://stackoverflow.com/questions/59460464/how-do-i-use-serde-to-deserialize-into-a-specific-enum-variant
|
/// to attempt to deserialize by looking at the value of the type field.
|
||||||
// pub fn into_typed_message(self) -> Result<TypedMessage, GolgiError> {
|
///
|
||||||
// let msg_type = self.get_message_type();
|
/// See documentation here: https://serde.rs/enum-representations.html#internally-tagged
|
||||||
// let msg = match msg_type {
|
///
|
||||||
// "post" => {
|
/// # Arguments
|
||||||
// let p: Post = serde_json::from_value(self.content)?;
|
///
|
||||||
// p
|
/// * `value` - A serde value to be parsed into a TypedMessage.
|
||||||
// },
|
pub fn get_typed_message_from_value(value: Value) -> Result<TypedMessage, GolgiError> {
|
||||||
// "vote" => {
|
let message_type = value.get("type").ok_or(GolgiError::ContentTypeDecode("no type field in content".to_string()))?;
|
||||||
// let p: Vote = serde_json::from_value(self.content)?;
|
let message_type_str = message_type.as_str().ok_or(GolgiError::ContentTypeDecode("invalid type field in content".to_string()))?;
|
||||||
// p
|
let to_return: TypedMessage = serde_json::from_value(value)?;
|
||||||
// },
|
Ok(to_return)
|
||||||
// _ => {
|
}
|
||||||
// Err(GolgiError::Sbot("No type included in message content".to_string()))
|
|
||||||
// }
|
/// Data type representing the `value` of a message object (`KVT`),
|
||||||
// };
|
/// with an additional field typed_message which contains a TypedMessage object
|
||||||
// Ok(msg)
|
/// made by deserializing the content field.
|
||||||
// }
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct TypedSsbMessageValue {
|
||||||
|
pub previous: Option<Multihash>,
|
||||||
|
pub author: String,
|
||||||
|
pub sequence: u64,
|
||||||
|
pub timestamp: LegacyF64,
|
||||||
|
pub hash: String,
|
||||||
|
pub content: Value,
|
||||||
|
pub typed_message: TypedMessage,
|
||||||
|
pub signature: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data type representing the `value` of a message object (`KVT`). More information concerning the
|
/// Data type representing the `value` of a message object (`KVT`). More information concerning the
|
||||||
|
|
Loading…
Reference in New Issue