Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ GUILD_ID = "Server ID"

# Config
# Channel Ids
CHANNEL_DAILY = "Channel id for Daily Challenges"
CHANNEL_DAILY = "1219703076944871616"
CHANNEL_SUGGEST = "824695624665923594"
CHANNEL_SHOWCASE = "Channel id for Showcase"
TEMPORAL_WAIT = ""
TEMPORAL_CATEGORY = ""
TEMPORAL_LOGS = ""
Expand All @@ -17,4 +17,4 @@ BOT_API_ADDR = 0.0.0.0
BOT_APIKEY = "PermitidoHacerCosas123"

# AI features (remove to disable)
GEMINI_KEY = " "
GEMINI_KEY = " "
5 changes: 3 additions & 2 deletions doc/VARIABLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Para ejecutar el bot, crea un archivo `.env` con las siguientes variables:
- `DISCORD_TOKEN`: Obtenlo desde el [Token del bot](https://discord.com/developers/applications)
- `GUILD_ID`: Activa el Modo Desarrollador en Discord, haz clic derecho en tu servidor y selecciona 'Copiar ID'
- `BOT_APIKEY`: Autorizacion para canal cifrado entre el bot y el servidor (Puede contener cualquier texto)
- `CHANNEL_DAILY` & `CHANNEL_SUGGEST`: Haz clic derecho en el canal de Discord y selecciona 'Copiar ID'
- `CHANNEL_DAILY`, `CHANNEL_SUGGEST` & `CHANNEL_SHOWCASE`: Haz clic derecho en el canal de Discord y selecciona 'Copiar ID'
- `LAVALINK_PASSWORD`: Contraseña Lavalink

**Opcionales**
Expand All @@ -24,4 +24,5 @@ GUILD_ID = "Server ID"
BOT_APIKEY = "API key for secure communication"
CHANNEL_DAILY = "Channel ID for daily challenges"
CHANNEL_SUGGEST = "Channel ID for suggestions"
```
CHANNEL_SHOWCASE = "Channel ID for showcase forum"
```
1 change: 1 addition & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub fn build_router(secrets: &CangrebotSecrets, ctx: Arc<Http>) -> Router {
axum::routing::post(routes::daily_challenge),
)
.route("/send_message", axum::routing::post(routes::send_message))
.route("/showcase", axum::routing::post(routes::showcase))
.layer(axum::middleware::from_fn_with_state(
secrets.clone(),
auth::middleware,
Expand Down
4 changes: 4 additions & 0 deletions src/api/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ mod daily_challenge;
use axum::http::StatusCode;
use axum::response::IntoResponse;
pub use daily_challenge::daily_challenge;

mod send_message;
pub use send_message::send_message;

mod showcase;
pub use showcase::showcase;

pub mod send_stats;

pub async fn healthcheck() -> impl IntoResponse {
Expand Down
68 changes: 68 additions & 0 deletions src/api/routes/showcase.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::Json;
use serde::{Deserialize, Serialize};
use tracing::info;

use crate::api::RouteState;
use crate::serenity::builder::{CreateForumPost, CreateMessage};
use crate::serenity::model::prelude::ChannelId;

#[derive(Deserialize, Serialize)]
pub struct ShowcaseRequest {
name: String,
desc: String,
#[serde(default)]
tags: Vec<String>,
url: String,
}

pub async fn showcase(
State((secrets, ctx)): State<RouteState>,
Json(ShowcaseRequest {
name,
desc,
tags,
url,
}): Json<ShowcaseRequest>,
) -> impl IntoResponse {
info!("Running showcase creation from API");

let msg_channel = ChannelId::new(secrets.channel_showcase);

let Ok(channel) = msg_channel.to_channel(&ctx).await else {
return (
StatusCode::INTERNAL_SERVER_ERROR,
"Cannot convert to channel".to_string(),
);
};

let Some(forum) = channel.guild() else {
return (StatusCode::NOT_FOUND, "Guild channel not found".to_string());
};

let mut forum_post = CreateForumPost::new(
name,
CreateMessage::new().content(format!("{desc}\n\n{url}")),
);

for tag_name in tags {
let Some(tag) = forum.available_tags.iter().find(|tag| tag.name == tag_name) else {
return (StatusCode::NOT_FOUND, format!("Tag '{tag_name}' not found"));
};

forum_post = forum_post.add_applied_tag(tag.id);
}

match msg_channel.create_forum_post(&ctx, forum_post).await {
Ok(_) => (StatusCode::OK, "Ok".to_string()),
Err(err) => {
tracing::error!("Cannot create showcase forum post: {err:?}");
(
StatusCode::INTERNAL_SERVER_ERROR,
"Cannot create showcase forum post".to_string(),
)
}
}
}
10 changes: 4 additions & 6 deletions src/bot/commands/tts/tts_regex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,18 @@ pub const MULTI_LINE_DOUBLE_CODE_BLOCK_REGEX: &str = r"``([^`\n]+)``";
pub const MULTI_LINE_TRIPLE_CODE_BLOCK_REGEX: &str = r"```([\s\S]*?)```";
pub const CORRECTION_REGEX: &str = r"^\w+\*$";


#[cfg(test)]
mod tests {
use super::*;
use regex::Regex;

fn aux_match(regex: &str,haystack: &str) -> bool {
fn aux_match(regex: &str, haystack: &str) -> bool {
match Regex::new(regex) {
Ok(re) => re.is_match(haystack),
Err(_) => false,
}
}


#[test]
fn regex_definition() {
assert!(Regex::new(LINK_REGEX).is_ok());
Expand Down Expand Up @@ -52,13 +50,13 @@ mod tests {

#[test]
fn links_not_matchs() {
let cases = [
let cases = [
"ftp://b32.i2p/",
"https://grüße.tld",
"https://example.موقع"
"https://example.موقع",
];
for case in cases {
assert!(! aux_match(LINK_REGEX, case));
assert!(!aux_match(LINK_REGEX, case));
}
}
}
6 changes: 6 additions & 0 deletions src/secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub struct CangrebotSecrets {
pub channel_daily: u64,
/// Channel id for Suggest
pub channel_suggest: u64,
/// Channel id for Showcase
pub channel_showcase: u64,
/// Waiting channel id for temporal voice chats
pub temporal_wait: u64,
/// Category id for temporal voice chats
Expand Down Expand Up @@ -41,6 +43,10 @@ impl CangrebotSecrets {
.expect("'CHANNEL_SUGGEST' was not found")
.parse()
.expect("Cannot parse 'CHANNEL_SUGGEST'"),
channel_showcase: secrets("CHANNEL_SHOWCASE")
.expect("'CHANNEL_SHOWCASE' was not found")
.parse()
.expect("Cannot parse 'CHANNEL_SHOWCASE'"),
temporal_wait: secrets("TEMPORAL_WAIT")
.expect("'TEMPORAL_WAIT' was not found")
.parse()
Expand Down
Loading