aboutsummaryrefslogtreecommitdiffstats
path: root/src/commands/qr.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/commands/qr.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/commands/qr.rs b/src/commands/qr.rs
new file mode 100644
index 0000000..26232ee
--- /dev/null
+++ b/src/commands/qr.rs
@@ -0,0 +1,87 @@
1use poise::serenity_prelude as serenity;
2
3use crate::Data;
4use crate::error::{Error, Result};
5use crate::lang;
6
7type Context<'a> = poise::Context<'a, Data, Error>;
8
9/// QR group
10#[poise::command(slash_command, subcommands("dekodowanie", "generowanie",))]
11pub async fn qr(_ctx: Context<'_>) -> Result<()> {
12 Ok(())
13}
14
15/// Generate a QR code from text
16#[poise::command(slash_command)]
17pub async fn generowanie(
18 ctx: Context<'_>,
19 #[description = "Zawartość kodu QR"] text: String,
20) -> Result<()> {
21 ctx.defer().await?;
22
23 let code = qrcode::QrCode::new(text.as_bytes())?;
24 let image = code.render::<image::Luma<u8>>().build();
25
26 let scaled = image::imageops::resize(
27 &image,
28 image.width() * 10,
29 image.height() * 10,
30 image::imageops::Nearest,
31 );
32
33 let mut buf = std::io::Cursor::new(Vec::new());
34 scaled.write_to(&mut buf, image::ImageFormat::Png)?;
35
36 ctx.send(
37 poise::CreateReply::default()
38 .content(lang::L_QR_GENERATED)
39 .attachment(serenity::CreateAttachment::bytes(
40 buf.into_inner(),
41 "qrcode.png",
42 )),
43 )
44 .await?;
45 Ok(())
46}
47
48/// Decode a QR code from an uploaded image
49#[poise::command(slash_command)]
50pub async fn dekodowanie(
51 ctx: Context<'_>,
52 #[description = "Obraz zawierający kod QR"] image: serenity::Attachment,
53) -> Result<()> {
54 ctx.defer().await?;
55
56 let img_data = ctx
57 .data()
58 .http_client
59 .get(&image.url)
60 .send()
61 .await?
62 .bytes()
63 .await?;
64 let img = image::load_from_memory(&img_data)?;
65 let gray = img.to_luma8();
66
67 let decoded = decode_qr_simple(&gray);
68 match decoded {
69 Some(text) => {
70 ctx.say(lang::fmt_qr_decoded(&text)).await?;
71 }
72 None => {
73 ctx.say(lang::L_QR_DECODE_FAILED).await?;
74 }
75 }
76 Ok(())
77}
78
79fn decode_qr_simple(img: &image::ImageBuffer<image::Luma<u8>, Vec<u8>>) -> Option<String> {
80 rxing::helpers::detect_in_luma(img.as_raw().to_vec(), img.width(), img.height(), None)
81 .ok()
82 .map(|r| r.getText().to_owned())
83}
84
85pub fn commands() -> Vec<poise::Command<Data, Error>> {
86 vec![qr()]
87}