feat(revcord): ✨ inital revcord commit
This commit is contained in:
126
Cargo.lock
generated
126
Cargo.lock
generated
@@ -2244,6 +2244,15 @@ dependencies = [
|
|||||||
"syn 0.11.11",
|
"syn 0.11.11",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-float"
|
||||||
|
version = "2.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_info"
|
name = "os_info"
|
||||||
version = "3.4.0"
|
version = "3.4.0"
|
||||||
@@ -2974,6 +2983,88 @@ dependencies = [
|
|||||||
"quick-error 1.2.3",
|
"quick-error 1.2.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "revcord-api"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-channel",
|
||||||
|
"async-std",
|
||||||
|
"bitfield",
|
||||||
|
"chrono",
|
||||||
|
"ctrlc",
|
||||||
|
"dashmap",
|
||||||
|
"dotenv",
|
||||||
|
"env_logger",
|
||||||
|
"futures",
|
||||||
|
"impl_ops",
|
||||||
|
"lazy_static",
|
||||||
|
"lettre",
|
||||||
|
"linkify 0.6.0",
|
||||||
|
"log",
|
||||||
|
"lru",
|
||||||
|
"mobc",
|
||||||
|
"mobc-redis",
|
||||||
|
"mongodb 1.2.5",
|
||||||
|
"nanoid",
|
||||||
|
"num_enum",
|
||||||
|
"once_cell",
|
||||||
|
"rauth",
|
||||||
|
"redis 0.21.5",
|
||||||
|
"regex",
|
||||||
|
"reqwest",
|
||||||
|
"revcord-models",
|
||||||
|
"revolt-quark",
|
||||||
|
"rocket",
|
||||||
|
"rocket_cors",
|
||||||
|
"rocket_okapi",
|
||||||
|
"schemars",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"ulid 0.4.1",
|
||||||
|
"url",
|
||||||
|
"validator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "revcord-models"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-recursion",
|
||||||
|
"async-std",
|
||||||
|
"async-trait",
|
||||||
|
"bincode",
|
||||||
|
"bitfield",
|
||||||
|
"bson 2.2.0",
|
||||||
|
"deadqueue",
|
||||||
|
"dotenv",
|
||||||
|
"futures",
|
||||||
|
"impl_ops",
|
||||||
|
"iso8601-timestamp",
|
||||||
|
"lazy_static",
|
||||||
|
"linkify 0.8.1",
|
||||||
|
"log",
|
||||||
|
"num_enum",
|
||||||
|
"okapi",
|
||||||
|
"optional_struct",
|
||||||
|
"pretty_env_logger",
|
||||||
|
"rauth",
|
||||||
|
"redis-kiss",
|
||||||
|
"regex",
|
||||||
|
"revolt-quark",
|
||||||
|
"rocket",
|
||||||
|
"rocket_okapi",
|
||||||
|
"schemars",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"twilight-model",
|
||||||
|
"ulid 0.5.0",
|
||||||
|
"validator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "revcord-ws"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-bonfire"
|
name = "revolt-bonfire"
|
||||||
version = "1.0.6-patch.2"
|
version = "1.0.6-patch.2"
|
||||||
@@ -3541,6 +3632,16 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde-value"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||||
|
dependencies = [
|
||||||
|
"ordered-float",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_bytes"
|
name = "serde_bytes"
|
||||||
version = "0.11.6"
|
version = "0.11.6"
|
||||||
@@ -3584,6 +3685,17 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_repr"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote 1.0.18",
|
||||||
|
"syn 1.0.95",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@@ -4419,6 +4531,20 @@ dependencies = [
|
|||||||
"utf-8",
|
"utf-8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "twilight-model"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c44d87f62a032ea0d8053481672844cab0115330d99d655791be94a31d585256"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"serde",
|
||||||
|
"serde-value",
|
||||||
|
"serde_repr",
|
||||||
|
"time 0.3.9",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typed-builder"
|
name = "typed-builder"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["crates/*"]
|
members = ["crates/bonfire", "crates/delta", "crates/quark", "crates/revcord/*"]
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
This is a monorepo for the Revolt backend.
|
This is a monorepo for the Revolt backend.
|
||||||
|
|
||||||
| Crate | Description |
|
| Crate | Description |
|
||||||
| ------------- | --------------------------------- |
|
| ---------------- | ------------------------------------ |
|
||||||
| `delta` | REST API server |
|
| `delta` | REST API server |
|
||||||
| `bonfire` | WebSocket events server |
|
| `bonfire` | WebSocket events server |
|
||||||
| `quark` | Models and logic |
|
| `quark` | Models and logic |
|
||||||
| `revcord/api` | Discord REST translation layer |
|
| `revcord/api` | Discord REST translation layer |
|
||||||
| `revcord/ws` | Discord gateway translation layer |
|
| `revcord/ws` | Discord gateway translation layer |
|
||||||
|
| `revcord/models` | Discord models and quark translation |
|
||||||
|
|
||||||
Note: `january`, `autumn`, and `vortex` are yet to be moved into this monorepo.
|
Note: `january`, `autumn`, and `vortex` are yet to be moved into this monorepo.
|
||||||
|
|
||||||
|
|||||||
5
crates/revcord/README.md
Normal file
5
crates/revcord/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Revcord
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Revcord is a compatibility layer for Discord
|
||||||
66
crates/revcord/api/Cargo.toml
Normal file
66
crates/revcord/api/Cargo.toml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
[package]
|
||||||
|
name = "revcord-api"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# Utility
|
||||||
|
lru = "0.7.0"
|
||||||
|
url = "2.2.2"
|
||||||
|
log = "0.4.11"
|
||||||
|
dotenv = "0.15.0"
|
||||||
|
dashmap = "5.2.0"
|
||||||
|
linkify = "0.6.0"
|
||||||
|
once_cell = "1.4.1"
|
||||||
|
env_logger = "0.7.1"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
ctrlc = { version = "3.0", features = ["termination"] }
|
||||||
|
|
||||||
|
# Lang. Utilities
|
||||||
|
regex = "1"
|
||||||
|
num_enum = "0.5.1"
|
||||||
|
impl_ops = "0.1.1"
|
||||||
|
bitfield = "0.13.2"
|
||||||
|
|
||||||
|
# ID / key generation
|
||||||
|
ulid = "0.4.1"
|
||||||
|
nanoid = "0.4.0"
|
||||||
|
|
||||||
|
# serde
|
||||||
|
serde_json = "1.0.57"
|
||||||
|
serde = { version = "1.0.115", features = ["derive"] }
|
||||||
|
validator = { version = "0.14", features = ["derive"] }
|
||||||
|
|
||||||
|
# async
|
||||||
|
futures = "0.3.8"
|
||||||
|
chrono = "0.4.15"
|
||||||
|
async-channel = "1.6.1"
|
||||||
|
reqwest = { version = "0.11.4", features = ["json"] }
|
||||||
|
async-std = { version = "1.8.0", features = ["tokio1", "tokio02", "attributes"] }
|
||||||
|
|
||||||
|
# internal util
|
||||||
|
lettre = "0.10.0-alpha.4"
|
||||||
|
rauth = { git = "https://github.com/insertish/rauth", rev = "001a9698c56cea79e69e4ae71d7bc2cb48aec1a6" }
|
||||||
|
|
||||||
|
# redis
|
||||||
|
redis = { version = "0.21.2", features = ["async-std-comp"] }
|
||||||
|
mobc = { version = "0.7.3" }
|
||||||
|
mobc-redis = { version = "0.7.0", default-features = false, features = ["async-std-comp"] }
|
||||||
|
|
||||||
|
# web
|
||||||
|
rocket = { version = "0.5.0-rc.1", default-features = false, features = ["json"] }
|
||||||
|
mongodb = { version = "1.2.2", features = ["async-std-runtime"], default-features = false }
|
||||||
|
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "5843861a88958c16bfaa0b40f0d8910772bcd2f6" }
|
||||||
|
|
||||||
|
# spec generation
|
||||||
|
schemars = "0.8.8"
|
||||||
|
# rocket_okapi = "0.8.0-rc.1"
|
||||||
|
rocket_okapi = { git = "https://github.com/insertish/okapi", rev = "dcf0df115596ee07a587a7a543cddf3d7944645b", features = [ "swagger" ] }
|
||||||
|
|
||||||
|
# quark
|
||||||
|
revolt-quark = { path = "../../quark" }
|
||||||
|
|
||||||
|
# discord
|
||||||
|
revcord-models = { path = "../models" }
|
||||||
74
crates/revcord/api/src/main.rs
Normal file
74
crates/revcord/api/src/main.rs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate rocket;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate rocket_okapi;
|
||||||
|
extern crate ctrlc;
|
||||||
|
|
||||||
|
pub mod routes;
|
||||||
|
pub mod version;
|
||||||
|
|
||||||
|
use log::info;
|
||||||
|
use rauth::{
|
||||||
|
config::Config,
|
||||||
|
logic::Auth,
|
||||||
|
};
|
||||||
|
use revolt_quark::DatabaseInfo;
|
||||||
|
use rocket_cors::AllowedOrigins;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[async_std::main]
|
||||||
|
async fn main() {
|
||||||
|
let _guard = revolt_quark::setup_logging();
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Starting Revcord server [version {}].",
|
||||||
|
crate::version::VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
revolt_quark::variables::delta::preflight_checks();
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
ctrlc::set_handler(move || {
|
||||||
|
// Force ungraceful exit to avoid hang.
|
||||||
|
std::process::exit(0);
|
||||||
|
})
|
||||||
|
.expect("Error setting Ctrl-C handler");
|
||||||
|
|
||||||
|
let cors = rocket_cors::CorsOptions {
|
||||||
|
allowed_origins: AllowedOrigins::All,
|
||||||
|
allowed_methods: [
|
||||||
|
"Get", "Put", "Post", "Delete", "Options", "Head", "Trace", "Connect", "Patch",
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.map(|s| FromStr::from_str(s).unwrap())
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.to_cors()
|
||||||
|
.expect("Failed to create CORS.");
|
||||||
|
|
||||||
|
let db = DatabaseInfo::Auto.connect().await.unwrap();
|
||||||
|
|
||||||
|
// This is entirely temporary code until rauth is migrated to quark.
|
||||||
|
// (and / or otherwise gets updated to MongoDB v2 driver)
|
||||||
|
let mongo_db = mongodb::Client::with_uri_str(
|
||||||
|
&std::env::var("MONGODB").unwrap_or_else(|_| "mongodb://localhost".to_string()),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("Failed to init db connection.");
|
||||||
|
|
||||||
|
// Launch background task workers.
|
||||||
|
async_std::task::spawn(revolt_quark::tasks::start_workers(db.clone()));
|
||||||
|
|
||||||
|
let auth = Auth::new(mongo_db.database("revolt"), Config::default());
|
||||||
|
let rocket = rocket::build();
|
||||||
|
routes::mount(rocket)
|
||||||
|
.mount("/", rocket_cors::catch_all_options_routes())
|
||||||
|
.manage(auth)
|
||||||
|
.manage(db)
|
||||||
|
.manage(cors.clone())
|
||||||
|
.attach(cors)
|
||||||
|
.launch()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
15
crates/revcord/api/src/routes/channels/fetch_channel.rs
Normal file
15
crates/revcord/api/src/routes/channels/fetch_channel.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
use revolt_quark::{perms, Database, Permission, Ref, Result};
|
||||||
|
use revcord_models::{QuarkConversion, channel::Channel, user::User};
|
||||||
|
use rocket::{serde::json::Json, State};
|
||||||
|
|
||||||
|
#[openapi(tag = "Channel Information")]
|
||||||
|
#[get("/<target>")]
|
||||||
|
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<Channel>> {
|
||||||
|
let channel = target.as_channel(db).await?;
|
||||||
|
perms(&user.to_quark().await)
|
||||||
|
.channel(&channel)
|
||||||
|
.throw_permission(db, Permission::ViewChannel)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Json(Channel::from_quark(channel).await))
|
||||||
|
}
|
||||||
10
crates/revcord/api/src/routes/channels/mod.rs
Normal file
10
crates/revcord/api/src/routes/channels/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
use rocket::Route;
|
||||||
|
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||||
|
|
||||||
|
mod fetch_channel;
|
||||||
|
|
||||||
|
pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||||
|
openapi_get_routes_spec![
|
||||||
|
fetch_channel::req,
|
||||||
|
]
|
||||||
|
}
|
||||||
23
crates/revcord/api/src/routes/mod.rs
Normal file
23
crates/revcord/api/src/routes/mod.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
pub use rocket::http::Status;
|
||||||
|
pub use rocket::response::Redirect;
|
||||||
|
use rocket::{Build, Rocket};
|
||||||
|
use rocket_okapi::{settings::OpenApiSettings, okapi::openapi3::OpenApi};
|
||||||
|
|
||||||
|
pub mod channels;
|
||||||
|
|
||||||
|
pub fn mount(mut rocket: Rocket<Build>) -> Rocket<Build> {
|
||||||
|
let settings = OpenApiSettings::default();
|
||||||
|
|
||||||
|
mount_endpoints_and_merged_docs! {
|
||||||
|
rocket, "/".to_owned(), settings,
|
||||||
|
"/" => (vec![], custom_openapi_spec()),
|
||||||
|
"/channels" => channels::routes(),
|
||||||
|
};
|
||||||
|
|
||||||
|
rocket
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn custom_openapi_spec() -> OpenApi {
|
||||||
|
OpenApi::default()
|
||||||
|
}
|
||||||
1
crates/revcord/api/src/version.rs
Normal file
1
crates/revcord/api/src/version.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub const VERSION: &str = "0.0.1";
|
||||||
58
crates/revcord/models/Cargo.toml
Normal file
58
crates/revcord/models/Cargo.toml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
[package]
|
||||||
|
name = "revcord-models"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
validator = { version = "0.14", features = ["derive"] }
|
||||||
|
iso8601-timestamp = { version = "0.1.8", features = ["schema", "bson"] }
|
||||||
|
optional_struct = { git = "https://github.com/insertish/OptionalStruct", rev = "e275d2726595474632485934aa0887fa52281f70" }
|
||||||
|
|
||||||
|
# Formats
|
||||||
|
bincode = "1.3.3"
|
||||||
|
serde_json = "1.0.78"
|
||||||
|
bson = { version = "2.1.0", features = ["chrono-0_4"] }
|
||||||
|
|
||||||
|
# Spec Generation
|
||||||
|
schemars = "0.8.8"
|
||||||
|
okapi = { git = "https://github.com/insertish/okapi", rev = "dcf0df115596ee07a587a7a543cddf3d7944645b" }
|
||||||
|
rocket_okapi = { git = "https://github.com/insertish/okapi", rev = "dcf0df115596ee07a587a7a543cddf3d7944645b" }
|
||||||
|
# okapi = "0.7.0-rc.1"
|
||||||
|
# rocket_okapi = "0.8.0-rc.1"
|
||||||
|
|
||||||
|
# Databases
|
||||||
|
redis-kiss = { version = "0.1.3" }
|
||||||
|
|
||||||
|
# Async
|
||||||
|
futures = "0.3.19"
|
||||||
|
deadqueue = "0.2.1"
|
||||||
|
async-trait = "0.1.51"
|
||||||
|
async-recursion = "1.0.0"
|
||||||
|
async-std = { version = "1.8.0", features = ["attributes"], optional = true }
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log = "0.4.14"
|
||||||
|
pretty_env_logger = "0.4.0"
|
||||||
|
|
||||||
|
# Util
|
||||||
|
ulid = "0.5.0"
|
||||||
|
regex = "1.5.5"
|
||||||
|
linkify = "0.8.1"
|
||||||
|
dotenv = "0.15.0"
|
||||||
|
impl_ops = "0.1.1"
|
||||||
|
num_enum = "0.5.6"
|
||||||
|
bitfield = "0.13.2"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
|
||||||
|
# Implementations
|
||||||
|
revolt-quark = { path = "../../quark" }
|
||||||
|
rauth = { git = "https://github.com/insertish/rauth", rev = "001a9698c56cea79e69e4ae71d7bc2cb48aec1a6" }
|
||||||
|
|
||||||
|
# Discord
|
||||||
|
twilight-model = "0.11.0"
|
||||||
|
|
||||||
|
# Web
|
||||||
|
rocket = { version = "0.5.0-rc.1", features = ["json"] }
|
||||||
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");
|
||||||
|
}
|
||||||
8
crates/revcord/ws/Cargo.toml
Normal file
8
crates/revcord/ws/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "revcord-ws"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
3
crates/revcord/ws/src/main.rs
Normal file
3
crates/revcord/ws/src/main.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user