encode.rs (11531B)
1 #[cfg(not(feature = "std"))] 2 use alloc::{ 3 string::{String, ToString}, 4 vec, 5 vec::Vec, 6 }; 7 8 use radroots_events::{ 9 group::{ 10 KIND_GROUP_ADMINS, KIND_GROUP_CREATE_GROUP, KIND_GROUP_CREATE_INVITE, 11 KIND_GROUP_DELETE_EVENT, KIND_GROUP_DELETE_GROUP, KIND_GROUP_EDIT_METADATA, 12 KIND_GROUP_JOIN_REQUEST, KIND_GROUP_LEAVE_REQUEST, KIND_GROUP_MEMBERS, KIND_GROUP_METADATA, 13 KIND_GROUP_PUT_USER, KIND_GROUP_REMOVE_USER, KIND_GROUP_ROLES, RadrootsGroupAdmins, 14 RadrootsGroupCreateGroup, RadrootsGroupCreateInvite, RadrootsGroupDeleteEvent, 15 RadrootsGroupDeleteGroup, RadrootsGroupEditMetadata, RadrootsGroupEditableMetadata, 16 RadrootsGroupJoinRequest, RadrootsGroupLeaveRequest, RadrootsGroupMembers, 17 RadrootsGroupMetadata, RadrootsGroupPutUser, RadrootsGroupRemoveUser, RadrootsGroupRole, 18 RadrootsGroupRoles, RadrootsGroupUserRef, 19 }, 20 tags::{TAG_D, TAG_E, TAG_H, TAG_P}, 21 }; 22 23 use crate::error::EventEncodeError; 24 use crate::field_helpers::{ 25 push_optional_tag, push_tag, push_tag_values, validate_non_empty_field, 26 }; 27 use crate::wire::WireEventParts; 28 29 const TAG_ABOUT: &str = "about"; 30 const TAG_CLOSED: &str = "closed"; 31 const TAG_CODE: &str = "code"; 32 const TAG_HIDDEN: &str = "hidden"; 33 const TAG_NAME: &str = "name"; 34 const TAG_PICTURE: &str = "picture"; 35 const TAG_PRIVATE: &str = "private"; 36 const TAG_RESTRICTED: &str = "restricted"; 37 const TAG_ROLE: &str = "role"; 38 const TAG_SUPPORTED_KINDS: &str = "supported_kinds"; 39 40 pub fn group_put_user_build_tags( 41 event: &RadrootsGroupPutUser, 42 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 43 let mut tags = h_tags(&event.group_id)?; 44 push_user_tag(&mut tags, &event.pubkey, &event.roles)?; 45 Ok(tags) 46 } 47 48 pub fn group_remove_user_build_tags( 49 event: &RadrootsGroupRemoveUser, 50 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 51 let mut tags = h_tags(&event.group_id)?; 52 push_tag(&mut tags, TAG_P, event.pubkey.as_str()); 53 validate_non_empty_field(&event.pubkey, "pubkey")?; 54 Ok(tags) 55 } 56 57 pub fn group_create_group_build_tags( 58 event: &RadrootsGroupCreateGroup, 59 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 60 let mut tags = h_tags(&event.group_id)?; 61 push_metadata_tags(&mut tags, &event.metadata)?; 62 Ok(tags) 63 } 64 65 pub fn group_edit_metadata_build_tags( 66 event: &RadrootsGroupEditMetadata, 67 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 68 let mut tags = h_tags(&event.group_id)?; 69 push_metadata_tags(&mut tags, &event.metadata)?; 70 Ok(tags) 71 } 72 73 pub fn group_delete_group_build_tags( 74 event: &RadrootsGroupDeleteGroup, 75 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 76 h_tags(&event.group_id) 77 } 78 79 pub fn group_delete_event_build_tags( 80 event: &RadrootsGroupDeleteEvent, 81 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 82 let mut tags = h_tags(&event.group_id)?; 83 validate_non_empty_field(&event.event_id, "event_id")?; 84 push_tag(&mut tags, TAG_E, event.event_id.as_str()); 85 Ok(tags) 86 } 87 88 pub fn group_create_invite_build_tags( 89 event: &RadrootsGroupCreateInvite, 90 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 91 let mut tags = h_tags(&event.group_id)?; 92 validate_non_empty_field(&event.code, "code")?; 93 push_tag(&mut tags, TAG_CODE, event.code.as_str()); 94 Ok(tags) 95 } 96 97 pub fn group_join_request_build_tags( 98 event: &RadrootsGroupJoinRequest, 99 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 100 let mut tags = h_tags(&event.group_id)?; 101 push_optional_tag(&mut tags, TAG_CODE, event.code.as_deref()); 102 validate_optional(event.code.as_deref(), "code")?; 103 Ok(tags) 104 } 105 106 pub fn group_leave_request_build_tags( 107 event: &RadrootsGroupLeaveRequest, 108 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 109 h_tags(&event.group_id) 110 } 111 112 pub fn group_metadata_build_tags( 113 event: &RadrootsGroupMetadata, 114 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 115 let mut tags = d_tags(&event.d_tag)?; 116 push_metadata_tags(&mut tags, &event.metadata)?; 117 Ok(tags) 118 } 119 120 pub fn group_admins_build_tags( 121 event: &RadrootsGroupAdmins, 122 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 123 let mut tags = d_tags(&event.d_tag)?; 124 push_user_refs(&mut tags, &event.admins)?; 125 Ok(tags) 126 } 127 128 pub fn group_members_build_tags( 129 event: &RadrootsGroupMembers, 130 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 131 let mut tags = d_tags(&event.d_tag)?; 132 push_user_refs(&mut tags, &event.members)?; 133 Ok(tags) 134 } 135 136 pub fn group_roles_build_tags( 137 event: &RadrootsGroupRoles, 138 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 139 let mut tags = d_tags(&event.d_tag)?; 140 for role in &event.roles { 141 validate_role(role)?; 142 let mut values = vec![role.name.clone()]; 143 if let Some(description) = role.description.as_deref() { 144 values.push(description.to_string()); 145 } 146 values.extend(role.permissions.iter().cloned()); 147 push_tag_values(&mut tags, TAG_ROLE, values); 148 } 149 Ok(tags) 150 } 151 152 pub fn group_put_user_to_wire_parts( 153 event: &RadrootsGroupPutUser, 154 ) -> Result<WireEventParts, EventEncodeError> { 155 message_wire( 156 KIND_GROUP_PUT_USER, 157 group_put_user_build_tags(event)?, 158 event.message.as_deref(), 159 ) 160 } 161 162 pub fn group_remove_user_to_wire_parts( 163 event: &RadrootsGroupRemoveUser, 164 ) -> Result<WireEventParts, EventEncodeError> { 165 message_wire( 166 KIND_GROUP_REMOVE_USER, 167 group_remove_user_build_tags(event)?, 168 event.message.as_deref(), 169 ) 170 } 171 172 pub fn group_create_group_to_wire_parts( 173 event: &RadrootsGroupCreateGroup, 174 ) -> Result<WireEventParts, EventEncodeError> { 175 message_wire( 176 KIND_GROUP_CREATE_GROUP, 177 group_create_group_build_tags(event)?, 178 event.message.as_deref(), 179 ) 180 } 181 182 pub fn group_edit_metadata_to_wire_parts( 183 event: &RadrootsGroupEditMetadata, 184 ) -> Result<WireEventParts, EventEncodeError> { 185 message_wire( 186 KIND_GROUP_EDIT_METADATA, 187 group_edit_metadata_build_tags(event)?, 188 event.message.as_deref(), 189 ) 190 } 191 192 pub fn group_delete_group_to_wire_parts( 193 event: &RadrootsGroupDeleteGroup, 194 ) -> Result<WireEventParts, EventEncodeError> { 195 message_wire( 196 KIND_GROUP_DELETE_GROUP, 197 group_delete_group_build_tags(event)?, 198 event.message.as_deref(), 199 ) 200 } 201 202 pub fn group_delete_event_to_wire_parts( 203 event: &RadrootsGroupDeleteEvent, 204 ) -> Result<WireEventParts, EventEncodeError> { 205 message_wire( 206 KIND_GROUP_DELETE_EVENT, 207 group_delete_event_build_tags(event)?, 208 event.message.as_deref(), 209 ) 210 } 211 212 pub fn group_create_invite_to_wire_parts( 213 event: &RadrootsGroupCreateInvite, 214 ) -> Result<WireEventParts, EventEncodeError> { 215 message_wire( 216 KIND_GROUP_CREATE_INVITE, 217 group_create_invite_build_tags(event)?, 218 event.message.as_deref(), 219 ) 220 } 221 222 pub fn group_join_request_to_wire_parts( 223 event: &RadrootsGroupJoinRequest, 224 ) -> Result<WireEventParts, EventEncodeError> { 225 message_wire( 226 KIND_GROUP_JOIN_REQUEST, 227 group_join_request_build_tags(event)?, 228 event.message.as_deref(), 229 ) 230 } 231 232 pub fn group_leave_request_to_wire_parts( 233 event: &RadrootsGroupLeaveRequest, 234 ) -> Result<WireEventParts, EventEncodeError> { 235 message_wire( 236 KIND_GROUP_LEAVE_REQUEST, 237 group_leave_request_build_tags(event)?, 238 event.message.as_deref(), 239 ) 240 } 241 242 pub fn group_metadata_to_wire_parts( 243 event: &RadrootsGroupMetadata, 244 ) -> Result<WireEventParts, EventEncodeError> { 245 empty_wire(KIND_GROUP_METADATA, group_metadata_build_tags(event)?) 246 } 247 248 pub fn group_admins_to_wire_parts( 249 event: &RadrootsGroupAdmins, 250 ) -> Result<WireEventParts, EventEncodeError> { 251 message_wire( 252 KIND_GROUP_ADMINS, 253 group_admins_build_tags(event)?, 254 event.description.as_deref(), 255 ) 256 } 257 258 pub fn group_members_to_wire_parts( 259 event: &RadrootsGroupMembers, 260 ) -> Result<WireEventParts, EventEncodeError> { 261 message_wire( 262 KIND_GROUP_MEMBERS, 263 group_members_build_tags(event)?, 264 event.description.as_deref(), 265 ) 266 } 267 268 pub fn group_roles_to_wire_parts( 269 event: &RadrootsGroupRoles, 270 ) -> Result<WireEventParts, EventEncodeError> { 271 message_wire( 272 KIND_GROUP_ROLES, 273 group_roles_build_tags(event)?, 274 event.description.as_deref(), 275 ) 276 } 277 278 fn h_tags(group_id: &str) -> Result<Vec<Vec<String>>, EventEncodeError> { 279 validate_non_empty_field(group_id, "group_id")?; 280 let mut tags = Vec::new(); 281 push_tag(&mut tags, TAG_H, group_id); 282 Ok(tags) 283 } 284 285 fn d_tags(d_tag: &str) -> Result<Vec<Vec<String>>, EventEncodeError> { 286 validate_non_empty_field(d_tag, "d_tag")?; 287 let mut tags = Vec::new(); 288 push_tag(&mut tags, TAG_D, d_tag); 289 Ok(tags) 290 } 291 292 fn push_metadata_tags( 293 tags: &mut Vec<Vec<String>>, 294 metadata: &RadrootsGroupEditableMetadata, 295 ) -> Result<(), EventEncodeError> { 296 push_optional_tag(tags, TAG_NAME, metadata.name.as_deref()); 297 push_optional_tag(tags, TAG_ABOUT, metadata.about.as_deref()); 298 push_optional_tag(tags, TAG_PICTURE, metadata.picture.as_deref()); 299 if metadata.is_private { 300 push_marker_tag(tags, TAG_PRIVATE); 301 } 302 if metadata.is_restricted { 303 push_marker_tag(tags, TAG_RESTRICTED); 304 } 305 if metadata.is_closed { 306 push_marker_tag(tags, TAG_CLOSED); 307 } 308 if metadata.is_hidden { 309 push_marker_tag(tags, TAG_HIDDEN); 310 } 311 if let Some(supported_kinds) = metadata.supported_kinds.as_deref() { 312 push_tag_values( 313 tags, 314 TAG_SUPPORTED_KINDS, 315 supported_kinds.iter().map(ToString::to_string), 316 ); 317 } 318 validate_optional(metadata.name.as_deref(), "name")?; 319 validate_optional(metadata.about.as_deref(), "about")?; 320 validate_optional(metadata.picture.as_deref(), "picture")?; 321 Ok(()) 322 } 323 324 fn push_marker_tag(tags: &mut Vec<Vec<String>>, key: &str) { 325 tags.push(vec![key.to_string()]); 326 } 327 328 fn push_user_refs( 329 tags: &mut Vec<Vec<String>>, 330 users: &[RadrootsGroupUserRef], 331 ) -> Result<(), EventEncodeError> { 332 for user in users { 333 push_user_tag(tags, &user.pubkey, &user.roles)?; 334 } 335 Ok(()) 336 } 337 338 fn push_user_tag( 339 tags: &mut Vec<Vec<String>>, 340 pubkey: &str, 341 roles: &[String], 342 ) -> Result<(), EventEncodeError> { 343 validate_non_empty_field(pubkey, "pubkey")?; 344 for role in roles { 345 validate_non_empty_field(role, "roles")?; 346 } 347 let mut values = vec![pubkey.to_string()]; 348 values.extend(roles.iter().cloned()); 349 push_tag_values(tags, TAG_P, values); 350 Ok(()) 351 } 352 353 fn validate_role(role: &RadrootsGroupRole) -> Result<(), EventEncodeError> { 354 validate_non_empty_field(&role.name, "role.name")?; 355 validate_optional(role.description.as_deref(), "role.description")?; 356 for permission in &role.permissions { 357 validate_non_empty_field(permission, "role.permissions")?; 358 } 359 Ok(()) 360 } 361 362 fn validate_optional(value: Option<&str>, field: &'static str) -> Result<(), EventEncodeError> { 363 if let Some(value) = value { 364 validate_non_empty_field(value, field)?; 365 } 366 Ok(()) 367 } 368 369 fn empty_wire(kind: u32, tags: Vec<Vec<String>>) -> Result<WireEventParts, EventEncodeError> { 370 Ok(WireEventParts { 371 kind, 372 content: String::new(), 373 tags, 374 }) 375 } 376 377 fn message_wire( 378 kind: u32, 379 tags: Vec<Vec<String>>, 380 message: Option<&str>, 381 ) -> Result<WireEventParts, EventEncodeError> { 382 validate_optional(message, "message")?; 383 Ok(WireEventParts { 384 kind, 385 content: message.unwrap_or_default().to_string(), 386 tags, 387 }) 388 }