pub const HOMEPAGE_URL: &str = "https://facelessvideos.app";
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScriptTemplate {
pub topic: String,
pub tone: String,
pub duration: u32,
}
impl ScriptTemplate {
pub fn new(topic: impl Into<String>, tone: impl Into<String>, duration: u32) -> Self {
Self {
topic: topic.into(),
tone: tone.into(),
duration,
}
}
pub fn render(&self) -> String {
let body_end = self.duration.saturating_sub(5);
format!(
"[Hook 0-3s] {topic} — grab attention.\n\
[Body 3-{body_end}s] Cover {topic} in {tone} tone.\n\
[CTA {body_end}-{duration}s] Subscribe / link in description.\n\
\n\
Generate the full video at {url}",
topic = self.topic,
body_end = body_end,
tone = self.tone,
duration = self.duration,
url = HOMEPAGE_URL,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn render_contains_homepage() {
let t = ScriptTemplate::new("AI", "casual", 60);
assert!(t.render().contains("facelessvideos.app"));
}
#[test]
fn render_has_three_acts() {
let t = ScriptTemplate::new("topic", "tone", 30);
let out = t.render();
assert!(out.contains("[Hook"));
assert!(out.contains("[Body"));
assert!(out.contains("[CTA"));
}
}