summaryrefslogtreecommitdiff
path: root/angelsharkd/src/routes/extensions/simple_busy/mod.rs
blob: 23f05fd58b4172c9586c9ba5078f69ccfd9041bf (plain) (blame)
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
97
98
use crate::routes::dtos::{Error, Response};
use libangelshark::{AcmRunner, Message, ParallelIterator};
use log::error;
use serde::Deserialize;
use warp::{
    body::{content_length_limit, json},
    hyper::StatusCode,
    path, post, reply, Filter, Rejection, Reply,
};

const SIXTEEN_K: u64 = 1024 * 16;

pub fn busy_filter(
    runner: AcmRunner,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
    post()
        .and(path!("service" / "busyout" / ..))
        .and(content_length_limit(SIXTEEN_K))
        .and(json())
        .map(move |entries| queue_and_run(entries, "busyout", runner.to_owned()))
}

pub fn release_filter(
    runner: AcmRunner,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
    post()
        .and(path!("service" / "release" / ..))
        .and(content_length_limit(SIXTEEN_K))
        .and(json())
        .map(move |entries| queue_and_run(entries, "release", runner.to_owned()))
}

pub fn toggle_filter(
    runner: AcmRunner,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
    post()
        .and(path!("service" / "toggle" / ..))
        .and(content_length_limit(SIXTEEN_K))
        .and(json())
        .map(move |entries| queue_and_run(entries, "toggle", runner.to_owned()))
}

fn queue_and_run(entries: Entries, command: &str, mut runner: AcmRunner) -> impl Reply {
    for entry in entries.into_iter() {
        if command == "toggle" {
            runner.queue_input(
                &entry.acm,
                &Message::new(&format!("busyout station {}", entry.ext)),
            );
            runner.queue_input(
                &entry.acm,
                &Message::new(&format!("release station {}", entry.ext)),
            );
        } else {
            runner.queue_input(
                &entry.acm,
                &Message::new(&format!("{} station {}", command, entry.ext)),
            );
        }
    }

    // generate output on runner
    let output: Result<Vec<Vec<_>>, _> = runner
        .run()
        .map(|(name, output)| -> Result<Vec<Response>, anyhow::Error> {
            Ok(output?
                .into_iter()
                .filter_map(move |msg| {
                    (msg.command != "logoff").then(|| Response::from((name.to_owned(), msg)))
                })
                .collect())
        })
        .collect();

    // handle errors and package output as json
    match output {
        Err(e) => {
            error!("busyout-release extension: {}", e);
            reply::with_status(
                reply::json(&Error {
                    reason: e.to_string(),
                }),
                StatusCode::INTERNAL_SERVER_ERROR,
            )
        }
        Ok(r) => reply::with_status(
            reply::json(&r.into_iter().flatten().collect::<Vec<_>>()),
            StatusCode::OK,
        ),
    }
}

type Entries = Vec<Entry>;
#[derive(Debug, Deserialize)]
struct Entry {
    acm: String,
    ext: String,
}