Náhledy přes magick + malé změny
Tento commit je obsažen v:
rodič
11b3c852a8
revize
7a0d219f08
@ -152,7 +152,7 @@ impl From<sqlx::Error> for NekrochanError {
|
||||
Self::OverboardError
|
||||
} else {
|
||||
error!("{e:#?}");
|
||||
|
||||
|
||||
Self::InternalError
|
||||
}
|
||||
}
|
||||
|
72
src/files.rs
72
src/files.rs
@ -2,7 +2,6 @@ use actix_multipart::form::tempfile::TempFile;
|
||||
use anyhow::Error;
|
||||
use chrono::Utc;
|
||||
use glob::glob;
|
||||
use image::io::Reader as ImageReader;
|
||||
use std::{collections::HashSet, process::Command};
|
||||
use tokio::{
|
||||
fs::{remove_file, rename},
|
||||
@ -144,18 +143,34 @@ async fn process_image(
|
||||
new_name: String,
|
||||
thumb_name: Option<String>,
|
||||
) -> Result<(u32, u32), NekrochanError> {
|
||||
let original_name_ = original_name.clone();
|
||||
let new_name_ = new_name.clone();
|
||||
|
||||
let img = spawn_blocking(move || {
|
||||
ImageReader::open(format!("/tmp/{new_name}"))?
|
||||
.decode()
|
||||
.map_err(|_| {
|
||||
NekrochanError::FileError(original_name_, "nepodařilo se dekódovat obrázek")
|
||||
})
|
||||
let identify_out = spawn_blocking(move || {
|
||||
Command::new("identify")
|
||||
.args(["-format", "%wx%h", &format!("/tmp/{new_name_}[0]")])
|
||||
.output()
|
||||
})
|
||||
.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 {
|
||||
return Err(NekrochanError::FileError(
|
||||
@ -168,29 +183,27 @@ async fn process_image(
|
||||
return Ok((width, height));
|
||||
};
|
||||
|
||||
let thumb_w = if width > cfg.files.thumb_size {
|
||||
cfg.files.thumb_size
|
||||
} else {
|
||||
width
|
||||
};
|
||||
let thumb_size = cfg.files.thumb_size;
|
||||
|
||||
let thumb_h = if height > cfg.files.thumb_size {
|
||||
cfg.files.thumb_size
|
||||
} else {
|
||||
height
|
||||
};
|
||||
|
||||
spawn_blocking(move || {
|
||||
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")
|
||||
})
|
||||
let output = spawn_blocking(move || {
|
||||
Command::new("convert")
|
||||
.arg(&format!("/tmp/{new_name}"))
|
||||
.arg("-thumbnail")
|
||||
.arg(&format!("{thumb_size}x{thumb_size}>"))
|
||||
.arg(&format!("./uploads/thumb/{thumb_name}"))
|
||||
.output()
|
||||
})
|
||||
.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))
|
||||
}
|
||||
|
||||
@ -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 (width, height) = out_string
|
||||
|
@ -13,6 +13,7 @@ lazy_static! {
|
||||
pub fn czech_humantime(time: &DateTime<Utc>) -> askama::Result<String> {
|
||||
let duration = (Utc::now() - *time).abs();
|
||||
|
||||
let seconds = duration.num_seconds();
|
||||
let minutes = duration.num_minutes();
|
||||
let hours = duration.num_hours();
|
||||
let days = duration.num_days();
|
||||
@ -22,6 +23,14 @@ pub fn czech_humantime(time: &DateTime<Utc>) -> askama::Result<String> {
|
||||
|
||||
let mut time = "Teď".into();
|
||||
|
||||
if seconds > 0 {
|
||||
time = format!(
|
||||
"{} {}",
|
||||
seconds,
|
||||
czech_plural("sekunda|sekundy|sekund", seconds)?
|
||||
);
|
||||
}
|
||||
|
||||
if minutes > 0 {
|
||||
time = format!(
|
||||
"{} {}",
|
||||
|
@ -135,8 +135,9 @@ where
|
||||
<B as MessageBody>::Error: ResponseError + 'static,
|
||||
{
|
||||
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() {
|
||||
Some(bytes) => String::from_utf8(bytes.to_vec()).unwrap_or_default(),
|
||||
None => String::default(),
|
||||
@ -147,7 +148,9 @@ where
|
||||
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();
|
||||
|
||||
Ok(ErrorHandlerResponse::Response(res))
|
||||
|
@ -1,8 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use fancy_regex::{Captures, Regex};
|
||||
use lazy_static::lazy_static;
|
||||
use sqlx::query_as;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
ctx::Ctx,
|
||||
|
@ -339,8 +339,8 @@ summary {
|
||||
}
|
||||
|
||||
.thumb {
|
||||
max-width: 150px;
|
||||
max-height: 150px;
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.post-content {
|
||||
|
@ -4,7 +4,7 @@
|
||||
<b>/{{ post.board }}/{{ post.id }}</b>
|
||||
{% if let Some(file) = post.files.0.get(0) %}
|
||||
<a href="{{ post.post_url_notarget() }}">
|
||||
<img src="{{ file.thumb_url() }}">
|
||||
<img class="thumb" src="{{ file.thumb_url() }}">
|
||||
</a>
|
||||
{% else %}
|
||||
<p><b><a href="{{ post.post_url_notarget() }}">[Link]</a></b></p>
|
||||
|
Načítá se…
Odkázat v novém úkolu
Zablokovat Uživatele