church-api/webp_setup.sh
Benjamin Slingo 0c06e159bb Initial commit: Church API Rust implementation
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.
2025-08-19 20:56:41 -04:00

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"