chore(thanos): strip down codebase to just API routes
This commit is contained in:
@@ -1,38 +1,6 @@
|
||||
use crate::database::*;
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
#[put("/<target>/ack/<message>")]
|
||||
pub async fn req(user: User, target: Ref, message: Ref) -> Result<EmptyResponse> {
|
||||
if user.bot.is_some() {
|
||||
return Err(Error::IsBot)
|
||||
}
|
||||
|
||||
let target = target.fetch_channel().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
crate::task_queue::task_ack::queue(
|
||||
target.id().into(),
|
||||
user.id.clone(),
|
||||
crate::task_queue::task_ack::AckEvent::AckMessage {
|
||||
id: message.id.clone()
|
||||
}
|
||||
).await;
|
||||
|
||||
ClientboundNotification::ChannelAck {
|
||||
id: target.id().into(),
|
||||
user: user.id.clone(),
|
||||
message_id: message.id,
|
||||
}
|
||||
.publish(user.id);
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref, message: Ref*/ target: String, message: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,119 +1,8 @@
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::{database::*, notifications::events::ClientboundNotification};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
|
||||
#[delete("/<target>")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<EmptyResponse> {
|
||||
let target = target.fetch_channel().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
match &target {
|
||||
Channel::SavedMessages { .. } => Err(Error::NoEffect),
|
||||
Channel::DirectMessage { .. } => {
|
||||
get_collection("channels")
|
||||
.update_one(
|
||||
doc! {
|
||||
"_id": target.id()
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"active": false
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channel",
|
||||
})?;
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
}
|
||||
Channel::Group {
|
||||
id,
|
||||
owner,
|
||||
recipients,
|
||||
..
|
||||
} => {
|
||||
if &user.id == owner {
|
||||
if let Some(new_owner) = recipients.iter().find(|x| *x != &user.id) {
|
||||
get_collection("channels")
|
||||
.update_one(
|
||||
doc! {
|
||||
"_id": &id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"owner": new_owner
|
||||
},
|
||||
"$pull": {
|
||||
"recipients": &user.id
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channel",
|
||||
})?;
|
||||
|
||||
target.publish_update(json!({ "owner": new_owner })).await?;
|
||||
} else {
|
||||
target.delete().await?;
|
||||
return Ok(EmptyResponse {});
|
||||
}
|
||||
} else {
|
||||
get_collection("channels")
|
||||
.update_one(
|
||||
doc! {
|
||||
"_id": &id
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"recipients": &user.id
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channel",
|
||||
})?;
|
||||
}
|
||||
|
||||
ClientboundNotification::ChannelGroupLeave {
|
||||
id: id.clone(),
|
||||
user: user.id.clone(),
|
||||
}
|
||||
.publish(id.clone());
|
||||
|
||||
Content::SystemMessage(SystemMessage::UserLeft { id: user.id })
|
||||
.send_as_system(&target)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
}
|
||||
Channel::TextChannel { .. } |
|
||||
Channel::VoiceChannel { .. } => {
|
||||
if perm.get_manage_channel() {
|
||||
target.delete().await?;
|
||||
Ok(EmptyResponse {})
|
||||
} else {
|
||||
Err(Error::MissingPermission)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::{database::*, notifications::events::RemoveChannelField};
|
||||
use revolt_quark::{EmptyResponse, Result, models::channel::FieldsChannel};
|
||||
|
||||
use mongodb::bson::{doc, to_document};
|
||||
use mongodb::bson::doc;
|
||||
use rocket::serde::json::Json;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
@@ -17,144 +15,12 @@ pub struct Data {
|
||||
description: Option<String>,
|
||||
#[validate(length(min = 1, max = 128))]
|
||||
icon: Option<String>,
|
||||
remove: Option<RemoveChannelField>,
|
||||
remove: Option<FieldsChannel>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
nsfw: Option<bool>
|
||||
}
|
||||
|
||||
#[patch("/<target>", data = "<data>")]
|
||||
pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let data = data.into_inner();
|
||||
data.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
if data.name.is_none()
|
||||
&& data.description.is_none()
|
||||
&& data.icon.is_none()
|
||||
&& data.remove.is_none()
|
||||
&& data.nsfw.is_none()
|
||||
{
|
||||
return Ok(EmptyResponse {});
|
||||
}
|
||||
|
||||
let target = target.fetch_channel().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_channel() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
match &target {
|
||||
Channel::Group { id, icon, .. }
|
||||
| Channel::TextChannel { id, icon, .. }
|
||||
| Channel::VoiceChannel { id, icon, .. } => {
|
||||
let mut set = doc! {};
|
||||
let mut unset = doc! {};
|
||||
|
||||
let mut remove_icon = false;
|
||||
if let Some(remove) = &data.remove {
|
||||
match remove {
|
||||
RemoveChannelField::Icon => {
|
||||
unset.insert("icon", 1);
|
||||
remove_icon = true;
|
||||
}
|
||||
RemoveChannelField::Description => {
|
||||
unset.insert("description", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(name) = &data.name {
|
||||
set.insert("name", name);
|
||||
}
|
||||
|
||||
if let Some(description) = &data.description {
|
||||
set.insert("description", description);
|
||||
}
|
||||
|
||||
if let Some(attachment_id) = &data.icon {
|
||||
let attachment =
|
||||
File::find_and_use(&attachment_id, "icons", "object", target.id()).await?;
|
||||
set.insert(
|
||||
"icon",
|
||||
to_document(&attachment).map_err(|_| Error::DatabaseError {
|
||||
operation: "to_document",
|
||||
with: "attachment",
|
||||
})?,
|
||||
);
|
||||
|
||||
remove_icon = true;
|
||||
}
|
||||
|
||||
if let Some(nsfw) = &data.nsfw {
|
||||
set.insert("nsfw", nsfw);
|
||||
}
|
||||
|
||||
let mut operations = doc! {};
|
||||
if set.len() > 0 {
|
||||
operations.insert("$set", &set);
|
||||
}
|
||||
|
||||
if unset.len() > 0 {
|
||||
operations.insert("$unset", unset);
|
||||
}
|
||||
|
||||
if operations.len() > 0 {
|
||||
get_collection("channels")
|
||||
.update_one(doc! { "_id": &id }, operations, None)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channel",
|
||||
})?;
|
||||
}
|
||||
|
||||
ClientboundNotification::ChannelUpdate {
|
||||
id: id.clone(),
|
||||
data: json!(set),
|
||||
clear: data.remove,
|
||||
}
|
||||
.publish(id.clone());
|
||||
|
||||
if let Channel::Group { .. } = &target {
|
||||
if let Some(name) = data.name {
|
||||
Content::SystemMessage(SystemMessage::ChannelRenamed {
|
||||
name,
|
||||
by: user.id.clone(),
|
||||
})
|
||||
.send_as_system(&target)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
if let Some(_) = data.description {
|
||||
Content::SystemMessage(SystemMessage::ChannelDescriptionChanged {
|
||||
by: user.id.clone(),
|
||||
})
|
||||
.send_as_system(&target)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
if let Some(_) = data.icon {
|
||||
Content::SystemMessage(SystemMessage::ChannelIconChanged { by: user.id })
|
||||
.send_as_system(&target)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
if remove_icon {
|
||||
if let Some(old_icon) = icon {
|
||||
old_icon.delete().await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
}
|
||||
_ => Err(Error::InvalidOperation),
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::Result;
|
||||
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
#[get("/<target>")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
||||
let target = target.fetch_channel().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
Ok(json!(target))
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,24 +1,8 @@
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::database::*;
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
|
||||
#[put("/<target>/recipients/<member>")]
|
||||
pub async fn req(user: User, target: Ref, member: Ref) -> Result<EmptyResponse> {
|
||||
if get_relationship(&user, &member.id) != RelationshipStatus::Friend {
|
||||
Err(Error::NotFriends)?
|
||||
}
|
||||
|
||||
let channel = target.fetch_channel().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&channel)
|
||||
.for_channel()
|
||||
.await?;
|
||||
|
||||
if !perm.get_invite_others() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
channel.add_to_group(member.id, user.id).await?;
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref, member: Ref*/ target: String, member: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::idempotency::IdempotencyKey;
|
||||
use crate::util::result::{Error, Result};
|
||||
use crate::util::variables::MAX_GROUP_SIZE;
|
||||
use revolt_quark::Result;
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use rocket::serde::json::{Json, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
use std::iter::FromIterator;
|
||||
use ulid::Ulid;
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Validate, Serialize, Deserialize)]
|
||||
@@ -23,47 +17,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[post("/create", data = "<info>")]
|
||||
pub async fn req(_idempotency: IdempotencyKey, user: User, info: Json<Data>) -> Result<Value> {
|
||||
if user.bot.is_some() {
|
||||
return Err(Error::IsBot)
|
||||
}
|
||||
|
||||
let info = info.into_inner();
|
||||
info.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
let mut set: HashSet<String> = HashSet::from_iter(info.users.iter().cloned());
|
||||
set.insert(user.id.clone());
|
||||
|
||||
if set.len() > *MAX_GROUP_SIZE {
|
||||
Err(Error::GroupTooLarge {
|
||||
max: *MAX_GROUP_SIZE,
|
||||
})?
|
||||
}
|
||||
|
||||
for target in &set {
|
||||
match get_relationship(&user, target) {
|
||||
RelationshipStatus::Friend | RelationshipStatus::User => {}
|
||||
_ => {
|
||||
return Err(Error::NotFriends);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let id = Ulid::new().to_string();
|
||||
let channel = Channel::Group {
|
||||
id,
|
||||
name: info.name,
|
||||
description: info.description,
|
||||
owner: user.id,
|
||||
recipients: set.into_iter().collect::<Vec<String>>(),
|
||||
icon: None,
|
||||
last_message_id: None,
|
||||
permissions: None,
|
||||
nsfw: info.nsfw.unwrap_or_default()
|
||||
};
|
||||
|
||||
channel.clone().publish().await?;
|
||||
|
||||
Ok(json!(channel))
|
||||
pub async fn req(/*_idempotency: IdempotencyKey, user: User,*/ info: Json<Data>) -> Result<Value> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
@@ -1,66 +1,8 @@
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::{database::*, notifications::events::ClientboundNotification};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
|
||||
#[delete("/<target>/recipients/<member>")]
|
||||
pub async fn req(user: User, target: Ref, member: Ref) -> Result<EmptyResponse> {
|
||||
if &user.id == &member.id {
|
||||
Err(Error::CannotRemoveYourself)?
|
||||
}
|
||||
|
||||
let channel = target.fetch_channel().await?;
|
||||
|
||||
if let Channel::Group {
|
||||
id,
|
||||
owner,
|
||||
recipients,
|
||||
..
|
||||
} = &channel
|
||||
{
|
||||
if &user.id != owner {
|
||||
// figure out if we want to use perm system here
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
if recipients.iter().find(|x| *x == &member.id).is_none() {
|
||||
Err(Error::NotInGroup)?
|
||||
}
|
||||
|
||||
get_collection("channels")
|
||||
.update_one(
|
||||
doc! {
|
||||
"_id": &id
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"recipients": &member.id
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channel",
|
||||
})?;
|
||||
|
||||
ClientboundNotification::ChannelGroupLeave {
|
||||
id: id.clone(),
|
||||
user: member.id.clone(),
|
||||
}
|
||||
.publish(id.clone());
|
||||
|
||||
Content::SystemMessage(SystemMessage::UserRemove {
|
||||
id: member.id,
|
||||
by: user.id,
|
||||
})
|
||||
.send_as_system(&channel)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
} else {
|
||||
Err(Error::InvalidOperation)
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref, member: Ref*/ target: String, member: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::Result;
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use nanoid::nanoid;
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
lazy_static! {
|
||||
@@ -14,35 +12,6 @@ lazy_static! {
|
||||
}
|
||||
|
||||
#[post("/<target>/invites")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
||||
let target = target.fetch_channel().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
|
||||
if !perm.get_invite_others() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
let code = nanoid!(8, &*ALPHABET);
|
||||
match &target {
|
||||
Channel::Group { .. } => {
|
||||
unimplemented!()
|
||||
}
|
||||
Channel::TextChannel { id, server, .. }
|
||||
| Channel::VoiceChannel { id, server, .. } => {
|
||||
Invite::Server {
|
||||
code: code.clone(),
|
||||
creator: user.id,
|
||||
server: server.clone(),
|
||||
channel: id.clone(),
|
||||
}
|
||||
.save()
|
||||
.await?;
|
||||
|
||||
Ok(json!({ "code": code }))
|
||||
}
|
||||
_ => Err(Error::InvalidOperation),
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,23 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::Result;
|
||||
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
#[get("/<target>/members")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
||||
let target = target.fetch_channel().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
if let Channel::Group { recipients, .. } = target {
|
||||
Ok(json!(user.fetch_multiple_users(&recipients).await?))
|
||||
} else {
|
||||
Err(Error::InvalidOperation)
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,29 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
|
||||
#[delete("/<target>/messages/<msg>")]
|
||||
pub async fn req(user: User, target: Ref, msg: Ref) -> Result<EmptyResponse> {
|
||||
let channel = target.fetch_channel().await?;
|
||||
channel.has_messaging()?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&channel)
|
||||
.for_channel()
|
||||
.await?;
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let message = msg.fetch_message(&channel).await?;
|
||||
if message.author != user.id && !perm.get_manage_messages() {
|
||||
match channel {
|
||||
Channel::SavedMessages { .. } => unreachable!(),
|
||||
_ => Err(Error::CannotEditMessage)?,
|
||||
}
|
||||
}
|
||||
|
||||
message.delete().await?;
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref, msg: Ref*/ target: String, msg: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::routes::channels::message_send::SendableEmbed;
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use chrono::Utc;
|
||||
use mongodb::bson::{Bson, Document, doc, to_document};
|
||||
@@ -12,95 +10,11 @@ use validator::Validate;
|
||||
pub struct Data {
|
||||
#[validate(length(min = 1, max = 2000))]
|
||||
content: Option<String>,
|
||||
#[validate(length(min = 0, max = 10))]
|
||||
embeds: Option<Vec<SendableEmbed>>
|
||||
// #[validate(length(min = 0, max = 10))]
|
||||
// embeds: Option<Vec<SendableEmbed>>
|
||||
}
|
||||
|
||||
#[patch("/<target>/messages/<msg>", data = "<edit>")]
|
||||
pub async fn req(user: User, target: Ref, msg: Ref, edit: Json<Data>) -> Result<EmptyResponse> {
|
||||
edit.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
let channel = target.fetch_channel().await?;
|
||||
channel.has_messaging()?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&channel)
|
||||
.for_channel()
|
||||
.await?;
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let mut message = msg.fetch_message(&channel).await?;
|
||||
if message.author != user.id {
|
||||
Err(Error::CannotEditMessage)?
|
||||
}
|
||||
|
||||
let edited = Utc::now();
|
||||
let mut set = doc! { "edited": Bson::DateTime(edited) };
|
||||
let mut unset = doc! {};
|
||||
let mut update = json!({ "edited": Bson::DateTime(edited) });
|
||||
|
||||
if let Some(new_content) = &edit.content {
|
||||
set.insert("content", new_content.clone());
|
||||
update.as_object_mut().unwrap().insert("content".to_string(), json!(new_content.clone()));
|
||||
message.content = Content::Text(new_content.clone());
|
||||
}
|
||||
|
||||
let mut new_embeds: Vec<Embed> = vec![];
|
||||
|
||||
if let Some(embeds) = &message.embeds {
|
||||
for embed in embeds {
|
||||
match embed {
|
||||
Embed::Text(embed) => new_embeds.push(Embed::Text(embed.clone())),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(edited_embeds) = &edit.embeds {
|
||||
new_embeds.clear();
|
||||
|
||||
for embed in edited_embeds {
|
||||
new_embeds.push(embed.clone().into_embed(message.id.clone()).await?);
|
||||
}
|
||||
}
|
||||
|
||||
if new_embeds.len() > 0 {
|
||||
let embed_docs: Vec<Document> = new_embeds
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|embed| to_document(&embed).unwrap())
|
||||
.collect();
|
||||
|
||||
let obj = update.as_object_mut().unwrap();
|
||||
obj.insert("embeds".to_string(), json!(embed_docs));
|
||||
set.insert("embeds", embed_docs);
|
||||
message.embeds = Some(new_embeds)
|
||||
} else if edit.embeds.is_some() {
|
||||
let obj = update.as_object_mut().unwrap();
|
||||
obj.insert("embeds".to_string(), json!([]));
|
||||
unset.insert("embeds", 1 as u32);
|
||||
}
|
||||
|
||||
get_collection("messages")
|
||||
.update_one(
|
||||
doc! {
|
||||
"_id": &message.id
|
||||
},
|
||||
doc! {
|
||||
"$set": set,
|
||||
"$unset": unset
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "message",
|
||||
})?;
|
||||
|
||||
message.publish_update(update).await?;
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref, msg: Ref,*/ target: String, msg: String, edit: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::Result;
|
||||
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
#[get("/<target>/messages/<msg>")]
|
||||
pub async fn req(user: User, target: Ref, msg: Ref) -> Result<Value> {
|
||||
let channel = target.fetch_channel().await?;
|
||||
channel.has_messaging()?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&channel)
|
||||
.for_channel()
|
||||
.await?;
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let message = msg.fetch_message(&channel).await?;
|
||||
Ok(json!(message))
|
||||
pub async fn req(/*user: UserRef, target: Ref, msg: Ref*/ target: String, msg: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use futures::{StreamExt, try_join};
|
||||
use mongodb::{
|
||||
@@ -36,151 +35,6 @@ pub struct Options {
|
||||
}
|
||||
|
||||
#[get("/<target>/messages?<options..>")]
|
||||
pub async fn req(user: User, target: Ref, options: Options) -> Result<Value> {
|
||||
options
|
||||
.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
let target = target.fetch_channel().await?;
|
||||
target.has_messaging()?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let mut messages = vec![];
|
||||
|
||||
let collection = get_collection("messages");
|
||||
let limit = options.limit.unwrap_or(50);
|
||||
let channel = target.id();
|
||||
if let Some(nearby) = &options.nearby {
|
||||
let mut cursors = try_join!(
|
||||
collection.find(
|
||||
doc! {
|
||||
"channel": channel,
|
||||
"_id": {
|
||||
"$gte": &nearby
|
||||
}
|
||||
},
|
||||
FindOptions::builder()
|
||||
.limit(limit / 2 + 1)
|
||||
.sort(doc! {
|
||||
"_id": 1
|
||||
})
|
||||
.build(),
|
||||
),
|
||||
collection.find(
|
||||
doc! {
|
||||
"channel": channel,
|
||||
"_id": {
|
||||
"$lt": &nearby
|
||||
}
|
||||
},
|
||||
FindOptions::builder()
|
||||
.limit(limit / 2)
|
||||
.sort(doc! {
|
||||
"_id": -1
|
||||
})
|
||||
.build(),
|
||||
)
|
||||
)
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "find",
|
||||
with: "messages",
|
||||
})?;
|
||||
|
||||
while let Some(result) = cursors.0.next().await {
|
||||
if let Ok(doc) = result {
|
||||
messages.push(
|
||||
from_document::<Message>(doc).map_err(|_| Error::DatabaseError {
|
||||
operation: "from_document",
|
||||
with: "message",
|
||||
})?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(result) = cursors.1.next().await {
|
||||
if let Ok(doc) = result {
|
||||
messages.push(
|
||||
from_document::<Message>(doc).map_err(|_| Error::DatabaseError {
|
||||
operation: "from_document",
|
||||
with: "message",
|
||||
})?,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut query = doc! { "channel": target.id() };
|
||||
if let Some(before) = &options.before {
|
||||
query.insert("_id", doc! { "$lt": before });
|
||||
}
|
||||
|
||||
if let Some(after) = &options.after {
|
||||
query.insert("_id", doc! { "$gt": after });
|
||||
}
|
||||
|
||||
let sort: i32 = if let Sort::Latest = options.sort.as_ref().unwrap_or_else(|| &Sort::Latest) {
|
||||
-1
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
let mut cursor = collection
|
||||
.find(
|
||||
query,
|
||||
FindOptions::builder()
|
||||
.limit(limit)
|
||||
.sort(doc! {
|
||||
"_id": sort
|
||||
})
|
||||
.build(),
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "find",
|
||||
with: "messages",
|
||||
})?;
|
||||
|
||||
while let Some(result) = cursor.next().await {
|
||||
if let Ok(doc) = result {
|
||||
messages.push(
|
||||
from_document::<Message>(doc).map_err(|_| Error::DatabaseError {
|
||||
operation: "from_document",
|
||||
with: "message",
|
||||
})?,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if options.include_users.unwrap_or_else(|| false) {
|
||||
let mut ids = HashSet::new();
|
||||
for message in &messages {
|
||||
message.add_associated_user_ids(&mut ids);
|
||||
}
|
||||
|
||||
ids.remove(&user.id);
|
||||
let user_ids = ids.into_iter().collect();
|
||||
let users = user.fetch_multiple_users(&user_ids).await?;
|
||||
|
||||
if let Channel::TextChannel { server, .. } = target {
|
||||
Ok(json!({
|
||||
"messages": messages,
|
||||
"users": users,
|
||||
"members": Server::fetch_members_with_ids(&server, &user_ids).await?
|
||||
}))
|
||||
} else {
|
||||
Ok(json!({
|
||||
"messages": messages,
|
||||
"users": users,
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
Ok(json!(messages))
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, options: Options) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use futures::StreamExt;
|
||||
use mongodb::bson::{doc, from_document};
|
||||
@@ -12,63 +11,6 @@ pub struct Options {
|
||||
}
|
||||
|
||||
#[post("/<target>/messages/stale", data = "<data>")]
|
||||
pub async fn req(user: User, target: Ref, data: Json<Options>) -> Result<Value> {
|
||||
if data.ids.len() > 150 {
|
||||
return Err(Error::TooManyIds);
|
||||
}
|
||||
|
||||
let target = target.fetch_channel().await?;
|
||||
target.has_messaging()?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let mut cursor = get_collection("messages")
|
||||
.find(
|
||||
doc! {
|
||||
"_id": {
|
||||
"$in": &data.ids
|
||||
},
|
||||
"channel": target.id()
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "find",
|
||||
with: "messages",
|
||||
})?;
|
||||
|
||||
let mut updated = vec![];
|
||||
let mut found_ids = vec![];
|
||||
while let Some(result) = cursor.next().await {
|
||||
if let Ok(doc) = result {
|
||||
let msg = from_document::<Message>(doc).map_err(|_| Error::DatabaseError {
|
||||
operation: "from_document",
|
||||
with: "message",
|
||||
})?;
|
||||
|
||||
found_ids.push(msg.id.clone());
|
||||
if msg.edited.is_some() {
|
||||
updated.push(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut deleted = vec![];
|
||||
for id in &data.ids {
|
||||
if found_ids.iter().find(|x| *x == id).is_none() {
|
||||
deleted.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(json!({
|
||||
"updated": updated,
|
||||
"deleted": deleted
|
||||
}))
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Options>) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::Result;
|
||||
|
||||
use futures::StreamExt;
|
||||
use mongodb::{
|
||||
@@ -42,121 +39,6 @@ pub struct Options {
|
||||
}
|
||||
|
||||
#[post("/<target>/search", data = "<options>")]
|
||||
pub async fn req(user: User, target: Ref, options: Json<Options>) -> Result<Value> {
|
||||
options
|
||||
.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
let target = target.fetch_channel().await?;
|
||||
target.has_messaging()?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let mut messages = vec![];
|
||||
let limit = options.limit.unwrap_or(50);
|
||||
|
||||
let mut filter = doc! {
|
||||
"channel": target.id(),
|
||||
"$text": {
|
||||
"$search": &options.query
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(doc) = match (&options.before, &options.after) {
|
||||
(Some(before), Some(after)) => Some(doc! {
|
||||
"lt": before,
|
||||
"gt": after
|
||||
}),
|
||||
(Some(before), _) => Some(doc! {
|
||||
"lt": before
|
||||
}),
|
||||
(_, Some(after)) => Some(doc! {
|
||||
"gt": after
|
||||
}),
|
||||
_ => None
|
||||
} {
|
||||
filter.insert("_id", doc);
|
||||
}
|
||||
|
||||
let mut cursor = get_collection("messages")
|
||||
.find(
|
||||
filter,
|
||||
FindOptions::builder()
|
||||
.projection(
|
||||
if let Sort::Relevance = &options.sort {
|
||||
doc! {
|
||||
"score": {
|
||||
"$meta": "textScore"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doc! {}
|
||||
}
|
||||
)
|
||||
.limit(limit)
|
||||
.sort(
|
||||
match &options.sort {
|
||||
Sort::Relevance => doc! {
|
||||
"score": {
|
||||
"$meta": "textScore"
|
||||
}
|
||||
},
|
||||
Sort::Latest => doc! {
|
||||
"_id": -1 as i32
|
||||
},
|
||||
Sort::Oldest => doc! {
|
||||
"_id": 1 as i32
|
||||
}
|
||||
}
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "find",
|
||||
with: "messages",
|
||||
})?;
|
||||
|
||||
while let Some(result) = cursor.next().await {
|
||||
if let Ok(doc) = result {
|
||||
messages.push(
|
||||
from_document::<Message>(doc).map_err(|_| Error::DatabaseError {
|
||||
operation: "from_document",
|
||||
with: "message",
|
||||
})?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if options.include_users.unwrap_or_else(|| false) {
|
||||
let mut ids = HashSet::new();
|
||||
for message in &messages {
|
||||
message.add_associated_user_ids(&mut ids);
|
||||
}
|
||||
|
||||
ids.remove(&user.id);
|
||||
let user_ids = ids.into_iter().collect();
|
||||
let users = user.fetch_multiple_users(&user_ids).await?;
|
||||
|
||||
if let Channel::TextChannel { server, .. } = target {
|
||||
Ok(json!({
|
||||
"messages": messages,
|
||||
"users": users,
|
||||
"members": Server::fetch_members_with_ids(&server, &user_ids).await?
|
||||
}))
|
||||
} else {
|
||||
Ok(json!({
|
||||
"messages": messages,
|
||||
"users": users,
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
Ok(json!(messages))
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, options: Json<Options>) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::database::*;
|
||||
use crate::util::idempotency::IdempotencyKey;
|
||||
use crate::util::ratelimit::{Ratelimiter, RatelimitResponse};
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Result, models::message::Masquerade};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use regex::Regex;
|
||||
use rocket::serde::json::{Json, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ulid::Ulid;
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -29,24 +23,6 @@ pub struct SendableEmbed {
|
||||
media: Option<String>,
|
||||
colour: Option<String>,
|
||||
}
|
||||
|
||||
impl SendableEmbed {
|
||||
pub async fn into_embed(self, message_id: String) -> Result<Embed> {
|
||||
let media = if let Some(id) = self.media {
|
||||
Some(File::find_and_use(&id, "attachments", "message", &message_id).await?)
|
||||
} else { None };
|
||||
|
||||
Ok(Embed::Text(Text {
|
||||
icon_url: self.icon_url,
|
||||
url: self.url,
|
||||
title: self.title,
|
||||
description: self.description,
|
||||
media,
|
||||
colour: self.colour
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Validate, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
#[validate(length(min = 0, max = 2000))]
|
||||
@@ -55,7 +31,7 @@ pub struct Data {
|
||||
attachments: Option<Vec<String>>,
|
||||
nonce: Option<String>,
|
||||
replies: Option<Vec<Reply>>,
|
||||
#[validate]
|
||||
//#[validate]
|
||||
masquerade: Option<Masquerade>,
|
||||
#[validate(length(min = 1, max = 10))]
|
||||
embeds: Option<Vec<SendableEmbed>>
|
||||
@@ -67,115 +43,6 @@ lazy_static! {
|
||||
}
|
||||
|
||||
#[post("/<target>/messages", data = "<message>")]
|
||||
pub async fn message_send(user: User, _r: Ratelimiter, mut idempotency: IdempotencyKey, target: Ref, message: Json<Data>) -> Result<RatelimitResponse<Value>> {
|
||||
let message = message.into_inner();
|
||||
idempotency.consume_nonce(message.nonce.clone());
|
||||
|
||||
message
|
||||
.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
if message.content.len() == 0
|
||||
&& (message.attachments.is_none() || message.attachments.as_ref().unwrap().len() == 0)
|
||||
{
|
||||
return Err(Error::EmptyMessage);
|
||||
}
|
||||
|
||||
let target = target.fetch_channel().await?;
|
||||
target.has_messaging()?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
|
||||
if !perm.get_send_message() {
|
||||
return Err(Error::MissingPermission)
|
||||
}
|
||||
|
||||
let mut mentions = HashSet::new();
|
||||
for capture in RE_MENTION.captures_iter(&message.content) {
|
||||
if let Some(mention) = capture.get(1) {
|
||||
mentions.insert(mention.as_str().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(_) = &message.masquerade {
|
||||
if !perm.get_masquerade() {
|
||||
return Err(Error::MissingPermission)
|
||||
}
|
||||
}
|
||||
|
||||
let mut replies = HashSet::new();
|
||||
if let Some(entries) = message.replies {
|
||||
// ! FIXME: move this to app config
|
||||
if entries.len() > 5 {
|
||||
return Err(Error::TooManyReplies)
|
||||
}
|
||||
|
||||
for Reply { id, mention } in entries {
|
||||
let message = Ref::from_unchecked(id)
|
||||
.fetch_message(&target)
|
||||
.await?;
|
||||
|
||||
replies.insert(message.id);
|
||||
|
||||
if mention {
|
||||
mentions.insert(message.author);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let id = Ulid::new().to_string();
|
||||
let mut attachments = vec![];
|
||||
|
||||
if let Some(ids) = &message.attachments {
|
||||
if ids.len() > 0 && !perm.get_upload_files() {
|
||||
return Err(Error::MissingPermission)
|
||||
}
|
||||
|
||||
// ! FIXME: move this to app config
|
||||
if ids.len() > 5 {
|
||||
return Err(Error::TooManyAttachments)
|
||||
}
|
||||
|
||||
for attachment_id in ids {
|
||||
attachments
|
||||
.push(File::find_and_use(attachment_id, "attachments", "message", &id).await?);
|
||||
}
|
||||
}
|
||||
|
||||
let mut embeds = vec![];
|
||||
|
||||
if let Some(sendable_embeds) = message.embeds {
|
||||
for sendable_embed in sendable_embeds {
|
||||
embeds.push(sendable_embed.into_embed(id.clone()).await?)
|
||||
}
|
||||
}
|
||||
|
||||
let msg = Message {
|
||||
id,
|
||||
channel: target.id().to_string(),
|
||||
author: user.id,
|
||||
|
||||
content: Content::Text(message.content.clone()),
|
||||
nonce: Some(idempotency.key),
|
||||
edited: None,
|
||||
embeds: if embeds.len() > 0 { Some(embeds) } else { None },
|
||||
attachments: if attachments.len() > 0 { Some(attachments) } else { None },
|
||||
mentions: if mentions.len() > 0 {
|
||||
Some(mentions.into_iter().collect::<Vec<String>>())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
replies: if replies.len() > 0 {
|
||||
Some(replies.into_iter().collect::<Vec<String>>())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
masquerade: message.masquerade
|
||||
};
|
||||
|
||||
msg.clone().publish(&target, perm.get_embed_links()).await?;
|
||||
Ok(RatelimitResponse(json!(msg)))
|
||||
pub async fn message_send(/*user: UserRef, _r: Ratelimiter, mut idempotency: IdempotencyKey, target: Ref,*/ target: String, message: Json<Data>) -> /*Result<RatelimitResponse<Value>>*/ Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@ use rocket::serde::json::Json;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use validator::Contains;
|
||||
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
@@ -13,56 +11,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[put("/<target>/permissions/<role>", data = "<data>", rank = 2)]
|
||||
pub async fn req(user: User, target: Ref, role: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let target = target.fetch_channel().await?;
|
||||
|
||||
match target {
|
||||
Channel::TextChannel { id, server, mut role_permissions, .. }
|
||||
| Channel::VoiceChannel { id, server, mut role_permissions, .. } => {
|
||||
let target = Ref::from_unchecked(server).fetch_server().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_roles() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
if !target.roles.has_element(&role) {
|
||||
return Err(Error::NotFound);
|
||||
}
|
||||
|
||||
let permissions: u32 = data.permissions;
|
||||
|
||||
get_collection("channels")
|
||||
.update_one(
|
||||
doc! { "_id": &id },
|
||||
doc! {
|
||||
"$set": {
|
||||
"role_permissions.".to_owned() + &role: permissions as i32
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channel"
|
||||
})?;
|
||||
|
||||
role_permissions.insert(role, permissions as i32);
|
||||
ClientboundNotification::ChannelUpdate {
|
||||
id: id.clone(),
|
||||
data: json!({
|
||||
"role_permissions": role_permissions
|
||||
}),
|
||||
clear: None
|
||||
}
|
||||
.publish(id);
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
}
|
||||
_ => Err(Error::InvalidOperation)
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, role: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@ use mongodb::bson::doc;
|
||||
use rocket::serde::json::Json;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::database::*;
|
||||
use crate::database::permissions::channel::{ ChannelPermission, DEFAULT_PERMISSION_DM };
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
@@ -13,85 +10,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[put("/<target>/permissions/default", data = "<data>", rank = 1)]
|
||||
pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let target = target.fetch_channel().await?;
|
||||
|
||||
match target {
|
||||
Channel::Group { id, owner, .. } => {
|
||||
if user.id == owner {
|
||||
let permissions: u32 = ChannelPermission::View as u32 | (data.permissions & *DEFAULT_PERMISSION_DM);
|
||||
|
||||
get_collection("channels")
|
||||
.update_one(
|
||||
doc! { "_id": &id },
|
||||
doc! {
|
||||
"$set": {
|
||||
"permissions": permissions as i32
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channel"
|
||||
})?;
|
||||
|
||||
ClientboundNotification::ChannelUpdate {
|
||||
id: id.clone(),
|
||||
data: json!({
|
||||
"permissions": permissions as i32
|
||||
}),
|
||||
clear: None
|
||||
}
|
||||
.publish(id);
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
} else {
|
||||
Err(Error::MissingPermission)
|
||||
}
|
||||
}
|
||||
Channel::TextChannel { id, server, .. }
|
||||
| Channel::VoiceChannel { id, server, .. } => {
|
||||
let target = Ref::from_unchecked(server).fetch_server().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_roles() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
let permissions: u32 = data.permissions;
|
||||
|
||||
get_collection("channels")
|
||||
.update_one(
|
||||
doc! { "_id": &id },
|
||||
doc! {
|
||||
"$set": {
|
||||
"default_permissions": permissions as i32
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channel"
|
||||
})?;
|
||||
|
||||
ClientboundNotification::ChannelUpdate {
|
||||
id: id.clone(),
|
||||
data: json!({
|
||||
"default_permissions": permissions as i32
|
||||
}),
|
||||
clear: None
|
||||
}
|
||||
.publish(id);
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
}
|
||||
_ => Err(Error::InvalidOperation)
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use crate::util::variables::{USE_VOSO, VOSO_MANAGE_TOKEN, VOSO_URL};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use rocket::serde::json::Value;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -11,81 +9,6 @@ struct CreateUserResponse {
|
||||
}
|
||||
|
||||
#[post("/<target>/join_call")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
||||
if !*USE_VOSO {
|
||||
return Err(Error::VosoUnavailable);
|
||||
}
|
||||
|
||||
let target = target.fetch_channel().await?;
|
||||
match target {
|
||||
Channel::SavedMessages { .. } | Channel::TextChannel { .. } => {
|
||||
return Err(Error::CannotJoinCall)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_channel(&target)
|
||||
.for_channel()
|
||||
.await?;
|
||||
|
||||
if !perm.get_voice_call() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
// To join a call:
|
||||
// - Check if the room exists.
|
||||
// - If not, create it.
|
||||
let client = reqwest::Client::new();
|
||||
let result = client
|
||||
.get(&format!("{}/room/{}", *VOSO_URL, target.id()))
|
||||
.header(
|
||||
reqwest::header::AUTHORIZATION,
|
||||
VOSO_MANAGE_TOKEN.to_string(),
|
||||
)
|
||||
.send()
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Err(_) => return Err(Error::VosoUnavailable),
|
||||
Ok(result) => match result.status() {
|
||||
reqwest::StatusCode::OK => (),
|
||||
reqwest::StatusCode::NOT_FOUND => {
|
||||
if let Err(_) = client
|
||||
.post(&format!("{}/room/{}", *VOSO_URL, target.id()))
|
||||
.header(
|
||||
reqwest::header::AUTHORIZATION,
|
||||
VOSO_MANAGE_TOKEN.to_string(),
|
||||
)
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
return Err(Error::VosoUnavailable);
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::VosoUnavailable),
|
||||
},
|
||||
}
|
||||
|
||||
// Then create a user for the room.
|
||||
if let Ok(response) = client
|
||||
.post(&format!(
|
||||
"{}/room/{}/user/{}",
|
||||
*VOSO_URL,
|
||||
target.id(),
|
||||
user.id
|
||||
))
|
||||
.header(
|
||||
reqwest::header::AUTHORIZATION,
|
||||
VOSO_MANAGE_TOKEN.to_string(),
|
||||
)
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
let res: CreateUserResponse = response.json().await.map_err(|_| Error::InvalidOperation)?;
|
||||
|
||||
Ok(json!(res))
|
||||
} else {
|
||||
Err(Error::VosoUnavailable)
|
||||
}
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user