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
82
83
84
use anyhow::{anyhow, Result};
use clap::Parser;
use serde_json::Value;

use super::types::ChannelType;
use crate::commands::channels::utils::create_channel;
use crate::state::State;
use crate::utils::validate_json_non_null;

#[derive(Debug, Parser, Default, PartialEq, Eq)]
#[clap(about = "Create a new Channel")]
#[group(skip)]
pub struct Options {
    #[clap(short = 'i', long = "id", help = "Custom ID for the channel")]
    custom_id: Option<String>,

    #[clap(short = 't', long = "type", help = "Type of the channel")]
    channel_type: Option<ChannelType>,

    #[clap(short, long, help = "Initial state of the channel", value_parser = validate_json_non_null )]
    state: Option<Value>,
}

pub async fn handle(options: Options, state: State) -> Result<()> {
    let project_id = state.ctx.current_project_error()?.id;

    let (type_, id, init_state) = if Options::default() == options {
        let type_ = dialoguer::Select::new()
            .with_prompt("Select a channel type")
            .items(&ChannelType::variants())
            .default(0)
            .interact()?;

        let type_ = ChannelType::variants()[type_].clone();

        let id = if dialoguer::Confirm::new()
            .with_prompt("Do you want to specify a custom Channel ID?")
            .default(false)
            .interact()?
        {
            Some(
                dialoguer::Input::<String>::new()
                    .with_prompt("Enter a custom ID")
                    .interact()?,
            )
        } else {
            None
        };

        let state = dialoguer::Input::new()
            .with_prompt("Enter the initial state of the channel")
            .default("{}".to_string())
            .validate_with(|s: &String| -> Result<(), String> {
                validate_json_non_null(s)
                    .map(|_| ())
                    .map_err(|e| e.to_string())
            })
            .interact()?;

        let state = serde_json::from_str(&state)?;

        (type_, id, state)
    } else {
        (
            options.channel_type.clone().ok_or_else(|| {
                anyhow!(
                    "The argument '--type <CHANNELTYPE>' requires a value but none was supplied"
                )
            })?,
            options.custom_id.clone(),
            options
                .state
                .clone()
                .unwrap_or_else(|| Value::Object(serde_json::Map::new())),
        )
    };

    let channel =
        create_channel(&state.http, &project_id, &type_, &init_state, id.as_deref()).await?;

    log::info!("Created Channel `{}`", channel.id);

    Ok(())
}