make sure post entry has expected content type, reorganize post members

This commit is contained in:
postscriptum 2025-07-02 20:38:22 +03:00
parent 5d24b9e46e
commit b6d2088863
6 changed files with 73 additions and 43 deletions

View file

@ -42,6 +42,10 @@ fn sync(snac: &Snac, nex: &Nex) -> Result<(usize, usize)> {
println!("\tsync profile for `{}`...", user.name);
for post in user.public()? {
t += 1;
// make sure post entry has expected content type
if !post.is_note() {
todo!()
}
// skip non authorized content
if let Some(content) = post.source_content {
println!("\t\tsync post `{}`...", post.id);

View file

@ -1,43 +1,2 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, de::Error};
use std::str::FromStr;
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Attachment {
pub media_type: String,
pub url: String,
pub name: String,
}
#[derive(Deserialize, Debug)]
pub struct Tag {
pub name: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Post {
pub attachment: Option<Vec<Attachment>>,
pub id: String,
#[serde(default, deserialize_with = "time")]
pub published: DateTime<Utc>,
pub source_content: Option<String>,
pub tag: Option<Vec<Tag>>,
#[serde(default, deserialize_with = "time_option")]
pub updated: Option<DateTime<Utc>>,
pub url: String,
}
fn time<'de, D: serde::Deserializer<'de>>(d: D) -> Result<DateTime<Utc>, D::Error> {
let s = String::deserialize(d)?;
DateTime::from_str(&s).map_err(Error::custom)
}
fn time_option<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> {
let s: Option<String> = Option::deserialize(d)?;
match s {
Some(ref t) => DateTime::from_str(t).map(Some).map_err(Error::custom),
None => Ok(None),
}
}
mod post;
pub use post::Post;

View file

@ -0,0 +1,52 @@
mod attachment;
mod ptype;
mod tag;
use attachment::Attachment;
use chrono::{DateTime, Utc};
use ptype::Type;
use serde::{Deserialize, de::Error};
use std::str::FromStr;
use tag::Tag;
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Post {
#[serde(rename = "type", deserialize_with = "ptype")]
pub ptype: Type,
pub attachment: Option<Vec<Attachment>>,
pub id: String,
#[serde(default, deserialize_with = "time")]
pub published: DateTime<Utc>,
pub source_content: Option<String>,
pub tag: Option<Vec<Tag>>,
#[serde(default, deserialize_with = "time_option")]
pub updated: Option<DateTime<Utc>>,
pub url: String,
}
impl Post {
pub fn is_note(&self) -> bool {
matches!(self.ptype, Type::Note)
}
}
fn ptype<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Type, D::Error> {
if String::deserialize(d)?.to_lowercase() == "note" {
return Ok(Type::Note);
}
Err(D::Error::custom("Invalid post type"))
}
fn time<'de, D: serde::Deserializer<'de>>(d: D) -> Result<DateTime<Utc>, D::Error> {
let s = String::deserialize(d)?;
DateTime::from_str(&s).map_err(Error::custom)
}
fn time_option<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> {
let s: Option<String> = Option::deserialize(d)?;
match s {
Some(ref t) => DateTime::from_str(t).map(Some).map_err(Error::custom),
None => Ok(None),
}
}

View file

@ -0,0 +1,7 @@
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Attachment {
pub media_type: String,
pub url: String,
pub name: String,
}

View file

@ -0,0 +1,4 @@
#[derive(Debug)]
pub enum Type {
Note,
}

View file

@ -0,0 +1,4 @@
#[derive(serde::Deserialize, Debug)]
pub struct Tag {
pub name: String,
}