feat: reintroduce tag command

Signed-off-by: seth <getchoo@tuta.io>
This commit is contained in:
seth 2023-12-04 05:11:54 -05:00
parent a8eb4a212a
commit 30cc4a6220
No known key found for this signature in database
GPG key ID: D31BD0D494BBEE86
12 changed files with 256 additions and 10 deletions

37
Cargo.lock generated
View file

@ -548,6 +548,18 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "gray_matter"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cf2fb99fac0b821a4e61c61abff076324bb0e5c3b4a83815bbc3518a38971ad"
dependencies = [
"serde",
"serde_json",
"toml",
"yaml-rust",
]
[[package]]
name = "h2"
version = "0.3.22"
@ -807,6 +819,12 @@ version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.4.12"
@ -1209,6 +1227,7 @@ dependencies = [
"color-eyre",
"dotenvy",
"env_logger",
"gray_matter",
"log",
"octocrab",
"once_cell",
@ -1885,6 +1904,15 @@ dependencies = [
"tracing",
]
[[package]]
name = "toml"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"serde",
]
[[package]]
name = "tower"
version = "0.4.13"
@ -2411,6 +2439,15 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[package]]
name = "zeroize"
version = "1.7.0"

View file

@ -5,8 +5,14 @@ edition = "2021"
repository = "https://github.com/PrismLauncher/refraction"
license = "GPL-3.0-or-later"
readme = "README.md"
build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
gray_matter = "0.2.6"
poise = "0.5.7"
serde = "1.0.193"
serde_json = "1.0.108"
[dependencies]
color-eyre = "0.6.2"

121
build.rs Normal file
View file

@ -0,0 +1,121 @@
use std::collections::HashMap;
use std::path::Path;
use std::{env, fs};
use gray_matter::{engine, Matter};
include!("src/tags.rs");
/// generate the ChoiceParameter enum and tag data we will use in the `tag` command
#[allow(dead_code)]
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let generated = Path::new(&out_dir).join("generated.rs");
let tag_files: Vec<String> = fs::read_dir(TAG_DIR)
.unwrap()
.map(|f| f.unwrap().file_name().to_string_lossy().to_string())
.collect();
let tags: Vec<Tag> = tag_files
.clone()
.into_iter()
.map(|name| {
let file_name = format!("{TAG_DIR}/{name}");
let content = fs::read_to_string(&file_name).unwrap();
let matter = Matter::<engine::YAML>::new();
let frontmatter: TagFrontmatter = matter
.parse(&content)
.data
.unwrap()
.deserialize()
.unwrap_or_else(|e| {
// actually handling the error since this is the most likely thing to fail -getchoo
panic!(
"Failed to parse file {file_name}! Here's what it looked like:\n{content}\n\nReported Error:\n{e}\n",
)
});
Tag {
content,
file_name: name,
frontmatter,
}
})
.collect();
let aliases: HashMap<String, Vec<String>> = tags
.iter()
.filter_map(|t| {
t.frontmatter
.aliases
.clone()
.map(|aliases| (t.file_name.clone(), aliases))
})
.collect();
let formatted_names: Vec<String> = tags
.iter()
.flat_map(|t| {
let mut res = Vec::from([t.file_name.replace(".md", "").replace('-', "_")]);
if let Some(tag_aliases) = aliases.get(&t.file_name) {
res.append(&mut tag_aliases.clone())
}
res
})
.collect();
let tag_choice = format!(
r#"
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Clone, Debug, poise::ChoiceParameter)]
pub enum TagChoice {{
{}
}}"#,
formatted_names.join(",\n")
);
let to_str = format!(
r#"
impl TagChoice {{
fn as_str(&self) -> &str {{
match &self {{
{}
}}
}}
}}
"#,
formatted_names
.iter()
.map(|n| {
let file_name = n.replace('_', "-") + ".md";
// assume this is an alias if we can't match the file name
let name = if tag_files.contains(&file_name) {
file_name
} else {
aliases
.iter()
.find(|a| a.1.contains(n))
.unwrap()
.0
.to_string()
};
format!("Self::{n} => \"{name}\",")
})
.collect::<Vec<String>>()
.join("\n")
);
let contents = Vec::from([tag_choice, to_str]).join("\n\n");
fs::write(generated, contents).unwrap();
println!(
"cargo:rustc-env=TAGS={}",
// make sure we can deserialize with env! at runtime
serde_json::to_string(&tags).unwrap()
);
}

