Skip to content

Commit 853bcc2

Browse files
committed
feat: refactor discord webhooks
1 parent b4804e7 commit 853bcc2

File tree

9 files changed

+249
-96
lines changed

9 files changed

+249
-96
lines changed

src/database/repository/developers.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use crate::types::api::ApiError;
2+
use crate::types::models::developer::FetchedDeveloper;
3+
use sqlx::PgConnection;
4+
5+
pub async fn get_owner_for_mod(
6+
mod_id: &str,
7+
conn: &mut PgConnection,
8+
) -> Result<FetchedDeveloper, ApiError> {
9+
Ok(sqlx::query_as!(
10+
FetchedDeveloper,
11+
"SELECT
12+
dev.id,
13+
dev.username,
14+
dev.display_name,
15+
dev.verified,
16+
dev.admin
17+
FROM developers dev
18+
INNER JOIN mods_developers md ON md.developer_id = dev.id
19+
WHERE md.mod_id = $1
20+
AND md.is_owner = true",
21+
mod_id
22+
)
23+
.fetch_one(&mut *conn)
24+
.await
25+
.map_err(|e| match e {
26+
sqlx::Error::RowNotFound => {
27+
log::error!("Mod {} doesn't have an owner!", mod_id);
28+
ApiError::InternalError
29+
}
30+
_ => {
31+
log::error!("Failed to fetch owner for mod {}", mod_id);
32+
ApiError::InternalError
33+
}
34+
})?)
35+
}

src/database/repository/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod mod_tags;
2-
pub mod mods;
2+
pub mod mods;
3+
pub mod developers;

src/endpoints/mod_versions.rs

+47-37
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ use actix_web::{dev::ConnectionInfo, get, post, put, web, HttpResponse, Responde
44
use serde::Deserialize;
55
use sqlx::{types::ipnetwork::IpNetwork, Acquire};
66

7+
use crate::database::repository::developers;
8+
use crate::events::mod_created::{
9+
NewModAcceptedEvent, NewModVersionAcceptedEvent, NewModVersionVerification,
10+
};
11+
use crate::webhook::discord::DiscordWebhook;
712
use crate::{
813
extractors::auth::Auth,
914
types::{
@@ -18,7 +23,6 @@ use crate::{
1823
mod_version_status::ModVersionStatusEnum,
1924
},
2025
},
21-
webhook::send_webhook,
2226
AppData,
2327
};
2428

@@ -300,30 +304,27 @@ pub async fn create_version(
300304
.or(Err(ApiError::TransactionError))?;
301305
return Err(e);
302306
}
303-
304-
if dev.verified {
305-
send_webhook(
306-
json.id.clone(),
307-
json.name.clone(),
308-
json.version.clone(),
309-
true,
310-
Developer {
311-
id: dev.id,
312-
username: dev.username.clone(),
313-
display_name: dev.display_name.clone(),
314-
is_owner: true,
315-
},
316-
dev.clone(),
317-
data.webhook_url.clone(),
318-
data.app_url.clone(),
319-
)
320-
.await;
321-
}
322-
323307
transaction
324308
.commit()
325309
.await
326310
.or(Err(ApiError::TransactionError))?;
311+
312+
let approved_count = ModVersion::get_accepted_count(&json.id, &mut pool).await?;
313+
314+
if dev.verified && approved_count != 0 {
315+
let owner = developers::get_owner_for_mod(&json.id, &mut *pool).await?;
316+
317+
NewModVersionAcceptedEvent {
318+
id: json.id.clone(),
319+
name: json.name.clone(),
320+
version: json.version.clone(),
321+
owner,
322+
verified: NewModVersionVerification::Admin(dev),
323+
base_url: data.app_url.clone(),
324+
}
325+
.to_discord_webhook()
326+
.send(&data.webhook_url);
327+
}
327328
Ok(HttpResponse::NoContent())
328329
}
329330

