mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-07-12 11:16:24 +02:00
sdkfjsadklfsdklfdjsakfljas
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
d5db11eb45
commit
b3986b3350
4 changed files with 142 additions and 5 deletions
|
@ -1,4 +1,4 @@
|
||||||
use ruma::api::client::error::ErrorKind;
|
use ruma::{api::client::error::ErrorKind, OwnedUserId};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -25,8 +25,12 @@ impl service::media::Data for KeyValueDatabase {
|
||||||
self.mediaid_file.insert(&key, &[])?;
|
self.mediaid_file.insert(&key, &[])?;
|
||||||
|
|
||||||
if let Some(user) = sender_user {
|
if let Some(user) = sender_user {
|
||||||
let key = mxc.as_bytes().to_vec();
|
let mut key = mxc.as_bytes().to_vec();
|
||||||
let user = user.as_bytes().to_vec();
|
key.push(0xFF);
|
||||||
|
|
||||||
|
let mut user = user.as_bytes().to_vec();
|
||||||
|
user.push(0xFF);
|
||||||
|
|
||||||
self.mediaid_user.insert(&key, &user)?;
|
self.mediaid_user.insert(&key, &user)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +69,8 @@ impl service::media::Data for KeyValueDatabase {
|
||||||
let mut prefix = mxc.as_bytes().to_vec();
|
let mut prefix = mxc.as_bytes().to_vec();
|
||||||
prefix.push(0xFF);
|
prefix.push(0xFF);
|
||||||
|
|
||||||
|
debug!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA prefix: {:?}", prefix);
|
||||||
|
|
||||||
let mut keys: Vec<Vec<u8>> = vec![];
|
let mut keys: Vec<Vec<u8>> = vec![];
|
||||||
|
|
||||||
for (key, _) in self.mediaid_file.scan_prefix(prefix) {
|
for (key, _) in self.mediaid_file.scan_prefix(prefix) {
|
||||||
|
@ -82,6 +88,23 @@ impl service::media::Data for KeyValueDatabase {
|
||||||
Ok(keys)
|
Ok(keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_all_media_keys_by_user(&self, user_id: OwnedUserId) -> Result<Vec<Vec<u8>>> {
|
||||||
|
debug!("User ID: {user_id:?}");
|
||||||
|
|
||||||
|
let mut user = user_id.as_bytes().to_vec();
|
||||||
|
user.push(0xFF);
|
||||||
|
|
||||||
|
let mut keys: Vec<Vec<u8>> = vec![];
|
||||||
|
|
||||||
|
for (key, value) in self.mediaid_user.iter() {
|
||||||
|
if value == user {
|
||||||
|
keys.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(keys)
|
||||||
|
}
|
||||||
|
|
||||||
fn search_file_metadata(
|
fn search_file_metadata(
|
||||||
&self, mxc: String, width: u32, height: u32,
|
&self, mxc: String, width: u32, height: u32,
|
||||||
) -> Result<(Option<String>, Option<String>, Vec<u8>)> {
|
) -> Result<(Option<String>, Option<String>, Vec<u8>)> {
|
||||||
|
|
|
@ -94,6 +94,12 @@ enum MediaCommand {
|
||||||
event_id: Option<Box<EventId>>,
|
event_id: Option<Box<EventId>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Deletes all **uploaded** local media from the specified user.
|
||||||
|
DeleteFromUser {
|
||||||
|
/// User ID to delete all media from
|
||||||
|
user_id: Box<UserId>,
|
||||||
|
},
|
||||||
|
|
||||||
/// - Deletes a codeblock list of MXC URLs from our database and on the
|
/// - Deletes a codeblock list of MXC URLs from our database and on the
|
||||||
/// filesystem
|
/// filesystem
|
||||||
DeleteList,
|
DeleteList,
|
||||||
|
@ -105,6 +111,13 @@ enum MediaCommand {
|
||||||
/// past 5 minutes
|
/// past 5 minutes
|
||||||
duration: String,
|
duration: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// - Lists all **uploaded** local media from the specified user with their
|
||||||
|
/// MXC URLs.
|
||||||
|
ListFromUser {
|
||||||
|
/// User ID to list all media from
|
||||||
|
user_id: Box<UserId>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(test, derive(Debug))]
|
#[cfg_attr(test, derive(Debug))]
|
||||||
|
@ -806,6 +819,17 @@ impl Service {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
MediaCommand::DeleteFromUser {
|
||||||
|
user_id,
|
||||||
|
} => {
|
||||||
|
let deleted_count = services().media.delete_from_user(user_id.into()).await?;
|
||||||
|
|
||||||
|
debug!("Deleted {deleted_count} total media files.");
|
||||||
|
|
||||||
|
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"Deleted {deleted_count} total media files.",
|
||||||
|
)));
|
||||||
|
},
|
||||||
MediaCommand::DeleteList => {
|
MediaCommand::DeleteList => {
|
||||||
if body.len() > 2 && body[0].trim().starts_with("```") && body.last().unwrap().trim() == "```" {
|
if body.len() > 2 && body[0].trim().starts_with("```") && body.last().unwrap().trim() == "```" {
|
||||||
let mxc_list = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>();
|
let mxc_list = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>();
|
||||||
|
@ -839,6 +863,25 @@ impl Service {
|
||||||
deleted_count
|
deleted_count
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
|
MediaCommand::ListFromUser {
|
||||||
|
user_id,
|
||||||
|
} => {
|
||||||
|
let mxc_list = services().media.list_all_media_by_user(user_id.clone().into()).await?;
|
||||||
|
|
||||||
|
let output_plain = format!(
|
||||||
|
"All MXC URLs {user_id} Uploaded:\n{}",
|
||||||
|
mxc_list.iter().map(ToOwned::to_owned).collect::<Vec<_>>().join("\n")
|
||||||
|
);
|
||||||
|
let output_html = format!(
|
||||||
|
"<table><caption>All MXC URLs {user_id} \
|
||||||
|
Uploaded</caption>\n<tr><th>URL</th></tr>\n{}</table>",
|
||||||
|
mxc_list.iter().fold(String::new(), |mut output, mxc| {
|
||||||
|
writeln!(output, "<tr><td>{}</td></tr>", mxc).unwrap();
|
||||||
|
output
|
||||||
|
})
|
||||||
|
);
|
||||||
|
RoomMessageEventContent::text_html(output_plain, output_html)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AdminCommand::Users(command) => match command {
|
AdminCommand::Users(command) => match command {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use ruma::OwnedUserId;
|
||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
pub trait Data: Send + Sync {
|
pub trait Data: Send + Sync {
|
||||||
|
@ -15,6 +17,8 @@ pub trait Data: Send + Sync {
|
||||||
|
|
||||||
fn search_mxc_metadata_prefix(&self, mxc: String) -> Result<Vec<Vec<u8>>>;
|
fn search_mxc_metadata_prefix(&self, mxc: String) -> Result<Vec<Vec<u8>>>;
|
||||||
|
|
||||||
|
fn get_all_media_keys_by_user(&self, user_id: OwnedUserId) -> Result<Vec<Vec<u8>>>;
|
||||||
|
|
||||||
fn get_all_media_keys(&self) -> Result<Vec<Vec<u8>>>;
|
fn get_all_media_keys(&self) -> Result<Vec<Vec<u8>>>;
|
||||||
|
|
||||||
fn remove_url_preview(&self, url: &str) -> Result<()>;
|
fn remove_url_preview(&self, url: &str) -> Result<()>;
|
||||||
|
|
|
@ -12,7 +12,7 @@ use tokio::{
|
||||||
};
|
};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
use crate::{services, utils, Error, Result};
|
use crate::{services, utils::string_from_bytes, Error, Result};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FileMeta {
|
pub struct FileMeta {
|
||||||
|
@ -110,6 +110,71 @@ impl Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deletes all media in the database and from the media directory by a
|
||||||
|
/// specific user
|
||||||
|
pub async fn delete_from_user(&self, user_id: OwnedUserId) -> Result<u32> {
|
||||||
|
if let Ok(user_keys) = self.db.get_all_media_keys_by_user(user_id.clone()) {
|
||||||
|
if user_keys.is_empty() {
|
||||||
|
error!("User \"{user_id}\" has not uploaded any media.");
|
||||||
|
return Err(Error::bad_database("User has not uploaded any media."));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mxc_deletion_count = 0;
|
||||||
|
|
||||||
|
for key in user_keys {
|
||||||
|
let mxc = String::from_utf8_lossy(&key);
|
||||||
|
|
||||||
|
let keys = self.db.search_mxc_metadata_prefix(mxc.to_string())?; // the MXC alone does not determine the file path, it is only the prefix
|
||||||
|
|
||||||
|
for key in keys {
|
||||||
|
let mxc = String::from_utf8_lossy(&key);
|
||||||
|
|
||||||
|
debug!("Deleting MXC {mxc} from database");
|
||||||
|
|
||||||
|
self.delete(mxc.to_string()).await?;
|
||||||
|
|
||||||
|
mxc_deletion_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(mxc_deletion_count)
|
||||||
|
} else {
|
||||||
|
error!("Failed to find any media keys for user \"{user_id}\" in our database");
|
||||||
|
Err(Error::bad_database(
|
||||||
|
"Failed to find any media keys for the provided user in our database",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_all_media_by_user(&self, user_id: OwnedUserId) -> Result<Vec<String>> {
|
||||||
|
if let Ok(keys) = self.db.get_all_media_keys_by_user(user_id.clone()) {
|
||||||
|
if keys.is_empty() {
|
||||||
|
error!("User \"{user_id}\" has not uploaded any media.");
|
||||||
|
return Err(Error::bad_database("User has not uploaded any media."));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mxc_list: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for key in keys {
|
||||||
|
let mxc_string = string_from_bytes(&key).map_err(|e| {
|
||||||
|
error!("Failed to convert MXC key to string in database for user \"{user_id}\": {e}");
|
||||||
|
Error::bad_database("Failed to convert MXC key to string in database")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// TODO: add the file name
|
||||||
|
|
||||||
|
mxc_list.push(mxc_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(mxc_list)
|
||||||
|
} else {
|
||||||
|
error!("Failed to find any media keys for user \"{user_id}\" in our database");
|
||||||
|
Err(Error::bad_database(
|
||||||
|
"Failed to find any media keys for the provided user in our database",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Uploads or replaces a file thumbnail.
|
/// Uploads or replaces a file thumbnail.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn upload_thumbnail(
|
pub async fn upload_thumbnail(
|
||||||
|
@ -200,7 +265,7 @@ impl Service {
|
||||||
let mxc = parts
|
let mxc = parts
|
||||||
.next()
|
.next()
|
||||||
.map(|bytes| {
|
.map(|bytes| {
|
||||||
utils::string_from_bytes(bytes).map_err(|e| {
|
string_from_bytes(bytes).map_err(|e| {
|
||||||
error!("Failed to parse MXC unicode bytes from our database: {}", e);
|
error!("Failed to parse MXC unicode bytes from our database: {}", e);
|
||||||
Error::bad_database("Failed to parse MXC unicode bytes from our database")
|
Error::bad_database("Failed to parse MXC unicode bytes from our database")
|
||||||
})
|
})
|
||||||
|
@ -502,6 +567,8 @@ mod tests {
|
||||||
|
|
||||||
fn search_mxc_metadata_prefix(&self, _mxc: String) -> Result<Vec<Vec<u8>>> { todo!() }
|
fn search_mxc_metadata_prefix(&self, _mxc: String) -> Result<Vec<Vec<u8>>> { todo!() }
|
||||||
|
|
||||||
|
fn get_all_media_keys_by_user(&self, _user_id: OwnedUserId) -> Result<Vec<Vec<u8>>> { todo!() }
|
||||||
|
|
||||||
fn get_all_media_keys(&self) -> Result<Vec<Vec<u8>>> { todo!() }
|
fn get_all_media_keys(&self) -> Result<Vec<Vec<u8>>> { todo!() }
|
||||||
|
|
||||||
fn search_file_metadata(
|
fn search_file_metadata(
|
||||||
|
|
Loading…
Add table
Reference in a new issue