aboutsummaryrefslogtreecommitdiff
path: root/backend/src/routes/bots.rs
blob: 413c14548557d09f8db34a30a37732f209e88fb3 (plain)
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
85
86
87
88
89
90
91
92
93
94
95
96
use rand::Rng;
use rocket::data::ToByteUnit;
use rocket::fs::TempFile;
use rocket::Data;
use rocket::{response::status, serde::json::Json};
use serde::{Deserialize, Serialize};
use std::io::Cursor;
use std::path::Path;

use crate::DbConn;

use crate::db::bots::{self, CodeBundle};
use crate::db::users::User;
use bots::Bot;

#[derive(Serialize, Deserialize, Debug)]
pub struct BotParams {
    name: String,
}

// TODO: handle errors
#[post("/bots", data = "<params>")]
pub async fn create_bot(
    db_conn: DbConn,
    user: User,
    params: Json<BotParams>,
) -> status::Created<Json<Bot>> {
    db_conn
        .run(move |conn| {
            let bot_params = bots::NewBot {
                owner_id: user.id,
                name: &params.name,
            };
            let bot = bots::create_bot(&bot_params, conn).unwrap();
            let bot_url = uri!(get_bot(bot.id)).to_string();
            status::Created::new(bot_url).body(Json(bot))
        })
        .await
}

// TODO: handle errors
#[get("/bots/<bot_id>")]
pub async fn get_bot(db_conn: DbConn, bot_id: i32) -> Json<Bot> {
    db_conn
        .run(move |conn| {
            let bot = bots::find_bot(bot_id, conn).unwrap();
            Json(bot)
        })
        .await
}

// TODO: proper error handling
#[post("/bots/<bot_id>/upload", data = "<data>")]
pub async fn upload_bot_code(
    db_conn: DbConn,
    user: User,
    bot_id: i32,
    data: Data<'_>,
) -> status::Created<Json<CodeBundle>> {
    // TODO: put in config somewhere
    let data_path = "./data/bots";

    let bot = db_conn
        .run(move |conn| bots::find_bot(bot_id, conn))
        .await
        .expect("Bot not found");

    assert_eq!(user.id, bot.owner_id);

    // generate a random filename
    let token: [u8; 16] = rand::thread_rng().gen();
    let name = base64::encode(&token);

    let path = Path::new(data_path).join(name);
    let capped_buf = data.open(10usize.megabytes()).into_bytes().await.unwrap();
    assert!(capped_buf.is_complete());
    let buf = capped_buf.into_inner();

    zip::ZipArchive::new(Cursor::new(buf))
        .unwrap()
        .extract(&path)
        .unwrap();

    let code_bundle = db_conn
        .run(move |conn| {
            let bundle = bots::NewCodeBundle {
                bot_id: bot.id,
                path: path.to_str().unwrap(),
            };
            bots::create_code_bundle(&bundle, conn).expect("Failed to create code bundle")
        })
        .await;

    // TODO: proper location
    status::Created::new("").body(Json(code_bundle))
}