systemprompt_content/
list_branding_provider.rs1use std::sync::Arc;
2
3use anyhow::Result;
4use async_trait::async_trait;
5use serde_json::Value;
6use systemprompt_models::ContentConfigRaw;
7use systemprompt_models::services::ServicesConfig;
8use systemprompt_provider_contracts::{PageContext, PageDataProvider};
9
10#[derive(Debug, Clone, Copy, Default)]
11pub struct DefaultListBrandingProvider;
12
13fn resolve_content_raw<'a>(ctx: &'a PageContext<'_>) -> Result<&'a ContentConfigRaw> {
14 if let Some(services) = ctx.content_config::<ServicesConfig>() {
15 return Ok(&services.content.raw);
16 }
17 ctx.content_config::<ContentConfigRaw>()
18 .ok_or_else(|| anyhow::anyhow!("ContentConfig not available in PageContext"))
19}
20
21#[async_trait]
22impl PageDataProvider for DefaultListBrandingProvider {
23 fn provider_id(&self) -> &'static str {
24 "default-list-branding"
25 }
26
27 async fn provide_page_data(&self, ctx: &PageContext<'_>) -> Result<Value> {
28 let Some(source_name) = ctx.page_type.strip_suffix("-list") else {
29 return Ok(serde_json::json!({}));
30 };
31
32 let content_config = resolve_content_raw(ctx)?;
33
34 let source = content_config.content_sources.get(source_name);
35 let org = &content_config.metadata.structured_data.organization;
36 let language = &content_config.metadata.language;
37 let branding = &ctx.web_config.branding;
38
39 let source_branding = source.and_then(|s| s.branding.as_ref());
40
41 let blog_name = source_branding
42 .and_then(|b| b.name.as_deref())
43 .unwrap_or(&branding.name);
44
45 let blog_description = source_branding
46 .and_then(|b| b.description.as_deref())
47 .unwrap_or(&branding.description);
48
49 let blog_image = source_branding
50 .and_then(|b| b.image.as_deref())
51 .map_or_else(String::new, |img| format!("{}{}", org.url, img));
52
53 let blog_keywords = source_branding
54 .and_then(|b| b.keywords.as_deref())
55 .unwrap_or("");
56
57 Ok(serde_json::json!({
58 "BLOG_NAME": blog_name,
59 "BLOG_DESCRIPTION": blog_description,
60 "BLOG_IMAGE": blog_image,
61 "BLOG_KEYWORDS": blog_keywords,
62 "BLOG_URL": format!("{}/{}", org.url, source_name),
63 "BLOG_LANGUAGE": language,
64 }))
65 }
66}
67
68pub fn default_list_branding_provider() -> Arc<dyn PageDataProvider> {
69 Arc::new(DefaultListBrandingProvider)
70}