Náhledy přes magick + malé změny

Tento commit je obsažen v:
sneedmaster 2023-12-12 18:54:48 +01:00
rodič 11b3c852a8
revize 7a0d219f08
7 změnil soubory, kde provedl 61 přidání a 38 odebrání

Zobrazit soubor

@ -152,7 +152,7 @@ impl From<sqlx::Error> for NekrochanError {
Self::OverboardError Self::OverboardError
} else { } else {
error!("{e:#?}"); error!("{e:#?}");
Self::InternalError Self::InternalError
} }
} }

Zobrazit soubor

@ -2,7 +2,6 @@ use actix_multipart::form::tempfile::TempFile;
use anyhow::Error; use anyhow::Error;
use chrono::Utc; use chrono::Utc;
use glob::glob; use glob::glob;
use image::io::Reader as ImageReader;
use std::{collections::HashSet, process::Command}; use std::{collections::HashSet, process::Command};
use tokio::{ use tokio::{
fs::{remove_file, rename}, fs::{remove_file, rename},
@ -144,18 +143,34 @@ async fn process_image(
new_name: String, new_name: String,
thumb_name: Option<String>, thumb_name: Option<String>,
) -> Result<(u32, u32), NekrochanError> { ) -> Result<(u32, u32), NekrochanError> {
let original_name_ = original_name.clone(); let new_name_ = new_name.clone();
let img = spawn_blocking(move || { let identify_out = spawn_blocking(move || {
ImageReader::open(format!("/tmp/{new_name}"))? Command::new("identify")
.decode() .args(["-format", "%wx%h", &format!("/tmp/{new_name_}[0]")])
.map_err(|_| { .output()
NekrochanError::FileError(original_name_, "nepodařilo se dekódovat obrázek")
})
}) })
.await??; .await??;
let (width, height) = (img.width(), img.height()); let invalid_dimensions = "imagemagick vrátil neplatné rozměry";
let out_string = String::from_utf8_lossy(&identify_out.stdout);
let (width, height) = out_string
.trim()
.split_once('x')
.ok_or(NekrochanError::FileError(
original_name.clone(),
invalid_dimensions,
))?;
let (width, height) = (
width
.parse()
.map_err(|_| NekrochanError::FileError(original_name.clone(), invalid_dimensions))?,
height
.parse()
.map_err(|_| NekrochanError::FileError(original_name.clone(), invalid_dimensions))?,
);
if width > cfg.files.max_width || height > cfg.files.max_height { if width > cfg.files.max_width || height > cfg.files.max_height {
return Err(NekrochanError::FileError( return Err(NekrochanError::FileError(
@ -168,29 +183,27 @@ async fn process_image(
return Ok((width, height)); return Ok((width, height));
}; };
let thumb_w = if width > cfg.files.thumb_size { let thumb_size = cfg.files.thumb_size;
cfg.files.thumb_size
} else {
width
};
let thumb_h = if height > cfg.files.thumb_size { let output = spawn_blocking(move || {
cfg.files.thumb_size Command::new("convert")
} else { .arg(&format!("/tmp/{new_name}"))
height .arg("-thumbnail")
}; .arg(&format!("{thumb_size}x{thumb_size}>"))
.arg(&format!("./uploads/thumb/{thumb_name}"))
spawn_blocking(move || { .output()
let thumb = img.thumbnail(thumb_w, thumb_h);
thumb
.save(format!("./uploads/thumb/{thumb_name}"))
.map_err(|_| {
NekrochanError::FileError(original_name, "nepodařilo se vytvořit náhled obrázku")
})
}) })
.await??; .await??;
if !output.status.success() {
println!("{}", String::from_utf8_lossy(&output.stderr));
return Err(NekrochanError::FileError(
original_name,
"nepodařilo se vytvořit náhled obrázku",
));
}
Ok((width, height)) Ok((width, height))
} }
@ -226,8 +239,7 @@ async fn process_video(
)); ));
} }
let invalid_dimensions = "ffprobe vrátil neplatné rozměry"; let invalid_dimensions = "ffmeg vrátil neplatné rozměry";
let out_string = String::from_utf8_lossy(&ffprobe_out.stdout); let out_string = String::from_utf8_lossy(&ffprobe_out.stdout);
let (width, height) = out_string let (width, height) = out_string

Zobrazit soubor

@ -13,6 +13,7 @@ lazy_static! {
pub fn czech_humantime(time: &DateTime<Utc>) -> askama::Result<String> { pub fn czech_humantime(time: &DateTime<Utc>) -> askama::Result<String> {
let duration = (Utc::now() - *time).abs(); let duration = (Utc::now() - *time).abs();
let seconds = duration.num_seconds();
let minutes = duration.num_minutes(); let minutes = duration.num_minutes();
let hours = duration.num_hours(); let hours = duration.num_hours();
let days = duration.num_days(); let days = duration.num_days();
@ -22,6 +23,14 @@ pub fn czech_humantime(time: &DateTime<Utc>) -> askama::Result<String> {
let mut time = "Teď".into(); let mut time = "Teď".into();
if seconds > 0 {
time = format!(
"{} {}",
seconds,
czech_plural("sekunda|sekundy|sekund", seconds)?
);
}
if minutes > 0 { if minutes > 0 {
time = format!( time = format!(
"{} {}", "{} {}",

Zobrazit soubor

@ -135,8 +135,9 @@ where
<B as MessageBody>::Error: ResponseError + 'static, <B as MessageBody>::Error: ResponseError + 'static,
{ {
let (req, res) = res.into_parts(); let (req, res) = res.into_parts();
let status = res.status();
let error_code = res.status().as_u16(); let error_code = status.as_u16();
let error_message = match res.into_body().try_into_bytes().ok() { let error_message = match res.into_body().try_into_bytes().ok() {
Some(bytes) => String::from_utf8(bytes.to_vec()).unwrap_or_default(), Some(bytes) => String::from_utf8(bytes.to_vec()).unwrap_or_default(),
None => String::default(), None => String::default(),
@ -147,7 +148,9 @@ where
error_message, error_message,
}; };
let res = template_response(&template)?; let mut res = template_response(&template)?;
*(res.status_mut()) = status;
let res = ServiceResponse::new(req, res).map_into_right_body(); let res = ServiceResponse::new(req, res).map_into_right_body();
Ok(ErrorHandlerResponse::Response(res)) Ok(ErrorHandlerResponse::Response(res))

Zobrazit soubor

@ -1,8 +1,7 @@
use std::collections::HashMap;
use fancy_regex::{Captures, Regex}; use fancy_regex::{Captures, Regex};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use sqlx::query_as; use sqlx::query_as;
use std::collections::HashMap;
use crate::{ use crate::{
ctx::Ctx, ctx::Ctx,

Zobrazit soubor

@ -339,8 +339,8 @@ summary {
} }
.thumb { .thumb {
max-width: 150px; max-width: 200px;
max-height: 150px; max-height: 200px;
} }
.post-content { .post-content {

Zobrazit soubor

@ -4,7 +4,7 @@
<b>/{{ post.board }}/{{ post.id }}</b> <b>/{{ post.board }}/{{ post.id }}</b>
{% if let Some(file) = post.files.0.get(0) %} {% if let Some(file) = post.files.0.get(0) %}
<a href="{{ post.post_url_notarget() }}"> <a href="{{ post.post_url_notarget() }}">
<img src="{{ file.thumb_url() }}"> <img class="thumb" src="{{ file.thumb_url() }}">
</a> </a>
{% else %} {% else %}
<p><b><a href="{{ post.post_url_notarget() }}">[Link]</a></b></p> <p><b><a href="{{ post.post_url_notarget() }}">[Link]</a></b></p>