chore(doc): comment channel routes
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
use revolt_quark::{models::User, perms, Db, EmptyResponse, Permission, Ref, Result};
|
use revolt_quark::{models::User, perms, Db, EmptyResponse, Permission, Ref, Result};
|
||||||
|
|
||||||
|
/// # Acknowledge Message
|
||||||
|
///
|
||||||
|
/// Lets the server and all other clients know that we've seen this message id in this channel.
|
||||||
|
#[openapi(tag = "Messaging")]
|
||||||
#[put("/<target>/ack/<message>")]
|
#[put("/<target>/ack/<message>")]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref, message: Ref) -> Result<EmptyResponse> {
|
pub async fn req(db: &Db, user: User, target: Ref, message: Ref) -> Result<EmptyResponse> {
|
||||||
let channel = target.as_channel(db).await?;
|
let channel = target.as_channel(db).await?;
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ use revolt_quark::{
|
|||||||
perms, Db, EmptyResponse, Error, Permission, Ref, Result,
|
perms, Db, EmptyResponse, Error, Permission, Ref, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// # Close Channel
|
||||||
|
///
|
||||||
|
/// Deletes a server channel, leaves a group or closes a group.
|
||||||
|
#[openapi(tag = "Channel Information")]
|
||||||
#[delete("/<target>")]
|
#[delete("/<target>")]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
|
pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
|
||||||
let mut channel = target.as_channel(db).await?;
|
let mut channel = target.as_channel(db).await?;
|
||||||
|
|||||||
@@ -10,28 +10,39 @@ use rocket::{serde::json::Json, State};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Validate, Serialize, Deserialize)]
|
/// # Channel Details
|
||||||
pub struct Data {
|
#[derive(Validate, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct DataEditChannel {
|
||||||
|
/// Channel name
|
||||||
#[validate(length(min = 1, max = 32))]
|
#[validate(length(min = 1, max = 32))]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
/// Channel description
|
||||||
#[validate(length(min = 0, max = 1024))]
|
#[validate(length(min = 0, max = 1024))]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
|
/// Icon
|
||||||
|
///
|
||||||
|
/// Provide an Autumn attachment Id.
|
||||||
#[validate(length(min = 1, max = 128))]
|
#[validate(length(min = 1, max = 128))]
|
||||||
icon: Option<String>,
|
icon: Option<String>,
|
||||||
|
/// Whether this channel is age-restricted
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
nsfw: Option<bool>,
|
nsfw: Option<bool>,
|
||||||
#[validate(length(min = 1))]
|
#[validate(length(min = 1))]
|
||||||
remove: Option<Vec<FieldsChannel>>,
|
remove: Option<Vec<FieldsChannel>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Edit Channel
|
||||||
|
///
|
||||||
|
/// Edit a channel object by its id.
|
||||||
|
#[openapi(tag = "Channel Information")]
|
||||||
#[patch("/<target>", data = "<data>")]
|
#[patch("/<target>", data = "<data>")]
|
||||||
pub async fn req(
|
pub async fn req(
|
||||||
db: &State<Database>,
|
db: &State<Database>,
|
||||||
user: User,
|
user: User,
|
||||||
target: Ref,
|
target: Ref,
|
||||||
data: Json<Data>,
|
data: Json<DataEditChannel>,
|
||||||
) -> Result<Json<Channel>> {
|
) -> Result<Json<Channel>> {
|
||||||
let data = data.into_inner();
|
let data = data.into_inner();
|
||||||
data.validate()
|
data.validate()
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ use revolt_quark::{
|
|||||||
|
|
||||||
use rocket::{serde::json::Json, State};
|
use rocket::{serde::json::Json, State};
|
||||||
|
|
||||||
|
/// # Fetch Channel
|
||||||
|
///
|
||||||
|
/// Fetch channel by its id.
|
||||||
|
#[openapi(tag = "Channel Information")]
|
||||||
#[get("/<target>")]
|
#[get("/<target>")]
|
||||||
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<Channel>> {
|
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<Channel>> {
|
||||||
let channel = target.as_channel(db).await?;
|
let channel = target.as_channel(db).await?;
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ use revolt_quark::{
|
|||||||
perms, Db, EmptyResponse, Error, Permission, Ref, Result,
|
perms, Db, EmptyResponse, Error, Permission, Ref, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// # Add Member to Group
|
||||||
|
///
|
||||||
|
/// Adds another user to the group.
|
||||||
|
#[openapi(tag = "Groups")]
|
||||||
#[put("/<target>/recipients/<member>")]
|
#[put("/<target>/recipients/<member>")]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref, member: Ref) -> Result<EmptyResponse> {
|
pub async fn req(db: &Db, user: User, target: Ref, member: Ref) -> Result<EmptyResponse> {
|
||||||
let channel = target.as_channel(db).await?;
|
let channel = target.as_channel(db).await?;
|
||||||
|
|||||||
@@ -13,19 +13,31 @@ use validator::Validate;
|
|||||||
|
|
||||||
use crate::util::variables::MAX_GROUP_SIZE;
|
use crate::util::variables::MAX_GROUP_SIZE;
|
||||||
|
|
||||||
#[derive(Validate, Serialize, Deserialize)]
|
/// # Group Data
|
||||||
pub struct Data {
|
#[derive(Validate, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct DataCreateGroup {
|
||||||
|
/// Group name
|
||||||
#[validate(length(min = 1, max = 32))]
|
#[validate(length(min = 1, max = 32))]
|
||||||
name: String,
|
name: String,
|
||||||
|
/// Group description
|
||||||
#[validate(length(min = 0, max = 1024))]
|
#[validate(length(min = 0, max = 1024))]
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
|
/// Array of user IDs to add to the group
|
||||||
|
///
|
||||||
|
/// Must be friends with these users.
|
||||||
|
#[validate(length(min = 0, max = 49))]
|
||||||
users: Vec<String>,
|
users: Vec<String>,
|
||||||
|
/// Whether this group is age-restricted
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
nsfw: Option<bool>,
|
nsfw: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Create Group
|
||||||
|
///
|
||||||
|
/// Create a new group channel.
|
||||||
|
#[openapi(tag = "Groups")]
|
||||||
#[post("/create", data = "<info>")]
|
#[post("/create", data = "<info>")]
|
||||||
pub async fn req(db: &Db, user: User, info: Json<Data>) -> Result<Json<Channel>> {
|
pub async fn req(db: &Db, user: User, info: Json<DataCreateGroup>) -> Result<Json<Channel>> {
|
||||||
let info = info.into_inner();
|
let info = info.into_inner();
|
||||||
info.validate()
|
info.validate()
|
||||||
.map_err(|error| Error::FailedValidation { error })?;
|
.map_err(|error| Error::FailedValidation { error })?;
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ use revolt_quark::{
|
|||||||
Db, EmptyResponse, Error, Permission, Ref, Result,
|
Db, EmptyResponse, Error, Permission, Ref, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// # Remove Member from Group
|
||||||
|
///
|
||||||
|
/// Removes a user from the group.
|
||||||
|
#[openapi(tag = "Groups")]
|
||||||
#[delete("/<target>/recipients/<member>")]
|
#[delete("/<target>/recipients/<member>")]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref, member: Ref) -> Result<EmptyResponse> {
|
pub async fn req(db: &Db, user: User, target: Ref, member: Ref) -> Result<EmptyResponse> {
|
||||||
let channel = target.as_channel(db).await?;
|
let channel = target.as_channel(db).await?;
|
||||||
|
|||||||
@@ -5,6 +5,12 @@ use revolt_quark::{
|
|||||||
|
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
|
|
||||||
|
/// # Create Invite
|
||||||
|
///
|
||||||
|
/// Creates an invite to this channel.
|
||||||
|
///
|
||||||
|
/// Channel must be a `TextChannel`.
|
||||||
|
#[openapi(tag = "Channel Invites")]
|
||||||
#[post("/<target>/invites")]
|
#[post("/<target>/invites")]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref) -> Result<Json<Invite>> {
|
pub async fn req(db: &Db, user: User, target: Ref) -> Result<Json<Invite>> {
|
||||||
let channel = target.as_channel(db).await?;
|
let channel = target.as_channel(db).await?;
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ use revolt_quark::{
|
|||||||
|
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
|
|
||||||
|
/// # Fetch Group Members
|
||||||
|
///
|
||||||
|
/// Retrieves all users who are part of this group.
|
||||||
|
#[openapi(tag = "Groups")]
|
||||||
#[get("/<target>/members")]
|
#[get("/<target>/members")]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref) -> Result<Json<Vec<User>>> {
|
pub async fn req(db: &Db, user: User, target: Ref) -> Result<Json<Vec<User>>> {
|
||||||
let channel = target.as_channel(db).await?;
|
let channel = target.as_channel(db).await?;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Permission, Ref, Result};
|
use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Permission, Ref, Result};
|
||||||
|
|
||||||
|
/// # Delete Message
|
||||||
|
///
|
||||||
|
/// Delete a message you've sent or one you have permission to delete.
|
||||||
|
#[openapi(tag = "Messaging")]
|
||||||
#[delete("/<target>/messages/<msg>")]
|
#[delete("/<target>/messages/<msg>")]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref, msg: Ref) -> Result<EmptyResponse> {
|
pub async fn req(db: &Db, user: User, target: Ref, msg: Ref) -> Result<EmptyResponse> {
|
||||||
let message = msg.as_message(db).await?;
|
let message = msg.as_message(db).await?;
|
||||||
|
|||||||
@@ -11,21 +11,28 @@ use rocket::serde::json::Json;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Validate, Serialize, Deserialize)]
|
/// # Message Details
|
||||||
pub struct Data {
|
#[derive(Validate, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct DataEditMessage {
|
||||||
|
/// New message content
|
||||||
#[validate(length(min = 1, max = 2000))]
|
#[validate(length(min = 1, max = 2000))]
|
||||||
content: Option<String>,
|
content: Option<String>,
|
||||||
|
/// Embeds to include in the message
|
||||||
#[validate(length(min = 0, max = 10))]
|
#[validate(length(min = 0, max = 10))]
|
||||||
embeds: Option<Vec<SendableEmbed>>,
|
embeds: Option<Vec<SendableEmbed>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Edit Message
|
||||||
|
///
|
||||||
|
/// Edits a message that you've previously sent.
|
||||||
|
#[openapi(tag = "Messaging")]
|
||||||
#[patch("/<target>/messages/<msg>", data = "<edit>")]
|
#[patch("/<target>/messages/<msg>", data = "<edit>")]
|
||||||
pub async fn req(
|
pub async fn req(
|
||||||
db: &Db,
|
db: &Db,
|
||||||
user: User,
|
user: User,
|
||||||
target: String,
|
target: String,
|
||||||
msg: Ref,
|
msg: Ref,
|
||||||
edit: Json<Data>,
|
edit: Json<DataEditMessage>,
|
||||||
) -> Result<Json<Message>> {
|
) -> Result<Json<Message>> {
|
||||||
let edit = edit.into_inner();
|
let edit = edit.into_inner();
|
||||||
edit.validate()
|
edit.validate()
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ use revolt_quark::{
|
|||||||
|
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
|
|
||||||
|
/// # Fetch Message
|
||||||
|
///
|
||||||
|
/// Retrieves a message by its id.
|
||||||
|
#[openapi(tag = "Messaging")]
|
||||||
#[get("/<target>/messages/<msg>")]
|
#[get("/<target>/messages/<msg>")]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref, msg: Ref) -> Result<Json<Message>> {
|
pub async fn req(db: &Db, user: User, target: Ref, msg: Ref) -> Result<Json<Message>> {
|
||||||
let channel = target.as_channel(db).await?;
|
let channel = target.as_channel(db).await?;
|
||||||
|
|||||||
@@ -9,29 +9,43 @@ use rocket::serde::json::Json;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Validate, Serialize, Deserialize, FromForm)]
|
/// # Query Parameters
|
||||||
pub struct Options {
|
#[derive(Validate, Serialize, Deserialize, JsonSchema, FromForm)]
|
||||||
|
pub struct OptionsQueryMessages {
|
||||||
|
/// Maximum number of messages to fetch
|
||||||
|
///
|
||||||
|
/// For fetching nearby messages, this is \`(limit + 1)\`.
|
||||||
#[validate(range(min = 1, max = 100))]
|
#[validate(range(min = 1, max = 100))]
|
||||||
limit: Option<i64>,
|
limit: Option<i64>,
|
||||||
|
/// Message id before which messages should be fetched
|
||||||
#[validate(length(min = 26, max = 26))]
|
#[validate(length(min = 26, max = 26))]
|
||||||
before: Option<String>,
|
before: Option<String>,
|
||||||
|
/// Message id after which messages should be fetched
|
||||||
#[validate(length(min = 26, max = 26))]
|
#[validate(length(min = 26, max = 26))]
|
||||||
after: Option<String>,
|
after: Option<String>,
|
||||||
|
/// Message sort direction
|
||||||
sort: Option<MessageSort>,
|
sort: Option<MessageSort>,
|
||||||
// Specifying 'nearby' ignores 'before', 'after' and 'sort'.
|
/// Message id to search around
|
||||||
// It will also take half of limit rounded as the limits to each side.
|
///
|
||||||
// It also fetches the message ID specified.
|
/// Specifying 'nearby' ignores 'before', 'after' and 'sort'.
|
||||||
|
/// It will also take half of limit rounded as the limits to each side.
|
||||||
|
/// It also fetches the message ID specified.
|
||||||
#[validate(length(min = 26, max = 26))]
|
#[validate(length(min = 26, max = 26))]
|
||||||
nearby: Option<String>,
|
nearby: Option<String>,
|
||||||
|
/// Whether to include user (and member, if server channel) objects
|
||||||
include_users: Option<bool>,
|
include_users: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Fetch Messages
|
||||||
|
///
|
||||||
|
/// Fetch multiple messages.
|
||||||
|
#[openapi(tag = "Messaging")]
|
||||||
#[get("/<target>/messages?<options..>")]
|
#[get("/<target>/messages?<options..>")]
|
||||||
pub async fn req(
|
pub async fn req(
|
||||||
db: &Db,
|
db: &Db,
|
||||||
user: User,
|
user: User,
|
||||||
target: Ref,
|
target: Ref,
|
||||||
options: Options,
|
options: OptionsQueryMessages,
|
||||||
) -> Result<Json<BulkMessageResponse>> {
|
) -> Result<Json<BulkMessageResponse>> {
|
||||||
options
|
options
|
||||||
.validate()
|
.validate()
|
||||||
@@ -47,7 +61,7 @@ pub async fn req(
|
|||||||
.throw_permission_and_view_channel(db, Permission::ReadMessageHistory)
|
.throw_permission_and_view_channel(db, Permission::ReadMessageHistory)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let Options {
|
let OptionsQueryMessages {
|
||||||
limit,
|
limit,
|
||||||
before,
|
before,
|
||||||
after,
|
after,
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
use revolt_quark::{models::User, Ref, Result};
|
use revolt_quark::{models::User, Ref, Result};
|
||||||
|
|
||||||
use rocket::serde::json::{Json, Value};
|
use rocket::serde::json::Json;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
/// # Query Parameters
|
||||||
pub struct Options {
|
#[derive(Validate, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct OptionsQueryStale {
|
||||||
|
/// Array of message IDs
|
||||||
|
#[validate(length(min = 0, max = 150))]
|
||||||
ids: Vec<String>,
|
ids: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Poll Message Changes
|
||||||
|
///
|
||||||
|
/// This route returns any changed message objects and tells you if any have been deleted.
|
||||||
|
///
|
||||||
|
/// Don't actually poll this route, instead use this to update your local database.
|
||||||
|
///
|
||||||
|
/// **DEPRECATED**
|
||||||
|
#[openapi(tag = "Messaging")]
|
||||||
#[post("/<_target>/messages/stale", data = "<_data>")]
|
#[post("/<_target>/messages/stale", data = "<_data>")]
|
||||||
pub async fn req(_user: User, _target: Ref, _data: Json<Options>) -> Result<Value> {
|
pub async fn req(_user: User, _target: Ref, _data: Json<OptionsQueryStale>) -> Result<()> {
|
||||||
unimplemented!()
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,28 +10,43 @@ use rocket::serde::json::Json;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Validate, Serialize, Deserialize, FromForm)]
|
/// # Search Parameters
|
||||||
pub struct Options {
|
#[derive(Validate, Serialize, Deserialize, JsonSchema, FromForm)]
|
||||||
|
pub struct OptionsMessageSearch {
|
||||||
|
/// Full-text search query
|
||||||
|
///
|
||||||
|
/// See [MongoDB documentation](https://docs.mongodb.com/manual/text-search/#-text-operator) for more information.
|
||||||
#[validate(length(min = 1, max = 64))]
|
#[validate(length(min = 1, max = 64))]
|
||||||
query: String,
|
query: String,
|
||||||
|
|
||||||
|
/// Maximum number of messages to fetch
|
||||||
#[validate(range(min = 1, max = 100))]
|
#[validate(range(min = 1, max = 100))]
|
||||||
limit: Option<i64>,
|
limit: Option<i64>,
|
||||||
|
/// Message id before which messages should be fetched
|
||||||
#[validate(length(min = 26, max = 26))]
|
#[validate(length(min = 26, max = 26))]
|
||||||
before: Option<String>,
|
before: Option<String>,
|
||||||
|
/// Message id after which messages should be fetched
|
||||||
#[validate(length(min = 26, max = 26))]
|
#[validate(length(min = 26, max = 26))]
|
||||||
after: Option<String>,
|
after: Option<String>,
|
||||||
|
/// Message sort direction
|
||||||
|
///
|
||||||
|
/// By default, it will be sorted by relevance.
|
||||||
#[serde(default = "MessageSort::default")]
|
#[serde(default = "MessageSort::default")]
|
||||||
sort: MessageSort,
|
sort: MessageSort,
|
||||||
|
/// Whether to include user (and member, if server channel) objects
|
||||||
include_users: Option<bool>,
|
include_users: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Search for Messages
|
||||||
|
///
|
||||||
|
/// This route searches for messages within the given parameters.
|
||||||
|
#[openapi(tag = "Messaging")]
|
||||||
#[post("/<target>/search", data = "<options>")]
|
#[post("/<target>/search", data = "<options>")]
|
||||||
pub async fn req(
|
pub async fn req(
|
||||||
db: &Db,
|
db: &Db,
|
||||||
user: User,
|
user: User,
|
||||||
target: Ref,
|
target: Ref,
|
||||||
options: Json<Options>,
|
options: Json<OptionsMessageSearch>,
|
||||||
) -> Result<Json<BulkMessageResponse>> {
|
) -> Result<Json<BulkMessageResponse>> {
|
||||||
let options = options.into_inner();
|
let options = options.into_inner();
|
||||||
options
|
options
|
||||||
@@ -44,7 +59,7 @@ pub async fn req(
|
|||||||
.throw_permission_and_view_channel(db, Permission::ReadMessageHistory)
|
.throw_permission_and_view_channel(db, Permission::ReadMessageHistory)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let Options {
|
let OptionsMessageSearch {
|
||||||
query,
|
query,
|
||||||
limit,
|
limit,
|
||||||
before,
|
before,
|
||||||
|
|||||||
@@ -16,19 +16,27 @@ use validator::Validate;
|
|||||||
|
|
||||||
use crate::util::idempotency::IdempotencyKey;
|
use crate::util::idempotency::IdempotencyKey;
|
||||||
|
|
||||||
#[derive(Validate, Serialize, Deserialize)]
|
#[derive(Validate, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct Data {
|
pub struct DataMessageSend {
|
||||||
|
/// Unique token to prevent duplicate message sending
|
||||||
|
///
|
||||||
|
/// **This is deprecated and replaced by Idempotency-Token!**
|
||||||
nonce: Option<String>,
|
nonce: Option<String>,
|
||||||
|
|
||||||
|
/// Message content to send
|
||||||
#[validate(length(min = 0, max = 2000))]
|
#[validate(length(min = 0, max = 2000))]
|
||||||
content: String,
|
content: String,
|
||||||
|
/// Attachments to include in message
|
||||||
#[validate(length(min = 1, max = 128))]
|
#[validate(length(min = 1, max = 128))]
|
||||||
attachments: Option<Vec<String>>,
|
attachments: Option<Vec<String>>,
|
||||||
|
/// Messages to reply to
|
||||||
replies: Option<Vec<Reply>>,
|
replies: Option<Vec<Reply>>,
|
||||||
#[validate]
|
/// Embeds to include in message
|
||||||
masquerade: Option<Masquerade>,
|
|
||||||
#[validate(length(min = 1, max = 10))]
|
#[validate(length(min = 1, max = 10))]
|
||||||
embeds: Option<Vec<SendableEmbed>>,
|
embeds: Option<Vec<SendableEmbed>>,
|
||||||
|
/// Masquerade to apply to this message
|
||||||
|
#[validate]
|
||||||
|
masquerade: Option<Masquerade>,
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@@ -36,12 +44,16 @@ lazy_static! {
|
|||||||
static ref RE_MENTION: Regex = Regex::new(r"<@([0-9A-HJKMNP-TV-Z]{26})>").unwrap();
|
static ref RE_MENTION: Regex = Regex::new(r"<@([0-9A-HJKMNP-TV-Z]{26})>").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Send Message
|
||||||
|
///
|
||||||
|
/// Sends a message to the given channel.
|
||||||
|
#[openapi(tag = "Messaging")]
|
||||||
#[post("/<target>/messages", data = "<data>")]
|
#[post("/<target>/messages", data = "<data>")]
|
||||||
pub async fn message_send(
|
pub async fn message_send(
|
||||||
db: &Db,
|
db: &Db,
|
||||||
user: User,
|
user: User,
|
||||||
target: Ref,
|
target: Ref,
|
||||||
data: Json<Data>,
|
data: Json<DataMessageSend>,
|
||||||
mut idempotency: IdempotencyKey,
|
mut idempotency: IdempotencyKey,
|
||||||
) -> Result<Json<Message>> {
|
) -> Result<Json<Message>> {
|
||||||
let data = data.into_inner();
|
let data = data.into_inner();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
|
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||||
|
|
||||||
mod channel_ack;
|
mod channel_ack;
|
||||||
mod channel_delete;
|
mod channel_delete;
|
||||||
@@ -20,8 +21,8 @@ mod permissions_set;
|
|||||||
mod permissions_set_default;
|
mod permissions_set_default;
|
||||||
mod voice_join;
|
mod voice_join;
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||||
routes![
|
openapi_get_routes_spec![
|
||||||
channel_ack::req,
|
channel_ack::req,
|
||||||
channel_fetch::req,
|
channel_fetch::req,
|
||||||
members_fetch::req,
|
members_fetch::req,
|
||||||
|
|||||||
@@ -6,11 +6,19 @@ use revolt_quark::{
|
|||||||
perms, Db, Error, Override, Permission, Ref, Result,
|
perms, Db, Error, Override, Permission, Ref, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
/// # Permission Value
|
||||||
|
#[derive(Deserialize, JsonSchema)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
|
/// Allow / deny values to set for this role
|
||||||
permissions: Override,
|
permissions: Override,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Set Role Permission
|
||||||
|
///
|
||||||
|
/// Sets permissions for the specified role in this channel.
|
||||||
|
///
|
||||||
|
/// Channel must be a `TextChannel` or `VoiceChannel`.
|
||||||
|
#[openapi(tag = "Channel Permissions")]
|
||||||
#[put("/<target>/permissions/<role_id>", data = "<data>", rank = 2)]
|
#[put("/<target>/permissions/<role_id>", data = "<data>", rank = 2)]
|
||||||
pub async fn req(
|
pub async fn req(
|
||||||
db: &Db,
|
db: &Db,
|
||||||
|
|||||||
@@ -6,15 +6,33 @@ use revolt_quark::{
|
|||||||
perms, Db, Error, Override, Permission, Ref, Result,
|
perms, Db, Error, Override, Permission, Ref, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
/// # Permission Value
|
||||||
|
#[derive(Deserialize, JsonSchema)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum Data {
|
pub enum DataDefaultChannelPermissions {
|
||||||
Value { permissions: u64 },
|
Value {
|
||||||
Field { permissions: Override },
|
/// Permission values to set for members in a `Group`
|
||||||
|
permissions: u64,
|
||||||
|
},
|
||||||
|
Field {
|
||||||
|
/// Allow / deny values to set for members in this `TextChannel` or `VoiceChannel`
|
||||||
|
permissions: Override,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Set Default Permission
|
||||||
|
///
|
||||||
|
/// Sets permissions for the default role in this channel.
|
||||||
|
///
|
||||||
|
/// Channel must be a `Group`, `TextChannel` or `VoiceChannel`.
|
||||||
|
#[openapi(tag = "Channel Permissions")]
|
||||||
#[put("/<target>/permissions/default", data = "<data>", rank = 1)]
|
#[put("/<target>/permissions/default", data = "<data>", rank = 1)]
|
||||||
pub async fn req(db: &Db, user: User, target: Ref, data: Json<Data>) -> Result<Json<Channel>> {
|
pub async fn req(
|
||||||
|
db: &Db,
|
||||||
|
user: User,
|
||||||
|
target: Ref,
|
||||||
|
data: Json<DataDefaultChannelPermissions>,
|
||||||
|
) -> Result<Json<Channel>> {
|
||||||
let data = data.into_inner();
|
let data = data.into_inner();
|
||||||
|
|
||||||
let mut channel = target.as_channel(db).await?;
|
let mut channel = target.as_channel(db).await?;
|
||||||
@@ -25,7 +43,7 @@ pub async fn req(db: &Db, user: User, target: Ref, data: Json<Data>) -> Result<J
|
|||||||
|
|
||||||
match &channel {
|
match &channel {
|
||||||
Channel::Group { .. } => {
|
Channel::Group { .. } => {
|
||||||
if let Data::Value { permissions } = data {
|
if let DataDefaultChannelPermissions::Value { permissions } = data {
|
||||||
channel
|
channel
|
||||||
.update(
|
.update(
|
||||||
db,
|
db,
|
||||||
@@ -48,7 +66,7 @@ pub async fn req(db: &Db, user: User, target: Ref, data: Json<Data>) -> Result<J
|
|||||||
default_permissions,
|
default_permissions,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if let Data::Field { permissions } = data {
|
if let DataDefaultChannelPermissions::Field { permissions } = data {
|
||||||
perm.throw_permission_override(
|
perm.throw_permission_override(
|
||||||
db,
|
db,
|
||||||
default_permissions.map(|x| x.into()),
|
default_permissions.map(|x| x.into()),
|
||||||
|
|||||||
@@ -3,11 +3,17 @@ use revolt_quark::{models::User, Ref, Result};
|
|||||||
use rocket::serde::json::Value;
|
use rocket::serde::json::Value;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// # Token Response
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct CreateUserResponse {
|
struct CreateVoiceUserResponse {
|
||||||
|
/// Token for authenticating with the voice server
|
||||||
token: String,
|
token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Join Call
|
||||||
|
///
|
||||||
|
/// Asks the voice server for a token to join the call.
|
||||||
|
#[openapi(tag = "Voice")]
|
||||||
#[post("/<_target>/join_call")]
|
#[post("/<_target>/join_call")]
|
||||||
pub async fn req(_user: User, _target: Ref) -> Result<Value> {
|
pub async fn req(_user: User, _target: Ref) -> Result<Value> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ pub fn mount(mut rocket: Rocket<Build>) -> Rocket<Build> {
|
|||||||
rocket, "/".to_owned(), settings,
|
rocket, "/".to_owned(), settings,
|
||||||
"" => openapi_get_routes_spec![root::root, root::ping],
|
"" => openapi_get_routes_spec![root::root, root::ping],
|
||||||
"/bots" => bots::routes(),
|
"/bots" => bots::routes(),
|
||||||
|
"/channels" => channels::routes(),
|
||||||
};
|
};
|
||||||
|
|
||||||
rocket
|
rocket
|
||||||
@@ -27,7 +28,6 @@ pub fn mount(mut rocket: Rocket<Build>) -> Rocket<Build> {
|
|||||||
.mount("/auth/session", rauth::web::session::routes())
|
.mount("/auth/session", rauth::web::session::routes())
|
||||||
.mount("/onboard", onboard::routes())
|
.mount("/onboard", onboard::routes())
|
||||||
.mount("/users", users::routes())
|
.mount("/users", users::routes())
|
||||||
.mount("/channels", channels::routes())
|
|
||||||
.mount("/servers", servers::routes())
|
.mount("/servers", servers::routes())
|
||||||
.mount("/invites", invites::routes())
|
.mount("/invites", invites::routes())
|
||||||
.mount("/push", push::routes())
|
.mount("/push", push::routes())
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ use mongodb::bson::doc;
|
|||||||
use revolt_quark::{Error, Result};
|
use revolt_quark::{Error, Result};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::request::{FromRequest, Outcome};
|
use rocket::request::{FromRequest, Outcome};
|
||||||
|
use rocket_okapi::gen::OpenApiGenerator;
|
||||||
|
use rocket_okapi::okapi::openapi3::{Parameter, ParameterValue};
|
||||||
|
use rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
|
||||||
|
use schemars::schema::{InstanceType, SchemaObject, SingleOrVec};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
@@ -38,6 +42,35 @@ impl IdempotencyKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'r> OpenApiFromRequest<'r> for IdempotencyKey {
|
||||||
|
fn from_request_input(
|
||||||
|
_gen: &mut OpenApiGenerator,
|
||||||
|
_name: String,
|
||||||
|
_required: bool,
|
||||||
|
) -> rocket_okapi::Result<RequestHeaderInput> {
|
||||||
|
Ok(RequestHeaderInput::Parameter(Parameter {
|
||||||
|
name: "Idempotency-Key".to_string(),
|
||||||
|
description: Some("Unique key to prevent duplicate requests".to_string()),
|
||||||
|
allow_empty_value: false,
|
||||||
|
required: false,
|
||||||
|
deprecated: false,
|
||||||
|
extensions: schemars::Map::new(),
|
||||||
|
location: "sus".to_string(),
|
||||||
|
value: ParameterValue::Schema {
|
||||||
|
allow_reserved: false,
|
||||||
|
example: None,
|
||||||
|
examples: None,
|
||||||
|
explode: None,
|
||||||
|
style: None,
|
||||||
|
schema: SchemaObject {
|
||||||
|
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'r> FromRequest<'r> for IdempotencyKey {
|
impl<'r> FromRequest<'r> for IdempotencyKey {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|||||||
Reference in New Issue
Block a user