mod instructions;
use serde_json::{Value, json};
pub use instructions::{
ProviderInstruction, collect_post_setup_instructions, print_post_setup_instructions,
};
pub fn registration_result_from_declared_ops(config: &Value) -> Option<Value> {
let webhook_ops = config.get("webhook_ops")?.as_array()?;
if webhook_ops.is_empty() {
return None;
}
let subscription_ops = config
.get("subscription_ops")
.and_then(Value::as_array)
.cloned()
.unwrap_or_default();
let oauth_ops = config
.get("oauth_ops")
.and_then(Value::as_array)
.cloned()
.unwrap_or_default();
Some(json!({
"ok": true,
"mode": "declared_ops",
"webhook_ops": webhook_ops,
"subscription_ops": subscription_ops,
"oauth_ops": oauth_ops,
}))
}
pub fn has_webhook_url(answers: &Value) -> Option<&str> {
answers
.as_object()?
.get("public_base_url")?
.as_str()
.filter(|url| !url.is_empty() && url.starts_with("https://"))
}
pub fn register_webhook(
_provider_id: &str,
config: &Value,
_tenant: &str,
_team: Option<&str>,
) -> Option<Value> {
registration_result_from_declared_ops(config)
}
pub fn build_webhook_url(
public_base_url: &str,
provider_id: &str,
tenant: &str,
team: &str,
) -> String {
format!(
"{}/v1/messaging/ingress/{}/{}/{}",
public_base_url.trim_end_matches('/'),
provider_id,
tenant,
team,
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn has_webhook_url_valid() {
let config = json!({"public_base_url": "https://example.com"});
assert_eq!(has_webhook_url(&config), Some("https://example.com"));
}
#[test]
fn registration_result_from_declared_ops_uses_declared_ops() {
let config = json!({
"webhook_ops": [{"op": "register", "url": "https://example.com/webhook"}],
"subscription_ops": [{"op": "sync"}],
"oauth_ops": []
});
let result =
registration_result_from_declared_ops(&config).expect("declared ops registration");
assert_eq!(result["ok"], Value::Bool(true));
assert_eq!(result["mode"], Value::String("declared_ops".to_string()));
assert_eq!(
result["webhook_ops"][0]["op"],
Value::String("register".to_string())
);
}
#[test]
fn register_webhook_prefers_declared_ops() {
let config = json!({
"public_base_url": "http://example.com",
"webhook_ops": [{"op": "register", "url": "https://example.com/webhook"}]
});
let result = register_webhook("messaging-unknown", &config, "demo", None)
.expect("declared ops fallback");
assert_eq!(result["mode"], Value::String("declared_ops".to_string()));
}
#[test]
fn has_webhook_url_http_rejected() {
let config = json!({"public_base_url": "http://example.com"});
assert_eq!(has_webhook_url(&config), None);
}
#[test]
fn has_webhook_url_empty_rejected() {
let config = json!({"public_base_url": ""});
assert_eq!(has_webhook_url(&config), None);
}
#[test]
fn register_webhook_returns_none_without_declared_ops() {
let config = json!({"public_base_url": "https://example.com", "bot_token": "x"});
assert!(register_webhook("messaging-telegram", &config, "demo", None).is_none());
}
#[test]
fn register_webhook_returns_none_without_public_url() {
let config = json!({"bot_token": "x"});
assert!(register_webhook("messaging-telegram", &config, "demo", None).is_none());
}
#[test]
fn build_webhook_url_format() {
let url = build_webhook_url(
"https://example.com",
"messaging-telegram",
"demo",
"default",
);
assert_eq!(
url,
"https://example.com/v1/messaging/ingress/messaging-telegram/demo/default"
);
}
#[test]
fn build_webhook_url_trims_trailing_slash() {
let url = build_webhook_url(
"https://example.com/",
"messaging-telegram",
"demo",
"default",
);
assert_eq!(
url,
"https://example.com/v1/messaging/ingress/messaging-telegram/demo/default"
);
}
}