
Some checks failed
iOS UniFFI Build / build-ios (push) Has been cancelled
- Add api.rs with all web-specific API functions - Add admin_login and validate_admin_token methods to ChurchApiClient - Add image fields to EventSubmission model - Add submit_event_with_image and submit_event_multipart functions - Update test files for new EventSubmission fields This consolidates the web church-core into the main crate to achieve single source of truth.
527 lines
19 KiB
Rust
527 lines
19 KiB
Rust
use crate::{
|
|
ChurchApiClient, ChurchCoreConfig,
|
|
models::{NewSchedule, ScheduleUpdate, NewBulletin, BulletinUpdate, NewEvent, EventUpdate},
|
|
};
|
|
use tokio::runtime::Runtime;
|
|
use std::sync::OnceLock;
|
|
|
|
static CLIENT: OnceLock<ChurchApiClient> = OnceLock::new();
|
|
static RT: OnceLock<Runtime> = OnceLock::new();
|
|
|
|
fn get_client() -> &'static ChurchApiClient {
|
|
CLIENT.get_or_init(|| {
|
|
let config = ChurchCoreConfig::default();
|
|
ChurchApiClient::new(config).expect("Failed to create church client")
|
|
})
|
|
}
|
|
|
|
fn get_runtime() -> &'static Runtime {
|
|
RT.get_or_init(|| {
|
|
Runtime::new().expect("Failed to create async runtime")
|
|
})
|
|
}
|
|
|
|
// Configuration functions
|
|
pub fn get_church_name() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.church_name.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_contact_phone() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.contact_phone.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_contact_email() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.contact_email.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_church_address() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.church_address.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_church_physical_address() -> String {
|
|
get_church_address()
|
|
}
|
|
|
|
pub fn get_church_po_box() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.po_box.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_mission_statement() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.mission_statement.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_facebook_url() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.facebook_url.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_youtube_url() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.youtube_url.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_instagram_url() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => config.instagram_url.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
pub fn get_stream_live_status() -> bool {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_stream_status()) {
|
|
Ok(status) => status.is_live,
|
|
Err(_) => false,
|
|
}
|
|
}
|
|
|
|
pub fn get_livestream_url() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_live_stream()) {
|
|
Ok(stream) => stream.stream_title.unwrap_or_else(|| "".to_string()),
|
|
Err(e) => format!("Error: {}", e),
|
|
}
|
|
}
|
|
|
|
// JSON API functions
|
|
pub fn fetch_events_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_upcoming_events(Some(50))) {
|
|
Ok(events) => {
|
|
// Format events with display formatting using existing Event methods
|
|
let formatted_events: Vec<_> = events.iter().map(|event| {
|
|
let mut event_json = serde_json::to_value(event).unwrap_or_default();
|
|
|
|
// Add formatted fields using Event's built-in methods
|
|
if let Some(obj) = event_json.as_object_mut() {
|
|
obj.insert("formatted_date".to_string(), serde_json::Value::String(event.formatted_date_range()));
|
|
obj.insert("formatted_time".to_string(), serde_json::Value::String(event.formatted_start_time()));
|
|
}
|
|
event_json
|
|
}).collect();
|
|
|
|
serde_json::to_string(&formatted_events).unwrap_or_else(|_| "[]".to_string())
|
|
},
|
|
Err(_) => "[]".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn fetch_featured_events_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_featured_events_v2(Some(10))) {
|
|
Ok(events) => serde_json::to_string(&events).unwrap_or_else(|_| "[]".to_string()),
|
|
Err(_) => "[]".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn fetch_sermons_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_recent_sermons(Some(20))) {
|
|
Ok(sermons) => serde_json::to_string(&sermons).unwrap_or_else(|_| "[]".to_string()),
|
|
Err(_) => "[]".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn fetch_config_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_config()) {
|
|
Ok(config) => serde_json::to_string(&config).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(_) => "{}".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn fetch_random_bible_verse_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_random_verse()) {
|
|
Ok(verse) => serde_json::to_string(&verse).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(_) => "{}".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn fetch_bulletins_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_bulletins(true)) {
|
|
Ok(bulletins) => serde_json::to_string(&bulletins).unwrap_or_else(|_| "[]".to_string()),
|
|
Err(_) => "[]".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn fetch_current_bulletin_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_current_bulletin()) {
|
|
Ok(Some(bulletin)) => serde_json::to_string(&bulletin).unwrap_or_else(|_| "{}".to_string()),
|
|
Ok(None) => "{}".to_string(),
|
|
Err(_) => "{}".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn fetch_bible_verse_json(query: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_verse_by_reference(&query)) {
|
|
Ok(Some(verse)) => serde_json::to_string(&verse).unwrap_or_else(|_| "{}".to_string()),
|
|
Ok(None) => "{}".to_string(),
|
|
Err(_) => "{}".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn fetch_livestream_archive_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_livestreams()) {
|
|
Ok(streams) => serde_json::to_string(&streams).unwrap_or_else(|_| "[]".to_string()),
|
|
Err(_) => "[]".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn submit_contact_v2_json(name: String, email: String, subject: String, message: String, phone: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
let contact = crate::models::ContactForm::new(name, email, subject, message)
|
|
.with_phone(phone);
|
|
|
|
match rt.block_on(client.submit_contact_form_v2(contact)) {
|
|
Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn validate_contact_form_json(form_json: String) -> String {
|
|
match serde_json::from_str::<crate::models::ContactForm>(&form_json) {
|
|
Ok(_) => serde_json::to_string(&crate::utils::ValidationResult::valid()).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(_) => serde_json::to_string(&crate::utils::ValidationResult::invalid(vec!["Invalid JSON format".to_string()])).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn submit_event_json(
|
|
title: String,
|
|
description: String,
|
|
start_time: String,
|
|
end_time: String,
|
|
location: String,
|
|
location_url: Option<String>,
|
|
category: String,
|
|
recurring_type: Option<String>,
|
|
submitter_email: Option<String>
|
|
) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
let submission = crate::models::EventSubmission {
|
|
title,
|
|
description,
|
|
start_time,
|
|
end_time,
|
|
location,
|
|
location_url,
|
|
category,
|
|
recurring_type,
|
|
submitter_email: submitter_email.unwrap_or_else(|| "".to_string()),
|
|
is_featured: false,
|
|
bulletin_week: None,
|
|
image_data: None,
|
|
image_filename: None,
|
|
image_mime_type: None,
|
|
};
|
|
|
|
match rt.block_on(client.submit_event(submission)) {
|
|
Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn submit_event_with_image_json(
|
|
title: String,
|
|
description: String,
|
|
start_time: String,
|
|
end_time: String,
|
|
location: String,
|
|
location_url: Option<String>,
|
|
category: String,
|
|
recurring_type: Option<String>,
|
|
submitter_email: Option<String>,
|
|
image_data: Option<Vec<u8>>,
|
|
image_filename: Option<String>
|
|
) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
let submission = crate::models::EventSubmission {
|
|
title,
|
|
description,
|
|
start_time,
|
|
end_time,
|
|
location,
|
|
location_url,
|
|
category,
|
|
recurring_type,
|
|
submitter_email: submitter_email.unwrap_or_else(|| "".to_string()),
|
|
is_featured: false,
|
|
bulletin_week: None,
|
|
image_data: image_data.clone(),
|
|
image_filename: image_filename.clone(),
|
|
image_mime_type: None, // Could be improved to detect from filename or data
|
|
};
|
|
|
|
// Convert image data to format expected by multipart method
|
|
let image_multipart = if let (Some(data), Some(filename)) = (image_data, image_filename) {
|
|
Some((data, filename))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
match rt.block_on(crate::client::events::submit_event_with_image(client, submission, image_multipart)) {
|
|
Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
// Admin functions
|
|
pub fn fetch_all_schedules_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.get_all_admin_schedules()) {
|
|
Ok(schedules) => serde_json::to_string(&schedules).unwrap_or_else(|_| "[]".to_string()),
|
|
Err(_) => "[]".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn create_schedule_json(schedule_json: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match serde_json::from_str::<NewSchedule>(&schedule_json) {
|
|
Ok(schedule) => {
|
|
match rt.block_on(client.create_admin_schedule(schedule)) {
|
|
Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
},
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn update_schedule_json(date: String, update_json: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match serde_json::from_str::<ScheduleUpdate>(&update_json) {
|
|
Ok(update) => {
|
|
match rt.block_on(client.update_admin_schedule(&date, update)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
},
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn delete_schedule_json(date: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.delete_admin_schedule(&date)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
// Admin Auth Functions
|
|
pub fn admin_login_json(email: String, password: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.admin_login(&email, &password)) {
|
|
Ok(token) => serde_json::to_string(&serde_json::json!({"success": true, "token": token})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn validate_admin_token_json(token: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(client.validate_admin_token(&token)) {
|
|
Ok(valid) => serde_json::to_string(&serde_json::json!({"success": true, "valid": valid})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
// Admin Events Functions
|
|
pub fn fetch_pending_events_json() -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(crate::client::admin::get_pending_events(client)) {
|
|
Ok(events) => serde_json::to_string(&events).unwrap_or_else(|_| "[]".to_string()),
|
|
Err(_) => "[]".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn approve_pending_event_json(event_id: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(crate::client::admin::approve_pending_event(client, &event_id)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn reject_pending_event_json(event_id: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(crate::client::admin::reject_pending_event(client, &event_id)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn delete_pending_event_json(event_id: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(crate::client::admin::delete_pending_event(client, &event_id)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
|
|
pub fn update_admin_event_json(event_id: String, update_json: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match serde_json::from_str::<EventUpdate>(&update_json) {
|
|
Ok(update) => {
|
|
match rt.block_on(crate::client::admin::update_admin_event(client, &event_id, update)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
},
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn delete_admin_event_json(event_id: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(crate::client::admin::delete_admin_event(client, &event_id)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
// Admin Bulletins Functions
|
|
pub fn create_bulletin_json(bulletin_json: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match serde_json::from_str::<NewBulletin>(&bulletin_json) {
|
|
Ok(bulletin) => {
|
|
match rt.block_on(crate::client::admin::create_bulletin(client, bulletin)) {
|
|
Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
},
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn update_bulletin_json(bulletin_id: String, update_json: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match serde_json::from_str::<BulletinUpdate>(&update_json) {
|
|
Ok(update) => {
|
|
match rt.block_on(crate::client::admin::update_bulletin(client, &bulletin_id, update)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
},
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn delete_bulletin_json(bulletin_id: String) -> String {
|
|
let client = get_client();
|
|
let rt = get_runtime();
|
|
|
|
match rt.block_on(crate::client::admin::delete_bulletin(client, &bulletin_id)) {
|
|
Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()),
|
|
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
|
|
}
|
|
} |