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