forked from jmug/stoatchat
Compare commits
7
Commits
20230301-1
...
20230304-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82d868751f | ||
|
|
31b9f18921 | ||
|
|
fd80823910 | ||
|
|
6bd8221eda | ||
|
|
ce77e926a5 | ||
|
|
2710edb76b | ||
|
|
8f1ff9e774 |
Generated
+4
-4
@@ -2170,7 +2170,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "optional_struct"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/insertish/OptionalStruct?rev=e275d2726595474632485934aa0887fa52281f70#e275d2726595474632485934aa0887fa52281f70"
|
||||
source = "git+https://github.com/insertish/OptionalStruct?rev=ee56427cee1f007839825d93d07fffd5a5e038c7#ee56427cee1f007839825d93d07fffd5a5e038c7"
|
||||
dependencies = [
|
||||
"quote 0.3.15",
|
||||
"syn 0.11.11",
|
||||
@@ -2792,7 +2792,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-bonfire"
|
||||
version = "0.5.10"
|
||||
version = "0.5.15"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"async-tungstenite",
|
||||
@@ -2808,7 +2808,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-delta"
|
||||
version = "0.5.10"
|
||||
version = "0.5.15"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-std",
|
||||
@@ -2848,7 +2848,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-quark"
|
||||
version = "0.5.10"
|
||||
version = "0.5.15"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"async-recursion",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-bonfire"
|
||||
version = "0.5.10"
|
||||
version = "0.5.15"
|
||||
license = "AGPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-delta"
|
||||
version = "0.5.10"
|
||||
version = "0.5.15"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <paulmakles@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use revolt_quark::{
|
||||
models::message::{PartialMessage, SendableEmbed},
|
||||
models::{Message, User},
|
||||
perms,
|
||||
types::january::Embed,
|
||||
Db, Error, Ref, Result, Timestamp,
|
||||
Db, Error, Permission, Ref, Result, Timestamp,
|
||||
};
|
||||
|
||||
use rocket::serde::json::Json;
|
||||
@@ -28,7 +29,7 @@ pub struct DataEditMessage {
|
||||
pub async fn req(
|
||||
db: &Db,
|
||||
user: User,
|
||||
target: String,
|
||||
target: Ref,
|
||||
msg: Ref,
|
||||
edit: Json<DataEditMessage>,
|
||||
) -> Result<Json<Message>> {
|
||||
@@ -36,10 +37,17 @@ pub async fn req(
|
||||
edit.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
// Ensure we have permissions to send a message
|
||||
let channel = target.as_channel(db).await?;
|
||||
let mut permissions = perms(&user).channel(&channel);
|
||||
permissions
|
||||
.throw_permission_and_view_channel(db, Permission::SendMessage)
|
||||
.await?;
|
||||
|
||||
Message::validate_sum(&edit.content, &edit.embeds)?;
|
||||
|
||||
let mut message = msg.as_message(db).await?;
|
||||
if message.channel != target {
|
||||
if message.channel != channel.id() {
|
||||
return Err(Error::NotFound);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ mod push;
|
||||
mod root;
|
||||
mod safety;
|
||||
mod servers;
|
||||
mod stats;
|
||||
mod sync;
|
||||
mod users;
|
||||
|
||||
@@ -21,7 +22,7 @@ pub fn mount(mut rocket: Rocket<Build>) -> Rocket<Build> {
|
||||
mount_endpoints_and_merged_docs! {
|
||||
rocket, "/".to_owned(), settings,
|
||||
"/" => (vec![], custom_openapi_spec()),
|
||||
"" => openapi_get_routes_spec![root::root, root::ping],
|
||||
"" => openapi_get_routes_spec![root::root, stats::stats, root::ping],
|
||||
"/users" => users::routes(),
|
||||
"/bots" => bots::routes(),
|
||||
"/channels" => channels::routes(),
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
use revolt_quark::{
|
||||
models::{
|
||||
report::{PartialReport, ReportStatus},
|
||||
Report, User,
|
||||
},
|
||||
Db, Error, Ref, Result,
|
||||
};
|
||||
use rocket::serde::json::Json;
|
||||
use serde::Deserialize;
|
||||
use validator::Validate;
|
||||
|
||||
/// # Report Data
|
||||
#[derive(Validate, Deserialize, JsonSchema)]
|
||||
pub struct DataEditReport {
|
||||
/// New report status
|
||||
status: Option<ReportStatus>,
|
||||
/// Report notes
|
||||
notes: Option<String>,
|
||||
}
|
||||
|
||||
/// # Edit Report
|
||||
///
|
||||
/// Edit a report.
|
||||
#[openapi(tag = "User Safety")]
|
||||
#[patch("/reports/<report>", data = "<edit>")]
|
||||
pub async fn edit_report(
|
||||
db: &Db,
|
||||
user: User,
|
||||
report: Ref,
|
||||
edit: Json<DataEditReport>,
|
||||
) -> Result<Json<Report>> {
|
||||
// Must be privileged for this route
|
||||
if !user.privileged {
|
||||
return Err(Error::NotPrivileged);
|
||||
}
|
||||
|
||||
// Validate data
|
||||
let edit = edit.into_inner();
|
||||
edit.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
// Create and apply update to report
|
||||
let mut report = report.as_report(db).await?;
|
||||
report
|
||||
.update(
|
||||
db,
|
||||
PartialReport {
|
||||
status: edit.status,
|
||||
notes: edit.notes,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(report))
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
use revolt_quark::models::{Report, User};
|
||||
use revolt_quark::{Db, Error, Result};
|
||||
use rocket::serde::json::Json;
|
||||
|
||||
/// # Fetch Report
|
||||
///
|
||||
/// Fetch a report by its ID
|
||||
#[openapi(tag = "User Safety")]
|
||||
#[get("/report/<id>")]
|
||||
pub async fn fetch_report(db: &Db, user: User, id: String) -> Result<Json<Report>> {
|
||||
// Must be privileged for this route
|
||||
if !user.privileged {
|
||||
return Err(Error::NotPrivileged);
|
||||
}
|
||||
|
||||
db.fetch_report(&id).await.map(Json)
|
||||
}
|
||||
@@ -44,8 +44,13 @@ pub async fn fetch_snapshot(
|
||||
user_ids.insert(&message.author);
|
||||
channel_ids.insert(&message.channel);
|
||||
}
|
||||
_ => {
|
||||
todo!()
|
||||
SnapshotContent::User(user) => {
|
||||
user_ids.insert(&user.id);
|
||||
}
|
||||
SnapshotContent::Server(server) => {
|
||||
for channel in &server.channels {
|
||||
channel_ids.insert(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
|
||||
use rocket::Route;
|
||||
|
||||
mod edit_report;
|
||||
mod fetch_report;
|
||||
mod fetch_reports;
|
||||
mod report_content;
|
||||
|
||||
@@ -9,8 +11,10 @@ mod fetch_snapshot;
|
||||
pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![
|
||||
// Reports
|
||||
report_content::report_content,
|
||||
edit_report::edit_report,
|
||||
fetch_report::fetch_report,
|
||||
fetch_reports::fetch_reports,
|
||||
report_content::report_content,
|
||||
// Snapshots
|
||||
fetch_snapshot::fetch_snapshot
|
||||
]
|
||||
|
||||
@@ -149,7 +149,8 @@ pub async fn report_content(db: &Db, user: User, data: Json<DataReportContent>)
|
||||
author_id: user.id,
|
||||
content: data.content,
|
||||
additional_context: data.additional_context,
|
||||
status: ReportStatus::Created,
|
||||
status: ReportStatus::Created {},
|
||||
notes: String::new(),
|
||||
};
|
||||
|
||||
db.insert_report(&report).await?;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
use revolt_quark::models::stats::Stats;
|
||||
use revolt_quark::{Db, Result};
|
||||
|
||||
use rocket::serde::json::Json;
|
||||
|
||||
/// # Query Stats
|
||||
///
|
||||
/// Fetch various technical statistics.
|
||||
#[openapi(tag = "Core")]
|
||||
#[get("/stats")]
|
||||
pub async fn stats(db: &Db) -> Result<Json<Stats>> {
|
||||
Ok(Json(db.generate_stats().await?))
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-quark"
|
||||
version = "0.5.10"
|
||||
version = "0.5.15"
|
||||
license = "AGPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
|
||||
@@ -29,7 +29,7 @@ default = [ "test" ]
|
||||
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" }
|
||||
optional_struct = { git = "https://github.com/insertish/OptionalStruct", rev = "ee56427cee1f007839825d93d07fffd5a5e038c7" }
|
||||
|
||||
# Formats
|
||||
bincode = "1.3.3"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
use crate::{models::stats::Stats, AbstractStats, Result};
|
||||
|
||||
use super::super::DummyDb;
|
||||
|
||||
#[async_trait]
|
||||
impl AbstractStats for DummyDb {
|
||||
async fn generate_stats(&self) -> Result<Stats> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ use crate::AbstractDatabase;
|
||||
|
||||
pub mod admin {
|
||||
pub mod migrations;
|
||||
pub mod stats;
|
||||
}
|
||||
|
||||
pub mod media {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::report::PartialReport;
|
||||
use crate::models::Report;
|
||||
use crate::{AbstractReport, Result};
|
||||
|
||||
@@ -10,6 +11,14 @@ impl AbstractReport for DummyDb {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_report(&self, _id: &str, _report: &PartialReport) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn fetch_report(&self, _report_id: &str) -> Result<Report> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn fetch_reports(&self) -> Result<Vec<Report>> {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
@@ -27,3 +27,7 @@ pub mod users {
|
||||
pub mod user;
|
||||
pub mod user_settings;
|
||||
}
|
||||
|
||||
pub mod safety {
|
||||
pub mod report;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
use crate::{models::report::PartialReport, models::Report, Database, Result};
|
||||
|
||||
impl Report {
|
||||
/// Update report data
|
||||
pub async fn update(&mut self, db: &Database, partial: PartialReport) -> Result<()> {
|
||||
self.apply_options(partial.clone());
|
||||
db.update_report(&self.id, &partial).await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use bson::{from_document, Document};
|
||||
use futures::StreamExt;
|
||||
|
||||
use crate::{
|
||||
models::stats::{Index, Stats},
|
||||
AbstractStats, Error, Result,
|
||||
};
|
||||
|
||||
use super::super::MongoDb;
|
||||
|
||||
#[async_trait]
|
||||
impl AbstractStats for MongoDb {
|
||||
async fn generate_stats(&self) -> Result<Stats> {
|
||||
let mut indices = HashMap::new();
|
||||
let mut coll_stats = HashMap::new();
|
||||
|
||||
let collection_names =
|
||||
self.db()
|
||||
.list_collection_names(None)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "list_collection_names",
|
||||
with: "database",
|
||||
})?;
|
||||
|
||||
for collection in collection_names {
|
||||
indices.insert(
|
||||
collection.to_string(),
|
||||
self.col::<Document>(&collection)
|
||||
.aggregate(
|
||||
vec![doc! {
|
||||
"$indexStats": { }
|
||||
}],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "aggregate",
|
||||
with: "col",
|
||||
})?
|
||||
.filter_map(|s| async { s.ok() })
|
||||
.collect::<Vec<Document>>()
|
||||
.await
|
||||
.into_iter()
|
||||
.filter_map(|doc| from_document(doc).ok())
|
||||
.collect::<Vec<Index>>(),
|
||||
);
|
||||
|
||||
coll_stats.insert(
|
||||
collection.to_string(),
|
||||
self.col::<Document>(&collection)
|
||||
.aggregate(
|
||||
vec![doc! {
|
||||
"$collStats": {
|
||||
"latencyStats": {
|
||||
"histograms": true
|
||||
},
|
||||
"storageStats": {},
|
||||
"count": {},
|
||||
"queryExecStats": {}
|
||||
}
|
||||
}],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "aggregate",
|
||||
with: "col",
|
||||
})?
|
||||
.filter_map(|s| async { s.ok() })
|
||||
.collect::<Vec<Document>>()
|
||||
.await
|
||||
.into_iter()
|
||||
.filter_map(|doc| from_document(doc).ok())
|
||||
.next()
|
||||
.ok_or(Error::DatabaseError {
|
||||
operation: "next aggregation",
|
||||
with: "col",
|
||||
})?,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(Stats {
|
||||
indices,
|
||||
coll_stats,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ use crate::{util::manipulation::prefix_keys, AbstractDatabase, Error, Result};
|
||||
|
||||
pub mod admin {
|
||||
pub mod migrations;
|
||||
pub mod stats;
|
||||
}
|
||||
|
||||
pub mod media {
|
||||
@@ -97,7 +98,14 @@ impl MongoDb {
|
||||
operation: "find",
|
||||
with: collection,
|
||||
})?
|
||||
.filter_map(|s| async { s.ok() })
|
||||
.filter_map(|s| async {
|
||||
if cfg!(debug_assertions) {
|
||||
// Hard fail on invalid documents
|
||||
Some(s.unwrap())
|
||||
} else {
|
||||
s.ok()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<T>>()
|
||||
.await)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::report::PartialReport;
|
||||
use crate::models::Report;
|
||||
use crate::{AbstractReport, Result};
|
||||
|
||||
@@ -11,6 +12,16 @@ impl AbstractReport for MongoDb {
|
||||
self.insert_one(COL, report).await.map(|_| ())
|
||||
}
|
||||
|
||||
async fn update_report(&self, id: &str, report: &PartialReport) -> Result<()> {
|
||||
self.update_one_by_id(COL, id, report, vec![], None)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
async fn fetch_report(&self, report_id: &str) -> Result<Report> {
|
||||
self.find_one_by_id(COL, report_id).await
|
||||
}
|
||||
|
||||
async fn fetch_reports(&self) -> Result<Vec<Report>> {
|
||||
self.find(COL, doc! {}).await
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use iso8601_timestamp::Timestamp;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Index access information
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||
pub struct IndexAccess {
|
||||
/// Operations since timestamp
|
||||
ops: i32,
|
||||
|
||||
/// Timestamp at which data keeping begun
|
||||
since: Timestamp,
|
||||
}
|
||||
|
||||
/// Collection index
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||
pub struct Index {
|
||||
/// Index name
|
||||
name: String,
|
||||
|
||||
/// Access information
|
||||
accesses: IndexAccess,
|
||||
}
|
||||
|
||||
/// Histogram entry
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||
pub struct LatencyHistogramEntry {
|
||||
/// Time
|
||||
micros: i64,
|
||||
|
||||
/// Count
|
||||
count: i64,
|
||||
}
|
||||
|
||||
/// Collection latency stats
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||
pub struct LatencyStats {
|
||||
/// Total operations
|
||||
ops: i64,
|
||||
|
||||
/// Timestamp at which data keeping begun
|
||||
latency: i64,
|
||||
|
||||
/// Histogram representation of latency data
|
||||
histogram: Vec<LatencyHistogramEntry>,
|
||||
}
|
||||
|
||||
/// Collection storage stats
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StorageStats {
|
||||
/// Uncompressed data size
|
||||
size: i64,
|
||||
|
||||
/// Data size on disk
|
||||
storage_size: i64,
|
||||
|
||||
/// Total size of all indexes
|
||||
total_index_size: i64,
|
||||
|
||||
/// Sum of storage size and total index size
|
||||
total_size: i64,
|
||||
|
||||
/// Individual index sizes
|
||||
index_sizes: HashMap<String, i64>,
|
||||
|
||||
/// Number of documents in collection
|
||||
count: i64,
|
||||
|
||||
/// Average size of each document
|
||||
avg_obj_size: i64,
|
||||
}
|
||||
|
||||
/// Query collection scan stats
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CollectionScans {
|
||||
/// Number of total collection scans
|
||||
total: i64,
|
||||
|
||||
/// Number of total collection scans not using a tailable cursor
|
||||
non_tailable: i64,
|
||||
}
|
||||
|
||||
/// Collection query execution stats
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct QueryExecStats {
|
||||
/// Stats regarding collection scans
|
||||
collection_scans: CollectionScans,
|
||||
}
|
||||
|
||||
/// Collection stats
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CollectionStats {
|
||||
/// Namespace
|
||||
ns: String,
|
||||
|
||||
/// Local time
|
||||
local_time: Timestamp,
|
||||
|
||||
/// Latency stats
|
||||
latency_stats: HashMap<String, LatencyStats>,
|
||||
|
||||
/// Query exec stats
|
||||
query_exec_stats: QueryExecStats,
|
||||
|
||||
/// Number of documents in collection
|
||||
count: u64,
|
||||
}
|
||||
|
||||
/// Server Stats
|
||||
#[derive(Serialize, JsonSchema, Debug)]
|
||||
pub struct Stats {
|
||||
/// Index usage information
|
||||
pub indices: HashMap<String, Vec<Index>>,
|
||||
|
||||
/// Collection stats
|
||||
pub coll_stats: HashMap<String, CollectionStats>,
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
mod admin {
|
||||
pub mod migrations;
|
||||
pub mod simple;
|
||||
pub mod stats;
|
||||
}
|
||||
|
||||
mod media {
|
||||
|
||||
@@ -76,17 +76,20 @@ pub enum ReportedContent {
|
||||
#[serde(tag = "status")]
|
||||
pub enum ReportStatus {
|
||||
/// Report is waiting for triage / action
|
||||
Created,
|
||||
Created {},
|
||||
|
||||
/// Report was rejected
|
||||
Rejected { rejection_reason: String },
|
||||
|
||||
/// Report was actioned and resolved
|
||||
Resolved,
|
||||
Resolved {},
|
||||
}
|
||||
|
||||
/// User-generated platform moderation report.
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, OptionalStruct, Clone)]
|
||||
#[optional_derive(Serialize, Deserialize, JsonSchema, Debug, Default, Clone)]
|
||||
#[optional_name = "PartialReport"]
|
||||
#[opt_skip_serializing_none]
|
||||
pub struct Report {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
@@ -98,6 +101,10 @@ pub struct Report {
|
||||
/// Additional report context
|
||||
pub additional_context: String,
|
||||
/// Status of the report
|
||||
#[opt_passthrough]
|
||||
#[serde(flatten)]
|
||||
pub status: ReportStatus,
|
||||
/// Additional notes included on the report
|
||||
#[serde(default)]
|
||||
pub notes: String,
|
||||
}
|
||||
|
||||
@@ -51,6 +51,10 @@ pub fn get_relationship(a: &User, b: &str) -> RelationshipStatus {
|
||||
async fn calculate_permission(data: &mut PermissionCalculator<'_>, db: &crate::Database) -> u32 {
|
||||
let user = data.user.get().unwrap();
|
||||
|
||||
if data.perspective.privileged {
|
||||
return u32::MAX;
|
||||
}
|
||||
|
||||
if data.perspective.id == user.id {
|
||||
return u32::MAX;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
use crate::{models::stats::Stats, Result};
|
||||
|
||||
#[async_trait]
|
||||
pub trait AbstractStats: Sync + Send {
|
||||
async fn generate_stats(&self) -> Result<Stats>;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
mod admin {
|
||||
pub mod migrations;
|
||||
pub mod stats;
|
||||
}
|
||||
|
||||
mod media {
|
||||
@@ -32,6 +33,7 @@ mod safety {
|
||||
}
|
||||
|
||||
pub use admin::migrations::AbstractMigrations;
|
||||
pub use admin::stats::AbstractStats;
|
||||
|
||||
pub use media::attachment::AbstractAttachment;
|
||||
pub use media::emoji::AbstractEmoji;
|
||||
@@ -56,6 +58,7 @@ pub trait AbstractDatabase:
|
||||
Sync
|
||||
+ Send
|
||||
+ AbstractMigrations
|
||||
+ AbstractStats
|
||||
+ AbstractAttachment
|
||||
+ AbstractEmoji
|
||||
+ AbstractChannel
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::report::PartialReport;
|
||||
use crate::models::Report;
|
||||
use crate::Result;
|
||||
|
||||
@@ -6,6 +7,12 @@ pub trait AbstractReport: Sync + Send {
|
||||
/// Insert a new report into the database
|
||||
async fn insert_report(&self, report: &Report) -> Result<()>;
|
||||
|
||||
/// Update a given report with new information
|
||||
async fn update_report(&self, id: &str, message: &PartialReport) -> Result<()>;
|
||||
|
||||
/// Fetch report
|
||||
async fn fetch_report(&self, report_id: &str) -> Result<Report>;
|
||||
|
||||
/// Fetch reports
|
||||
async fn fetch_reports(&self) -> Result<Vec<Report>>;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ use schemars::schema::{InstanceType, Schema, SchemaObject, SingleOrVec};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models::{Bot, Channel, Emoji, Invite, Member, Message, Server, ServerBan, User};
|
||||
use crate::models::{
|
||||
Bot, Channel, Emoji, Invite, Member, Message, Report, Server, ServerBan, User,
|
||||
};
|
||||
use crate::presence::presence_is_online;
|
||||
use crate::{Database, Error, Result};
|
||||
|
||||
@@ -78,6 +80,11 @@ impl Ref {
|
||||
pub async fn as_emoji(&self, db: &Database) -> Result<Emoji> {
|
||||
db.fetch_emoji(&self.id).await
|
||||
}
|
||||
|
||||
/// Fetch report from Ref
|
||||
pub async fn as_report(&self, db: &Database) -> Result<Report> {
|
||||
db.fetch_report(&self.id).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> FromParam<'r> for Ref {
|
||||
|
||||
Reference in New Issue
Block a user