forked from siketyan/stateless-discord-bot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontext.rs
55 lines (45 loc) · 1.7 KB
/
context.rs
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
use serde::Deserialize;
use std::collections::HashMap;
use crate::discord::interaction::Interaction;
use crate::discord::verification::verify_signature;
use crate::error::Error;
use crate::http::{HttpError, HttpRequest, HttpResponse};
#[derive(Deserialize)]
pub(crate) struct Context {
pub(crate) env: HashMap<String, String>,
pub(crate) request: HttpRequest,
}
impl Context {
fn env(&self, key: &str) -> Result<&String, Error> {
self.env
.get(key)
.ok_or_else(|| Error::EnvironmentVariableNotFound(key.to_string()))
}
fn perform_verification(&self) -> Result<(), Error> {
let public_key = self.env("PUBLIC_KEY")?;
let signature = self.request.header("x-signature-ed25519")?;
let timestamp = self.request.header("x-signature-timestamp")?;
verify_signature(public_key, signature, timestamp, &self.request.body)
.map_err(Error::VerificationFailed)
}
fn handle_payload(&self) -> Result<String, Error> {
let payload = &self.request.body;
let interaction =
serde_json::from_str::<Interaction>(payload).map_err(Error::JsonFailed)?;
let response = interaction.perform()?;
serde_json::to_string(&response).map_err(Error::JsonFailed)
}
pub(crate) fn handle_http_request(&self) -> HttpResponse {
let result = self
.perform_verification()
.and_then(|_| self.handle_payload())
.map_err(HttpError::from);
match result {
Ok(body) => HttpResponse { status: 200, body },
Err(error) => HttpResponse {
body: error.to_string(),
status: error.status as u16,
},
}
}
}