lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

social_events.rs (7394B)


      1 #![cfg(feature = "serde_json")]
      2 
      3 use radroots_events::{
      4     farm_crdt::RadrootsFarmCrdtDocumentKind,
      5     farm_file::{RadrootsFarmFileDimensions, RadrootsFarmFileMetadata},
      6     farm_workspace::RadrootsFarmWorkspaceRef,
      7     file_metadata::RadrootsFileMetadata,
      8     group::{RadrootsGroupEditableMetadata, RadrootsGroupMetadata},
      9     kinds::{
     10         KIND_ARTICLE, KIND_FARM, KIND_FARM_CRDT_CHANGE, KIND_GROUP_METADATA, KIND_HTTP_AUTH,
     11         KIND_LISTING, KIND_LISTING_DRAFT, KIND_POST, KIND_PUBLIC_FILE_METADATA, KIND_RELAY_AUTH,
     12         KIND_REPORT, is_home_feed_candidate_kind, is_market_candidate_kind,
     13         is_private_farm_ops_kind, is_public_social_kind,
     14     },
     15     social::RadrootsSocialMediaDimensions,
     16 };
     17 use radroots_events_codec::{
     18     article::decode::article_from_event,
     19     error::EventParseError,
     20     farm::decode::farm_from_event,
     21     farm_file::{
     22         decode::farm_file_metadata_from_event, encode::to_wire_parts as farm_file_to_wire_parts,
     23     },
     24     file_metadata::{
     25         decode::file_metadata_from_event, encode::to_wire_parts as public_file_to_wire_parts,
     26     },
     27     group::{decode::group_metadata_from_event, encode::group_metadata_to_wire_parts},
     28     listing::decode::listing_from_event,
     29     post::decode::post_from_event,
     30 };
     31 
     32 const SHA256: &str = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
     33 const OTHER_SHA256: &str = "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789";
     34 const D_TAG: &str = "AAAAAAAAAAAAAAAAAAAAAA";
     35 
     36 #[test]
     37 fn social_events_keep_public_and_private_file_metadata_apis_separate() {
     38     let public = public_file_to_wire_parts(&public_file_metadata()).unwrap();
     39     let decoded_public =
     40         file_metadata_from_event(public.kind, &public.tags, &public.content).unwrap();
     41     assert_eq!(decoded_public.url, "https://media.example.test/public.jpg");
     42     assert!(matches!(
     43         farm_file_metadata_from_event(public.kind, &public.tags, &public.content),
     44         Err(EventParseError::MissingTag("d"))
     45     ));
     46 
     47     let private = farm_file_to_wire_parts(&private_farm_file_metadata()).unwrap();
     48     let decoded_private =
     49         farm_file_metadata_from_event(private.kind, &private.tags, &private.content).unwrap();
     50     assert_eq!(decoded_private.owner_document_id, D_TAG);
     51     assert!(matches!(
     52         file_metadata_from_event(private.kind, &private.tags, &private.content),
     53         Err(EventParseError::InvalidTag("radroots:owner_document"))
     54     ));
     55 }
     56 
     57 #[test]
     58 fn social_events_reject_private_farm_ops_semantics_in_public_codecs() {
     59     let private_content = serde_json::json!({
     60         "workspace": {
     61             "pubkey": "workspace_pubkey",
     62             "d_tag": D_TAG
     63         },
     64         "farm_group_id": "field-group",
     65         "document_id": D_TAG,
     66         "document_kind": "FarmTask",
     67         "encoded_change": "abc-DEF_012"
     68     })
     69     .to_string();
     70     let farm_tags = vec![vec!["d".to_string(), D_TAG.to_string()]];
     71 
     72     assert!(matches!(
     73         farm_from_event(KIND_FARM, &farm_tags, &private_content),
     74         Err(EventParseError::InvalidJson("content"))
     75     ));
     76     assert!(matches!(
     77         post_from_event(KIND_FARM_CRDT_CHANGE, &[], "farm task"),
     78         Err(EventParseError::InvalidKind {
     79             expected: "1",
     80             got: KIND_FARM_CRDT_CHANGE
     81         })
     82     ));
     83     assert!(matches!(
     84         article_from_event(KIND_FARM_CRDT_CHANGE, &[], "farm task"),
     85         Err(EventParseError::InvalidKind {
     86             expected: "30023",
     87             got: KIND_FARM_CRDT_CHANGE
     88         })
     89     ));
     90     assert!(matches!(
     91         listing_from_event(KIND_FARM_CRDT_CHANGE, &[], "farm task"),
     92         Err(EventParseError::InvalidKind {
     93             expected: "30402 or 30403",
     94             got: KIND_FARM_CRDT_CHANGE
     95         })
     96     ));
     97     assert!(is_public_social_kind(KIND_POST));
     98     assert!(is_public_social_kind(KIND_ARTICLE));
     99     assert!(is_public_social_kind(KIND_PUBLIC_FILE_METADATA));
    100     assert!(!is_public_social_kind(KIND_FARM_CRDT_CHANGE));
    101     assert!(!is_public_social_kind(KIND_LISTING));
    102     assert!(is_home_feed_candidate_kind(KIND_LISTING));
    103     assert!(is_home_feed_candidate_kind(KIND_FARM));
    104     assert!(is_home_feed_candidate_kind(KIND_PUBLIC_FILE_METADATA));
    105     assert!(!is_home_feed_candidate_kind(KIND_LISTING_DRAFT));
    106     assert!(!is_home_feed_candidate_kind(KIND_REPORT));
    107     assert!(!is_home_feed_candidate_kind(KIND_FARM_CRDT_CHANGE));
    108     assert!(!is_home_feed_candidate_kind(KIND_RELAY_AUTH));
    109     assert!(!is_home_feed_candidate_kind(KIND_HTTP_AUTH));
    110     assert!(is_market_candidate_kind(KIND_LISTING));
    111     assert!(!is_market_candidate_kind(KIND_LISTING_DRAFT));
    112 }
    113 
    114 #[test]
    115 fn social_events_keep_nip29_groups_out_of_public_social_classification() {
    116     let group = RadrootsGroupMetadata {
    117         d_tag: "field-group".to_string(),
    118         metadata: RadrootsGroupEditableMetadata {
    119             name: Some("Field Group".to_string()),
    120             about: Some("Localhost field coordination".to_string()),
    121             picture: None,
    122             is_private: false,
    123             is_restricted: false,
    124             is_closed: false,
    125             is_hidden: false,
    126             supported_kinds: Some(vec![KIND_FARM_CRDT_CHANGE]),
    127         },
    128     };
    129     let parts = group_metadata_to_wire_parts(&group).unwrap();
    130     assert_eq!(parts.kind, KIND_GROUP_METADATA);
    131     assert!(!is_public_social_kind(KIND_GROUP_METADATA));
    132     assert!(!is_home_feed_candidate_kind(KIND_GROUP_METADATA));
    133     assert!(is_private_farm_ops_kind(KIND_GROUP_METADATA));
    134     assert_eq!(
    135         group_metadata_from_event(parts.kind, &parts.tags, &parts.content)
    136             .unwrap()
    137             .metadata
    138             .supported_kinds,
    139         Some(vec![KIND_FARM_CRDT_CHANGE])
    140     );
    141 }
    142 
    143 fn public_file_metadata() -> RadrootsFileMetadata {
    144     RadrootsFileMetadata {
    145         url: "https://media.example.test/public.jpg".to_string(),
    146         mime_type: "image/jpeg".to_string(),
    147         sha256: SHA256.to_string(),
    148         original_sha256: Some(OTHER_SHA256.to_string()),
    149         size: Some(4096),
    150         dimensions: Some(RadrootsSocialMediaDimensions {
    151             width: 1200,
    152             height: 800,
    153         }),
    154         blurhash: None,
    155         thumbnails: None,
    156         summary: Some("Public field photo".to_string()),
    157         alt: Some("Rows after harvest".to_string()),
    158         fallback: None,
    159         magnet: None,
    160         content_hashes: None,
    161         services: None,
    162         content: Some("caption".to_string()),
    163     }
    164 }
    165 
    166 fn private_farm_file_metadata() -> RadrootsFarmFileMetadata {
    167     RadrootsFarmFileMetadata {
    168         d_tag: D_TAG.to_string(),
    169         workspace: RadrootsFarmWorkspaceRef {
    170             pubkey: "workspace_pubkey".to_string(),
    171             d_tag: D_TAG.to_string(),
    172         },
    173         farm_group_id: "field-group".to_string(),
    174         owner_document_id: D_TAG.to_string(),
    175         owner_document_kind: RadrootsFarmCrdtDocumentKind::FarmTask,
    176         caption: Some("private caption".to_string()),
    177         url: "https://media.example.test/private.jpg".to_string(),
    178         mime_type: "image/jpeg".to_string(),
    179         sha256: SHA256.to_string(),
    180         original_sha256: Some(OTHER_SHA256.to_string()),
    181         size_bytes: Some(4096),
    182         dimensions: Some(RadrootsFarmFileDimensions { w: 1200, h: 800 }),
    183         blurhash: None,
    184         thumb: None,
    185         image: None,
    186         alt: Some("Private farm task attachment".to_string()),
    187         fallbacks: Vec::new(),
    188     }
    189 }