
Complete church management system with bulletin management, media processing, live streaming integration, and web interface. Includes authentication, email notifications, database migrations, and comprehensive test suite.
196 lines
6 KiB
Bash
Executable file
196 lines
6 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
echo "🚀 SETTING UP WEBP CONVERSION"
|
|
echo "============================="
|
|
|
|
# Step 1: Add dependencies
|
|
echo "📦 Adding WebP dependencies to Cargo.toml..."
|
|
if grep -q 'image = ' Cargo.toml; then
|
|
echo "✅ image dependency already exists"
|
|
else
|
|
echo 'image = "0.24"' >> Cargo.toml
|
|
echo "✅ Added image dependency"
|
|
fi
|
|
|
|
if grep -q 'webp = ' Cargo.toml; then
|
|
echo "✅ webp dependency already exists"
|
|
else
|
|
echo 'webp = "0.2"' >> Cargo.toml
|
|
echo "✅ Added webp dependency"
|
|
fi
|
|
|
|
# Step 2: Create utils directory if it doesn't exist
|
|
echo "📁 Creating utils directory..."
|
|
mkdir -p src/utils
|
|
|
|
# Step 3: Create the WebP conversion module
|
|
echo "🔧 Creating WebP conversion module..."
|
|
cat > src/utils/images.rs << 'EOF'
|
|
use image::ImageFormat;
|
|
use std::io::Cursor;
|
|
|
|
pub async fn convert_to_webp(image_bytes: &[u8]) -> Result<Vec<u8>, String> {
|
|
let bytes = image_bytes.to_vec();
|
|
|
|
tokio::task::spawn_blocking(move || {
|
|
let img = image::load_from_memory(&bytes)
|
|
.map_err(|e| format!("Failed to load image: {}", e))?;
|
|
|
|
// Resize if too large (optional optimization)
|
|
let img = if img.width() > 1920 || img.height() > 1920 {
|
|
img.resize(1920, 1920, image::imageops::FilterType::Lanczos3)
|
|
} else {
|
|
img
|
|
};
|
|
|
|
let rgb_img = img.to_rgb8();
|
|
let encoder = webp::Encoder::from_rgb(&rgb_img, img.width(), img.height());
|
|
let webp = encoder.encode(85.0); // 85% quality
|
|
|
|
Ok(webp.to_vec())
|
|
})
|
|
.await
|
|
.map_err(|e| format!("Task failed: {}", e))?
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[tokio::test]
|
|
async fn test_webp_conversion() {
|
|
// Create a simple 100x100 red image
|
|
let img = image::RgbImage::from_fn(100, 100, |_, _| image::Rgb([255, 0, 0]));
|
|
let mut buffer = Vec::new();
|
|
|
|
// Encode as PNG first
|
|
{
|
|
let mut cursor = Cursor::new(&mut buffer);
|
|
image::DynamicImage::ImageRgb8(img)
|
|
.write_to(&mut cursor, ImageFormat::Png)
|
|
.expect("Failed to write PNG");
|
|
}
|
|
|
|
// Convert to WebP
|
|
let webp_data = convert_to_webp(&buffer).await.expect("WebP conversion failed");
|
|
|
|
// Verify it's actually WebP data
|
|
assert!(webp_data.len() > 0);
|
|
assert!(webp_data.starts_with(b"RIFF")); // WebP signature
|
|
|
|
println!("✅ WebP conversion test passed!");
|
|
println!(" Original PNG: {} bytes", buffer.len());
|
|
println!(" WebP result: {} bytes", webp_data.len());
|
|
println!(" Compression: {:.1}%", (1.0 - webp_data.len() as f64 / buffer.len() as f64) * 100.0);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_invalid_image() {
|
|
let fake_data = b"not an image";
|
|
let result = convert_to_webp(fake_data).await;
|
|
assert!(result.is_err());
|
|
println!("✅ Invalid image test passed!");
|
|
}
|
|
}
|
|
EOF
|
|
|
|
echo "✅ Created src/utils/images.rs"
|
|
|
|
# Step 4: Update or create utils mod.rs
|
|
if [ -f src/utils/mod.rs ]; then
|
|
echo "📝 Updating src/utils/mod.rs..."
|
|
if ! grep -q "pub mod images;" src/utils/mod.rs; then
|
|
echo "pub mod images;" >> src/utils/mod.rs
|
|
fi
|
|
else
|
|
echo "📝 Creating src/utils/mod.rs..."
|
|
echo "pub mod images;" > src/utils/mod.rs
|
|
fi
|
|
|
|
echo "✅ Updated utils module"
|
|
|
|
# Step 5: Update main.rs or lib.rs to include utils
|
|
echo "📝 Checking for utils module inclusion..."
|
|
main_file=""
|
|
if [ -f src/main.rs ]; then
|
|
main_file="src/main.rs"
|
|
elif [ -f src/lib.rs ]; then
|
|
main_file="src/lib.rs"
|
|
fi
|
|
|
|
if [ -n "$main_file" ]; then
|
|
if ! grep -q "mod utils;" "$main_file"; then
|
|
echo "mod utils;" >> "$main_file"
|
|
echo "✅ Added utils module to $main_file"
|
|
else
|
|
echo "✅ Utils module already included in $main_file"
|
|
fi
|
|
else
|
|
echo "⚠️ Couldn't find main.rs or lib.rs - you'll need to add 'mod utils;' manually"
|
|
fi
|
|
|
|
# Step 6: Build to check for errors
|
|
echo "🔨 Building project to verify setup..."
|
|
if cargo build; then
|
|
echo "✅ Build successful!"
|
|
else
|
|
echo "❌ Build failed - check the errors above"
|
|
exit 1
|
|
fi
|
|
|
|
# Step 7: Run tests
|
|
echo "🧪 Running WebP conversion tests..."
|
|
if cargo test images::tests -- --nocapture; then
|
|
echo "✅ All tests passed!"
|
|
else
|
|
echo "❌ Tests failed"
|
|
exit 1
|
|
fi
|
|
|
|
# Step 8: Create example usage
|
|
echo "📄 Creating example usage file..."
|
|
cat > webp_example.rs << 'EOF'
|
|
// Example usage in your upload handler:
|
|
|
|
use crate::utils::images::convert_to_webp;
|
|
|
|
pub async fn handle_image_upload(image_data: Vec<u8>) -> Result<String, String> {
|
|
// Save original
|
|
let original_path = format!("uploads/original_{}.jpg", uuid::Uuid::new_v4());
|
|
tokio::fs::write(&original_path, &image_data).await
|
|
.map_err(|e| format!("Failed to save original: {}", e))?;
|
|
|
|
// Convert to WebP
|
|
let webp_data = convert_to_webp(&image_data).await?;
|
|
let webp_path = format!("uploads/webp_{}.webp", uuid::Uuid::new_v4());
|
|
tokio::fs::write(&webp_data, webp_data).await
|
|
.map_err(|e| format!("Failed to save WebP: {}", e))?;
|
|
|
|
Ok(webp_path)
|
|
}
|
|
|
|
// Or for immediate conversion (slower but simpler):
|
|
pub async fn convert_and_save_webp(image_data: Vec<u8>, filename: &str) -> Result<String, String> {
|
|
let webp_data = convert_to_webp(&image_data).await?;
|
|
let webp_path = format!("uploads/{}.webp", filename);
|
|
tokio::fs::write(&webp_path, webp_data).await
|
|
.map_err(|e| format!("Failed to save: {}", e))?;
|
|
Ok(webp_path)
|
|
}
|
|
EOF
|
|
|
|
echo "✅ Created webp_example.rs"
|
|
|
|
echo ""
|
|
echo "🎉 WEBP CONVERSION SETUP COMPLETE!"
|
|
echo "=================================="
|
|
echo "✅ Dependencies added to Cargo.toml"
|
|
echo "✅ WebP conversion module created"
|
|
echo "✅ Tests written and passing"
|
|
echo "✅ Example usage provided"
|
|
echo ""
|
|
echo "🔧 Next steps:"
|
|
echo "1. Import in your upload handler: use crate::utils::images::convert_to_webp;"
|
|
echo "2. Call convert_to_webp(&image_bytes).await in your code"
|
|
echo "3. Save the returned Vec<u8> as a .webp file"
|