Skip to content

Commit 375bb93

Browse files
committed
feat: add vote api
1 parent c38c934 commit 375bb93

24 files changed

Lines changed: 1578 additions & 182 deletions

File tree

api/Cargo.lock

Lines changed: 37 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ twilight = "0.16.0"
1616
twilight-http = "0.16.0"
1717
twilight-model = "0.16.0"
1818
aws-sdk-dynamodb = "1.89.0"
19+
aws-sdk-scheduler = "1.84.0"
1920
aws-config = "1.8.5"
2021
reqwest = { version = "0.12.23", features = ["json", "native-tls-vendored"] }
21-
chrono = "0.4.41"
22+
chrono = { version = "0.4.41", features = ["serde"] }
2223
ed25519-dalek = "2.2.0"
2324
once_cell = "1.21.3"
2425
hex = "0.4.3"
2526
http-body-util = "0.1.3"
2627
regex = "1.11.1"
2728
cached = { version = "0.56.0", features = ["async"] }
29+
uuid = { version = "1.18.0", features = ["v4"] }

api/src/discord.rs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ use tokio::time::sleep;
66
use twilight_http::{Client, Error, Response};
77
use twilight_http::api_error::ApiError;
88
use twilight_http::error::ErrorType;
9+
use twilight_model::channel::Message;
10+
use twilight_model::channel::message::Component;
911
use twilight_model::guild::{Guild, Member, Role};
1012
use twilight_model::id::Id;
11-
use twilight_model::id::marker::{GuildMarker, RoleMarker, UserMarker};
13+
use twilight_model::id::marker::{ChannelMarker, GuildMarker, MessageMarker, RoleMarker, UserMarker};
1214
use twilight_model::user::{CurrentUser, CurrentUserGuild};
1315

1416
pub fn ise<T: std::fmt::Debug>(e: T) -> StatusCode {
@@ -46,8 +48,14 @@ where
4648

4749
pub fn as_http_err(e: Error) -> StatusCode {
4850
match e.kind() {
49-
ErrorType::Response{ status, .. } => StatusCode::from_u16(status.get()).map_err(ise).unwrap(),
50-
_ => StatusCode::INTERNAL_SERVER_ERROR
51+
ErrorType::Response{ status, error, .. } => {
52+
error!("Discord Api Error: {} {:?}", status, error);
53+
StatusCode::from_u16(status.get()).map_err(ise).unwrap()
54+
},
55+
_ => {
56+
error!("Internal Server Error: {:?}", e);
57+
StatusCode::INTERNAL_SERVER_ERROR
58+
}
5159
}
5260
}
5361

@@ -93,3 +101,36 @@ pub async fn get_guild_role(guild_id: Id<GuildMarker>, role_id: Id<RoleMarker>,
93101
retry_on_rl(|| async { client.role(guild_id, role_id).await}).await.map_err(as_http_err)?.model().await.map_err(ise)
94102
}
95103

104+
pub async fn create_message(channel_id: Id<ChannelMarker>,
105+
content: Option<&str>,
106+
components: Option<&[Component]>,
107+
client: &Client) -> Result<Message,StatusCode> {
108+
retry_on_rl(|| async {
109+
let mut msg_builder = client.create_message(channel_id);
110+
if let Some(content) = content {
111+
msg_builder = msg_builder.content(content);
112+
}
113+
if let Some(components) = components {
114+
msg_builder = msg_builder.components(components);
115+
}
116+
msg_builder.await
117+
118+
}).await.map_err(as_http_err)?.model().await.map_err(ise)
119+
}
120+
121+
pub async fn update_message(channel_id: Id<ChannelMarker>,
122+
message_id: Id<MessageMarker>,
123+
content: Option<Option<&str>>,
124+
components: Option<Option<&[Component]>>,
125+
client: &Client) -> Result<Message,StatusCode> {
126+
retry_on_rl(|| async {
127+
let mut msg_builder = client.update_message(channel_id, message_id);
128+
if let Some(content) = content {
129+
msg_builder = msg_builder.content(content);
130+
}
131+
if let Some(components) = components {
132+
msg_builder = msg_builder.components(components);
133+
}
134+
msg_builder.await
135+
}).await.map_err(as_http_err)?.model().await.map_err(ise)
136+
}

api/src/dynamo.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use aws_sdk_dynamodb::types::AttributeValue;
2-
use std::collections::HashMap;
2+
use std::collections::{HashMap, HashSet};
33

44
pub fn as_string_opt(val: Option<&AttributeValue>) -> Option<String> {
55
if let Some(v) = val {
@@ -95,3 +95,15 @@ pub fn as_map(val: Option<&AttributeValue>) -> Option<&HashMap<String, Attribute
9595
}
9696
None
9797
}
98+
99+
pub fn as_u64_set(val: Option<&AttributeValue>) -> HashSet<u64> {
100+
if let Some(val) = val {
101+
if let Ok(val) = val.as_l() {
102+
return val
103+
.iter()
104+
.map(|v| as_u64(Some(v), 0))
105+
.collect();
106+
}
107+
}
108+
HashSet::new()
109+
}

api/src/guilds/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::{HashSet};
22
use crate::AppState;
3-
use crate::guilds::models::{Guild, VerifyRole};
3+
use crate::guilds::models::Guild;
44
use axum::extract::State;
55
use axum::{Extension, Json, Router, extract::Path, routing::get};
66
use http::StatusCode;
@@ -16,18 +16,21 @@ use twilight_model::id::marker::GuildMarker;
1616
use twilight_model::user::{CurrentUser, CurrentUserGuild};
1717
use crate::discord::{get_guild, get_guild_member};
1818
use crate::guilds::tasks::{add_role_to_guild, remove_role_from_guild};
19+
use crate::guilds::verify::models::VerifyRole;
1920
use crate::utils::{admin_guilds, is_client_admin_guild};
2021

2122
pub mod models;
2223
pub mod verify;
2324
pub(crate) mod utils;
2425
pub mod tasks;
26+
pub(crate) mod votes;
2527

2628
pub fn router() -> Router<AppState> {
2729
Router::new()
2830
.route("/", get(get_guilds).post(post_guilds))
2931
.route("/{guild_id}", get(get_guilds_id).put(put_guilds_id).post(post_guilds_id))
30-
.nest("/{guild_id}/verify", verify::router())
32+
.nest("/{guild_id}/verify", verify::controllers::router())
33+
.nest("/{guild_id}/votes", votes::controllers::router())
3134
.layer(CorsLayer::permissive())
3235
}
3336

0 commit comments

Comments
 (0)