push 1 checkpoiint *holy hell i sure hope it works*
This commit is contained in:
@@ -6,6 +6,23 @@ CREATE KEYSPACE IF NOT EXISTS payphone
|
|||||||
'enabled': false
|
'enabled': false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CREATE TYPE IF NOT EXISTS payphone.message_metadata (
|
||||||
|
call_id BIGINT,
|
||||||
|
author_id BIGINT,
|
||||||
|
author_name TEXT,
|
||||||
|
author_avatar_url TEXT,
|
||||||
|
author_mask ASCII,
|
||||||
|
content TEXT,
|
||||||
|
attachments LIST<TEXT>,
|
||||||
|
sticker BIGINT,
|
||||||
|
propagation_message_id BIGINT,
|
||||||
|
propagation_channel_id BIGINT,
|
||||||
|
replying_to_id BIGINT,
|
||||||
|
is_deleted BOOLEAN,
|
||||||
|
is_edited BOOLEAN,
|
||||||
|
is_censored BOOLEAN
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS payphone.users (
|
CREATE TABLE IF NOT EXISTS payphone.users (
|
||||||
user_id BIGINT PRIMARY KEY,
|
user_id BIGINT PRIMARY KEY,
|
||||||
|
|
||||||
@@ -64,25 +81,7 @@ CREATE TABLE IF NOT EXISTS payphone.participants (
|
|||||||
CREATE TABLE IF NOT EXISTS payphone.messages (
|
CREATE TABLE IF NOT EXISTS payphone.messages (
|
||||||
call_id BIGINT,
|
call_id BIGINT,
|
||||||
message_id BIGINT,
|
message_id BIGINT,
|
||||||
author_id BIGINT,
|
message_metadata FROZEN<payphone.message_metadata>,
|
||||||
|
|
||||||
author_name TEXT,
|
|
||||||
author_avatar_url TEXT,
|
|
||||||
author_mask ASCII,
|
|
||||||
|
|
||||||
content TEXT,
|
|
||||||
attachments LIST<TEXT>,
|
|
||||||
sticker BIGINT,
|
|
||||||
|
|
||||||
propagation_message_id BIGINT,
|
|
||||||
propagation_channel_id BIGINT,
|
|
||||||
|
|
||||||
replying_to_id BIGINT,
|
|
||||||
|
|
||||||
is_deleted BOOLEAN,
|
|
||||||
is_edited BOOLEAN,
|
|
||||||
is_censored BOOLEAN,
|
|
||||||
|
|
||||||
PRIMARY KEY (call_id, message_id)
|
PRIMARY KEY (call_id, message_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -95,61 +94,28 @@ CREATE TABLE IF NOT EXISTS payphone.servers (
|
|||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS payphone.reports (
|
CREATE TABLE IF NOT EXISTS payphone.reports (
|
||||||
report_id BIGINT,
|
report_id BIGINT,
|
||||||
|
message FROZEN<payphone.message_metadata>,
|
||||||
message_author_id BIGINT,
|
|
||||||
message_author_name TEXT,
|
|
||||||
message_author_avatar_url TEXT,
|
|
||||||
message_author_mask ASCII,
|
|
||||||
|
|
||||||
message_id BIGINT,
|
|
||||||
message_content TEXT,
|
|
||||||
message_attachments LIST<TEXT>,
|
|
||||||
message_sticker BIGINT,
|
|
||||||
|
|
||||||
message_replying_to_id BIGINT,
|
|
||||||
message_replying_to_content TEXT,
|
|
||||||
message_replying_to_attachments LIST<TEXT>,
|
|
||||||
message_replying_to_sticker BIGINT,
|
|
||||||
|
|
||||||
created_at TIMESTAMP,
|
created_at TIMESTAMP,
|
||||||
reviewed_at TIMESTAMP,
|
reviewed_at TIMESTAMP,
|
||||||
|
|
||||||
created_by_ids SET<BIGINT>,
|
created_by_ids SET<BIGINT>,
|
||||||
|
|
||||||
reviewed_by_id BIGINT,
|
reviewed_by_id BIGINT,
|
||||||
resolution ASCII,
|
resolution ASCII,
|
||||||
|
PRIMARY KEY (report_id)
|
||||||
PRIMARY KEY (message_author_id, report_id)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS payphone.user_incidents (
|
CREATE TABLE IF NOT EXISTS payphone.user_incidents (
|
||||||
user_id BIGINT,
|
user_id BIGINT,
|
||||||
incident_id BIGINT,
|
incident_id BIGINT,
|
||||||
|
|
||||||
-- ban, warning
|
-- ban, warning
|
||||||
type ASCII,
|
type ASCII,
|
||||||
|
|
||||||
call_id BIGINT,
|
call_id BIGINT,
|
||||||
report_id BIGINT,
|
report_id BIGINT,
|
||||||
|
message FROZEN<payphone.message_metadata>,
|
||||||
message_id BIGINT,
|
|
||||||
message_content TEXT,
|
|
||||||
message_attachments LIST<TEXT>,
|
|
||||||
message_sticker BIGINT,
|
|
||||||
|
|
||||||
message_replying_to_id BIGINT,
|
|
||||||
message_replying_to_content TEXT,
|
|
||||||
message_replying_to_attachments LIST<TEXT>,
|
|
||||||
message_replying_to_sticker BIGINT,
|
|
||||||
|
|
||||||
reason TEXT,
|
reason TEXT,
|
||||||
|
|
||||||
created_by_id BIGINT,
|
created_by_id BIGINT,
|
||||||
|
|
||||||
created_at TIMESTAMP,
|
created_at TIMESTAMP,
|
||||||
expires_at TIMESTAMP,
|
expires_at TIMESTAMP,
|
||||||
duration ASCII,
|
duration ASCII,
|
||||||
|
|
||||||
PRIMARY KEY (user_id)
|
PRIMARY KEY (user_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
use scylla::{SerializeValue, DeserializeValue};
|
||||||
|
#[derive(Debug, Clone, SerializeValue, DeserializeValue)]
|
||||||
|
pub struct MessageMetadata {
|
||||||
|
pub call_id: i64,
|
||||||
|
pub author_id: i64,
|
||||||
|
pub author_name: Option<String>,
|
||||||
|
pub author_avatar_url: Option<String>,
|
||||||
|
pub author_mask: Option<String>,
|
||||||
|
pub content: Option<String>,
|
||||||
|
pub attachments: Option<Vec<String>>,
|
||||||
|
pub sticker: Option<i64>,
|
||||||
|
pub propagation_message_id: Option<i64>,
|
||||||
|
pub propagation_channel_id: Option<i64>,
|
||||||
|
pub replying_to_id: Option<i64>,
|
||||||
|
pub is_deleted: Option<bool>,
|
||||||
|
pub is_edited: Option<bool>,
|
||||||
|
pub is_censored: Option<bool>,
|
||||||
|
}
|
||||||
use scylla::{
|
use scylla::{
|
||||||
client::session::Session,
|
client::session::Session,
|
||||||
deserialize::row::DeserializeRow,
|
deserialize::row::DeserializeRow,
|
||||||
@@ -190,6 +208,89 @@ impl From<TwilightUser> for User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- BEGIN: Payphone Message and Report Models ---
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Message {
|
||||||
|
pub call_id: u64,
|
||||||
|
pub message_id: u64,
|
||||||
|
pub message_metadata: MessageMetadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Message {
|
||||||
|
pub async fn get_by_id(call_id: u64, message_id: u64, session: &Session) -> Result<Option<Self>, DatabaseError> {
|
||||||
|
let call_id = u64_to_i64(call_id);
|
||||||
|
let message_id = u64_to_i64(message_id);
|
||||||
|
let result = session
|
||||||
|
.query_unpaged(
|
||||||
|
r#"
|
||||||
|
SELECT call_id, message_id, message_metadata
|
||||||
|
FROM payphone.messages
|
||||||
|
WHERE call_id = ? AND message_id = ?
|
||||||
|
LIMIT 1;
|
||||||
|
"#,
|
||||||
|
(call_id, message_id),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(DatabaseError::QueryError)?
|
||||||
|
.into_rows_result()
|
||||||
|
.map_err(|_| DatabaseError::ResultNotRows)?;
|
||||||
|
match result.single_row::<(i64, i64, MessageMetadata)>() {
|
||||||
|
Ok(row) => Ok(Some(Self {
|
||||||
|
call_id: i64_to_u64(row.0),
|
||||||
|
message_id: i64_to_u64(row.1),
|
||||||
|
message_metadata: row.2,
|
||||||
|
})),
|
||||||
|
Err(error) => match error {
|
||||||
|
SingleRowError::DeserializationFailed(_) | SingleRowError::TypeCheckFailed(_) => Err(DatabaseError::DeserializationFailed),
|
||||||
|
SingleRowError::UnexpectedRowCount(_) => Ok(None),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Report {
|
||||||
|
pub report_id: u64,
|
||||||
|
pub message: MessageMetadata,
|
||||||
|
pub created_at: OffsetDateTime,
|
||||||
|
pub reviewed_at: Option<OffsetDateTime>,
|
||||||
|
pub created_by_ids: Vec<u64>,
|
||||||
|
pub reviewed_by_id: Option<u64>,
|
||||||
|
pub resolution: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Report {
|
||||||
|
pub async fn insert(&self, session: &Session) -> Result<(), DatabaseError> {
|
||||||
|
session
|
||||||
|
.query_unpaged(
|
||||||
|
r#"
|
||||||
|
INSERT INTO payphone.reports (
|
||||||
|
report_id,
|
||||||
|
message,
|
||||||
|
created_at,
|
||||||
|
reviewed_at,
|
||||||
|
created_by_ids,
|
||||||
|
reviewed_by_id,
|
||||||
|
resolution
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?);
|
||||||
|
"#,
|
||||||
|
(
|
||||||
|
u64_to_i64(self.report_id),
|
||||||
|
&self.message,
|
||||||
|
self.created_at,
|
||||||
|
self.reviewed_at,
|
||||||
|
self.created_by_ids.iter().map(|&id| u64_to_i64(id)).collect::<Vec<i64>>(),
|
||||||
|
self.reviewed_by_id.map(u64_to_i64),
|
||||||
|
self.resolution.as_ref(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(DatabaseError::QueryError)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
|
|||||||
+23
-2
@@ -90,12 +90,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::framework::interactions::message_command::MessageCommand;
|
||||||
|
use crate::framework::interactions::message_command_registry::MessageCommandRegistry;
|
||||||
|
|
||||||
pub struct Bot<T: Send + Sync = ()> {
|
pub struct Bot<T: Send + Sync = ()> {
|
||||||
state: Arc<T>,
|
state: Arc<T>,
|
||||||
prefixes: Arc<dyn IntoPrefixes<T> + Send + Sync>,
|
prefixes: Arc<dyn IntoPrefixes<T> + Send + Sync>,
|
||||||
intents: Intents,
|
intents: Intents,
|
||||||
commands: Vec<Arc<dyn Command<T>>>,
|
commands: Vec<Arc<dyn Command<T>>>,
|
||||||
components: Vec<Arc<dyn Component<T>>>,
|
components: Vec<Arc<dyn Component<T>>>,
|
||||||
|
message_commands: Vec<Arc<dyn MessageCommand<T>>>,
|
||||||
on_ready_handlers: Vec<Arc<dyn OnReadyHandler<T>>>,
|
on_ready_handlers: Vec<Arc<dyn OnReadyHandler<T>>>,
|
||||||
on_reconnect_handlers: Vec<Arc<dyn OnReconnectHandler<T>>>,
|
on_reconnect_handlers: Vec<Arc<dyn OnReconnectHandler<T>>>,
|
||||||
on_interaction_handlers: Vec<Arc<dyn OnInteractionHandler<T>>>,
|
on_interaction_handlers: Vec<Arc<dyn OnInteractionHandler<T>>>,
|
||||||
@@ -115,6 +119,7 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
intents: Intents::empty(),
|
intents: Intents::empty(),
|
||||||
commands: Vec::new(),
|
commands: Vec::new(),
|
||||||
components: Vec::new(),
|
components: Vec::new(),
|
||||||
|
message_commands: Vec::new(),
|
||||||
on_ready_handlers: Vec::new(),
|
on_ready_handlers: Vec::new(),
|
||||||
on_reconnect_handlers: Vec::new(),
|
on_reconnect_handlers: Vec::new(),
|
||||||
on_interaction_handlers: Vec::new(),
|
on_interaction_handlers: Vec::new(),
|
||||||
@@ -126,6 +131,10 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
on_server_delete_handlers: Vec::new(),
|
on_server_delete_handlers: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn message_command(mut self, command: impl MessageCommand<T> + 'static) -> Self {
|
||||||
|
self.message_commands.push(Arc::new(command));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn intent(mut self, intent: Intents) -> Self {
|
pub fn intent(mut self, intent: Intents) -> Self {
|
||||||
self.intents.insert(intent);
|
self.intents.insert(intent);
|
||||||
@@ -198,17 +207,21 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
.await
|
.await
|
||||||
.inspect_err(|e| log::error!("Could not parse application data! {e:?}"))
|
.inspect_err(|e| log::error!("Could not parse application data! {e:?}"))
|
||||||
.map_err(|_| RuntimeError::ApplicationFetchingFailed)?;
|
.map_err(|_| RuntimeError::ApplicationFetchingFailed)?;
|
||||||
let registry = ComponentRegistry::new();
|
|
||||||
|
|
||||||
|
let registry = ComponentRegistry::new();
|
||||||
for component in &self.components {
|
for component in &self.components {
|
||||||
let component_id = component.custom_id();
|
let component_id = component.custom_id();
|
||||||
|
|
||||||
registry.register(
|
registry.register(
|
||||||
component_id.expect("The component registered by default must have a custom ID"),
|
component_id.expect("The component registered by default must have a custom ID"),
|
||||||
component.clone(),
|
component.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let message_command_registry = std::sync::Arc::new(MessageCommandRegistry::new());
|
||||||
|
for command in &self.message_commands {
|
||||||
|
message_command_registry.register(command.name(), command.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let bot = Arc::new(self);
|
let bot = Arc::new(self);
|
||||||
|
|
||||||
let runtime = Arc::new(Runtime {
|
let runtime = Arc::new(Runtime {
|
||||||
@@ -227,6 +240,7 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
let task_rt = runtime.clone();
|
let task_rt = runtime.clone();
|
||||||
let task_bot = bot.clone();
|
let task_bot = bot.clone();
|
||||||
|
|
||||||
|
let message_command_registry = message_command_registry.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
match event {
|
match event {
|
||||||
Event::Ready(event) => {
|
Event::Ready(event) => {
|
||||||
@@ -252,6 +266,9 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::InteractionCreate(interaction) => {
|
Event::InteractionCreate(interaction) => {
|
||||||
|
// First, try message command registry
|
||||||
|
if let Err(e) = message_command_registry.execute(&interaction, task_rt.clone()).await {
|
||||||
|
// If not a message command, fall back to interaction handlers
|
||||||
for handler in &task_bot.on_interaction_handlers {
|
for handler in &task_bot.on_interaction_handlers {
|
||||||
handler
|
handler
|
||||||
.on_interaction(&interaction, task_rt.clone())
|
.on_interaction(&interaction, task_rt.clone())
|
||||||
@@ -261,6 +278,10 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
)
|
)
|
||||||
.bye();
|
.bye();
|
||||||
}
|
}
|
||||||
|
if !matches!(e, crate::framework::interactions::InteractionError::InteractionTypeUnsent) {
|
||||||
|
log::error!("Message command dispatch error: {e:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Event::MessageCreate(message) => {
|
Event::MessageCreate(message) => {
|
||||||
for handler in &task_bot.on_message_handlers {
|
for handler in &task_bot.on_message_handlers {
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use twilight_model::gateway::payload::incoming::InteractionCreate;
|
||||||
|
use crate::framework::interactions::{InteractionError, context::InteractionContext};
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait MessageCommand<T>: Send + Sync + Debug {
|
||||||
|
fn name(&self) -> &'static str;
|
||||||
|
fn description(&self) -> &'static str {
|
||||||
|
"A message context menu command duh."
|
||||||
|
}
|
||||||
|
async fn execute(&self, ctx: InteractionContext<T>, target_message_id: u64) -> Result<(), InteractionError>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use scc::HashMap;
|
||||||
|
use twilight_model::{
|
||||||
|
application::interaction::InteractionData, application::command::CommandType, gateway::payload::incoming::InteractionCreate,
|
||||||
|
};
|
||||||
|
use crate::framework::{
|
||||||
|
interactions::{InteractionError, context::InteractionContext, message_command::MessageCommand},
|
||||||
|
runtime::Runtime,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct MessageCommandRegistry<T> {
|
||||||
|
inner: HashMap<String, Arc<dyn MessageCommand<T>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MessageCommandRegistry<T>
|
||||||
|
where
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register(&self, name: impl ToString, command: Arc<dyn MessageCommand<T>>) {
|
||||||
|
self.inner.upsert(name.to_string(), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unregister(&self, name: impl ToString) {
|
||||||
|
self.inner.remove(&name.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn execute(
|
||||||
|
&self,
|
||||||
|
event: &InteractionCreate,
|
||||||
|
rt: Arc<Runtime<T>>,
|
||||||
|
) -> Result<(), InteractionError> {
|
||||||
|
if let Some(data) = &event.data {
|
||||||
|
if let InteractionData::ApplicationCommand(data) = data {
|
||||||
|
if data.kind == CommandType::Message {
|
||||||
|
if let Some(command) = self.inner.get_async(&data.name).await {
|
||||||
|
let prefixes = rt
|
||||||
|
.get_prefixes(
|
||||||
|
event.guild_id.map(|id| id.get()),
|
||||||
|
event.author_id().map(|id| id.get()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let prefix = prefixes
|
||||||
|
.first()
|
||||||
|
.ok_or(InteractionError::PrefixesVectorEmpty)?;
|
||||||
|
// Message commands have a resolved target_id
|
||||||
|
if let Some(target_id) = data.target_id {
|
||||||
|
command
|
||||||
|
.execute(
|
||||||
|
InteractionContext::new(event.clone(), rt.clone(), prefix.to_string()),
|
||||||
|
target_id.get(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
} else {
|
||||||
|
Err(InteractionError::InteractionNotFound)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(InteractionError::InteractionNotFound)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(InteractionError::InteractionTypeUnsent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(InteractionError::InteractionTypeUnsent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(InteractionError::InteractionTypeUnsent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ pub mod components;
|
|||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod registry;
|
pub mod registry;
|
||||||
pub mod runner;
|
pub mod runner;
|
||||||
|
pub mod message_command;
|
||||||
|
pub mod message_command_registry;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum InteractionError {
|
pub enum InteractionError {
|
||||||
|
|||||||
@@ -3,11 +3,74 @@ use scc::HashSet;
|
|||||||
use twilight_model::id::Id;
|
use twilight_model::id::Id;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::models::{Call, Channel},
|
database::models::{Call, Channel, Message, Report},
|
||||||
framework::commands::{Command, CommandError, context::CommandContext},
|
framework::commands::{Command, CommandError, context::CommandContext},
|
||||||
|
framework::interactions::{message_command::MessageCommand, InteractionError, context::InteractionContext},
|
||||||
state::State,
|
state::State,
|
||||||
utils::Bye,
|
utils::{Bye, get_random_u64},
|
||||||
};
|
};
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct ReportMessageCommand;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl MessageCommand<State> for ReportMessageCommand {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"Report Message"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description(&self) -> &'static str {
|
||||||
|
"Report a message to the moderators."
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn execute(&self, ctx: InteractionContext<State>, target_message_id: u64) -> Result<(), InteractionError> {
|
||||||
|
|
||||||
|
// Extract channel_id from resolved data or fallback to event.channel (Discord API v10+)
|
||||||
|
let channel_id = ctx.event.channel.as_ref().map(|c| c.id.get())
|
||||||
|
.or_else(|| ctx.event.channel.as_ref().map(|c| c.id.get()))
|
||||||
|
.ok_or(InteractionError::InteractionNotFound)?;
|
||||||
|
let db = &ctx.rt.state.db;
|
||||||
|
let channel = Channel::get_by_id(channel_id, db).await.map_err(|_| InteractionError::InteractionNotFound)?;
|
||||||
|
let call_id = channel.and_then(|c| c.call_id).ok_or(InteractionError::InteractionNotFound)?;
|
||||||
|
|
||||||
|
// Fetch the message from the database
|
||||||
|
let message = Message::get_by_id(call_id, target_message_id, db)
|
||||||
|
.await
|
||||||
|
.map_err(|_| InteractionError::InteractionNotFound)?
|
||||||
|
.ok_or(InteractionError::InteractionNotFound)?;
|
||||||
|
|
||||||
|
// Build the report using the new UDT-based message metadata
|
||||||
|
let report = Report {
|
||||||
|
report_id: get_random_u64(),
|
||||||
|
message: message.message_metadata.clone(),
|
||||||
|
created_at: time::OffsetDateTime::now_utc(),
|
||||||
|
reviewed_at: None,
|
||||||
|
created_by_ids: vec![ctx.event.author_id().map(|id| id.get()).unwrap_or(0)],
|
||||||
|
reviewed_by_id: None,
|
||||||
|
resolution: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Insert the report
|
||||||
|
report.insert(db).await.map_err(|_| InteractionError::DeferringFailed)?;
|
||||||
|
|
||||||
|
// Respond to the user
|
||||||
|
ctx.rt.http
|
||||||
|
.interaction(ctx.rt.app.id)
|
||||||
|
.create_response(
|
||||||
|
ctx.event.id,
|
||||||
|
&ctx.event.token,
|
||||||
|
&twilight_model::http::interaction::InteractionResponse {
|
||||||
|
kind: twilight_model::http::interaction::InteractionResponseType::ChannelMessageWithSource,
|
||||||
|
data: Some(twilight_model::http::interaction::InteractionResponseData {
|
||||||
|
content: Some("Message has been reported to the moderators.".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|_| InteractionError::DeferringFailed)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct CallCommand {
|
pub struct CallCommand {
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ async fn start(token: String, database_addr: String) {
|
|||||||
.command(CallCommand::new())
|
.command(CallCommand::new())
|
||||||
.command(HangupCommand)
|
.command(HangupCommand)
|
||||||
.component(HelpGoBackButton)
|
.component(HelpGoBackButton)
|
||||||
|
.message_command(crate::groups::calls::commands::ReportMessageCommand)
|
||||||
.on_ready(ReadyHandler)
|
.on_ready(ReadyHandler)
|
||||||
.on_reconnect(ReconnectHandler)
|
.on_reconnect(ReconnectHandler)
|
||||||
.on_message(MessageRedirector)
|
.on_message(MessageRedirector)
|
||||||
|
|||||||
Reference in New Issue
Block a user