Plume/src/routes/medias.rs

108 lines
3.9 KiB
Rust
Raw Normal View History

2018-09-02 22:55:42 +02:00
use guid_create::GUID;
use multipart::server::{Multipart, save::{SavedData, SaveResult}};
use rocket::{Data, http::ContentType, response::{Redirect, status}};
use rocket_i18n::I18n;
use std::fs;
2018-09-02 22:55:42 +02:00
use plume_models::{db_conn::DbConn, medias::*, users::User};
use template_utils::Ructe;
2018-09-02 22:55:42 +02:00
#[get("/medias")]
pub fn list(user: User, conn: DbConn, intl: I18n) -> Ructe {
2018-09-02 22:55:42 +02:00
let medias = Media::for_user(&*conn, user.id);
render!(medias::index(
&(&*conn, &intl.catalog, Some(user)),
medias
))
2018-09-02 22:55:42 +02:00
}
#[get("/medias/new")]
pub fn new(user: User, conn: DbConn, intl: I18n) -> Ructe {
render!(medias::new(
&(&*conn, &intl.catalog, Some(user))
))
2018-09-02 22:55:42 +02:00
}
#[post("/medias/new", data = "<data>")]
pub fn upload(user: User, data: Data, ct: &ContentType, conn: DbConn) -> Result<Redirect, status::BadRequest<&'static str>> {
2018-09-02 22:55:42 +02:00
if ct.is_form_data() {
let (_, boundary) = ct.params().find(|&(k, _)| k == "boundary").ok_or_else(|| status::BadRequest(Some("No boundary")))?;
2018-09-02 22:55:42 +02:00
match Multipart::with_body(data.open(), boundary).save().temp() {
SaveResult::Full(entries) => {
let fields = entries.fields;
let filename = fields.get(&"file".to_string()).and_then(|v| v.into_iter().next())
.ok_or_else(|| status::BadRequest(Some("No file uploaded")))?.headers
.filename.clone();
let ext = filename.and_then(|f| f.rsplit('.').next().map(|ext| ext.to_owned()))
.unwrap_or_else(|| "png".to_owned());
2018-10-12 21:22:57 +02:00
let dest = format!("static/media/{}.{}", GUID::rand().to_string(), ext);
2018-09-02 22:55:42 +02:00
match fields[&"file".to_string()][0].data {
SavedData::Bytes(ref bytes) => fs::write(&dest, bytes).expect("media::upload: Couldn't save upload"),
SavedData::File(ref path, _) => {fs::copy(path, &dest).expect("media::upload: Couldn't copy upload");},
_ => {
println!("not a file");
return Ok(Redirect::to(uri!(new)));
2018-09-02 22:55:42 +02:00
}
}
let has_cw = !read(&fields[&"cw".to_string()][0].data).is_empty();
2018-09-02 22:55:42 +02:00
let media = Media::insert(&*conn, NewMedia {
file_path: dest,
alt_text: read(&fields[&"alt".to_string()][0].data),
is_remote: false,
remote_url: None,
sensitive: has_cw,
content_warning: if has_cw {
Some(read(&fields[&"cw".to_string()][0].data))
} else {
None
},
owner_id: user.id
});
println!("ok");
Ok(Redirect::to(uri!(details: id = media.id)))
2018-09-02 22:55:42 +02:00
},
SaveResult::Partial(_, _) | SaveResult::Error(_) => {
println!("partial err");
Ok(Redirect::to(uri!(new)))
2018-09-02 22:55:42 +02:00
}
}
} else {
println!("not form data");
Ok(Redirect::to(uri!(new)))
2018-09-02 22:55:42 +02:00
}
}
fn read(data: &SavedData) -> String {
if let SavedData::Text(s) = data {
s.clone()
} else {
panic!("Field is not a string")
}
}
#[get("/medias/<id>")]
pub fn details(id: i32, user: User, conn: DbConn, intl: I18n) -> Ructe {
let media = Media::get(&*conn, id).expect("Media::details: media not found");
render!(medias::details(
&(&*conn, &intl.catalog, Some(user)),
media
))
2018-09-02 22:55:42 +02:00
}
#[post("/medias/<id>/delete")]
pub fn delete(id: i32, _user: User, conn: DbConn) -> Option<Redirect> {
let media = Media::get(&*conn, id)?;
2018-09-02 23:10:15 +02:00
media.delete(&*conn);
Some(Redirect::to(uri!(list)))
2018-09-02 23:10:15 +02:00
}
#[post("/medias/<id>/avatar")]
pub fn set_avatar(id: i32, user: User, conn: DbConn) -> Option<Redirect> {
let media = Media::get(&*conn, id)?;
2018-09-03 14:04:17 +02:00
user.set_avatar(&*conn, media.id);
Some(Redirect::to(uri!(details: id = id)))
2018-09-03 14:04:17 +02:00
}