pikadick/commands/tic_tac_toe/
concede.rs

1use crate::{
2    checks::ENABLED_CHECK,
3    database::model::TicTacToePlayer,
4    ClientDataKey,
5};
6use serenity::{
7    builder::{
8        CreateAttachment,
9        CreateMessage,
10    },
11    client::Context,
12    framework::standard::{
13        macros::command,
14        Args,
15        CommandResult,
16    },
17    model::prelude::*,
18};
19use tracing::error;
20
21#[command]
22#[description("Concede a game of Tic-Tac-Toe")]
23#[usage("")]
24#[example("")]
25#[min_args(0)]
26#[max_args(0)]
27#[checks(Enabled)]
28#[bucket("default")]
29pub async fn concede(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
30    let data_lock = ctx.data.read().await;
31    let client_data = data_lock
32        .get::<ClientDataKey>()
33        .expect("missing client data");
34    let tic_tac_toe_data = client_data.tic_tac_toe_data.clone();
35    let db = client_data.db.clone();
36    drop(data_lock);
37
38    let guild_id = msg.guild_id;
39    let author_id = msg.author.id;
40
41    let game = match db
42        .concede_tic_tac_toe_game(guild_id.into(), author_id)
43        .await
44    {
45        Ok(Some(game)) => game,
46        Ok(None) => {
47            let response = "Failed to concede as you have no games in this server".to_string();
48            msg.channel_id.say(&ctx.http, response).await?;
49            return Ok(());
50        }
51        Err(e) => {
52            error!("{:?}", e);
53            msg.channel_id.say(&ctx.http, "database error").await?;
54            return Ok(());
55        }
56    };
57
58    let opponent = game
59        .get_opponent(TicTacToePlayer::User(author_id))
60        .expect("author is not playing the game");
61
62    let file = match tic_tac_toe_data
63        .renderer
64        .render_board_async(game.board)
65        .await
66    {
67        Ok(file) => CreateAttachment::bytes(file, format!("ttt-{}.png", game.board.encode_u16())),
68        Err(error) => {
69            error!("failed to render Tic-Tac-Toe board: {error}");
70            msg.channel_id
71                .say(
72                    &ctx.http,
73                    format!("Failed to render Tic-Tac-Toe board: {error}"),
74                )
75                .await?;
76            return Ok(());
77        }
78    };
79
80    let content = format!(
81        "{} has conceded to {}.",
82        author_id.mention(),
83        opponent.mention()
84    );
85
86    let message_builder = CreateMessage::new().content(content).add_file(file);
87    msg.channel_id
88        .send_message(&ctx.http, message_builder)
89        .await?;
90
91    Ok(())
92}