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