Invite bot to server / group for #8.

This commit is contained in:
Paul
2021-08-12 09:24:06 +01:00
parent 93610ebbc3
commit 9f749cfdf8
7 changed files with 127 additions and 51 deletions

View File

@@ -3,6 +3,7 @@ use std::collections::HashMap;
use crate::database::*;
use crate::notifications::events::ClientboundNotification;
use crate::util::result::{Error, Result};
use crate::util::variables::MAX_GROUP_SIZE;
use futures::StreamExt;
use mongodb::bson::Bson;
use mongodb::{
@@ -344,4 +345,53 @@ impl Channel {
Ok(())
}
pub async fn add_to_group(&self, member: String, by_user: String) -> Result<()> {
if let Channel::Group { id, recipients, .. } = &self {
if recipients.len() >= *MAX_GROUP_SIZE {
Err(Error::GroupTooLarge {
max: *MAX_GROUP_SIZE,
})?
}
if recipients.iter().find(|x| *x == &member).is_some() {
Err(Error::AlreadyInGroup)?
}
get_collection("channels")
.update_one(
doc! {
"_id": &id
},
doc! {
"$push": {
"recipients": &member
}
},
None,
)
.await
.map_err(|_| Error::DatabaseError {
operation: "update_one",
with: "channel",
})?;
ClientboundNotification::ChannelGroupJoin {
id: id.clone(),
user: member.clone(),
}
.publish(id.clone());
Content::SystemMessage(SystemMessage::UserAdded {
id: member,
by: by_user,
})
.send_as_system(&self)
.await
.ok();
Ok(())
} else {
Err(Error::InvalidOperation)
}
}
}

View File

@@ -61,6 +61,10 @@ impl Ref {
self.fetch("channel_invites").await
}
pub async fn fetch_bot(&self) -> Result<Bot> {
self.fetch("bots").await
}
pub async fn fetch_member(&self, server: &str) -> Result<Member> {
let doc = get_collection("server_members")
.find_one(

65
src/routes/bots/invite.rs Normal file
View File

@@ -0,0 +1,65 @@
use crate::database::*;
use crate::util::result::{Error, Result};
use rocket::serde::json::Json;
use serde::Deserialize;
#[derive(Deserialize)]
pub struct ServerId {
server: String
}
#[derive(Deserialize)]
pub struct GroupId {
group: String
}
#[derive(Deserialize)]
#[serde(untagged)]
pub enum Destination {
Server(ServerId),
Group(GroupId)
}
#[post("/<target>/invite", data = "<dest>")]
pub async fn invite_bot(user: User, target: Ref, dest: Json<Destination>) -> Result<()> {
let bot = target.fetch_bot().await?;
if !bot.public {
if bot.owner != user.id {
return Err(Error::BotIsPrivate);
}
}
match dest.into_inner() {
Destination::Server(ServerId { server }) => {
let server = Ref::from(server)?.fetch_server().await?;
let perm = permissions::PermissionCalculator::new(&user)
.with_server(&server)
.for_server()
.await?;
if !perm.get_manage_server() {
Err(Error::MissingPermission)?
}
server.join_member(&bot.id).await?;
Ok(())
}
Destination::Group(GroupId { group }) => {
let channel = Ref::from(group)?.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(bot.id, user.id).await
}
}
}

View File

@@ -1,9 +1,11 @@
use rocket::Route;
mod create;
mod invite;
pub fn routes() -> Vec<Route> {
routes![
create::create_bot
create::create_bot,
invite::invite_bot
]
}

View File

@@ -1,6 +1,5 @@
use crate::util::result::{Error, Result};
use crate::util::variables::MAX_GROUP_SIZE;
use crate::{database::*, notifications::events::ClientboundNotification};
use crate::database::*;
use mongodb::bson::doc;
@@ -20,51 +19,5 @@ pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
Err(Error::MissingPermission)?
}
if let Channel::Group { id, recipients, .. } = &channel {
if recipients.len() >= *MAX_GROUP_SIZE {
Err(Error::GroupTooLarge {
max: *MAX_GROUP_SIZE,
})?
}
if recipients.iter().find(|x| *x == &member.id).is_some() {
Err(Error::AlreadyInGroup)?
}
get_collection("channels")
.update_one(
doc! {
"_id": &id
},
doc! {
"$push": {
"recipients": &member.id
}
},
None,
)
.await
.map_err(|_| Error::DatabaseError {
operation: "update_one",
with: "channel",
})?;
ClientboundNotification::ChannelGroupJoin {
id: id.clone(),
user: member.id.clone(),
}
.publish(id.clone());
Content::SystemMessage(SystemMessage::UserAdded {
id: member.id,
by: user.id,
})
.send_as_system(&channel)
.await
.ok();
Ok(())
} else {
Err(Error::InvalidOperation)
}
channel.add_to_group(member.id, user.id).await
}

View File

@@ -1,5 +1,5 @@
use crate::database::*;
use crate::util::result::Result;
use crate::util::result::{Error, Result};
use mongodb::bson::doc;
use rocket::serde::json::Value;

View File

@@ -47,6 +47,7 @@ pub enum Error {
// ? Bot related errors.
ReachedMaximumBots,
IsBot,
BotIsPrivate,
// ? General errors.
TooManyIds,
@@ -104,6 +105,7 @@ impl<'r> Responder<'r, 'static> for Error {
Error::ReachedMaximumBots => Status::BadRequest,
Error::IsBot => Status::BadRequest,
Error::BotIsPrivate => Status::Forbidden,
Error::FailedValidation { .. } => Status::UnprocessableEntity,
Error::DatabaseError { .. } => Status::InternalServerError,