use std::collections::HashSet;
use std::fmt;
use url::Url;
pub use crate::build::group::GroupBuilder;
use crate::build::split::format_comment;
mod group;
mod split;
#[derive(Debug, Default, Clone)]
pub struct RobotsBuilder {
groups: Vec<GroupBuilder>,
sitemaps: HashSet<Url>,
header: Option<String>,
footer: Option<String>,
}
impl RobotsBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn header(mut self, header: &str) -> Self {
self.header = Some(header.to_string());
self
}
pub fn group<'a>(
mut self,
group: impl IntoIterator<Item = &'a str>,
factory: impl FnOnce(GroupBuilder) -> GroupBuilder,
) -> Self {
let section = GroupBuilder::from_iter(group);
self.groups.push(factory(section));
self
}
pub fn sitemap(mut self, sitemap: Url) -> Self {
self.sitemaps.insert(sitemap);
self
}
pub fn footer(mut self, footer: &str) -> Self {
self.footer = Some(footer.to_string());
self
}
#[cfg(feature = "parser")]
#[cfg_attr(docsrs, doc(cfg(feature = "parser")))]
pub fn parse(&self, user_agent: &str) -> crate::Robots {
let txt = self.to_string();
crate::Robots::from_bytes(txt.as_bytes(), user_agent)
}
}
impl fmt::Display for RobotsBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let header = self.header.as_ref().map(|h| format_comment(h));
let footer = self.footer.as_ref().map(|f| format_comment(f));
let groups = self.groups.iter().map(|u| u.to_string());
let groups = groups.collect::<Vec<_>>().join("\n\n");
let result = [header, Some(groups), footer];
let result = result.iter().filter_map(|u| u.clone());
let result = result.collect::<Vec<_>>().join("\n\n");
write!(f, "{}", result.as_str())
}
}
#[cfg(test)]
mod builder {
use crate::{Result, RobotsBuilder};
#[test]
fn readme() -> Result<()> {
let txt = RobotsBuilder::default()
.header("Robots.txt: Start")
.group(["foobot"], |u| {
u.crawl_delay(5)
.header("Rules for Foobot: Start")
.allow("/example/yeah.txt")
.disallow("/example/nope.txt")
.footer("Rules for Foobot: End")
})
.group(["barbot", "nombot"], |u| {
u.crawl_delay(2)
.disallow("/example/yeah.txt")
.disallow("/example/nope.txt")
})
.sitemap("https://example.com/sitemap_1.xml".try_into()?)
.sitemap("https://example.com/sitemap_2.xml".try_into()?)
.footer("Robots.txt: End");
println!("{}", txt.to_string());
Ok(())
}
}