View file

@ -3,9 +3,11 @@ mod members;
mod rory;
mod say;
mod stars;
mod tag;
pub use joke::joke;
pub use members::members;
pub use rory::rory;
pub use say::say;
pub use stars::stars;
pub use tag::tag;

View file

@ -0,0 +1,57 @@
#![allow(non_camel_case_types, clippy::upper_case_acronyms)]
use crate::tags::Tag;
use crate::{consts, Context};
use std::env;
use color_eyre::eyre::{eyre, Result};
use once_cell::sync::Lazy;
use poise::serenity_prelude::{Color, User};
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
static TAGS: Lazy<Vec<Tag>> = Lazy::new(|| serde_json::from_str(env!("TAGS")).unwrap());
/// Send a tag
#[poise::command(slash_command)]
pub async fn tag(
ctx: Context<'_>,
#[description = "the copypasta you want to send"] name: TagChoice,
user: Option<User>,
) -> Result<()> {
let tag_file = name.as_str();
let tag = TAGS
.iter()
.find(|t| t.file_name == tag_file)
.ok_or_else(|| eyre!("Tried to get non-existent tag: {tag_file}"))?;
let frontmatter = &tag.frontmatter;
ctx.send(|m| {
if let Some(user) = user {
m.content(format!("<@{}>", user.id));
}
m.embed(|e| {
if let Some(color) = &frontmatter.color {
let color = *consts::COLORS
.get(color.as_str())
.unwrap_or(&Color::default());
e.color(color);
}
if let Some(image) = &frontmatter.image {
e.image(image);
}
if let Some(fields) = &frontmatter.fields {
for field in fields {
e.field(&field.name, &field.value, field.inline);
}
}
e
})
})
.await?;
Ok(())
}

View file

@ -13,6 +13,7 @@ pub fn to_global_commands() -> Vec<Command<Data, Report>> {
general::rory(),
general::say(),
general::stars(),
general::tag(),
moderation::ban_user(),
moderation::kick_user(),
]

View file

@ -1,14 +1,15 @@
use std::collections::HashMap;
use once_cell::sync::Lazy;
use poise::serenity_prelude::Color;
pub static COLORS: Lazy<HashMap<&str, (u8, u8, u8)>> = Lazy::new(|| {
pub static COLORS: Lazy<HashMap<&str, Color>> = Lazy::new(|| {
HashMap::from([
("red", (239, 68, 68)),
("green", (34, 197, 94)),
("blue", (96, 165, 250)),
("yellow", (253, 224, 71)),
("orange", (251, 146, 60)),
("red", Color::from((239, 68, 68))),
("green", Color::from((34, 197, 94))),
("blue", Color::from((96, 165, 250))),
("yellow", Color::from((253, 224, 71))),
("orange", Color::from((251, 146, 60))),
])
});

View file

@ -9,8 +9,8 @@ mod eta;
pub async fn handle(
ctx: &Context,
event: &Event<'_>,
framework: FrameworkContext<'_, Data, Report>,
data: &Data,
_framework: FrameworkContext<'_, Data, Report>,
_data: &Data,
) -> Result<()> {
match event {
Event::Ready { data_about_bot } => {

View file

@ -12,6 +12,7 @@ mod commands;
mod config;
mod consts;
mod handlers;
mod tags;
mod utils;
type Context<'a> = poise::Context<'a, Data, Report>;

21
src/tags.rs Normal file
View file

@ -0,0 +1,21 @@
use poise::serenity_prelude::EmbedField;
use serde::{Deserialize, Serialize};
#[allow(dead_code)]
pub const TAG_DIR: &str = "tags";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TagFrontmatter {
pub title: String,
pub aliases: Option<Vec<String>>,
pub color: Option<String>,
pub image: Option<String>,
pub fields: Option<Vec<EmbedField>>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Tag {
pub content: String,
pub file_name: String,
pub frontmatter: TagFrontmatter,
}

View file

@ -1,7 +1,6 @@
---
title: Can I install/download FTB packs directly from Prism?
color: orange
aliases: ['FTB']
---
You cannot download FTB packs directly from Prism Launcher.

View file

@ -1,7 +1,7 @@
---
title: Upload Logs
color: orange
aliases: ['sendlog', 'logs', '🪵']
aliases: ['sendlog', 'logs']
image: https://cdn.discordapp.com/attachments/1031694870756204566/1156971972232740874/image.png
---