use crate::log::StyledText;
use crate::pyproject::PyProjectConfig;
use anyhow::{Context, Result};
use dialoguer::Confirm;
use dialoguer::theme::ColorfulTheme;
use std::fmt::Write;
use std::fs;
use std::path::Path;
use tracing::error;
pub async fn generate_bot_file(work_dir: &Path, force: bool) -> Result<()> {
let filename = "bot.py";
let bot_path = work_dir.join(filename);
if bot_path.exists()
&& !force
&& !Confirm::with_theme(&ColorfulTheme::default())
.with_prompt(format!("File '{filename}' already exists. Overwrite"))
.default(false)
.interact()?
{
error!("File generation cancelled.");
return Ok(());
}
let content = generate_bot_content(work_dir)?;
fs::write(&bot_path, content).context("Failed to write bot file")?;
StyledText::new(" ")
.green_bold("✓ Successfully generated bot file:")
.cyan_bold(filename)
.println();
Ok(())
}
pub fn generate_bot_content(work_dir: &Path) -> Result<String> {
let pyproject = PyProjectConfig::parse(Some(work_dir))?;
let nonebot = pyproject
.nonebot()
.context("No tool.nonebot in pyproject.toml")?;
let name_module_tuples = nonebot
.adapters
.as_ref()
.unwrap_or(&vec![])
.iter()
.map(|a| (a.alias(), a.module_name.to_owned()))
.collect::<Vec<_>>();
let mut adapters_import = String::new();
let mut adapters_register = String::new();
let mut iter = name_module_tuples.iter().peekable();
while let Some((alias, module)) = iter.next() {
write!(adapters_import, "from {module} import Adapter as {alias}")?;
write!(adapters_register, "driver.register_adapter({alias})")?;
if iter.peek().is_some() {
adapters_import.push('\n');
adapters_register.push('\n');
}
}
let mut builtin_plugins_load = String::new();
if let Some(builtin_plugins) = nonebot.builtin_plugins.as_ref() {
write!(builtin_plugins_load, "nonebot.load_builtin_plugins(")?;
let mut iter = builtin_plugins.iter().peekable();
while let Some(plugin) = iter.next() {
write!(builtin_plugins_load, r#""{plugin}""#)?;
if iter.peek().is_some() {
write!(builtin_plugins_load, ", ")?;
}
}
builtin_plugins_load.push(')');
}
let content = format!(
include_str!("templates/bot"),
adapters_import, adapters_register, builtin_plugins_load
);
Ok(content)
}
pub async fn handle(force: bool) -> Result<()> {
let work_dir = std::env::current_dir()?;
generate_bot_file(&work_dir, force).await?;
Ok(())
}