use std::sync::Arc;
use archivist_core::api::{FichubClient, SearchParams};
use archivist_core::cache::PageCache;
use archivist_core::config::BotConfig;
use archivist_core::core::{
ActionRow, Button, ButtonStyle, PlatformMessage, RichItem, pagination_row,
};
use archivist_core::dispatch::CoreCtx;
fn build_core_ctx() -> CoreCtx {
let config = Arc::new(BotConfig::default()); let client = FichubClient::new(config.clone()).expect("builds without I/O");
let cache = PageCache::offline(); CoreCtx::new(client, cache, config)
}
fn parse_search(raw: &str) -> SearchParams {
SearchParams {
q: raw
.strip_prefix("!search")
.unwrap_or(raw)
.trim()
.to_string(),
..Default::default()
}
}
fn render(msg: &PlatformMessage) {
match msg {
PlatformMessage::Text(s) => println!("[text] {s}"),
PlatformMessage::Rich {
header,
items,
actions,
} => {
if let Some(h) = header {
println!("[rich] {h}");
}
for item in items {
if let Some(t) = &item.title {
println!(" {t}");
}
if let Some(u) = &item.url {
println!(" {u}");
}
if !item.body.is_empty() {
println!(" {}", item.body);
}
for (k, v) in &item.fields {
println!(" {k}: {v}");
}
if let Some(f) = &item.footer {
println!(" — {f}");
}
}
for row in actions {
match row {
ActionRow::Buttons(bs) => {
let labels: Vec<String> = bs.iter().map(button_label).collect();
println!(" buttons: {}", labels.join(" "));
}
ActionRow::SelectMenu {
placeholder,
options,
} => {
let opts: Vec<&str> = options.iter().map(|o| o.label.as_str()).collect();
println!(" select \"{placeholder}\": {}", opts.join(", "));
}
}
}
}
PlatformMessage::File {
filename,
data,
caption,
} => {
if let Some(c) = caption {
println!("[file] {c}");
}
println!(" upload {filename} ({} bytes)", data.len());
}
PlatformMessage::Ephemeral(inner) => {
println!("[ephemeral →]");
render(inner);
}
}
}
fn button_label(b: &Button) -> String {
if b.label.is_empty() {
b.emoji.clone().unwrap_or_default()
} else {
b.label.clone()
}
}
fn main() {
let ctx = build_core_ctx();
let user_id = 42;
let params = parse_search("!search drarry");
let _ = (&ctx, params.q.len(), user_id);
let search_reply = PlatformMessage::Rich {
header: Some("Search: drarry".into()),
items: vec![
RichItem::new("Harry Potter and the Pureblood Princess")
.title("The Pureblood Princess")
.url("https://archiveofourown.org/works/123")
.field("Author", "SomeAuthor")
.field("Words", "78,901")
.field("Kudos", "12,345")
.footer("1–5 of 238 results"),
RichItem::new("Another fine fic")
.title("Second Result")
.url("https://archiveofourown.org/works/456")
.field("Author", "OtherAuthor")
.field("Words", "3,210"),
],
actions: vec![pagination_row("sess-1", 238, 5, 1)],
};
let plain_text = PlatformMessage::Text("No results for 'xmascrack'.".into());
let file_msg = PlatformMessage::File {
filename: "The_Pureblood_Princess.epub".into(),
data: b"PK\x03\x04 fake epub bytes".to_vec(),
caption: Some("Here's your ebook".into()),
};
let ephemeral = PlatformMessage::ephemeral(PlatformMessage::Rich {
header: Some("Private note".into()),
items: vec![RichItem::new("Your download link is ready.")],
actions: vec![ActionRow::Buttons(vec![Button {
id: "dl:123".into(),
label: "Download".into(),
emoji: None,
style: ButtonStyle::Primary,
disabled: false,
}])],
});
render(&search_reply);
println!();
render(&plain_text);
println!();
render(&file_msg);
println!();
render(&ephemeral);
}