feat(revcord): ✨ inital revcord commit
This commit is contained in:
24
crates/revcord/models/src/lib.rs
Normal file
24
crates/revcord/models/src/lib.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
mod models;
|
||||
|
||||
pub use twilight_model;
|
||||
pub use models::{channel, user};
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
|
||||
|
||||
#[async_trait]
|
||||
pub trait QuarkConversion: Sized {
|
||||
type Type;
|
||||
|
||||
async fn to_quark(self) -> Self::Type;
|
||||
async fn from_quark(data: Self::Type) -> Self;
|
||||
}
|
||||
|
||||
pub fn to_snowflake<T, S: ToString>(ulid: S) -> twilight_model::id::Id<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn to_ulid<T>(snowflake: twilight_model::id::Id<T>) -> String {
|
||||
todo!()
|
||||
}
|
||||
136
crates/revcord/models/src/models/channel.rs
Normal file
136
crates/revcord/models/src/models/channel.rs
Normal file
@@ -0,0 +1,136 @@
|
||||
use crate::{QuarkConversion, to_snowflake, to_ulid};
|
||||
use revolt_quark::models::{Channel as RevoltChannel};
|
||||
use twilight_model::channel::{Channel as DiscordChannel, ChannelType};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use rocket_okapi::{JsonSchema, okapi::schemars::schema::{Schema, SchemaObject}};
|
||||
use async_trait::async_trait;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[serde(transparent)]
|
||||
#[repr(transparent)]
|
||||
pub struct Channel(DiscordChannel);
|
||||
|
||||
#[async_trait]
|
||||
impl QuarkConversion for Channel {
|
||||
type Type = RevoltChannel;
|
||||
|
||||
async fn to_quark(self) -> Self::Type {
|
||||
let DiscordChannel { guild_id, id, kind, last_message_id, name, nsfw, recipients, topic, owner_id, .. } = self.0;
|
||||
|
||||
match kind {
|
||||
ChannelType::GuildText => RevoltChannel::TextChannel {
|
||||
id: to_ulid(id),
|
||||
server: to_ulid(guild_id.unwrap()),
|
||||
name: name.unwrap(),
|
||||
description: topic,
|
||||
icon: None,
|
||||
last_message_id: last_message_id.map(to_ulid),
|
||||
default_permissions: None, // TODO
|
||||
role_permissions: HashMap::new(),
|
||||
nsfw: nsfw.unwrap_or_default()
|
||||
},
|
||||
ChannelType::Private => RevoltChannel::DirectMessage {
|
||||
id: to_ulid(id),
|
||||
active: false,
|
||||
recipients: recipients.unwrap_or_default().iter().map(|user| to_ulid(user.id)).collect(),
|
||||
last_message_id: last_message_id.map(to_ulid)
|
||||
},
|
||||
ChannelType::GuildVoice => RevoltChannel::VoiceChannel {
|
||||
id: to_ulid(id),
|
||||
server: to_ulid(guild_id.unwrap()),
|
||||
name: name.unwrap(),
|
||||
description: topic,
|
||||
icon: None,
|
||||
default_permissions: None, // TODO
|
||||
role_permissions: HashMap::new(),
|
||||
nsfw: nsfw.unwrap_or_default()
|
||||
},
|
||||
ChannelType::Group => RevoltChannel::Group {
|
||||
id: to_ulid(id),
|
||||
name: name.unwrap(),
|
||||
owner: to_ulid(owner_id.unwrap()),
|
||||
description: topic,
|
||||
recipients: recipients.unwrap_or_default().iter().map(|user| to_ulid(user.id)).collect(),
|
||||
icon: None,
|
||||
last_message_id: last_message_id.map(to_ulid),
|
||||
permissions: None, // TODO
|
||||
nsfw: nsfw.unwrap_or_default()
|
||||
},
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
|
||||
async fn from_quark(data: Self::Type) -> Self {
|
||||
Self(DiscordChannel {
|
||||
application_id: None,
|
||||
bitrate: None,
|
||||
default_auto_archive_duration: None,
|
||||
guild_id: match &data {
|
||||
RevoltChannel::TextChannel { server, ..} => Some(to_snowflake(server.clone())),
|
||||
RevoltChannel::VoiceChannel { server, .. } => Some(to_snowflake(server.clone())),
|
||||
_ => None
|
||||
},
|
||||
icon: None, // TODO,
|
||||
id: to_snowflake(data.id()),
|
||||
invitable: None,
|
||||
kind: match &data {
|
||||
RevoltChannel::SavedMessages { .. } => ChannelType::Private,
|
||||
RevoltChannel::DirectMessage { .. } => ChannelType::Private,
|
||||
RevoltChannel::Group { .. } => ChannelType::Group,
|
||||
RevoltChannel::TextChannel { .. } => ChannelType::GuildText,
|
||||
RevoltChannel::VoiceChannel { .. } => ChannelType::GuildVoice
|
||||
},
|
||||
last_message_id: match &data {
|
||||
RevoltChannel::Group { last_message_id, .. } => last_message_id.clone().map(to_snowflake),
|
||||
RevoltChannel::TextChannel { last_message_id, .. } => last_message_id.clone().map(to_snowflake),
|
||||
RevoltChannel::DirectMessage { last_message_id, .. } => last_message_id.clone().map(to_snowflake),
|
||||
_ => None
|
||||
},
|
||||
last_pin_timestamp: None,
|
||||
member: None,
|
||||
member_count: None,
|
||||
message_count: None,
|
||||
name: match &data {
|
||||
RevoltChannel::Group { name, .. } => Some(name),
|
||||
RevoltChannel::TextChannel { name, ..} => Some(name),
|
||||
RevoltChannel::VoiceChannel { name, .. } => Some(name),
|
||||
_ => None
|
||||
}.cloned(),
|
||||
newly_created: None,
|
||||
nsfw: match &data {
|
||||
RevoltChannel::Group { nsfw, .. } => Some(*nsfw),
|
||||
RevoltChannel::TextChannel { nsfw, .. } => Some(*nsfw),
|
||||
RevoltChannel::VoiceChannel { nsfw, .. } => Some(*nsfw),
|
||||
_ => None
|
||||
},
|
||||
owner_id: None,
|
||||
parent_id: None,
|
||||
permission_overwrites: None, // TODO,
|
||||
position: None, // TODO
|
||||
rate_limit_per_user: None,
|
||||
recipients: None,
|
||||
rtc_region: None,
|
||||
thread_metadata: None,
|
||||
topic: match &data {
|
||||
RevoltChannel::Group { description, .. } => description,
|
||||
RevoltChannel::TextChannel { description, ..} => description,
|
||||
RevoltChannel::VoiceChannel { description, ..} => description,
|
||||
_ => &None
|
||||
}.clone(),
|
||||
user_limit: None,
|
||||
video_quality_mode: None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonSchema for Channel {
|
||||
fn schema_name() -> String {
|
||||
"Channel".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
Schema::Object(SchemaObject::default())
|
||||
}
|
||||
}
|
||||
|
||||
2
crates/revcord/models/src/models/mod.rs
Normal file
2
crates/revcord/models/src/models/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod channel;
|
||||
pub mod user;
|
||||
140
crates/revcord/models/src/models/user.rs
Normal file
140
crates/revcord/models/src/models/user.rs
Normal file
@@ -0,0 +1,140 @@
|
||||
use crate::{QuarkConversion, to_snowflake, to_ulid};
|
||||
use revolt_quark::{models::{User as RevoltUser, user::{BotInformation, UserHint}}, Database};
|
||||
use twilight_model::user::{User as DiscordUser};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use rocket_okapi::{JsonSchema, okapi::{schemars::schema::{Schema, SchemaObject}, openapi3::{SecurityScheme, SecuritySchemeData}}, gen::OpenApiGenerator, request::{OpenApiFromRequest, RequestHeaderInput}};
|
||||
use async_trait::async_trait;
|
||||
use rocket::{Request, request::{self, FromRequest, Outcome}, http::Status};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[serde(transparent)]
|
||||
#[repr(transparent)]
|
||||
pub struct User(DiscordUser);
|
||||
|
||||
impl User {
|
||||
pub fn into_inner(self) -> DiscordUser {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl QuarkConversion for User {
|
||||
type Type = RevoltUser;
|
||||
|
||||
async fn to_quark(self) -> Self::Type {
|
||||
let DiscordUser { bot, id, name , ..} = self.into_inner();
|
||||
|
||||
RevoltUser {
|
||||
id: to_ulid(id),
|
||||
username: name,
|
||||
avatar: None, // TODO,
|
||||
relations: None,
|
||||
badges: None, // TODO,
|
||||
status: None, // TODO,
|
||||
profile: None, // TODO,
|
||||
flags: None,
|
||||
privileged: false,
|
||||
bot: if bot {
|
||||
Some(BotInformation {
|
||||
owner: "0".to_string()
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
relationship: None,
|
||||
online: None
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async fn from_quark(data: Self::Type) -> Self {
|
||||
Self(DiscordUser {
|
||||
accent_color: None,
|
||||
avatar: None, // TODO
|
||||
bot: data.bot.is_some(),
|
||||
banner: None, // TODO
|
||||
discriminator: 1,
|
||||
email: None,
|
||||
flags: None,
|
||||
id: to_snowflake(data.id),
|
||||
locale: None,
|
||||
mfa_enabled: None,
|
||||
name: data.username,
|
||||
premium_type: None,
|
||||
public_flags: None,
|
||||
system: None,
|
||||
verified: None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonSchema for User {
|
||||
fn schema_name() -> String {
|
||||
"User".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
Schema::Object(SchemaObject::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[rocket::async_trait]
|
||||
impl<'r> FromRequest<'r> for User {
|
||||
type Error = rauth::util::Error;
|
||||
|
||||
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
||||
let user: &Option<User> = request
|
||||
.local_cache_async(async {
|
||||
let db = request
|
||||
.rocket()
|
||||
.state::<Database>()
|
||||
.expect("Database state not reachable!");
|
||||
|
||||
let header_token = request
|
||||
.headers()
|
||||
.get("Authorization")
|
||||
.next()
|
||||
.and_then(|x| x.split(' ').nth(1).map(|s| s.to_string()));
|
||||
|
||||
if let Some(token) = header_token {
|
||||
if let Ok(user) = RevoltUser::from_token(db, &token, UserHint::Any).await {
|
||||
return Some(User::from_quark(user).await);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
})
|
||||
.await;
|
||||
|
||||
if let Some(user) = user {
|
||||
Outcome::Success(user.clone())
|
||||
} else {
|
||||
Outcome::Failure((Status::Unauthorized, rauth::util::Error::InvalidSession))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> OpenApiFromRequest<'r> for User {
|
||||
fn from_request_input(
|
||||
_gen: &mut OpenApiGenerator,
|
||||
_name: String,
|
||||
_required: bool,
|
||||
) -> rocket_okapi::Result<RequestHeaderInput> {
|
||||
let mut requirements = schemars::Map::new();
|
||||
requirements.insert("Api Key".to_owned(), vec![]);
|
||||
|
||||
Ok(RequestHeaderInput::Security(
|
||||
"Api Key".to_owned(),
|
||||
SecurityScheme {
|
||||
data: SecuritySchemeData::ApiKey {
|
||||
name: "Authorization".to_owned(),
|
||||
location: "header".to_owned(),
|
||||
},
|
||||
description: Some("Session Token".to_owned()),
|
||||
extensions: schemars::Map::new(),
|
||||
},
|
||||
requirements,
|
||||
))
|
||||
}
|
||||
}
|
||||
6
crates/revcord/models/src/variables.rs
Normal file
6
crates/revcord/models/src/variables.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
use lazy_static::lazy_static;
|
||||
use std::env;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref REVCORD_URL: String = env::var("REVCORD_URL").expect("Missing REVCORD_URL environment variable");
|
||||
}
|
||||
Reference in New Issue
Block a user