@@ -391,22 +392,31 @@ pub async fn update_version(
391392
if payload.status == ModVersionStatusEnum::Accepted {
392393
let is_update = approved_count > 0;
393394

394-
let owner = Developer::fetch_for_mod(version.mod_id.as_str(), &mut pool)
395-
.await?
396-
.into_iter()
397-
.find(|dev| dev.is_owner);
398-
399-
send_webhook(
400-
version.mod_id,
401-
version.name.clone(),
402-
version.version.clone(),
403-
is_update,
404-
owner.as_ref().unwrap().clone(),
405-
dev.clone(),
406-
data.webhook_url.clone(),
407-
data.app_url.clone(),
408-
)
409-
.await;
395+
let owner = developers::get_owner_for_mod(&version.mod_id, &mut pool).await?;
396+
397+
if !is_update {
398+
NewModAcceptedEvent {
399+
id: version.mod_id,
400+
name: version.name.clone(),
401+
version: version.version.clone(),
402+
owner,
403+
verified_by: dev,
404+
base_url: data.app_url.clone(),
405+
}
406+
.to_discord_webhook()
407+
.send(&data.webhook_url);
408+
} else {
409+
NewModVersionAcceptedEvent {
410+
id: version.mod_id,
411+
name: version.name.clone(),
412+
version: version.version.clone(),
413+
owner,
414+
verified: NewModVersionVerification::Admin(dev),
415+
base_url: data.app_url.clone(),
416+
}
417+
.to_discord_webhook()
418+
.send(&data.webhook_url);
419+
}
410420
}
411421

412422
Ok(HttpResponse::NoContent())

src/events/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod mod_created;

src/events/mod_created.rs

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use crate::types::models::developer::FetchedDeveloper;
2+
use crate::webhook::discord::{DiscordMessage, DiscordWebhook};
3+
4+
pub struct NewModAcceptedEvent {
5+
pub id: String,
6+
pub name: String,
7+
pub version: String,
8+
pub owner: FetchedDeveloper,
9+
pub verified_by: FetchedDeveloper,
10+
pub base_url: String,
11+
}
12+
13+
pub enum NewModVersionVerification {
14+
VerifiedDev,
15+
Admin(FetchedDeveloper),
16+
}
17+
18+
pub struct NewModVersionAcceptedEvent {
19+
pub id: String,
20+
pub name: String,
21+
pub version: String,
22+
pub owner: FetchedDeveloper,
23+
pub verified: NewModVersionVerification,
24+
pub base_url: String,
25+
}
26+
27+
impl DiscordWebhook for NewModAcceptedEvent {
28+
fn to_discord_webhook(&self) -> DiscordMessage {
29+
DiscordMessage::new().embed(
30+
&format!("New mod accepted: {} {}", self.name, self.version),
31+
Some(&format!("https://geode-sdk.org/mods/{}\n\nOwned by: [{}](https://github.com/{})\nAccepted by: [{}](https://github.com/{}))",
32+
self.id, self.owner.display_name, self.owner.username, self.verified_by.display_name, self.verified_by.username)),
33+
Some(&format!("{}/v1/mods/{}/logo", self.base_url, self.id)),
34+
)
35+
}
36+
}
37+
38+
impl DiscordWebhook for NewModVersionAcceptedEvent {
39+
fn to_discord_webhook(&self) -> DiscordMessage {
40+
let accepted_msg = match &self.verified {
41+
NewModVersionVerification::VerifiedDev => String::from("Developer is verified"),
42+
NewModVersionVerification::Admin(admin) => format!(
43+
"Verified by [{}](https://github.com/{})",
44+
admin.display_name, admin.username
45+
),
46+
};
47+
48+
DiscordMessage::new().embed(
49+
&format!("Mod update accepted: {} {}", self.name, self.version),
50+
Some(&format!(
51+
"https://geode-sdk.org/mods/{}\n\nOwned by: [{}](https://github.com/{})\n{})",
52+
self.id, self.owner.display_name, self.owner.username, accepted_msg
53+
)),
54+
Some(&format!("{}/v1/mods/{}/logo", self.base_url, self.id)),
55+
)
56+
}
57+
}

src/main.rs

+2-16
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
use actix_cors::Cors;
22
use actix_web::{
3-
get,
43
middleware::Logger,
54
web::{self, QueryConfig},
6-
App, HttpServer, Responder,
5+
App, HttpServer
76
};
8-
use clap::Parser;
97

108
use crate::types::api;
11-
use crate::types::api::ApiError;
129

1310
mod auth;
1411
mod cli;
1512
mod database;
1613
mod endpoints;
14+
mod events;
1715
mod extractors;
1816
mod jobs;
1917
mod types;
@@ -30,18 +28,6 @@ pub struct AppData {
3028
max_download_mb: u32,
3129
}
3230

33-
#[derive(Debug, Parser)]
34-
struct Args {
35-
/// Name of the script to run
36-
#[arg(short, long)]
37-
script: Option<String>,
38-
}
39-
40-
#[get("/")]
41-
async fn health() -> Result<impl Responder, ApiError> {
42-
Ok(web::Json("The Geode Index is running"))
43-
}
44-
4531
#[tokio::main]
4632
async fn main() -> anyhow::Result<()> {
4733
log4rs::init_file("config/log4rs.yaml", Default::default())

src/webhook.rs

-42
This file was deleted.

0 commit comments

Comments
 (0)