Initialize Twilight project, set up basic framework, initialize DB module

This commit is contained in:
2025-08-07 04:32:34 -03:00
parent 00d61545eb
commit 24d2344f37
29 changed files with 4095 additions and 0 deletions
+252
View File
@@ -0,0 +1,252 @@
use std::{
future::{Future, IntoFuture},
pin::Pin,
sync::Arc,
};
use twilight_http::{Error, Response, response::marker::EmptyBody};
use twilight_model::{
channel::{
Message,
message::{Component as TwilightComponent, Embed},
},
http::interaction::{InteractionResponse, InteractionResponseType},
id::{
Id,
marker::{ChannelMarker, InteractionMarker},
},
};
use twilight_util::builder::InteractionResponseDataBuilder;
use crate::framework::{
handlers::Handlers,
interactions::components::{ActionRow, Component},
};
pub struct MessageSender {
channel_id: Id<ChannelMarker>,
handlers: Arc<Handlers>,
content: Option<String>,
embeds: Vec<Embed>,
// Row index, component
components: Vec<(u8, Arc<dyn Component>)>,
}
impl MessageSender {
pub fn new(channel_id: Id<ChannelMarker>, handlers: Arc<Handlers>) -> Self {
Self {
channel_id,
handlers,
content: None,
components: vec![],
embeds: vec![],
}
}
pub fn content(mut self, content: impl ToString) -> Self {
self.content = Some(content.to_string());
self
}
pub fn embed(mut self, embed: Embed) -> Self {
self.embeds.push(embed);
self
}
pub fn component(mut self, component: impl Component + 'static, row: u8) -> Self {
self.components.push((row, Arc::new(component)));
self
}
pub async fn send(self) -> Result<Response<Message>, Error> {
let mut builder = self.handlers.http.create_message(self.channel_id);
if let Some(content) = &self.content {
builder = builder.content(content);
}
let mut current_row = ActionRow::new(&[]);
let mut current_index = 0;
let mut rows: Vec<TwilightComponent> = vec![];
let mut custom_ids: Vec<String> = vec![];
for (index, component) in self.components {
if index != current_index {
if current_row.len() > 0 {
rows.push(current_row.build());
current_row = ActionRow::new(&[]);
}
current_index += 1;
}
let custom_id = component.custom_id();
if let Some(custom_id) = &custom_id {
custom_ids.push(custom_id.clone());
self.handlers
.registry
.register(custom_id, component.clone());
}
current_row.add(custom_id.clone(), component.clone());
}
if current_row.len() > 0 {
rows.push(current_row.build());
}
builder = builder.components(&rows);
builder = builder.embeds(&self.embeds);
let result = builder.await;
if result.is_err() {
for custom_id in custom_ids {
self.handlers.registry.unregister(custom_id);
}
}
result
}
}
impl IntoFuture for MessageSender {
type Output = Result<Response<Message>, Error>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.send())
}
}
pub struct OriginalMessageUpdater {
interaction_id: Id<InteractionMarker>,
interaction_token: String,
handlers: Arc<Handlers>,
content: Option<String>,
embeds: Vec<Embed>,
// Row index, component
components: Vec<(u8, Arc<dyn Component>)>,
}
impl OriginalMessageUpdater {
pub fn new(
interaction_id: Id<InteractionMarker>,
interaction_token: String,
handlers: Arc<Handlers>,
) -> Self {
Self {
interaction_id,
interaction_token,
handlers,
content: None,
components: vec![],
embeds: vec![],
}
}
pub fn content(mut self, content: impl ToString) -> Self {
self.content = Some(content.to_string());
self
}
pub fn embed(mut self, embed: Embed) -> Self {
self.embeds.push(embed);
self
}
pub fn component(mut self, component: impl Component + 'static, row: u8) -> Self {
self.components.push((row, Arc::new(component)));
self
}
pub async fn send(self) -> Result<Response<EmptyBody>, Error> {
let mut builder = InteractionResponseDataBuilder::new();
if let Some(content) = &self.content {
builder = builder.content(content);
}
let mut current_row = ActionRow::new(&[]);
let mut current_index = 0;
let mut rows: Vec<TwilightComponent> = vec![];
let mut custom_ids: Vec<String> = vec![];
for (index, component) in self.components {
if index != current_index {
if current_row.len() > 0 {
rows.push(current_row.build());
current_row = ActionRow::new(&[]);
}
current_index += 1;
}
let custom_id = component.custom_id();
if let Some(custom_id) = &custom_id {
custom_ids.push(custom_id.clone());
self.handlers
.registry
.register(custom_id, component.clone());
}
current_row.add(custom_id.clone(), component.clone());
}
if current_row.len() > 0 {
rows.push(current_row.build());
}
builder = builder.components(rows);
builder = builder.embeds(self.embeds);
let result = self
.handlers
.http
.interaction(self.handlers.app.id)
.create_response(
self.interaction_id,
&self.interaction_token,
&InteractionResponse {
data: Some(builder.build()),
kind: InteractionResponseType::UpdateMessage,
},
)
.await;
if result.is_err() {
for custom_id in custom_ids {
self.handlers.registry.unregister(custom_id);
}
}
result
}
}
impl IntoFuture for OriginalMessageUpdater {
type Output = Result<Response<EmptyBody>, Error>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.send())
}
}