changed stuff according to merge request !2
This commit is contained in:
@@ -5,25 +5,29 @@ CREATE KEYSPACE IF NOT EXISTS payphone
|
|||||||
} AND TABLETS = {
|
} AND TABLETS = {
|
||||||
'enabled': false
|
'enabled': false
|
||||||
};
|
};
|
||||||
|
CREATE TYPE IF NOT EXISTS payphone.message (
|
||||||
|
id BIGINT,
|
||||||
|
|
||||||
CREATE TYPE IF NOT EXISTS payphone.message_metadata (
|
|
||||||
call_id BIGINT,
|
|
||||||
author_id BIGINT,
|
author_id BIGINT,
|
||||||
author_name TEXT,
|
author_name TEXT,
|
||||||
author_avatar_url TEXT,
|
author_avatar_url TEXT,
|
||||||
author_mask ASCII,
|
author_mask ASCII,
|
||||||
|
|
||||||
content TEXT,
|
content TEXT,
|
||||||
attachments LIST<TEXT>,
|
attachments LIST<TEXT>,
|
||||||
sticker BIGINT,
|
sticker BIGINT,
|
||||||
|
|
||||||
propagation_message_id BIGINT,
|
propagation_message_id BIGINT,
|
||||||
propagation_channel_id BIGINT,
|
propagation_channel_id BIGINT,
|
||||||
replying_to_id BIGINT,
|
|
||||||
message_replied_to_metadata FROZEN<payphone.message_metadata>,
|
replying_to_id,
|
||||||
|
|
||||||
is_deleted BOOLEAN,
|
is_deleted BOOLEAN,
|
||||||
is_edited BOOLEAN,
|
is_edited BOOLEAN,
|
||||||
is_censored 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,
|
||||||
|
|
||||||
@@ -82,7 +86,9 @@ 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,
|
||||||
message_metadata FROZEN<payphone.message_metadata>,
|
|
||||||
|
data FROZEN<payphone.message>,
|
||||||
|
|
||||||
PRIMARY KEY (call_id, message_id)
|
PRIMARY KEY (call_id, message_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -92,31 +98,44 @@ CREATE TABLE IF NOT EXISTS payphone.servers (
|
|||||||
name TEXT,
|
name TEXT,
|
||||||
prefix TEXT,
|
prefix TEXT,
|
||||||
);
|
);
|
||||||
|
|
||||||
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 FROZEN<payphone.message>,
|
||||||
|
replying_to FROZEN<payphone.message>,
|
||||||
|
|
||||||
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 FROZEN<payphone.message>,
|
||||||
|
replying_to FROZEN<payphone.message>,
|
||||||
|
|
||||||
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)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+83
-41
@@ -1,5 +1,5 @@
|
|||||||
use scylla::{DeserializeValue, SerializeValue};
|
|
||||||
use scylla::{
|
use scylla::{
|
||||||
|
DeserializeValue, SerializeValue,
|
||||||
client::session::Session,
|
client::session::Session,
|
||||||
deserialize::row::DeserializeRow,
|
deserialize::row::DeserializeRow,
|
||||||
errors::{ExecutionError, SingleRowError},
|
errors::{ExecutionError, SingleRowError},
|
||||||
@@ -192,8 +192,8 @@ impl From<TwilightUser> for User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, SerializeValue, DeserializeValue)]
|
#[derive(Debug, Clone, SerializeValue, DeserializeValue)]
|
||||||
pub struct MessageMetadata {
|
pub struct Message {
|
||||||
pub call_id: i64,
|
pub id: i64,
|
||||||
pub author_id: i64,
|
pub author_id: i64,
|
||||||
pub author_name: Option<String>,
|
pub author_name: Option<String>,
|
||||||
pub author_avatar_url: Option<String>,
|
pub author_avatar_url: Option<String>,
|
||||||
@@ -204,13 +204,12 @@ pub struct MessageMetadata {
|
|||||||
pub propagation_message_id: Option<i64>,
|
pub propagation_message_id: Option<i64>,
|
||||||
pub propagation_channel_id: Option<i64>,
|
pub propagation_channel_id: Option<i64>,
|
||||||
pub replying_to_id: Option<i64>,
|
pub replying_to_id: Option<i64>,
|
||||||
pub message_replied_to_metadata: Option<Box<MessageMetadata>>,
|
|
||||||
pub is_deleted: Option<bool>,
|
pub is_deleted: Option<bool>,
|
||||||
pub is_edited: Option<bool>,
|
pub is_edited: Option<bool>,
|
||||||
pub is_censored: Option<bool>,
|
pub is_censored: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Object<'a> for MessageMetadata {
|
impl<'a> Object<'a> for Message {
|
||||||
type Row = (
|
type Row = (
|
||||||
i64,
|
i64,
|
||||||
i64,
|
i64,
|
||||||
@@ -223,14 +222,13 @@ impl<'a> Object<'a> for MessageMetadata {
|
|||||||
Option<i64>,
|
Option<i64>,
|
||||||
Option<i64>,
|
Option<i64>,
|
||||||
Option<i64>,
|
Option<i64>,
|
||||||
Option<Box<MessageMetadata>>,
|
|
||||||
Option<bool>,
|
Option<bool>,
|
||||||
Option<bool>,
|
Option<bool>,
|
||||||
Option<bool>,
|
Option<bool>,
|
||||||
);
|
);
|
||||||
fn from_row(row: Self::Row) -> Self {
|
fn from_row(row: Self::Row) -> Self {
|
||||||
Self {
|
Self {
|
||||||
call_id: row.0,
|
id: row.0,
|
||||||
author_id: row.1,
|
author_id: row.1,
|
||||||
author_name: row.2,
|
author_name: row.2,
|
||||||
author_avatar_url: row.3,
|
author_avatar_url: row.3,
|
||||||
@@ -241,15 +239,14 @@ impl<'a> Object<'a> for MessageMetadata {
|
|||||||
propagation_message_id: row.8,
|
propagation_message_id: row.8,
|
||||||
propagation_channel_id: row.9,
|
propagation_channel_id: row.9,
|
||||||
replying_to_id: row.10,
|
replying_to_id: row.10,
|
||||||
message_replied_to_metadata: row.11,
|
is_deleted: row.11,
|
||||||
is_deleted: row.12,
|
is_edited: row.12,
|
||||||
is_edited: row.13,
|
is_censored: row.13,
|
||||||
is_censored: row.14,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn to_row(value: Self) -> Self::Row {
|
fn to_row(value: Self) -> Self::Row {
|
||||||
(
|
(
|
||||||
value.call_id,
|
value.id,
|
||||||
value.author_id,
|
value.author_id,
|
||||||
value.author_name,
|
value.author_name,
|
||||||
value.author_avatar_url,
|
value.author_avatar_url,
|
||||||
@@ -260,7 +257,6 @@ impl<'a> Object<'a> for MessageMetadata {
|
|||||||
value.propagation_message_id,
|
value.propagation_message_id,
|
||||||
value.propagation_channel_id,
|
value.propagation_channel_id,
|
||||||
value.replying_to_id,
|
value.replying_to_id,
|
||||||
value.message_replied_to_metadata,
|
|
||||||
value.is_deleted,
|
value.is_deleted,
|
||||||
value.is_edited,
|
value.is_edited,
|
||||||
value.is_censored,
|
value.is_censored,
|
||||||
@@ -268,17 +264,14 @@ impl<'a> Object<'a> for MessageMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- BEGIN: Payphone Message and Report Models ---
|
pub struct MessageRow {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Message {
|
|
||||||
pub call_id: u64,
|
pub call_id: u64,
|
||||||
pub message_id: u64,
|
pub message_id: u64,
|
||||||
pub message_metadata: MessageMetadata,
|
pub data: Message,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message {
|
impl MessageRow {
|
||||||
pub async fn get_by_id(
|
pub async fn get_by_call_and_message_id(
|
||||||
call_id: u64,
|
call_id: u64,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
session: &Session,
|
session: &Session,
|
||||||
@@ -288,7 +281,7 @@ impl Message {
|
|||||||
let result = session
|
let result = session
|
||||||
.query_unpaged(
|
.query_unpaged(
|
||||||
r#"
|
r#"
|
||||||
SELECT call_id, message_id, message_metadata
|
SELECT call_id, message_id, data
|
||||||
FROM payphone.messages
|
FROM payphone.messages
|
||||||
WHERE call_id = ? AND message_id = ?
|
WHERE call_id = ? AND message_id = ?
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
@@ -299,12 +292,8 @@ impl Message {
|
|||||||
.map_err(DatabaseError::QueryError)?
|
.map_err(DatabaseError::QueryError)?
|
||||||
.into_rows_result()
|
.into_rows_result()
|
||||||
.map_err(|_| DatabaseError::ResultNotRows)?;
|
.map_err(|_| DatabaseError::ResultNotRows)?;
|
||||||
match result.single_row::<(i64, i64, MessageMetadata)>() {
|
match result.single_row::<<MessageRow as Object>::Row>() {
|
||||||
Ok(row) => Ok(Some(Self {
|
Ok(row) => Ok(Some(<MessageRow as Object>::from_row(row))),
|
||||||
call_id: i64_to_u64(row.0),
|
|
||||||
message_id: i64_to_u64(row.1),
|
|
||||||
message_metadata: row.2,
|
|
||||||
})),
|
|
||||||
Err(error) => match error {
|
Err(error) => match error {
|
||||||
SingleRowError::DeserializationFailed(_) | SingleRowError::TypeCheckFailed(_) => {
|
SingleRowError::DeserializationFailed(_) | SingleRowError::TypeCheckFailed(_) => {
|
||||||
Err(DatabaseError::DeserializationFailed)
|
Err(DatabaseError::DeserializationFailed)
|
||||||
@@ -315,10 +304,54 @@ impl Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Object<'a> for Report {
|
||||||
|
type Row = (
|
||||||
|
i64, // report_id
|
||||||
|
Message,
|
||||||
|
Option<Message>,
|
||||||
|
OffsetDateTime,
|
||||||
|
Option<OffsetDateTime>,
|
||||||
|
Vec<i64>,
|
||||||
|
Option<i64>,
|
||||||
|
Option<String>,
|
||||||
|
);
|
||||||
|
fn from_row(row: Self::Row) -> Self {
|
||||||
|
Self {
|
||||||
|
report_id: i64_to_u64(row.0),
|
||||||
|
message: row.1,
|
||||||
|
replying_to: row.2,
|
||||||
|
created_at: row.3,
|
||||||
|
reviewed_at: row.4,
|
||||||
|
created_by_ids: row.5.iter().map(|&id| i64_to_u64(id)).collect(),
|
||||||
|
reviewed_by_id: row.6.map(i64_to_u64),
|
||||||
|
resolution: row.7,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn to_row(value: Self) -> Self::Row {
|
||||||
|
(
|
||||||
|
u64_to_i64(value.report_id),
|
||||||
|
value.message,
|
||||||
|
value.replying_to,
|
||||||
|
value.created_at,
|
||||||
|
value.reviewed_at,
|
||||||
|
value
|
||||||
|
.created_by_ids
|
||||||
|
.iter()
|
||||||
|
.map(|&id| u64_to_i64(id))
|
||||||
|
.collect(),
|
||||||
|
value.reviewed_by_id.map(u64_to_i64),
|
||||||
|
value.resolution,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- BEGIN: Payphone Message and Report Models ---
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Report {
|
pub struct Report {
|
||||||
pub report_id: u64,
|
pub report_id: u64,
|
||||||
pub message: MessageMetadata,
|
pub message: Message,
|
||||||
|
pub replying_to: Option<Message>,
|
||||||
pub created_at: OffsetDateTime,
|
pub created_at: OffsetDateTime,
|
||||||
pub reviewed_at: Option<OffsetDateTime>,
|
pub reviewed_at: Option<OffsetDateTime>,
|
||||||
pub created_by_ids: Vec<u64>,
|
pub created_by_ids: Vec<u64>,
|
||||||
@@ -326,33 +359,42 @@ pub struct Report {
|
|||||||
pub resolution: Option<String>,
|
pub resolution: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Object<'a> for MessageRow {
|
||||||
|
type Row = (i64, i64, <Message as Object<'a>>::Row);
|
||||||
|
fn from_row(row: Self::Row) -> Self {
|
||||||
|
Self {
|
||||||
|
call_id: i64_to_u64(row.0),
|
||||||
|
message_id: i64_to_u64(row.1),
|
||||||
|
data: <Message as Object>::from_row(row.2),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn to_row(value: Self) -> Self::Row {
|
||||||
|
(
|
||||||
|
u64_to_i64(value.call_id),
|
||||||
|
u64_to_i64(value.message_id),
|
||||||
|
<Message as Object>::to_row(value.data),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Report {
|
impl Report {
|
||||||
pub async fn insert(&self, session: &Session) -> Result<(), DatabaseError> {
|
pub async fn insert(&self, session: &Session) -> Result<(), DatabaseError> {
|
||||||
|
let row = Self::to_row(self.clone());
|
||||||
session
|
session
|
||||||
.query_unpaged(
|
.query_unpaged(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO payphone.reports (
|
INSERT INTO payphone.reports (
|
||||||
report_id,
|
report_id,
|
||||||
message,
|
message,
|
||||||
|
replying_to,
|
||||||
created_at,
|
created_at,
|
||||||
reviewed_at,
|
reviewed_at,
|
||||||
created_by_ids,
|
created_by_ids,
|
||||||
reviewed_by_id,
|
reviewed_by_id,
|
||||||
resolution
|
resolution
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?);
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?);
|
||||||
"#,
|
"#,
|
||||||
(
|
row,
|
||||||
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
|
.await
|
||||||
.map_err(DatabaseError::QueryError)?;
|
.map_err(DatabaseError::QueryError)?;
|
||||||
|
|||||||
+23
-31
@@ -1,23 +1,23 @@
|
|||||||
use std::{fmt::Debug, sync::Arc};
|
use crate::framework::{
|
||||||
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use thiserror::Error;
|
|
||||||
use twilight_gateway::{Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt};
|
|
||||||
use twilight_http::Client;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
framework::{
|
|
||||||
commands::{Command, runner::CommandRunner},
|
commands::{Command, runner::CommandRunner},
|
||||||
events::traits::{
|
events::traits::{
|
||||||
OnInteractionHandler, OnMessageDeleteHandler, OnMessageEditHandler, OnMessageHandler,
|
OnInteractionHandler, OnMessageDeleteHandler, OnMessageEditHandler, OnMessageHandler,
|
||||||
OnReadyHandler, OnReconnectHandler, OnServerCreateHandler, OnServerDeleteHandler,
|
OnReadyHandler, OnReconnectHandler, OnServerCreateHandler, OnServerDeleteHandler,
|
||||||
OnServerUpdateHandler,
|
OnServerUpdateHandler,
|
||||||
},
|
},
|
||||||
interactions::{components::Component, registry::ComponentRegistry},
|
interactions::{
|
||||||
runtime::Runtime,
|
components::Component, message_command::MessageCommand,
|
||||||
|
message_command_registry::MessageCommandRegistry,
|
||||||
|
message_command_runner::MessageCommandRunner, registry::ComponentRegistry,
|
||||||
},
|
},
|
||||||
utils::Bye,
|
runtime::Runtime,
|
||||||
};
|
};
|
||||||
|
use crate::utils::Bye;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use std::{fmt::Debug, sync::Arc};
|
||||||
|
use thiserror::Error;
|
||||||
|
use twilight_gateway::{Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt};
|
||||||
|
use twilight_http::Client;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum RuntimeError {
|
pub enum RuntimeError {
|
||||||
@@ -70,10 +70,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::framework::interactions::message_command::MessageCommand;
|
pub struct Bot<T: Send + Sync + Debug = ()> {
|
||||||
use crate::framework::interactions::message_command_registry::MessageCommandRegistry;
|
|
||||||
|
|
||||||
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,
|
||||||
@@ -91,7 +88,7 @@ pub struct Bot<T: Send + Sync = ()> {
|
|||||||
on_server_delete_handlers: Vec<Arc<dyn OnServerDeleteHandler<T>>>,
|
on_server_delete_handlers: Vec<Arc<dyn OnServerDeleteHandler<T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static + Send + Sync> Bot<T> {
|
impl<T: 'static + Send + Sync + Debug> Bot<T> {
|
||||||
pub fn new(state: T, prefixes: impl IntoPrefixes<T> + Send + Sync + 'static) -> Self {
|
pub fn new(state: T, prefixes: impl IntoPrefixes<T> + Send + Sync + 'static) -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: Arc::new(state),
|
state: Arc::new(state),
|
||||||
@@ -102,7 +99,7 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
message_commands: 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(), // Will push MessageCommandRunner in run()
|
||||||
on_message_handlers: vec![Arc::new(CommandRunner)],
|
on_message_handlers: vec![Arc::new(CommandRunner)],
|
||||||
on_message_edit_handlers: Vec::new(),
|
on_message_edit_handlers: Vec::new(),
|
||||||
on_message_delete_handlers: Vec::new(),
|
on_message_delete_handlers: Vec::new(),
|
||||||
@@ -202,7 +199,14 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
message_command_registry.register(command.name(), command.clone());
|
message_command_registry.register(command.name(), command.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let bot = Arc::new(self);
|
let mut bot = self;
|
||||||
|
bot.on_interaction_handlers.insert(
|
||||||
|
0,
|
||||||
|
Arc::new(MessageCommandRunner {
|
||||||
|
registry: message_command_registry.clone(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let bot = Arc::new(bot);
|
||||||
|
|
||||||
let runtime = Arc::new(Runtime {
|
let runtime = Arc::new(Runtime {
|
||||||
http,
|
http,
|
||||||
@@ -219,8 +223,6 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
if let Some(Ok(event)) = gateway.next_event(EventTypeFlags::all()).await {
|
if let Some(Ok(event)) = gateway.next_event(EventTypeFlags::all()).await {
|
||||||
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) => {
|
||||||
@@ -246,12 +248,6 @@ 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,10 +257,6 @@ 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 {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use twilight_model::{
|
use twilight_model::{
|
||||||
gateway::payload::incoming::InteractionCreate,
|
gateway::payload::incoming::InteractionCreate,
|
||||||
http::interaction::{InteractionResponse, InteractionResponseType},
|
http::interaction::{InteractionResponse, InteractionResponseType},
|
||||||
@@ -17,6 +16,11 @@ pub struct InteractionContext<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> InteractionContext<T> {
|
impl<T> InteractionContext<T> {
|
||||||
|
pub fn send(
|
||||||
|
self: &Arc<Self>,
|
||||||
|
) -> crate::framework::interactions::messages::InteractionResponder<T> {
|
||||||
|
crate::framework::interactions::messages::InteractionResponder::new(self.clone())
|
||||||
|
}
|
||||||
pub fn new(event: InteractionCreate, rt: Arc<Runtime<T>>, prefix: String) -> Self {
|
pub fn new(event: InteractionCreate, rt: Arc<Runtime<T>>, prefix: String) -> Self {
|
||||||
Self { event, rt, prefix }
|
Self { event, rt, prefix }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use twilight_model::gateway::payload::incoming::InteractionCreate;
|
|||||||
pub trait MessageCommand<T>: Send + Sync + Debug {
|
pub trait MessageCommand<T>: Send + Sync + Debug {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
fn description(&self) -> &'static str {
|
fn description(&self) -> &'static str {
|
||||||
"A message context menu command duh."
|
"A Payphone context menu command."
|
||||||
}
|
}
|
||||||
async fn execute(
|
async fn execute(
|
||||||
&self,
|
&self,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// to be later integrated into interaction registry...currently component registry
|
||||||
use crate::framework::{
|
use crate::framework::{
|
||||||
interactions::{
|
interactions::{
|
||||||
InteractionError, context::InteractionContext, message_command::MessageCommand,
|
InteractionError, context::InteractionContext, message_command::MessageCommand,
|
||||||
@@ -11,7 +12,7 @@ use twilight_model::{
|
|||||||
gateway::payload::incoming::InteractionCreate,
|
gateway::payload::incoming::InteractionCreate,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Debug)]
|
||||||
pub struct MessageCommandRegistry<T> {
|
pub struct MessageCommandRegistry<T> {
|
||||||
inner: HashMap<String, Arc<dyn MessageCommand<T>>>,
|
inner: HashMap<String, Arc<dyn MessageCommand<T>>>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use twilight_model::gateway::payload::incoming::InteractionCreate;
|
||||||
|
|
||||||
|
use crate::framework::{
|
||||||
|
events::traits::{EventResult, OnInteractionHandler},
|
||||||
|
interactions::message_command_registry::MessageCommandRegistry,
|
||||||
|
runtime::Runtime,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MessageCommandRunner<T> {
|
||||||
|
pub registry: Arc<MessageCommandRegistry<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T: Send + Sync + std::fmt::Debug + 'static> OnInteractionHandler<T>
|
||||||
|
for MessageCommandRunner<T>
|
||||||
|
{
|
||||||
|
async fn on_interaction(&self, event: &InteractionCreate, rt: Arc<Runtime<T>>) -> EventResult {
|
||||||
|
if let Err(e) = self.registry.execute(event, rt).await {
|
||||||
|
// Only log errors that aren't "not a message command"
|
||||||
|
if !matches!(
|
||||||
|
e,
|
||||||
|
crate::framework::interactions::InteractionError::InteractionTypeUnsent
|
||||||
|
) {
|
||||||
|
log::error!("Message command dispatch error: {e:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use twilight_model::http::interaction::{
|
||||||
|
InteractionResponse, InteractionResponseData, InteractionResponseType,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::framework::{
|
||||||
|
interactions::{InteractionError, context::InteractionContext},
|
||||||
|
runtime::Runtime,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct InteractionResponder<T> {
|
||||||
|
ctx: Arc<InteractionContext<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> InteractionResponder<T> {
|
||||||
|
pub fn new(ctx: Arc<InteractionContext<T>>) -> Self {
|
||||||
|
Self { ctx }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn content(&self, content: impl Into<String>) -> Result<(), InteractionError> {
|
||||||
|
self.ctx
|
||||||
|
.rt
|
||||||
|
.http
|
||||||
|
.interaction(self.ctx.rt.app.id)
|
||||||
|
.create_response(
|
||||||
|
self.ctx.event.id,
|
||||||
|
&self.ctx.event.token,
|
||||||
|
&InteractionResponse {
|
||||||
|
kind: InteractionResponseType::ChannelMessageWithSource,
|
||||||
|
data: Some(InteractionResponseData {
|
||||||
|
content: Some(content.into()),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|_| InteractionError::DeferringFailed)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
|
pub mod message_command_runner;
|
||||||
|
pub mod messages;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
pub mod components;
|
pub mod components;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod message_command;
|
pub mod message_command;
|
||||||
@@ -25,4 +26,7 @@ pub enum InteractionError {
|
|||||||
|
|
||||||
#[error("No prefixes were returned for the event")]
|
#[error("No prefixes were returned for the event")]
|
||||||
PrefixesVectorEmpty,
|
PrefixesVectorEmpty,
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
DatabaseError(#[from] crate::database::models::DatabaseError),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use scc::HashSet;
|
use scc::HashSet;
|
||||||
|
use std::sync::Arc;
|
||||||
use twilight_model::id::Id;
|
use twilight_model::id::Id;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::models::{Call, Channel, Message, Report},
|
database::models::{Call, Channel, Message, MessageRow, Report},
|
||||||
framework::commands::{Command, CommandError, context::CommandContext},
|
framework::commands::{Command, CommandError, context::CommandContext},
|
||||||
framework::interactions::{
|
framework::interactions::{
|
||||||
InteractionError, context::InteractionContext, message_command::MessageCommand,
|
InteractionError, context::InteractionContext, message_command::MessageCommand,
|
||||||
@@ -46,26 +47,29 @@ impl MessageCommand<State> for ReportMessageCommand {
|
|||||||
.ok_or(InteractionError::InteractionNotFound)?;
|
.ok_or(InteractionError::InteractionNotFound)?;
|
||||||
|
|
||||||
// Fetch the message from the database
|
// Fetch the message from the database
|
||||||
let message = Message::get_by_id(call_id, target_message_id, db)
|
let message_row = MessageRow::get_by_call_and_message_id(call_id, target_message_id, db)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| InteractionError::InteractionNotFound)?
|
.map_err(|_| InteractionError::InteractionNotFound)?
|
||||||
.ok_or(InteractionError::InteractionNotFound)?;
|
.ok_or(InteractionError::InteractionNotFound)?;
|
||||||
|
|
||||||
// If the message is a reply, fetch the replied-to message and denormalize its metadata
|
// If the message is a reply, fetch the replied-to message and store in replying_to
|
||||||
let mut message_metadata = message.message_metadata.clone();
|
let replying_to = if let Some(replying_to_id) = message_row.data.replying_to_id {
|
||||||
if let Some(replying_to_id) = message_metadata.replying_to_id {
|
if let Ok(Some(reply_msg_row)) =
|
||||||
if let Ok(Some(reply_msg)) =
|
MessageRow::get_by_call_and_message_id(call_id, replying_to_id as u64, db).await
|
||||||
Message::get_by_id(call_id, replying_to_id as u64, db).await
|
|
||||||
{
|
{
|
||||||
message_metadata.message_replied_to_metadata =
|
Some(reply_msg_row.data)
|
||||||
Some(Box::new(reply_msg.message_metadata));
|
} else {
|
||||||
}
|
None
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// Build the report using the new UDT-based message metadata
|
// Build the report using the new flat message and replying_to
|
||||||
let report = Report {
|
let report = Report {
|
||||||
report_id: get_random_u64(),
|
report_id: get_random_u64(),
|
||||||
message: message_metadata,
|
message: message_row.data,
|
||||||
|
replying_to,
|
||||||
created_at: time::OffsetDateTime::now_utc(),
|
created_at: time::OffsetDateTime::now_utc(),
|
||||||
reviewed_at: None,
|
reviewed_at: None,
|
||||||
created_by_ids: vec![ctx.event.author_id().map(|id| id.get()).unwrap_or(0)],
|
created_by_ids: vec![ctx.event.author_id().map(|id| id.get()).unwrap_or(0)],
|
||||||
@@ -77,24 +81,13 @@ impl MessageCommand<State> for ReportMessageCommand {
|
|||||||
report
|
report
|
||||||
.insert(db)
|
.insert(db)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| InteractionError::DeferringFailed)?;
|
.map_err(InteractionError::DatabaseError)?;
|
||||||
|
|
||||||
// Respond to the user
|
// Respond to the user
|
||||||
ctx.rt.http
|
Arc::new(ctx)
|
||||||
.interaction(ctx.rt.app.id)
|
.send()
|
||||||
.create_response(
|
.content("Message has been reported to the moderators.")
|
||||||
ctx.event.id,
|
.await?;
|
||||||
&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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -107,13 +107,7 @@ use std::{
|
|||||||
sync::mpsc,
|
sync::mpsc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use axum::{Router, response::Redirect, routing};
|
use crate::groups::calls::commands::ReportMessageCommand;
|
||||||
use clap::Parser;
|
|
||||||
use notify::{Event, EventKind, Watcher};
|
|
||||||
use tokio::net::TcpListener;
|
|
||||||
use tower_http::services::ServeDir;
|
|
||||||
use twilight_gateway::Intents;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::{Args, Commands},
|
cli::{Args, Commands},
|
||||||
framework::bot::Bot,
|
framework::bot::Bot,
|
||||||
@@ -128,6 +122,12 @@ use crate::{
|
|||||||
},
|
},
|
||||||
state::State,
|
state::State,
|
||||||
};
|
};
|
||||||
|
use axum::{Router, response::Redirect, routing};
|
||||||
|
use clap::Parser;
|
||||||
|
use notify::{Event, EventKind, Watcher};
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
use tower_http::services::ServeDir;
|
||||||
|
use twilight_gateway::Intents;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod constants;
|
mod constants;
|
||||||
@@ -185,7 +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)
|
.message_command(ReportMessageCommand)
|
||||||
.on_ready(ReadyHandler)
|
.on_ready(ReadyHandler)
|
||||||
.on_reconnect(ReconnectHandler)
|
.on_reconnect(ReconnectHandler)
|
||||||
.on_message(MessageRedirector)
|
.on_message(MessageRedirector)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use scylla::client::session::Session;
|
use scylla::client::session::Session;
|
||||||
|
#[derive(Debug)]
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub db: Session,
|
pub db: Session,
|
||||||
|
|||||||
Reference in New Issue
Block a user