Upload files to "src/core"

This commit is contained in:
jhoninck 2025-09-02 15:06:31 +00:00
commit baa720b769
4 changed files with 1599 additions and 0 deletions

408
src/core/docs_api_guide.rs Normal file
View file

@ -0,0 +1,408 @@
//! API Guide for Continuwuity Enhanced Types
//!
//! This module provides a comprehensive guide for using our enhanced types
//! and error handling in Continuwuity applications.
use crate::types::*;
use crate::error::*;
/// API Guide: Enhanced Error Handling
///
/// Our enhanced error system provides better user experience and debugging capabilities.
///
/// # Key Features
///
/// - **User-friendly messages**: Clear, actionable error messages for users
/// - **Sanitized logging**: Safe error messages for logs without sensitive data
/// - **Matrix compliance**: Proper Matrix error codes and HTTP status codes
/// - **Contextual information**: Rich error context for better debugging
///
/// # Usage Examples
///
/// ## Creating Errors
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// // Authentication errors
/// let auth_error = EnhancedError::auth_failed("Invalid token");
///
/// // Room errors
/// let room_error = EnhancedError::room_not_found("!room123:example.com");
///
/// // User errors
/// let user_error = EnhancedError::user_not_found("@user:example.com");
///
/// // Permission errors
/// let perm_error = EnhancedError::insufficient_permissions("Admin role required");
///
/// // Federation errors
/// let fed_error = EnhancedError::federation_error("matrix.org", "Connection timeout");
///
/// // Configuration errors
/// let config_error = EnhancedError::config_error("database_url", "Invalid format");
///
/// // Database errors
/// let db_error = EnhancedError::database_error("user_lookup", "Connection lost");
///
/// // Network errors
/// let net_error = EnhancedError::network_error("federation", "DNS resolution failed");
///
/// // Validation errors
/// let val_error = EnhancedError::validation_error("room_name", "Too long");
///
/// // Rate limit errors
/// let rate_error = EnhancedError::rate_limit_exceeded("room_creation", 60);
/// ```
///
/// ## Using Error Information
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// let error = EnhancedError::room_not_found("!room123:example.com");
///
/// // Get user-friendly message
/// let user_msg = error.user_message();
/// // "The room '!room123:example.com' could not be found. It may have been deleted or you may not have access."
///
/// // Get sanitized message for logging
/// let log_msg = error.sanitized_message();
/// // "Room not found: !room123:example.com"
///
/// // Get Matrix error code
/// let matrix_code = error.matrix_error_code();
/// // "M_NOT_FOUND"
///
/// // Get HTTP status code
/// let http_code = error.http_status_code();
/// // 404
/// ```
pub fn enhanced_error_guide() {
// This function demonstrates the enhanced error handling API
let _auth_error = EnhancedError::auth_failed("Invalid token");
let _room_error = EnhancedError::room_not_found("!room123:example.com");
let _user_error = EnhancedError::user_not_found("@user:example.com");
}
/// API Guide: Enhanced Room Types
///
/// Our enhanced room types provide better organization and functionality for room operations.
///
/// # Key Features
///
/// - **Rich room information**: Comprehensive room data with metadata
/// - **Permission checking**: Built-in methods for checking user permissions
/// - **Power level management**: Easy power level configuration and checking
/// - **State management**: Proper room state handling
///
/// # Usage Examples
///
/// ## Creating Room Information
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let room = EnhancedRoomInfo::new("!room123:example.com".to_string());
///
/// // Set room properties
/// let mut room = EnhancedRoomInfo::new("!room123:example.com".to_string());
/// room.name = Some("My Awesome Room".to_string());
/// room.topic = Some("A room for awesome discussions".to_string());
/// room.is_public = true;
/// room.join_rule = JoinRule::Public;
/// ```
///
/// ## Checking Permissions
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let room = EnhancedRoomInfo::new("!room123:example.com".to_string());
///
/// // Check if user is admin
/// let is_admin = room.is_admin("@admin:example.com");
///
/// // Check if user can send messages
/// let can_send = room.can_send_message("@user:example.com");
/// ```
///
/// ## Power Level Management
///
/// ```rust
/// use conduwuit_core::types::*;
/// use std::collections::HashMap;
///
/// let mut power_levels = PowerLevels::default();
/// power_levels.users.insert("@admin:example.com".to_string(), 100);
/// power_levels.users.insert("@moderator:example.com".to_string(), 50);
/// power_levels.events_default = 0;
/// power_levels.state_default = 50;
/// ```
pub fn enhanced_room_guide() {
// This function demonstrates the enhanced room types API
let room = EnhancedRoomInfo::new("!room123:example.com".to_string());
let _is_admin = room.is_admin("@admin:example.com");
let _can_send = room.can_send_message("@user:example.com");
}
/// API Guide: Enhanced User Types
///
/// Our enhanced user types provide better user information and management.
///
/// # Key Features
///
/// - **Rich user information**: Comprehensive user data with presence
/// - **Membership checking**: Built-in methods for checking user membership
/// - **Permission checking**: Easy permission level checking
/// - **Profile management**: Complete user profile information
///
/// # Usage Examples
///
/// ## Creating User Information
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let user = EnhancedUserInfo::new("@user:example.com".to_string());
///
/// // Set user properties
/// let mut user = EnhancedUserInfo::new("@user:example.com".to_string());
/// user.display_name = Some("Alice".to_string());
/// user.avatar_url = Some("mxc://example.com/avatar123".to_string());
/// user.is_online = true;
/// user.power_level = 50;
/// user.membership_state = MembershipState::Join;
/// ```
///
/// ## Checking User Status
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let user = EnhancedUserInfo::new("@user:example.com".to_string());
///
/// // Check if user is a member
/// let is_member = user.is_member();
///
/// // Check if user is a moderator
/// let is_moderator = user.is_moderator();
/// ```
///
/// ## User Profiles
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let profile = EnhancedUserProfile {
/// user_id: "@alice:example.com".to_string(),
/// display_name: Some("Alice".to_string()),
/// avatar_url: Some("mxc://example.com/avatar123".to_string()),
/// is_online: true,
/// last_seen: Some(1640995200),
/// presence: PresenceState::Online,
/// status_msg: Some("Working on Matrix stuff".to_string()),
/// };
/// ```
pub fn enhanced_user_guide() {
// This function demonstrates the enhanced user types API
let user = EnhancedUserInfo::new("@user:example.com".to_string());
let _is_member = user.is_member();
let _is_moderator = user.is_moderator();
}
/// API Guide: Enhanced Message Types
///
/// Our enhanced message types provide better message handling and processing.
///
/// # Key Features
///
/// - **Rich message content**: Comprehensive message data with metadata
/// - **Reply handling**: Built-in support for message replies
/// - **Thread support**: Easy thread message handling
/// - **Mention support**: Built-in mention handling
///
/// # Usage Examples
///
/// ## Creating Messages
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// // Create a simple text message
/// let message = EnhancedMessageContent::new_text("Hello, world!".to_string());
///
/// // Create a notice message
/// let notice = EnhancedMessageContent::new_notice("System message".to_string());
/// ```
///
/// ## Creating Replies
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let mut reply = EnhancedMessageContent::new_text("This is a reply".to_string());
/// reply.relates_to = Some(RelatesTo {
/// in_reply_to: Some(InReplyTo {
/// event_id: "$original_event_id".to_string(),
/// }),
/// rel_type: None,
/// event_id: None,
/// });
///
/// // Check if message is a reply
/// let is_reply = reply.is_reply();
/// ```
///
/// ## Creating Thread Messages
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let mut thread_message = EnhancedMessageContent::new_text("Thread message".to_string());
/// thread_message.thread = Some(ThreadInfo {
/// event_id: "$thread_root_event_id".to_string(),
/// is_falling_back: None,
/// is_editing: None,
/// });
///
/// // Check if message is in a thread
/// let is_thread = thread_message.is_thread();
/// ```
///
/// ## Adding Mentions
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let mut message = EnhancedMessageContent::new_text("Hello @alice:example.com!".to_string());
/// message.mentions = Some(Mentions {
/// user_ids: vec!["@alice:example.com".to_string()],
/// room: false,
/// });
/// ```
pub fn enhanced_message_guide() {
// This function demonstrates the enhanced message types API
let message = EnhancedMessageContent::new_text("Hello, world!".to_string());
let _is_reply = message.is_reply();
let _is_thread = message.is_thread();
}
/// API Guide: Room Creation and Management
///
/// Our enhanced types provide better room creation and management capabilities.
///
/// # Key Features
///
/// - **Structured room creation**: Well-defined room creation requests
/// - **Member management**: Easy room member handling
/// - **Room summaries**: Rich room information for listings
/// - **State management**: Proper room state handling
///
/// # Usage Examples
///
/// ## Creating Rooms
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let room_request = EnhancedRoomCreateRequest {
/// name: Some("My Awesome Room".to_string()),
/// topic: Some("A room for awesome discussions".to_string()),
/// preset: Some(RoomPreset::PublicChat),
/// room_version: Some("10".to_string()),
/// is_direct: Some(false),
/// invite: Some(vec!["@alice:example.com".to_string()]),
/// initial_state: None,
/// };
/// ```
///
/// ## Managing Room Members
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let member = EnhancedRoomMember {
/// user_id: "@alice:example.com".to_string(),
/// display_name: Some("Alice".to_string()),
/// avatar_url: Some("mxc://example.com/avatar123".to_string()),
/// membership: MembershipState::Join,
/// power_level: 50,
/// is_direct: false,
/// third_party_invite: None,
/// };
/// ```
///
/// ## Room Summaries
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let room_summary = EnhancedRoomSummary {
/// room_id: "!room123:example.com".to_string(),
/// name: Some("General Discussion".to_string()),
/// topic: Some("A place for general chat".to_string()),
/// avatar_url: Some("mxc://example.com/room_avatar".to_string()),
/// member_count: 42,
/// is_public: true,
/// last_activity: 1640995200,
/// unread_count: 5,
/// highlight_count: 2,
/// notification_count: 7,
/// };
/// ```
pub fn room_management_guide() {
// This function demonstrates the room management API
let _room_request = EnhancedRoomCreateRequest {
name: Some("Example Room".to_string()),
topic: Some("Example topic".to_string()),
preset: Some(RoomPreset::PublicChat),
room_version: Some("10".to_string()),
is_direct: Some(false),
invite: None,
initial_state: None,
};
let _room_summary = EnhancedRoomSummary {
room_id: "!room123:example.com".to_string(),
name: Some("General Discussion".to_string()),
topic: Some("A place for general chat".to_string()),
avatar_url: Some("mxc://example.com/room_avatar".to_string()),
member_count: 42,
is_public: true,
last_activity: 1640995200,
unread_count: 5,
highlight_count: 2,
notification_count: 7,
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_enhanced_error_guide() {
enhanced_error_guide();
}
#[test]
fn test_enhanced_room_guide() {
enhanced_room_guide();
}
#[test]
fn test_enhanced_user_guide() {
enhanced_user_guide();
}
#[test]
fn test_enhanced_message_guide() {
enhanced_message_guide();
}
#[test]
fn test_room_management_guide() {
room_management_guide();
}
}

View file

@ -0,0 +1,379 @@
//! Best Practices for Continuwuity Development
//!
//! This module provides best practices and guidelines for developing
//! with Continuwuity and our enhanced types.
use crate::types::*;
use crate::error::*;
/// Best Practice: Error Handling
///
/// Always use our enhanced error types for better user experience.
///
/// # Best Practices
///
/// 1. **Use Enhanced Errors**: Always use `EnhancedError` for user-facing errors
/// 2. **Provide Context**: Include relevant context in error messages
/// 3. **Sanitize Logs**: Use `sanitized_message()` for logging to avoid sensitive data
/// 4. **Return Proper Codes**: Ensure Matrix error codes are correct
///
/// # Example
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// fn validate_room_id(room_id: &str) -> Result<(), EnhancedError> {
/// if room_id.is_empty() {
/// return Err(EnhancedError::validation_error("room_id", "Room ID cannot be empty"));
/// }
///
/// if !room_id.starts_with('!') {
/// return Err(EnhancedError::validation_error("room_id", "Room ID must start with '!'"));
/// }
///
/// Ok(())
/// }
/// ```
pub fn error_handling_best_practices() {
// This function demonstrates error handling best practices
let _example_error = EnhancedError::validation_error("room_id", "Room ID cannot be empty");
}
/// Best Practice: Room Management
///
/// Use enhanced types for room operations to ensure consistency.
///
/// # Best Practices
///
/// 1. **Use Enhanced Types**: Always use `EnhancedRoomInfo` for room data
/// 2. **Validate Permissions**: Check power levels before operations
/// 3. **Handle State Changes**: Properly manage room state transitions
/// 4. **Log Important Events**: Log room creation, member changes, etc.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// fn can_user_send_message(room: &EnhancedRoomInfo, user_id: &str) -> bool {
/// room.can_send_message(user_id)
/// }
///
/// fn is_user_admin(room: &EnhancedRoomInfo, user_id: &str) -> bool {
/// room.is_admin(user_id)
/// }
/// ```
pub fn room_management_best_practices() {
// This function demonstrates room management best practices
let room = EnhancedRoomInfo::new("!example:example.com".to_string());
let _can_send = room.can_send_message("@user:example.com");
let _is_admin = room.is_admin("@admin:example.com");
}
/// Best Practice: Message Handling
///
/// Use enhanced message types for consistent message processing.
///
/// # Best Practices
///
/// 1. **Use Enhanced Types**: Always use `EnhancedMessageContent` for messages
/// 2. **Handle Replies**: Properly process reply relationships
/// 3. **Support Threads**: Handle thread messages correctly
/// 4. **Validate Content**: Check message content before processing
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// fn process_message(message: &EnhancedMessageContent) -> Result<(), EnhancedError> {
/// if message.body.is_empty() {
/// return Err(EnhancedError::validation_error("body", "Message body cannot be empty"));
/// }
///
/// if message.is_reply() {
/// // Handle reply logic
/// }
///
/// if message.is_thread() {
/// // Handle thread logic
/// }
///
/// Ok(())
/// }
/// ```
pub fn message_handling_best_practices() {
// This function demonstrates message handling best practices
let message = EnhancedMessageContent::new_text("Hello, world!".to_string());
let _is_reply = message.is_reply();
let _is_thread = message.is_thread();
}
/// Best Practice: User Management
///
/// Use enhanced user types for consistent user operations.
///
/// # Best Practices
///
/// 1. **Use Enhanced Types**: Always use `EnhancedUserInfo` for user data
/// 2. **Check Membership**: Verify user membership before operations
/// 3. **Handle Permissions**: Check user permissions appropriately
/// 4. **Update Presence**: Keep user presence information current
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// fn can_user_access_room(user: &EnhancedUserInfo, room: &EnhancedRoomInfo) -> bool {
/// user.is_member() && room.can_send_message(&user.user_id)
/// }
///
/// fn is_user_moderator(user: &EnhancedUserInfo) -> bool {
/// user.is_moderator()
/// }
/// ```
pub fn user_management_best_practices() {
// This function demonstrates user management best practices
let user = EnhancedUserInfo::new("@user:example.com".to_string());
let _is_member = user.is_member();
let _is_moderator = user.is_moderator();
}
/// Best Practice: Power Level Management
///
/// Properly manage power levels for room permissions.
///
/// # Best Practices
///
/// 1. **Use Default Values**: Start with sensible defaults
/// 2. **Document Changes**: Log power level changes
/// 3. **Validate Levels**: Ensure power levels are within valid ranges
/// 4. **Handle Inheritance**: Properly handle power level inheritance
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
/// use std::collections::HashMap;
///
/// fn set_user_power_level(power_levels: &mut PowerLevels, user_id: &str, level: i32) -> Result<(), EnhancedError> {
/// if level < -1 || level > 100 {
/// return Err(EnhancedError::validation_error("power_level", "Power level must be between -1 and 100"));
/// }
///
/// power_levels.users.insert(user_id.to_string(), level);
/// Ok(())
/// }
/// ```
pub fn power_level_management_best_practices() {
// This function demonstrates power level management best practices
let mut power_levels = PowerLevels::default();
power_levels.users.insert("@user:example.com".to_string(), 0);
}
/// Best Practice: Federation Handling
///
/// Properly handle federation operations with enhanced error types.
///
/// # Best Practices
///
/// 1. **Use Enhanced Errors**: Use `EnhancedError::federation_error` for federation issues
/// 2. **Handle Timeouts**: Implement proper timeout handling
/// 3. **Log Federation Events**: Log important federation operations
/// 4. **Validate Responses**: Validate federation responses before processing
///
/// # Example
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// async fn send_federation_request(server: &str, data: &[u8]) -> Result<(), EnhancedError> {
/// // Simulate federation request
/// if server.is_empty() {
/// return Err(EnhancedError::federation_error("unknown", "Server name cannot be empty"));
/// }
///
/// // Handle federation logic here
/// Ok(())
/// }
/// ```
pub fn federation_handling_best_practices() {
// This function demonstrates federation handling best practices
let _example_error = EnhancedError::federation_error("matrix.org", "Connection timeout");
}
/// Best Practice: Configuration Management
///
/// Use enhanced error types for configuration validation.
///
/// # Best Practices
///
/// 1. **Validate Early**: Validate configuration at startup
/// 2. **Use Enhanced Errors**: Use `EnhancedError::config_error` for config issues
/// 3. **Provide Context**: Include field names in error messages
/// 4. **Handle Defaults**: Provide sensible defaults where possible
///
/// # Example
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// fn validate_config_field(field_name: &str, value: &str) -> Result<(), EnhancedError> {
/// if value.is_empty() {
/// return Err(EnhancedError::config_error(field_name, "Value cannot be empty"));
/// }
///
/// Ok(())
/// }
/// ```
pub fn configuration_management_best_practices() {
// This function demonstrates configuration management best practices
let _example_error = EnhancedError::config_error("database_url", "Invalid format");
}
/// Best Practice: Database Operations
///
/// Use enhanced error types for database operations.
///
/// # Best Practices
///
/// 1. **Use Enhanced Errors**: Use `EnhancedError::database_error` for DB issues
/// 2. **Include Operation Context**: Specify the operation that failed
/// 3. **Handle Connections**: Properly handle database connection issues
/// 4. **Log Operations**: Log important database operations
///
/// # Example
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// async fn save_user_data(user_id: &str, data: &[u8]) -> Result<(), EnhancedError> {
/// // Simulate database operation
/// if user_id.is_empty() {
/// return Err(EnhancedError::database_error("save_user_data", "User ID cannot be empty"));
/// }
///
/// // Handle database logic here
/// Ok(())
/// }
/// ```
pub fn database_operations_best_practices() {
// This function demonstrates database operations best practices
let _example_error = EnhancedError::database_error("save_user_data", "Connection lost");
}
/// Best Practice: Network Operations
///
/// Use enhanced error types for network operations.
///
/// # Best Practices
///
/// 1. **Use Enhanced Errors**: Use `EnhancedError::network_error` for network issues
/// 2. **Specify Service**: Include the service that failed
/// 3. **Handle Timeouts**: Implement proper timeout handling
/// 4. **Retry Logic**: Implement appropriate retry logic
///
/// # Example
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// async fn make_http_request(url: &str) -> Result<(), EnhancedError> {
/// if url.is_empty() {
/// return Err(EnhancedError::network_error("http_client", "URL cannot be empty"));
/// }
///
/// // Handle HTTP request logic here
/// Ok(())
/// }
/// ```
pub fn network_operations_best_practices() {
// This function demonstrates network operations best practices
let _example_error = EnhancedError::network_error("http_client", "Connection timeout");
}
/// Best Practice: Rate Limiting
///
/// Use enhanced error types for rate limiting.
///
/// # Best Practices
///
/// 1. **Use Enhanced Errors**: Use `EnhancedError::rate_limit_exceeded` for rate limits
/// 2. **Include Resource**: Specify which resource was rate limited
/// 3. **Provide Retry Time**: Include when the user can retry
/// 4. **Log Rate Limits**: Log rate limit violations for monitoring
///
/// # Example
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// fn check_rate_limit(resource: &str, user_id: &str) -> Result<(), EnhancedError> {
/// // Simulate rate limit check
/// if resource == "room_creation" {
/// return Err(EnhancedError::rate_limit_exceeded(resource, 60));
/// }
///
/// Ok(())
/// }
/// ```
pub fn rate_limiting_best_practices() {
// This function demonstrates rate limiting best practices
let _example_error = EnhancedError::rate_limit_exceeded("room_creation", 60);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_handling_best_practices() {
error_handling_best_practices();
}
#[test]
fn test_room_management_best_practices() {
room_management_best_practices();
}
#[test]
fn test_message_handling_best_practices() {
message_handling_best_practices();
}
#[test]
fn test_user_management_best_practices() {
user_management_best_practices();
}
#[test]
fn test_power_level_management_best_practices() {
power_level_management_best_practices();
}
#[test]
fn test_federation_handling_best_practices() {
federation_handling_best_practices();
}
#[test]
fn test_configuration_management_best_practices() {
configuration_management_best_practices();
}
#[test]
fn test_database_operations_best_practices() {
database_operations_best_practices();
}
#[test]
fn test_network_operations_best_practices() {
network_operations_best_practices();
}
#[test]
fn test_rate_limiting_best_practices() {
rate_limiting_best_practices();
}
}

363
src/core/docs_examples.rs Normal file
View file

@ -0,0 +1,363 @@
//! Comprehensive Examples for Continuwuity
//!
//! This module provides practical examples for common Matrix operations
//! using our enhanced types and error handling.
use crate::types::*;
use crate::error::*;
/// Example: Creating a new room with enhanced types
///
/// This example shows how to create a new Matrix room using our enhanced
/// room creation request structure.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let room_request = EnhancedRoomCreateRequest {
/// name: Some("My Awesome Room".to_string()),
/// topic: Some("A room for awesome discussions".to_string()),
/// preset: Some(RoomPreset::PublicChat),
/// room_version: Some("10".to_string()),
/// is_direct: Some(false),
/// invite: Some(vec!["@alice:example.com".to_string()]),
/// initial_state: None,
/// };
///
/// // The room request is now ready to be sent to the Matrix server
/// ```
pub fn create_room_example() -> EnhancedRoomCreateRequest {
EnhancedRoomCreateRequest {
name: Some("Example Room".to_string()),
topic: Some("This is an example room created with enhanced types".to_string()),
preset: Some(RoomPreset::PublicChat),
room_version: Some("10".to_string()),
is_direct: Some(false),
invite: Some(vec!["@alice:example.com".to_string(), "@bob:example.com".to_string()]),
initial_state: None,
}
}
/// Example: Creating a text message with enhanced content
///
/// This example shows how to create a Matrix message using our enhanced
/// message content structure.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let message = EnhancedMessageContent::new_text("Hello, Matrix!".to_string());
///
/// // The message is ready to be sent to a room
/// ```
pub fn create_message_example() -> EnhancedMessageContent {
EnhancedMessageContent::new_text("Hello from Continuwuity!".to_string())
}
/// Example: Creating a reply message
///
/// This example shows how to create a reply to another message.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let mut reply = EnhancedMessageContent::new_text("This is a reply".to_string());
/// reply.relates_to = Some(RelatesTo {
/// in_reply_to: Some(InReplyTo {
/// event_id: "$original_event_id".to_string(),
/// }),
/// rel_type: None,
/// event_id: None,
/// });
///
/// // The reply is now properly linked to the original message
/// ```
pub fn create_reply_example() -> EnhancedMessageContent {
let mut reply = EnhancedMessageContent::new_text("This is a reply to your message".to_string());
reply.relates_to = Some(RelatesTo {
in_reply_to: Some(InReplyTo {
event_id: "$example_event_id".to_string(),
}),
rel_type: None,
event_id: None,
});
reply
}
/// Example: Creating a thread message
///
/// This example shows how to create a message in a thread.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let mut thread_message = EnhancedMessageContent::new_text("Thread message".to_string());
/// thread_message.thread = Some(ThreadInfo {
/// event_id: "$thread_root_event_id".to_string(),
/// is_falling_back: None,
/// is_editing: None,
/// });
///
/// // The message is now part of a thread
/// ```
pub fn create_thread_message_example() -> EnhancedMessageContent {
let mut thread_message = EnhancedMessageContent::new_text("This is a thread message".to_string());
thread_message.thread = Some(ThreadInfo {
event_id: "$thread_root_event_id".to_string(),
is_falling_back: None,
is_editing: None,
});
thread_message
}
/// Example: Setting up room power levels
///
/// This example shows how to configure power levels for a room.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
/// use std::collections::HashMap;
///
/// let mut power_levels = PowerLevels::default();
/// power_levels.users.insert("@admin:example.com".to_string(), 100);
/// power_levels.users.insert("@moderator:example.com".to_string(), 50);
/// power_levels.events_default = 0; // Anyone can send messages
/// power_levels.state_default = 50; // Only moderators can change state
///
/// // Power levels are now configured
/// ```
pub fn setup_power_levels_example() -> PowerLevels {
let mut power_levels = PowerLevels::default();
power_levels.users.insert("@admin:example.com".to_string(), 100);
power_levels.users.insert("@moderator:example.com".to_string(), 50);
power_levels.users.insert("@user:example.com".to_string(), 0);
power_levels.events_default = 0; // Anyone can send messages
power_levels.state_default = 50; // Only moderators can change state
power_levels.ban = 50; // Moderators can ban users
power_levels.kick = 50; // Moderators can kick users
power_levels
}
/// Example: Creating a user profile
///
/// This example shows how to create a user profile with enhanced information.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let user_profile = EnhancedUserProfile {
/// user_id: "@alice:example.com".to_string(),
/// display_name: Some("Alice".to_string()),
/// avatar_url: Some("mxc://example.com/avatar123".to_string()),
/// is_online: true,
/// last_seen: Some(1640995200), // Unix timestamp
/// presence: PresenceState::Online,
/// status_msg: Some("Working on Matrix stuff".to_string()),
/// };
///
/// // User profile is now complete
/// ```
pub fn create_user_profile_example() -> EnhancedUserProfile {
EnhancedUserProfile {
user_id: "@alice:example.com".to_string(),
display_name: Some("Alice".to_string()),
avatar_url: Some("mxc://example.com/avatar123".to_string()),
is_online: true,
last_seen: Some(1640995200), // Unix timestamp
presence: PresenceState::Online,
status_msg: Some("Working on Matrix stuff".to_string()),
}
}
/// Example: Error handling with enhanced errors
///
/// This example shows how to use our enhanced error handling for better
/// user experience and debugging.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::error::*;
///
/// // Create a user-friendly error
/// let error = EnhancedError::room_not_found("!nonexistent:example.com");
///
/// // Get user-friendly message
/// let user_message = error.user_message();
/// println!("User sees: {}", user_message);
///
/// // Get sanitized message for logging
/// let log_message = error.sanitized_message();
/// println!("Log shows: {}", log_message);
///
/// // Get Matrix error code
/// let matrix_code = error.matrix_error_code();
/// println!("Matrix error code: {}", matrix_code);
/// ```
pub fn error_handling_example() -> EnhancedError {
let error = EnhancedError::room_not_found("!example:example.com");
// Demonstrate different error message types
let _user_message = error.user_message();
let _log_message = error.sanitized_message();
let _matrix_code = error.matrix_error_code();
error
}
/// Example: Room member management
///
/// This example shows how to manage room members using enhanced types.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let member = EnhancedRoomMember {
/// user_id: "@alice:example.com".to_string(),
/// display_name: Some("Alice".to_string()),
/// avatar_url: Some("mxc://example.com/avatar123".to_string()),
/// membership: MembershipState::Join,
/// power_level: 50,
/// is_direct: false,
/// third_party_invite: None,
/// };
///
/// // Member information is now available
/// ```
pub fn room_member_example() -> EnhancedRoomMember {
EnhancedRoomMember {
user_id: "@alice:example.com".to_string(),
display_name: Some("Alice".to_string()),
avatar_url: Some("mxc://example.com/avatar123".to_string()),
membership: MembershipState::Join,
power_level: 50,
is_direct: false,
third_party_invite: None,
}
}
/// Example: Room summary for listings
///
/// This example shows how to create a room summary for display in room lists.
///
/// # Example
///
/// ```rust
/// use conduwuit_core::types::*;
///
/// let room_summary = EnhancedRoomSummary {
/// room_id: "!room123:example.com".to_string(),
/// name: Some("General Discussion".to_string()),
/// topic: Some("A place for general chat".to_string()),
/// avatar_url: Some("mxc://example.com/room_avatar".to_string()),
/// member_count: 42,
/// is_public: true,
/// last_activity: 1640995200,
/// unread_count: 5,
/// highlight_count: 2,
/// notification_count: 7,
/// };
///
/// // Room summary is ready for display
/// ```
pub fn room_summary_example() -> EnhancedRoomSummary {
EnhancedRoomSummary {
room_id: "!room123:example.com".to_string(),
name: Some("General Discussion".to_string()),
topic: Some("A place for general chat".to_string()),
avatar_url: Some("mxc://example.com/room_avatar".to_string()),
member_count: 42,
is_public: true,
last_activity: 1640995200,
unread_count: 5,
highlight_count: 2,
notification_count: 7,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_room_example() {
let room_request = create_room_example();
assert_eq!(room_request.name, Some("Example Room".to_string()));
assert_eq!(room_request.preset, Some(RoomPreset::PublicChat));
assert!(room_request.invite.is_some());
}
#[test]
fn test_create_message_example() {
let message = create_message_example();
assert_eq!(message.msgtype, MessageType::Text);
assert_eq!(message.body, "Hello from Continuwuity!");
}
#[test]
fn test_create_reply_example() {
let reply = create_reply_example();
assert!(reply.is_reply());
assert!(reply.relates_to.is_some());
}
#[test]
fn test_create_thread_message_example() {
let thread_message = create_thread_message_example();
assert!(thread_message.is_thread());
assert!(thread_message.thread.is_some());
}
#[test]
fn test_setup_power_levels_example() {
let power_levels = setup_power_levels_example();
assert_eq!(power_levels.users.len(), 3);
assert_eq!(power_levels.events_default, 0);
assert_eq!(power_levels.state_default, 50);
}
#[test]
fn test_create_user_profile_example() {
let profile = create_user_profile_example();
assert_eq!(profile.user_id, "@alice:example.com");
assert_eq!(profile.presence, PresenceState::Online);
assert!(profile.is_online);
}
#[test]
fn test_error_handling_example() {
let error = error_handling_example();
assert_eq!(error.matrix_error_code(), "M_NOT_FOUND");
assert_eq!(error.http_status_code(), 404);
}
#[test]
fn test_room_member_example() {
let member = room_member_example();
assert_eq!(member.user_id, "@alice:example.com");
assert_eq!(member.membership, MembershipState::Join);
assert_eq!(member.power_level, 50);
}
#[test]
fn test_room_summary_example() {
let summary = room_summary_example();
assert_eq!(summary.room_id, "!room123:example.com");
assert_eq!(summary.member_count, 42);
assert!(summary.is_public);
}
}

449
src/core/types_enhanced.rs Normal file
View file

@ -0,0 +1,449 @@
// Enhanced Type Definitions for Continuwuity
// Contributed from our chat-system improvements
// Provides cleaner, more focused type definitions for Matrix operations
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Enhanced room information with better organization
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedRoomInfo {
pub room_id: String,
pub name: Option<String>,
pub topic: Option<String>,
pub avatar_url: Option<String>,
pub member_count: u32,
pub is_public: bool,
pub join_rule: JoinRule,
pub power_levels: PowerLevels,
pub creation_time: u64,
pub last_activity: u64,
}
/// Enhanced user information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedUserInfo {
pub user_id: String,
pub display_name: Option<String>,
pub avatar_url: Option<String>,
pub is_online: bool,
pub last_seen: Option<u64>,
pub power_level: i32,
pub membership_state: MembershipState,
}
/// Join rules for rooms
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum JoinRule {
#[serde(rename = "public")]
Public,
#[serde(rename = "invite")]
Invite,
#[serde(rename = "private")]
Private,
#[serde(rename = "knock")]
Knock,
#[serde(rename = "knock_restricted")]
KnockRestricted,
}
/// Membership states
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum MembershipState {
#[serde(rename = "invite")]
Invite,
#[serde(rename = "join")]
Join,
#[serde(rename = "knock")]
Knock,
#[serde(rename = "leave")]
Leave,
#[serde(rename = "ban")]
Ban,
}
/// Power levels for room permissions
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PowerLevels {
pub users: HashMap<String, i32>,
pub events: HashMap<String, i32>,
pub events_default: i32,
pub state_default: i32,
pub ban: i32,
pub kick: i32,
pub redact: i32,
pub invite: i32,
}
impl Default for PowerLevels {
fn default() -> Self {
Self {
users: HashMap::new(),
events: HashMap::new(),
events_default: 0,
state_default: 50,
ban: 50,
kick: 50,
redact: 50,
invite: 0,
}
}
}
/// Enhanced message content with better structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedMessageContent {
pub msgtype: MessageType,
pub body: String,
pub formatted_body: Option<String>,
pub format: Option<String>,
pub relates_to: Option<RelatesTo>,
pub mentions: Option<Mentions>,
pub thread: Option<ThreadInfo>,
}
/// Message types
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum MessageType {
#[serde(rename = "m.text")]
Text,
#[serde(rename = "m.notice")]
Notice,
#[serde(rename = "m.emote")]
Emote,
#[serde(rename = "m.image")]
Image,
#[serde(rename = "m.file")]
File,
#[serde(rename = "m.video")]
Video,
#[serde(rename = "m.audio")]
Audio,
#[serde(rename = "m.location")]
Location,
}
/// Relates to information for replies/threads
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelatesTo {
#[serde(rename = "m.in_reply_to")]
pub in_reply_to: Option<InReplyTo>,
#[serde(rename = "rel_type")]
pub rel_type: Option<String>,
#[serde(rename = "event_id")]
pub event_id: Option<String>,
}
/// In-reply-to information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InReplyTo {
pub event_id: String,
}
/// Mentions in messages
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Mentions {
pub user_ids: Vec<String>,
pub room: bool,
}
/// Thread information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadInfo {
pub event_id: String,
pub is_falling_back: Option<bool>,
pub is_editing: Option<bool>,
}
/// Enhanced room creation request
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedRoomCreateRequest {
pub name: Option<String>,
pub topic: Option<String>,
pub preset: Option<RoomPreset>,
pub room_version: Option<String>,
pub is_direct: Option<bool>,
pub invite: Option<Vec<String>>,
pub initial_state: Option<Vec<InitialStateEvent>>,
}
/// Room presets
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum RoomPreset {
#[serde(rename = "private_chat")]
PrivateChat,
#[serde(rename = "trusted_private_chat")]
TrustedPrivateChat,
#[serde(rename = "public_chat")]
PublicChat,
}
/// Initial state events for room creation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InitialStateEvent {
#[serde(rename = "type")]
pub event_type: String,
pub state_key: String,
pub content: serde_json::Value,
}
/// Enhanced room member information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedRoomMember {
pub user_id: String,
pub display_name: Option<String>,
pub avatar_url: Option<String>,
pub membership: MembershipState,
pub power_level: i32,
pub is_direct: bool,
pub third_party_invite: Option<ThirdPartyInvite>,
}
/// Third party invite information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThirdPartyInvite {
pub display_name: String,
pub signed: SignedInvite,
}
/// Signed invite information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignedInvite {
pub mxid: String,
pub token: String,
pub signatures: HashMap<String, HashMap<String, String>>,
}
/// Enhanced room summary for listings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedRoomSummary {
pub room_id: String,
pub name: Option<String>,
pub topic: Option<String>,
pub avatar_url: Option<String>,
pub member_count: u32,
pub is_public: bool,
pub last_activity: u64,
pub unread_count: u32,
pub highlight_count: u32,
pub notification_count: u32,
}
/// Enhanced user profile
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedUserProfile {
pub user_id: String,
pub display_name: Option<String>,
pub avatar_url: Option<String>,
pub is_online: bool,
pub last_seen: Option<u64>,
pub presence: PresenceState,
pub status_msg: Option<String>,
}
/// Presence states
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum PresenceState {
#[serde(rename = "online")]
Online,
#[serde(rename = "offline")]
Offline,
#[serde(rename = "unavailable")]
Unavailable,
}
/// Helper functions for enhanced types
impl EnhancedRoomInfo {
pub fn new(room_id: String) -> Self {
Self {
room_id,
name: None,
topic: None,
avatar_url: None,
member_count: 0,
is_public: false,
join_rule: JoinRule::Invite,
power_levels: PowerLevels::default(),
creation_time: 0,
last_activity: 0,
}
}
pub fn is_admin(&self, user_id: &str) -> bool {
self.power_levels.users.get(user_id)
.map(|level| *level >= 100)
.unwrap_or(false)
}
pub fn can_send_message(&self, user_id: &str) -> bool {
let user_level = self.power_levels.users.get(user_id).unwrap_or(&0);
*user_level >= self.power_levels.events_default
}
}
impl EnhancedUserInfo {
pub fn new(user_id: String) -> Self {
Self {
user_id,
display_name: None,
avatar_url: None,
is_online: false,
last_seen: None,
power_level: 0,
membership_state: MembershipState::Leave,
}
}
pub fn is_member(&self) -> bool {
self.membership_state == MembershipState::Join
}
pub fn is_moderator(&self) -> bool {
self.power_level >= 50
}
}
impl EnhancedMessageContent {
pub fn new_text(body: String) -> Self {
Self {
msgtype: MessageType::Text,
body,
formatted_body: None,
format: None,
relates_to: None,
mentions: None,
thread: None,
}
}
pub fn new_notice(body: String) -> Self {
Self {
msgtype: MessageType::Notice,
body,
formatted_body: None,
format: None,
relates_to: None,
mentions: None,
thread: None,
}
}
pub fn is_reply(&self) -> bool {
self.relates_to.as_ref()
.and_then(|r| r.in_reply_to.as_ref())
.is_some()
}
pub fn is_thread(&self) -> bool {
self.thread.is_some()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_enhanced_room_info_creation() {
let room = EnhancedRoomInfo::new("!test:example.com".to_string());
assert_eq!(room.room_id, "!test:example.com");
assert_eq!(room.member_count, 0);
assert_eq!(room.join_rule, JoinRule::Invite);
}
#[test]
fn test_enhanced_user_info_creation() {
let user = EnhancedUserInfo::new("@user:example.com".to_string());
assert_eq!(user.user_id, "@user:example.com");
assert!(!user.is_online);
assert_eq!(user.membership_state, MembershipState::Leave);
}
#[test]
fn test_enhanced_message_content_creation() {
let message = EnhancedMessageContent::new_text("Hello world".to_string());
assert_eq!(message.msgtype, MessageType::Text);
assert_eq!(message.body, "Hello world");
assert!(!message.is_reply());
assert!(!message.is_thread());
}
#[test]
fn test_room_admin_check() {
let mut room = EnhancedRoomInfo::new("!test:example.com".to_string());
room.power_levels.users.insert("@admin:example.com".to_string(), 100);
room.power_levels.users.insert("@user:example.com".to_string(), 0);
assert!(room.is_admin("@admin:example.com"));
assert!(!room.is_admin("@user:example.com"));
assert!(!room.is_admin("@nonexistent:example.com"));
}
#[test]
fn test_room_message_permission() {
let mut room = EnhancedRoomInfo::new("!test:example.com".to_string());
room.power_levels.events_default = 0;
room.power_levels.users.insert("@user:example.com".to_string(), 0);
room.power_levels.users.insert("@muted:example.com".to_string(), -1);
assert!(room.can_send_message("@user:example.com"));
assert!(!room.can_send_message("@muted:example.com"));
}
#[test]
fn test_user_membership_check() {
let mut user = EnhancedUserInfo::new("@user:example.com".to_string());
user.membership_state = MembershipState::Join;
assert!(user.is_member());
user.membership_state = MembershipState::Leave;
assert!(!user.is_member());
}
#[test]
fn test_user_moderator_check() {
let mut user = EnhancedUserInfo::new("@user:example.com".to_string());
user.power_level = 50;
assert!(user.is_moderator());
user.power_level = 49;
assert!(!user.is_moderator());
}
#[test]
fn test_message_reply_check() {
let mut message = EnhancedMessageContent::new_text("Reply".to_string());
message.relates_to = Some(RelatesTo {
in_reply_to: Some(InReplyTo {
event_id: "$event123".to_string(),
}),
rel_type: None,
event_id: None,
});
assert!(message.is_reply());
}
#[test]
fn test_message_thread_check() {
let mut message = EnhancedMessageContent::new_text("Thread message".to_string());
message.thread = Some(ThreadInfo {
event_id: "$thread123".to_string(),
is_falling_back: None,
is_editing: None,
});
assert!(message.is_thread());
}
#[test]
fn test_power_levels_default() {
let power_levels = PowerLevels::default();
assert_eq!(power_levels.events_default, 0);
assert_eq!(power_levels.state_default, 50);
assert_eq!(power_levels.ban, 50);
assert_eq!(power_levels.kick, 50);
assert_eq!(power_levels.redact, 50);
assert_eq!(power_levels.invite, 0);
}
}