Clean up and add more documentation
Explore-Gitea-Actions Details

main
Volkor 1 month ago
parent 0e4b005bf3
commit 57c0dc4a81
Signed by: Volkor
GPG Key ID: BAD7CA8A81CC2DA5

@ -1,7 +1,7 @@
use sqlx::{sqlite::SqliteQueryResult, Pool, Sqlite};
use std::{collections::HashMap, time::SystemTime};
// This struct is used to store values for metrics file stats.
/// This struct represents a single file, with a few statistics about said file instance.
pub struct FileMetric {
pub filename: String,
pub filesize: i64,
@ -10,6 +10,7 @@ pub struct FileMetric {
pub expiry: i64,
}
// This struct represents a single mimetype, with a few statistics about said mimetype instance
pub struct MimetypeMetric {
pub mimetype: String,
pub host: String,
@ -21,8 +22,8 @@ pub struct MimetypeMetric {
pub views_dead: i64,
}
// Adding a file to the database
// TODO: Fix panic on fileadd with same filename (even if isDeleted) (UNIQUE constraint)
/// Adding a file to the database
/// TODO: Fix panic on fileadd with same filename (even if isDeleted) (UNIQUE constraint)
pub async fn add_file(
sqlconn: &Pool<Sqlite>,
file: String,
@ -95,8 +96,8 @@ pub async fn check_filename(sqlconn: &Pool<Sqlite>, filename: &String) -> bool {
}
}
// This function receives an adminkey, (and sqlpool) and returns a Some(String) containing the filename that corresponds to the adminkey.
// It returns files that haven't already been deleted, so this is a 'single-use' operation per file.
/// This function returns a filename that corresponds to the adminkey that is provided.
/// This is used for deleting files, so this is mostly a 'single-use' operation, but I imagine that it could be used for something else.
pub async fn check_adminkey(sqlconn: &Pool<Sqlite>, adminkey: String) -> Option<String> {
let result = sqlx::query!(
"SELECT file FROM files WHERE adminkey = ? AND isDeleted = 0",
@ -117,7 +118,8 @@ pub async fn check_adminkey(sqlconn: &Pool<Sqlite>, adminkey: String) -> Option<
}
}
// This function queries the database for a mimetype for the given file.
/// This returns the mimetype of the file from the database.
/// This is used for serving files, so that we can set the mimetype of unsafe files.
pub async fn get_mimetype(sqlconn: &Pool<Sqlite>, file: String) -> Option<String> {
let result = sqlx::query!(
"SELECT mimetype FROM files WHERE file = ? AND isDeleted = 0",
@ -138,8 +140,9 @@ pub async fn get_mimetype(sqlconn: &Pool<Sqlite>, file: String) -> Option<String
}
}
// Marking a file as deleted in the DB (Doesn't delete the file on disk)
// This function returns a Some(u64), with the number of rows modified.
/// This marks a file as deleted in the database.
/// This doesn't delete the file on disk, however.
/// Returns the number (Some(u64)) of the number of files deleted.
pub async fn delete_file(sqlconn: &Pool<Sqlite>, filename: String) -> Option<u64> {
tracing::debug!("delete_file(adminkey: {})", filename);
let result = sqlx::query!("UPDATE files SET isDeleted = 1 WHERE file = ?", filename)
@ -154,9 +157,8 @@ pub async fn delete_file(sqlconn: &Pool<Sqlite>, filename: String) -> Option<u64
}
}
// Updating a files viewcount and accesstime.
// This receives the a String with the filename, i32 unix timestamp (and sqlpool)
// This returns a Some(u64), with the number of rows affected.
/// Updates a file's viewcount and accesstime.
/// Returns a Some(u64), with the number of rows affected.
pub async fn update_fileview(
sqlconn: &Pool<Sqlite>,
filename: String,
@ -178,8 +180,8 @@ pub async fn update_fileview(
}
}
// Returns the unix timestamp of the last access - 0 if unviewed.
// This doesn't do the basic error handling like the above functions, this re-write it completely.
/// Returns the unix timestamp of the last access - 0 if unviewed.
/// This will break in 2038
pub async fn get_accesss_time(sqlconn: &Pool<Sqlite>, filename: String) -> i32 {
let result = sqlx::query!("SELECT accessed FROM files WHERE file = ?", filename)
.fetch_one(sqlconn)
@ -205,7 +207,7 @@ pub async fn get_accesss_time(sqlconn: &Pool<Sqlite>, filename: String) -> i32 {
}
}
// Generating a list of files that should be deleted
/// Generating a list of files that should be deleted
pub async fn get_old_files(sqlconn: &Pool<Sqlite>) -> Vec<String> {
// Get the current time
let time = SystemTime::now()
@ -240,9 +242,9 @@ pub async fn get_old_files(sqlconn: &Pool<Sqlite>) -> Vec<String> {
files
}
// This function adds a new QR code scan to the database
// This uses the current time.
// Version is the 'iteration' of the QR Code, since in the future there wil be different QR Codes.
/// This adds a new QR code scan to the database.
/// The version string is the 'iteration' of the qr code itself, as I'd like to print multiple qr codes with multiple features.
/// TODO: we should probably move the time out of this function, so we can change the time if backfilling.
pub async fn add_qrscan(
sqlconn: &Pool<Sqlite>,
ip: String,
@ -270,13 +272,20 @@ pub async fn add_qrscan(
result
}
// Updating the expiry_override of a file.
/// Updating the expiry_override of a file.
/// There are a few limitations and considerations for expiry_override:
///
/// 1. The expiry_override must be set lower than the expiry of the file.
/// 2. EXCEPT when the file has been uploaded by an API Key that has permission to change expiry_override beyond the expiry
/// 3. The expiry_override cannot be set longer than file_expiry_max, unless the file has been uploaded by an API Key that allows 'permanent' uploads.
///
/// If /any/ of those limits are broken, this function will not update and return an error, with the reason why.
fn update_expiry_override() {
todo!()
}
// This function gets a array of all the files uploaded by a specific API Key.
// This allows for the select few who hold an API key to view the information about the files they upload.
/// This function gets a array of all the files uploaded by a specific API Key.
/// This allows for the select few who hold an API key to view the information about the files they upload.
pub async fn get_my_files(sqlconn: &Pool<Sqlite>) -> Option<Vec<FileMetric>> {
// TODO: PLEASE OH PLEASE DO NOT USE THIS FUNCTION YET, this returns ALL files uploaded.
let result = sqlx::query!(
@ -312,8 +321,9 @@ pub async fn get_my_files(sqlconn: &Pool<Sqlite>) -> Option<Vec<FileMetric>> {
// Globally important stats.
// This function counts the total files that have been uploaded per ip.
// This returns a hashmap<String, i32> containing the IP, and the number of files uploaded.
/// This counts the total files that have been uploaded per ip address.
/// This returns a hashmap<String, i32> containing the IP, and the number of files uploaded.
/// This isn't perfect, as some devices that use IPv6 can sometimes use that, but then also switch to IPv4.
pub async fn get_total_uploads_ip(sqlconn: &Pool<Sqlite>) -> Option<HashMap<String, i32>> {
// SELECT ip, COUNT(file) as count FROM files GROUP BY ip ORDER BY COUNT;
let result = sqlx::query!(
@ -339,8 +349,12 @@ pub async fn get_total_uploads_ip(sqlconn: &Pool<Sqlite>) -> Option<HashMap<Stri
}
}
// This function queries the db for the total filesize of all alive files.
// Returns a Option<u128> because why not, an i32 isn't big enough anyway.
/// This queries the db for the total filesize (in bytes) of all alive files.
/// This can VERY Quickly become massive, so we use a u128.
///
/// 340,282,366,920,938,463,463,374,607,431,768,211,455 bytes
/// 3.095×10^26 TiB, or 309500000000000000000000000 TiB
/// or 3700000000000000000000 * more data than exists on the internet (as of 2014).
pub async fn total_alive_filesize(sqlconn: &Pool<Sqlite>) -> Option<u128> {
let mut total_filesize: u128 = 0;
let result = sqlx::query!(
@ -362,8 +376,14 @@ pub async fn total_alive_filesize(sqlconn: &Pool<Sqlite>) -> Option<u128> {
}
}
// This function queries the db for the total filesize of all alive files.
// Returns a Option<u128> because why not, an i32 isn't big enough anyway.
/// This queries the db for the total filesize (in bytes) of all dead files.
/// This can VERY Quickly become massive, so we use a u128.
///
/// 340,282,366,920,938,463,463,374,607,431,768,211,455 bytes
///
/// 3.095×10^26 TiB, or 309500000000000000000000000 TiB
///
/// or 3700000000000000000000 * more data than exists on the internet (as of 2014).
pub async fn total_dead_filesize(sqlconn: &Pool<Sqlite>) -> Option<u128> {
let mut total_dead_filesize: u128 = 0;
let result = sqlx::query!(
@ -385,10 +405,10 @@ pub async fn total_dead_filesize(sqlconn: &Pool<Sqlite>) -> Option<u128> {
}
}
// This function queries the db for the filesize for /each/ alive file. - We won't need to do this for dead files
// since they were alive at some point, and when they are removed from the alive list, we don't really care.
// This returns a Hashmap of the filename, filetype, and filesize inside a Vector. (How messy)
// We want to group them by file, or filetype, or total in grafana, so it needs to be run on each file.
/// This queries the db for the filesize for /each/ alive file. - We won't need to do this for dead files
/// since they were alive at some point, and when they are removed from the alive list, we don't really care.
/// This returns a Hashmap of the filename, filetype, and filesize inside a Vector. (How messy)
/// We want to group them by file, or filetype, or total in grafana, so it needs to be run on each file.
pub async fn get_file_metrics(sqlconn: &Pool<Sqlite>) -> Option<Vec<FileMetric>> {
let result = sqlx::query!(
"SELECT file, filesize, mimetype, views, expiry
@ -422,8 +442,8 @@ pub async fn get_file_metrics(sqlconn: &Pool<Sqlite>) -> Option<Vec<FileMetric>>
}
}
// This function queries the db for metrics related to mimetypes.
// Returns a Vec of if the MimetypeMetric Struct.
/// This function queries the db for metrics related to mimetypes.
/// Returns a Vec of if the MimetypeMetric Struct.
pub async fn get_mimetype_metrics(sqlconn: &Pool<Sqlite>) -> Option<Vec<MimetypeMetric>> {
// Get stats about the files
// This is insane, ChatGPT wrote this entire query. I did no changes at all and it just worked.

@ -46,6 +46,7 @@ struct TemplateStruct {
message2: String,
}
/// This handles and renders the main index(/) page
#[handler]
async fn index(req: &mut Request, res: &mut Response) {
// Get the headers (for Host header stuff thats needed later)
@ -62,6 +63,7 @@ async fn index(req: &mut Request, res: &mut Response) {
res.render(Text::Html(rendered));
}
/// This handles serving files from disk, and all the tracking that goes with it.
#[handler]
async fn serve_file(req: &mut Request, res: &mut Response) {
let headers = req.headers().clone();
@ -154,7 +156,7 @@ async fn serve_file(req: &mut Request, res: &mut Response) {
}
}
// This takes the adminkey in, and deletes the file that matches it in the DB.
/// This takes the adminkey in, and deletes the file that matches it in the DB.
#[handler]
async fn delete_file(req: &mut Request, res: &mut Response) {
let headers = req.headers().clone();

Loading…
Cancel
Save