Generate favicon from post
This commit is contained in:
parent
94269d82f0
commit
7553dd31dc
5 changed files with 34 additions and 7 deletions
|
|
@ -19,7 +19,6 @@ Still very much an early WIP.
|
||||||
|
|
||||||
### Roadmap
|
### Roadmap
|
||||||
|
|
||||||
- [ ] Favicon from post
|
|
||||||
- [ ] Delete pools
|
- [ ] Delete pools
|
||||||
- [ ] Logging and improved error handling
|
- [ ] Logging and improved error handling
|
||||||
- [ ] Lossless compression
|
- [ ] Lossless compression
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ struct NotFoundTemplate;
|
||||||
pub enum SameyError {
|
pub enum SameyError {
|
||||||
#[error("Integer conversion error: {0}")]
|
#[error("Integer conversion error: {0}")]
|
||||||
IntConversion(#[from] std::num::TryFromIntError),
|
IntConversion(#[from] std::num::TryFromIntError),
|
||||||
|
#[error("Integer parsing error: {0}")]
|
||||||
|
IntParse(#[from] std::num::ParseIntError),
|
||||||
#[error("IO error: {0}")]
|
#[error("IO error: {0}")]
|
||||||
IO(#[from] std::io::Error),
|
IO(#[from] std::io::Error),
|
||||||
#[error("Task error: {0}")]
|
#[error("Task error: {0}")]
|
||||||
|
|
@ -41,6 +43,7 @@ impl IntoResponse for SameyError {
|
||||||
println!("Server error - {}", &self);
|
println!("Server error - {}", &self);
|
||||||
match &self {
|
match &self {
|
||||||
SameyError::IntConversion(_)
|
SameyError::IntConversion(_)
|
||||||
|
| SameyError::IntParse(_)
|
||||||
| SameyError::IO(_)
|
| SameyError::IO(_)
|
||||||
| SameyError::Join(_)
|
| SameyError::Join(_)
|
||||||
| SameyError::Render(_)
|
| SameyError::Render(_)
|
||||||
|
|
|
||||||
32
src/views.rs
32
src/views.rs
|
|
@ -17,7 +17,7 @@ use axum_extra::extract::Form;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use image::{GenericImageView, ImageFormat, ImageReader};
|
use image::{GenericImageView, ImageFormat, ImageReader};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use migration::{Expr, OnConflict};
|
use migration::{Expr, OnConflict, Query as MigrationQuery};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveValue::Set, ColumnTrait, Condition, EntityTrait, FromQueryResult, IntoSimpleExpr,
|
ActiveValue::Set, ColumnTrait, Condition, EntityTrait, FromQueryResult, IntoSimpleExpr,
|
||||||
|
|
@ -1246,7 +1246,7 @@ pub(crate) async fn edit_tag(
|
||||||
.one(&db)
|
.one(&db)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
let subquery = migration::Query::select()
|
let subquery = MigrationQuery::select()
|
||||||
.column((SameyTagPost, samey_tag_post::Column::PostId))
|
.column((SameyTagPost, samey_tag_post::Column::PostId))
|
||||||
.from(SameyTagPost)
|
.from(SameyTagPost)
|
||||||
.and_where(samey_tag_post::Column::TagId.eq(new_tag_db.id))
|
.and_where(samey_tag_post::Column::TagId.eq(new_tag_db.id))
|
||||||
|
|
@ -1332,11 +1332,17 @@ pub(crate) async fn settings(
|
||||||
pub(crate) struct UpdateSettingsForm {
|
pub(crate) struct UpdateSettingsForm {
|
||||||
application_name: String,
|
application_name: String,
|
||||||
base_url: String,
|
base_url: String,
|
||||||
|
favicon_post_id: String,
|
||||||
age_confirmation: Option<bool>,
|
age_confirmation: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn update_settings(
|
pub(crate) async fn update_settings(
|
||||||
State(AppState { db, app_config, .. }): State<AppState>,
|
State(AppState {
|
||||||
|
db,
|
||||||
|
app_config,
|
||||||
|
files_dir,
|
||||||
|
..
|
||||||
|
}): State<AppState>,
|
||||||
auth_session: AuthSession,
|
auth_session: AuthSession,
|
||||||
Form(body): Form<UpdateSettingsForm>,
|
Form(body): Form<UpdateSettingsForm>,
|
||||||
) -> Result<impl IntoResponse, SameyError> {
|
) -> Result<impl IntoResponse, SameyError> {
|
||||||
|
|
@ -1390,6 +1396,21 @@ pub(crate) async fn update_settings(
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(favicon_post_id) = body.favicon_post_id.split_whitespace().next() {
|
||||||
|
match favicon_post_id.parse::<i32>() {
|
||||||
|
Ok(favicon_post_id) => {
|
||||||
|
let post = SameyPost::find_by_id(favicon_post_id)
|
||||||
|
.one(&db)
|
||||||
|
.await?
|
||||||
|
.ok_or(SameyError::NotFound)?;
|
||||||
|
ImageReader::open(files_dir.join(post.thumbnail))?
|
||||||
|
.decode()?
|
||||||
|
.save_with_format(files_dir.join("favicon.png"), ImageFormat::Png)?;
|
||||||
|
}
|
||||||
|
Err(err) => return Err(SameyError::IntParse(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Redirect::to("/"))
|
Ok(Redirect::to("/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1840,9 +1861,8 @@ pub(crate) async fn delete_post(
|
||||||
SameyPost::delete_by_id(post.id).exec(&db).await?;
|
SameyPost::delete_by_id(post.id).exec(&db).await?;
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let base_path = files_dir.as_ref();
|
let _ = std::fs::remove_file(files_dir.join(post.media));
|
||||||
let _ = std::fs::remove_file(base_path.join(post.media));
|
let _ = std::fs::remove_file(files_dir.join(post.thumbnail));
|
||||||
let _ = std::fs::remove_file(base_path.join(post.thumbnail));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(Redirect::to("/"))
|
Ok(Redirect::to("/"))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="icon" href="/files/favicon.png" />
|
||||||
<script src="/static/htmx.js"></script>
|
<script src="/static/htmx.js"></script>
|
||||||
<script defer src="/static/alpine.js"></script>
|
<script defer src="/static/alpine.js"></script>
|
||||||
<link rel="stylesheet" href="/static/water.css" />
|
<link rel="stylesheet" href="/static/water.css" />
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@
|
||||||
<label>Base URL</label>
|
<label>Base URL</label>
|
||||||
<input name="base_url" type="text" value="{{ base_url }}" />
|
<input name="base_url" type="text" value="{{ base_url }}" />
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Favicon post ID</label>
|
||||||
|
<input name="favicon_post_id" type="text" pattern="[0-9]*" />
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>Ask for age confirmation?</label>
|
<label>Ask for age confirmation?</label>
|
||||||
<input
|
<input
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue