1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use crate::{
    checks::ENABLED_CHECK,
    ClientDataKey,
};
use serenity::{
    builder::{
        CreateAttachment,
        CreateMessage,
    },
    client::Context,
    framework::standard::{
        macros::command,
        Args,
        CommandResult,
    },
    model::prelude::*,
};
use tracing::error;

#[command]
#[description("Print the current Tic-Tac-Toe board")]
#[usage("")]
#[example("")]
#[min_args(0)]
#[max_args(0)]
#[bucket("ttt-board")]
#[checks(Enabled)]
pub async fn board(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
    let data_lock = ctx.data.read().await;
    let client_data = data_lock
        .get::<ClientDataKey>()
        .expect("missing client data");
    let tic_tac_toe_data = client_data.tic_tac_toe_data.clone();
    let db = client_data.db.clone();
    drop(data_lock);

    let guild_id = msg.guild_id;
    let author_id = msg.author.id;

    match db
        .get_tic_tac_toe_game(guild_id.into(), author_id.into())
        .await
    {
        Ok(Some(game)) => {
            let file = match tic_tac_toe_data
                .renderer
                .render_board_async(game.board)
                .await
            {
                Ok(file) => {
                    CreateAttachment::bytes(file, format!("ttt-{}.png", game.board.encode_u16()))
                }
                Err(error) => {
                    error!("Failed to render Tic-Tac-Toe board: {error}");
                    msg.channel_id
                        .say(
                            &ctx.http,
                            format!("Failed to render Tic-Tac-Toe board: {error}"),
                        )
                        .await?;
                    return Ok(());
                }
            };
            let message_builder = CreateMessage::new().add_file(file);
            msg.channel_id
                .send_message(&ctx.http, message_builder)
                .await?;
        }
        Ok(None) => {
            let response = "Failed to print board as you have no games in this server".to_string();
            msg.channel_id.say(&ctx.http, response).await?;
            return Ok(());
        }
        Err(error) => {
            error!("{error:?}");
            msg.channel_id.say(&ctx.http, "database error").await?;
        }
    };

    Ok(())
}