2018-09-10 20:38:19 +02:00
use chrono ::Utc ;
2018-09-05 22:18:27 +02:00
use heck ::{ CamelCase , KebabCase } ;
2018-12-06 18:54:16 +01:00
use rocket ::request ::LenientForm ;
2018-06-04 21:57:03 +02:00
use rocket ::response ::{ Redirect , Flash } ;
2018-12-06 18:54:16 +01:00
use rocket_i18n ::I18n ;
2019-01-05 22:30:28 +01:00
use std ::{
collections ::{ HashMap , HashSet } ,
borrow ::Cow , time ::Duration ,
} ;
2018-07-06 11:51:19 +02:00
use validator ::{ Validate , ValidationError , ValidationErrors } ;
2018-04-23 16:25:39 +02:00
2018-09-01 17:28:47 +02:00
use plume_common ::activity_pub ::{ broadcast , ActivityStream , ApRequest , inbox ::Deletable } ;
2018-06-23 18:36:11 +02:00
use plume_common ::utils ;
use plume_models ::{
2018-05-19 09:39:59 +02:00
blogs ::* ,
2018-06-23 18:36:11 +02:00
db_conn ::DbConn ,
2018-12-24 11:23:04 +01:00
comments ::{ Comment , CommentTree } ,
2018-07-27 20:31:47 +02:00
instance ::Instance ,
2018-10-30 21:04:59 +01:00
medias ::Media ,
2018-06-20 22:58:11 +02:00
mentions ::Mention ,
2018-05-19 09:39:59 +02:00
post_authors ::* ,
posts ::* ,
2018-06-23 18:36:11 +02:00
safe_string ::SafeString ,
2018-09-05 22:18:27 +02:00
tags ::* ,
2018-05-19 09:39:59 +02:00
users ::User
} ;
2019-01-27 10:55:22 +01:00
use routes ::{ errors ::ErrorPage , comments ::NewCommentForm , ContentLen } ;
2018-12-06 18:54:16 +01:00
use template_utils ::Ructe ;
2018-12-02 17:37:51 +01:00
use Worker ;
use Searcher ;
2018-06-27 00:19:18 +02:00
2018-12-06 18:54:16 +01:00
#[ get( " /~/<blog>/<slug>?<responding_to> " , rank = 4) ]
2018-12-29 09:36:07 +01:00
pub fn details ( blog : String , slug : String , conn : DbConn , user : Option < User > , responding_to : Option < i32 > , intl : I18n ) -> Result < Ructe , ErrorPage > {
let blog = Blog ::find_by_fqn ( & * conn , & blog ) ? ;
let post = Post ::find_by_slug ( & * conn , & slug , blog . id ) ? ;
if post . published | | post . get_authors ( & * conn ) ? . into_iter ( ) . any ( | a | a . id = = user . clone ( ) . map ( | u | u . id ) . unwrap_or ( 0 ) ) {
let comments = CommentTree ::from_post ( & * conn , & post , user . as_ref ( ) ) ? ;
2018-12-06 18:54:16 +01:00
2018-12-29 09:36:07 +01:00
let previous = responding_to . and_then ( | r | Comment ::get ( & * conn , r ) . ok ( ) ) ;
2018-12-06 18:54:16 +01:00
Ok ( render! ( posts ::details (
& ( & * conn , & intl . catalog , user . clone ( ) ) ,
post . clone ( ) ,
blog ,
& NewCommentForm {
warning : previous . clone ( ) . map ( | p | p . spoiler_text ) . unwrap_or_default ( ) ,
2018-12-29 09:36:07 +01:00
content : previous . clone ( ) . and_then ( | p | Some ( format! (
2018-12-06 18:54:16 +01:00
" @{} {} " ,
2018-12-29 09:36:07 +01:00
p . get_author ( & * conn ) . ok ( ) ? . get_fqn ( & * conn ) ,
Mention ::list_for_comment ( & * conn , p . id ) . ok ( ) ?
2018-12-06 18:54:16 +01:00
. into_iter ( )
. filter_map ( | m | {
let user = user . clone ( ) ;
2018-12-29 09:36:07 +01:00
if let Ok ( mentioned ) = m . get_mentioned ( & * conn ) {
2018-12-06 18:54:16 +01:00
if user . is_none ( ) | | mentioned . id ! = user . expect ( " posts::details_response: user error while listing mentions " ) . id {
Some ( format! ( " @ {} " , mentioned . get_fqn ( & * conn ) ) )
} else {
None
}
} else {
None
}
} ) . collect ::< Vec < String > > ( ) . join ( " " ) )
2018-12-29 09:36:07 +01:00
) ) . unwrap_or_default ( ) ,
2018-12-06 18:54:16 +01:00
.. NewCommentForm ::default ( )
} ,
ValidationErrors ::default ( ) ,
2018-12-29 09:36:07 +01:00
Tag ::for_post ( & * conn , post . id ) ? ,
2018-12-24 11:23:04 +01:00
comments ,
2018-12-06 18:54:16 +01:00
previous ,
2018-12-29 09:36:07 +01:00
post . count_likes ( & * conn ) ? ,
post . count_reshares ( & * conn ) ? ,
user . clone ( ) . and_then ( | u | u . has_liked ( & * conn , & post ) . ok ( ) ) . unwrap_or ( false ) ,
user . clone ( ) . and_then ( | u | u . has_reshared ( & * conn , & post ) . ok ( ) ) . unwrap_or ( false ) ,
user . and_then ( | u | u . is_following ( & * conn , post . get_authors ( & * conn ) . ok ( ) ? [ 0 ] . id ) . ok ( ) ) . unwrap_or ( false ) ,
post . get_authors ( & * conn ) ? [ 0 ] . clone ( )
2018-12-06 18:54:16 +01:00
) ) )
} else {
2018-12-29 09:36:07 +01:00
Ok ( render! ( errors ::not_authorized (
2018-12-06 18:54:16 +01:00
& ( & * conn , & intl . catalog , user . clone ( ) ) ,
2019-02-02 15:23:50 +01:00
i18n! ( intl . catalog , " This post isn't published yet. " )
2018-12-06 18:54:16 +01:00
) ) )
}
2018-04-23 16:25:39 +02:00
}
2018-07-11 17:30:01 +02:00
#[ get( " /~/<blog>/<slug> " , rank = 3) ]
2018-12-09 18:43:34 +01:00
pub fn activity_details ( blog : String , slug : String , conn : DbConn , _ap : ApRequest ) -> Result < ActivityStream < LicensedArticle > , Option < String > > {
2018-12-29 09:36:07 +01:00
let blog = Blog ::find_by_fqn ( & * conn , & blog ) . map_err ( | _ | None ) ? ;
let post = Post ::find_by_slug ( & * conn , & slug , blog . id ) . map_err ( | _ | None ) ? ;
2018-09-12 17:58:38 +02:00
if post . published {
2018-12-29 09:36:07 +01:00
Ok ( ActivityStream ::new ( post . to_activity ( & * conn ) . map_err ( | _ | String ::from ( " Post serialization error " ) ) ? ) )
2018-09-12 17:58:38 +02:00
} else {
2018-10-20 11:04:20 +02:00
Err ( Some ( String ::from ( " Not published yet. " ) ) )
2018-09-12 17:58:38 +02:00
}
2018-04-23 16:25:39 +02:00
}
2018-06-04 21:57:03 +02:00
#[ get( " /~/<blog>/new " , rank = 2) ]
2018-12-06 18:54:16 +01:00
pub fn new_auth ( blog : String , i18n : I18n ) -> Flash < Redirect > {
2018-09-08 01:11:27 +02:00
utils ::requires_login (
2019-02-02 15:23:50 +01:00
& i18n! ( i18n . catalog , " You need to be logged in order to write a new post " ) ,
2018-11-26 10:21:52 +01:00
uri! ( new : blog = blog )
2018-09-08 01:11:27 +02:00
)
2018-04-23 16:25:39 +02:00
}
2018-06-19 21:16:18 +02:00
#[ get( " /~/<blog>/new " , rank = 1) ]
2019-01-27 10:55:22 +01:00
pub fn new ( blog : String , user : User , cl : ContentLen , conn : DbConn , intl : I18n ) -> Result < Ructe , ErrorPage > {
2018-11-26 10:21:52 +01:00
let b = Blog ::find_by_fqn ( & * conn , & blog ) ? ;
2018-06-20 10:44:56 +02:00
2018-12-29 09:36:07 +01:00
if ! user . is_author_in ( & * conn , & b ) ? {
2018-12-06 18:54:16 +01:00
// TODO actually return 403 error code
2018-12-29 09:36:07 +01:00
Ok ( render! ( errors ::not_authorized (
2018-12-06 18:54:16 +01:00
& ( & * conn , & intl . catalog , Some ( user ) ) ,
2019-02-02 15:23:50 +01:00
i18n! ( intl . catalog , " You are not author in this blog. " )
2018-12-06 18:54:16 +01:00
) ) )
2018-06-20 10:44:56 +02:00
} else {
2018-12-29 09:36:07 +01:00
let medias = Media ::for_user ( & * conn , user . id ) ? ;
Ok ( render! ( posts ::new (
2018-12-06 18:54:16 +01:00
& ( & * conn , & intl . catalog , Some ( user ) ) ,
2019-02-02 15:23:50 +01:00
i18n! ( intl . catalog , " New post " ) ,
2018-12-07 12:05:01 +01:00
b ,
2018-12-06 18:54:16 +01:00
false ,
2018-12-09 18:43:34 +01:00
& NewPostForm {
2018-12-29 09:36:07 +01:00
license : Instance ::get_local ( & * conn ) ? . default_license ,
2018-12-09 18:43:34 +01:00
.. NewPostForm ::default ( )
} ,
2018-12-07 12:05:01 +01:00
true ,
None ,
2018-12-06 18:54:16 +01:00
ValidationErrors ::default ( ) ,
2019-01-27 10:55:22 +01:00
medias ,
cl . 0
2018-12-06 18:54:16 +01:00
) ) )
2018-06-20 10:44:56 +02:00
}
2018-05-04 13:09:08 +02:00
}
2018-09-06 23:39:22 +02:00
#[ get( " /~/<blog>/<slug>/edit " ) ]
2019-01-27 10:55:22 +01:00
pub fn edit ( blog : String , slug : String , user : User , cl : ContentLen , conn : DbConn , intl : I18n ) -> Result < Ructe , ErrorPage > {
2018-11-26 10:21:52 +01:00
let b = Blog ::find_by_fqn ( & * conn , & blog ) ? ;
let post = Post ::find_by_slug ( & * conn , & slug , b . id ) ? ;
2018-09-06 23:39:22 +02:00
2018-12-29 09:36:07 +01:00
if ! user . is_author_in ( & * conn , & b ) ? {
Ok ( render! ( errors ::not_authorized (
2018-12-06 18:54:16 +01:00
& ( & * conn , & intl . catalog , Some ( user ) ) ,
2019-02-02 15:23:50 +01:00
i18n! ( intl . catalog , " You are not author in this blog. " )
2018-12-06 18:54:16 +01:00
) ) )
2018-09-06 23:39:22 +02:00
} else {
2018-11-26 10:21:52 +01:00
let source = if ! post . source . is_empty ( ) {
2018-12-07 12:05:01 +01:00
post . source . clone ( )
2018-09-08 13:05:22 +02:00
} else {
2018-10-20 11:04:20 +02:00
post . content . get ( ) . clone ( ) // fallback to HTML if the markdown was not stored
2018-09-08 13:05:22 +02:00
} ;
2018-12-29 09:36:07 +01:00
let medias = Media ::for_user ( & * conn , user . id ) ? ;
2019-02-02 15:23:50 +01:00
let title = post . title . clone ( ) ;
2018-12-29 09:36:07 +01:00
Ok ( render! ( posts ::new (
2018-12-06 18:54:16 +01:00
& ( & * conn , & intl . catalog , Some ( user ) ) ,
2019-02-02 15:23:50 +01:00
i18n! ( intl . catalog , " Edit {0} " ; & title ) ,
2018-12-07 12:05:01 +01:00
b ,
2018-12-06 18:54:16 +01:00
true ,
& NewPostForm {
2018-09-06 23:39:22 +02:00
title : post . title . clone ( ) ,
subtitle : post . subtitle . clone ( ) ,
2018-09-08 13:05:22 +02:00
content : source ,
2018-12-29 09:36:07 +01:00
tags : Tag ::for_post ( & * conn , post . id ) ?
2018-09-06 23:39:22 +02:00
. into_iter ( )
2018-10-20 19:27:49 +02:00
. filter_map ( | t | if ! t . is_hashtag { Some ( t . tag ) } else { None } )
2018-09-06 23:39:22 +02:00
. collect ::< Vec < String > > ( )
. join ( " , " ) ,
license : post . license . clone ( ) ,
2018-09-10 20:38:19 +02:00
draft : true ,
2018-10-30 21:04:59 +01:00
cover : post . cover_id ,
2018-09-10 20:38:19 +02:00
} ,
2018-12-07 12:05:01 +01:00
! post . published ,
Some ( post ) ,
2018-12-06 18:54:16 +01:00
ValidationErrors ::default ( ) ,
2019-01-27 10:55:22 +01:00
medias ,
cl . 0
2018-12-06 18:54:16 +01:00
) ) )
2018-09-06 23:39:22 +02:00
}
}
2018-12-06 18:54:16 +01:00
#[ post( " /~/<blog>/<slug>/edit " , data = " <form> " ) ]
2019-01-27 10:55:22 +01:00
pub fn update ( blog : String , slug : String , user : User , cl : ContentLen , form : LenientForm < NewPostForm > , worker : Worker , conn : DbConn , intl : I18n , searcher : Searcher )
2018-12-29 09:36:07 +01:00
-> Result < Redirect , Ructe > {
let b = Blog ::find_by_fqn ( & * conn , & blog ) . expect ( " post::update: blog error " ) ;
let mut post = Post ::find_by_slug ( & * conn , & slug , b . id ) . expect ( " post::update: find by slug error " ) ;
2018-09-06 23:39:22 +02:00
2018-10-11 14:23:23 +02:00
let new_slug = if ! post . published {
form . title . to_string ( ) . to_kebab_case ( )
} else {
2018-12-07 12:05:01 +01:00
post . slug . clone ( )
2018-10-11 14:23:23 +02:00
} ;
2018-09-06 23:39:22 +02:00
let mut errors = match form . validate ( ) {
Ok ( _ ) = > ValidationErrors ::new ( ) ,
Err ( e ) = > e
} ;
2018-09-07 19:51:53 +02:00
2018-12-29 09:36:07 +01:00
if new_slug ! = slug & & Post ::find_by_slug ( & * conn , & new_slug , b . id ) . is_ok ( ) {
2018-11-26 10:21:52 +01:00
errors . add ( " title " , ValidationError {
code : Cow ::from ( " existing_slug " ) ,
message : Some ( Cow ::from ( " A post with the same title already exists. " ) ) ,
params : HashMap ::new ( )
} ) ;
2018-09-06 23:39:22 +02:00
}
if errors . is_empty ( ) {
2018-12-29 09:36:07 +01:00
if ! user . is_author_in ( & * conn , & b ) . expect ( " posts::update: is author in error " ) {
2018-09-06 23:39:22 +02:00
// actually it's not "Ok"…
2018-12-13 22:20:19 +01:00
Ok ( Redirect ::to ( uri! ( super ::blogs ::details : name = blog , page = _ ) ) )
2018-09-06 23:39:22 +02:00
} else {
2018-12-23 11:12:15 +01:00
let ( content , mentions , hashtags ) = utils ::md_to_html ( form . content . to_string ( ) . as_ref ( ) , & Instance ::get_local ( & conn ) . expect ( " posts::update: Error getting local instance " ) . public_domain ) ;
2018-09-06 23:39:22 +02:00
2018-09-10 20:38:19 +02:00
// update publication date if when this article is no longer a draft
2018-10-28 11:42:01 +01:00
let newly_published = if ! post . published & & ! form . draft {
2018-09-10 20:38:19 +02:00
post . published = true ;
post . creation_date = Utc ::now ( ) . naive_utc ( ) ;
2018-10-28 11:42:01 +01:00
true
} else {
false
} ;
2018-09-10 20:38:19 +02:00
2018-09-06 23:39:22 +02:00
post . slug = new_slug . clone ( ) ;
post . title = form . title . clone ( ) ;
post . subtitle = form . subtitle . clone ( ) ;
post . content = SafeString ::new ( & content ) ;
post . source = form . content . clone ( ) ;
2018-12-09 18:43:34 +01:00
post . license = form . license . clone ( ) ;
2018-10-30 21:04:59 +01:00
post . cover_id = form . cover ;
2018-12-29 09:36:07 +01:00
post . update ( & * conn , & searcher ) . expect ( " post::update: update error " ) ; ;
let post = post . update_ap_url ( & * conn ) . expect ( " post::update: update ap url error " ) ;
2018-09-06 23:39:22 +02:00
2018-09-12 18:00:00 +02:00
if post . published {
2018-12-29 09:36:07 +01:00
post . update_mentions ( & conn , mentions . into_iter ( ) . filter_map ( | m | Mention ::build_activity ( & conn , & m ) . ok ( ) ) . collect ( ) )
. expect ( " post::update: mentions error " ) ; ;
2018-09-06 23:39:22 +02:00
}
2018-11-26 10:21:52 +01:00
let tags = form . tags . split ( ',' ) . map ( | t | t . trim ( ) . to_camel_case ( ) ) . filter ( | t | ! t . is_empty ( ) )
2018-12-29 09:36:07 +01:00
. collect ::< HashSet < _ > > ( ) . into_iter ( ) . filter_map ( | t | Tag ::build_activity ( & conn , t ) . ok ( ) ) . collect ::< Vec < _ > > ( ) ;
post . update_tags ( & conn , tags ) . expect ( " post::update: tags error " ) ;
2018-10-27 20:44:42 +02:00
2018-10-28 10:57:10 +01:00
let hashtags = hashtags . into_iter ( ) . map ( | h | h . to_camel_case ( ) ) . collect ::< HashSet < _ > > ( )
2018-12-29 09:36:07 +01:00
. into_iter ( ) . filter_map ( | t | Tag ::build_activity ( & conn , t ) . ok ( ) ) . collect ::< Vec < _ > > ( ) ;
post . update_hashtags ( & conn , hashtags ) . expect ( " post::update: hashtags error " ) ;
2018-09-06 23:39:22 +02:00
2018-09-10 20:38:19 +02:00
if post . published {
2018-10-28 11:42:01 +01:00
if newly_published {
2018-12-29 09:36:07 +01:00
let act = post . create_activity ( & conn ) . expect ( " post::update: act error " ) ;
let dest = User ::one_by_instance ( & * conn ) . expect ( " post::update: dest error " ) ;
2018-12-02 17:37:51 +01:00
worker . execute ( move | | broadcast ( & user , act , dest ) ) ;
2018-10-28 11:42:01 +01:00
} else {
2018-12-29 09:36:07 +01:00
let act = post . update_activity ( & * conn ) . expect ( " post::update: act error " ) ;
let dest = User ::one_by_instance ( & * conn ) . expect ( " posts::update: dest error " ) ;
2018-12-02 17:37:51 +01:00
worker . execute ( move | | broadcast ( & user , act , dest ) ) ;
2018-10-28 11:42:01 +01:00
}
2018-09-10 20:38:19 +02:00
}
2018-09-06 23:39:22 +02:00
2018-12-13 22:20:19 +01:00
Ok ( Redirect ::to ( uri! ( details : blog = blog , slug = new_slug , responding_to = _ ) ) )
2018-09-06 23:39:22 +02:00
}
} else {
2018-12-29 09:36:07 +01:00
let medias = Media ::for_user ( & * conn , user . id ) . expect ( " posts:update: medias error " ) ;
Err ( render! ( posts ::new (
2018-12-06 18:54:16 +01:00
& ( & * conn , & intl . catalog , Some ( user ) ) ,
2019-02-02 15:23:50 +01:00
i18n! ( intl . catalog , " Edit {0} " ; & form . title ) ,
2018-12-07 12:05:01 +01:00
b ,
2018-12-06 18:54:16 +01:00
true ,
& * form ,
2018-12-07 12:05:01 +01:00
form . draft . clone ( ) ,
Some ( post ) ,
2018-12-06 18:54:16 +01:00
errors . clone ( ) ,
2019-01-27 10:55:22 +01:00
medias . clone ( ) ,
cl . 0
2018-12-29 09:36:07 +01:00
) ) )
2018-09-06 23:39:22 +02:00
}
}
2018-12-06 18:54:16 +01:00
#[ derive(Default, FromForm, Validate, Serialize) ]
pub struct NewPostForm {
2018-07-07 22:51:48 +02:00
#[ validate(custom(function = " valid_slug " , message = " Invalid title " )) ]
2018-04-23 16:25:39 +02:00
pub title : String ,
2018-09-04 13:26:13 +02:00
pub subtitle : String ,
2018-04-23 16:25:39 +02:00
pub content : String ,
2018-09-05 22:18:27 +02:00
pub tags : String ,
2018-09-10 20:38:19 +02:00
pub license : String ,
pub draft : bool ,
2018-10-30 21:04:59 +01:00
pub cover : Option < i32 > ,
2018-04-23 16:25:39 +02:00
}
2018-12-06 18:54:16 +01:00
pub fn valid_slug ( title : & str ) -> Result < ( ) , ValidationError > {
2018-06-29 14:56:00 +02:00
let slug = title . to_string ( ) . to_kebab_case ( ) ;
2018-11-26 10:21:52 +01:00
if slug . is_empty ( ) {
2018-06-29 14:56:00 +02:00
Err ( ValidationError ::new ( " empty_slug " ) )
2018-07-06 11:51:19 +02:00
} else if slug = = " new " {
Err ( ValidationError ::new ( " invalid_slug " ) )
2018-06-29 14:56:00 +02:00
} else {
Ok ( ( ) )
}
}
2018-12-06 18:54:16 +01:00
#[ post( " /~/<blog_name>/new " , data = " <form> " ) ]
2019-01-27 10:55:22 +01:00
pub fn create ( blog_name : String , form : LenientForm < NewPostForm > , user : User , cl : ContentLen , conn : DbConn , worker : Worker , intl : I18n , searcher : Searcher ) -> Result < Redirect , Result < Ructe , ErrorPage > > {
2018-12-29 09:36:07 +01:00
let blog = Blog ::find_by_fqn ( & * conn , & blog_name ) . expect ( " post::create: blog error " ) ; ;
2018-04-23 16:25:39 +02:00
let slug = form . title . to_string ( ) . to_kebab_case ( ) ;
2018-09-03 15:59:02 +02:00
2018-07-06 11:51:19 +02:00
let mut errors = match form . validate ( ) {
Ok ( _ ) = > ValidationErrors ::new ( ) ,
Err ( e ) = > e
} ;
2018-12-29 09:36:07 +01:00
if Post ::find_by_slug ( & * conn , & slug , blog . id ) . is_ok ( ) {
2018-07-07 22:51:48 +02:00
errors . add ( " title " , ValidationError {
code : Cow ::from ( " existing_slug " ) ,
message : Some ( Cow ::from ( " A post with the same title already exists. " ) ) ,
params : HashMap ::new ( )
} ) ;
2018-07-06 11:51:19 +02:00
}
2018-05-24 12:42:45 +02:00
2018-07-06 11:51:19 +02:00
if errors . is_empty ( ) {
2018-12-29 09:36:07 +01:00
if ! user . is_author_in ( & * conn , & blog ) . expect ( " post::create: is author in error " ) {
2018-07-06 11:51:19 +02:00
// actually it's not "Ok"…
2018-12-13 22:20:19 +01:00
Ok ( Redirect ::to ( uri! ( super ::blogs ::details : name = blog_name , page = _ ) ) )
2018-06-20 10:44:56 +02:00
} else {
2018-12-29 09:36:07 +01:00
let ( content , mentions , hashtags ) = utils ::md_to_html (
form . content . to_string ( ) . as_ref ( ) ,
& Instance ::get_local ( & conn ) . expect ( " post::create: local instance error " ) . public_domain
) ;
2018-05-24 12:42:45 +02:00
2018-06-20 10:44:56 +02:00
let post = Post ::insert ( & * conn , NewPost {
blog_id : blog . id ,
slug : slug . to_string ( ) ,
title : form . title . to_string ( ) ,
content : SafeString ::new ( & content ) ,
2018-09-10 20:38:19 +02:00
published : ! form . draft ,
2018-12-09 18:43:34 +01:00
license : form . license . clone ( ) ,
2018-07-27 00:29:21 +02:00
ap_url : " " . to_string ( ) ,
2018-09-04 13:26:13 +02:00
creation_date : None ,
2018-09-06 21:00:55 +02:00
subtitle : form . subtitle . clone ( ) ,
source : form . content . clone ( ) ,
2018-10-30 21:04:59 +01:00
cover_id : form . cover ,
2018-12-02 17:37:51 +01:00
} ,
& searcher ,
2018-12-29 09:36:07 +01:00
) . expect ( " post::create: post save error " ) ;
let post = post . update_ap_url ( & * conn ) . expect ( " post::create: update ap url error " ) ;
2018-06-20 10:44:56 +02:00
PostAuthor ::insert ( & * conn , NewPostAuthor {
post_id : post . id ,
author_id : user . id
2018-12-29 09:36:07 +01:00
} ) . expect ( " post::create: author save error " ) ;
2018-05-01 17:51:49 +02:00
2018-11-26 10:21:52 +01:00
let tags = form . tags . split ( ',' )
. map ( | t | t . trim ( ) . to_camel_case ( ) )
. filter ( | t | ! t . is_empty ( ) )
. collect ::< HashSet < _ > > ( ) ;
2018-09-05 22:18:27 +02:00
for tag in tags {
Tag ::insert ( & * conn , NewTag {
2018-11-26 10:21:52 +01:00
tag ,
2018-10-20 19:27:49 +02:00
is_hashtag : false ,
post_id : post . id
2018-12-29 09:36:07 +01:00
} ) . expect ( " post::create: tags save error " ) ;
2018-10-20 19:27:49 +02:00
}
for hashtag in hashtags {
Tag ::insert ( & * conn , NewTag {
tag : hashtag . to_camel_case ( ) ,
is_hashtag : true ,
2018-09-05 22:18:27 +02:00
post_id : post . id
2018-12-29 09:36:07 +01:00
} ) . expect ( " post::create: hashtags save error " ) ;
2018-09-05 22:18:27 +02:00
}
2018-09-10 20:38:19 +02:00
if post . published {
2018-11-26 10:21:52 +01:00
for m in mentions {
2018-12-29 09:36:07 +01:00
Mention ::from_activity (
& * conn ,
& Mention ::build_activity ( & * conn , & m ) . expect ( " post::create: mention build error " ) ,
post . id ,
true ,
true
) . expect ( " post::create: mention save error " ) ;
2018-09-10 20:38:19 +02:00
}
2018-12-29 09:36:07 +01:00
let act = post . create_activity ( & * conn ) . expect ( " posts::create: activity error " ) ;
let dest = User ::one_by_instance ( & * conn ) . expect ( " posts::create: dest error " ) ;
2018-12-02 17:37:51 +01:00
worker . execute ( move | | broadcast ( & user , act , dest ) ) ;
2018-09-10 20:38:19 +02:00
}
2018-05-01 17:51:49 +02:00
2018-12-13 22:20:19 +01:00
Ok ( Redirect ::to ( uri! ( details : blog = blog_name , slug = slug , responding_to = _ ) ) )
2018-06-20 10:44:56 +02:00
}
2018-07-06 11:51:19 +02:00
} else {
2018-12-29 09:36:07 +01:00
let medias = Media ::for_user ( & * conn , user . id ) . expect ( " posts::create: medias error " ) ;
Err ( Ok ( render! ( posts ::new (
2018-12-06 18:54:16 +01:00
& ( & * conn , & intl . catalog , Some ( user ) ) ,
2019-02-02 15:23:50 +01:00
i18n! ( intl . catalog , " New post " ) ,
2018-12-07 12:05:01 +01:00
blog ,
2018-12-06 18:54:16 +01:00
false ,
& * form ,
2018-12-07 12:05:01 +01:00
form . draft ,
None ,
2018-12-06 18:54:16 +01:00
errors . clone ( ) ,
2019-01-27 10:55:22 +01:00
medias ,
cl . 0
2018-12-06 18:54:16 +01:00
) ) ) )
2018-06-19 21:16:18 +02:00
}
2018-04-23 16:25:39 +02:00
}
2018-09-01 17:28:47 +02:00
2018-09-19 19:13:07 +02:00
#[ post( " /~/<blog_name>/<slug>/delete " ) ]
2018-12-29 09:36:07 +01:00
pub fn delete ( blog_name : String , slug : String , conn : DbConn , user : User , worker : Worker , searcher : Searcher ) -> Result < Redirect , ErrorPage > {
2018-11-26 10:21:52 +01:00
let post = Blog ::find_by_fqn ( & * conn , & blog_name )
. and_then ( | blog | Post ::find_by_slug ( & * conn , & slug , blog . id ) ) ;
2018-09-01 17:28:47 +02:00
2018-12-29 09:36:07 +01:00
if let Ok ( post ) = post {
if ! post . get_authors ( & * conn ) ? . into_iter ( ) . any ( | a | a . id = = user . id ) {
Ok ( Redirect ::to ( uri! ( details : blog = blog_name . clone ( ) , slug = slug . clone ( ) , responding_to = _ ) ) )
2018-09-01 17:28:47 +02:00
} else {
2018-12-29 09:36:07 +01:00
let dest = User ::one_by_instance ( & * conn ) ? ;
let delete_activity = post . delete ( & ( & conn , & searcher ) ) ? ;
2019-01-05 22:30:28 +01:00
let user_c = user . clone ( ) ;
worker . execute ( move | | broadcast ( & user_c , delete_activity , dest ) ) ;
worker . execute_after ( Duration ::from_secs ( 10 * 60 ) , move | | { user . rotate_keypair ( & conn ) . expect ( " Failed to rotate keypair " ) ; } ) ;
2018-09-01 17:28:47 +02:00
2018-12-29 09:36:07 +01:00
Ok ( Redirect ::to ( uri! ( super ::blogs ::details : name = blog_name , page = _ ) ) )
2018-09-01 17:28:47 +02:00
}
} else {
2018-12-29 09:36:07 +01:00
Ok ( Redirect ::to ( uri! ( super ::blogs ::details : name = blog_name , page = _ ) ) )
2018-09-01 17:28:47 +02:00
}
}