2019-07-26 23:29:42 +00:00
package routes
import (
"database/sql"
2019-08-28 06:47:54 +00:00
"errors"
2019-07-26 23:29:42 +00:00
"net/http"
"strconv"
"strings"
2019-10-06 00:34:09 +00:00
2019-08-28 06:47:54 +00:00
//"log"
2019-07-26 23:29:42 +00:00
c "github.com/Azareal/Gosora/common"
2019-08-14 10:39:04 +00:00
p "github.com/Azareal/Gosora/common/phrases"
2019-07-26 23:29:42 +00:00
)
2019-10-06 00:34:09 +00:00
func Convos ( w http . ResponseWriter , r * http . Request , user c . User , h * c . Header ) c . RouteError {
accountEditHead ( "convos" , w , r , & user , h )
h . AddScript ( "convo.js" )
h . AddSheet ( h . Theme . Name + "/convo.css" )
h . AddNotice ( "convo_dev" )
2019-07-26 23:29:42 +00:00
ccount := c . Convos . GetUserCount ( user . ID )
page , _ := strconv . Atoi ( r . FormValue ( "page" ) )
offset , page , lastPage := c . PageOffset ( ccount , page , c . Config . ItemsPerPage )
pageList := c . Paginate ( page , lastPage , 5 )
2019-08-28 06:47:54 +00:00
convos , err := c . Convos . GetUserExtra ( user . ID , offset )
//log.Printf("convos: %+v\n", convos)
2019-10-07 21:22:33 +00:00
if err != sql . ErrNoRows && err != nil {
2019-07-26 23:29:42 +00:00
return c . InternalError ( err , w , r )
}
2019-10-06 00:34:09 +00:00
pi := c . Account { h , "dashboard" , "convos" , c . ConvoListPage { h , convos , c . Paginator { pageList , page , lastPage } } }
return renderTemplate ( "account" , w , r , h , pi )
2019-07-26 23:29:42 +00:00
}
func Convo ( w http . ResponseWriter , r * http . Request , user c . User , header * c . Header , scid string ) c . RouteError {
accountEditHead ( "convo" , w , r , & user , header )
2019-08-14 10:39:04 +00:00
header . AddSheet ( header . Theme . Name + "/convo.css" )
header . AddNotice ( "convo_dev" )
2019-07-26 23:29:42 +00:00
cid , err := strconv . Atoi ( scid )
if err != nil {
2019-08-14 10:39:04 +00:00
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
2019-07-26 23:29:42 +00:00
}
convo , err := c . Convos . Get ( cid )
if err == sql . ErrNoRows {
return c . NotFound ( w , r , header )
} else if err != nil {
return c . InternalError ( err , w , r )
}
pcount := convo . PostsCount ( )
if pcount == 0 {
return c . NotFound ( w , r , header )
}
page , _ := strconv . Atoi ( r . FormValue ( "page" ) )
offset , page , lastPage := c . PageOffset ( pcount , page , c . Config . ItemsPerPage )
pageList := c . Paginate ( page , lastPage , 5 )
2019-08-14 10:39:04 +00:00
posts , err := convo . Posts ( offset , c . Config . ItemsPerPage )
2019-07-26 23:29:42 +00:00
// TODO: Report a better error for no posts
if err == sql . ErrNoRows {
return c . NotFound ( w , r , header )
} else if err != nil {
return c . InternalError ( err , w , r )
}
2019-08-21 01:31:13 +00:00
uids , err := convo . Uids ( )
if err == sql . ErrNoRows {
return c . NotFound ( w , r , header )
} else if err != nil {
return c . InternalError ( err , w , r )
}
umap , err := c . Users . BulkGetMap ( uids )
if err == sql . ErrNoRows {
return c . NotFound ( w , r , header )
} else if err != nil {
return c . InternalError ( err , w , r )
}
2019-08-28 06:47:54 +00:00
users := make ( [ ] * c . User , len ( umap ) )
2019-08-21 01:31:13 +00:00
i := 0
for _ , user := range umap {
users [ i ] = user
i ++
}
2019-08-14 10:39:04 +00:00
pitems := make ( [ ] c . ConvoViewRow , len ( posts ) )
for i , post := range posts {
2019-08-21 01:31:13 +00:00
uuser , ok := umap [ post . CreatedBy ]
if ! ok {
return c . InternalError ( errors . New ( "convo post creator not in umap" ) , w , r )
2019-08-14 10:39:04 +00:00
}
2019-08-20 22:32:10 +00:00
canModify := user . ID == post . CreatedBy || user . IsSuperMod
pitems [ i ] = c . ConvoViewRow { post , uuser , "" , 4 , canModify }
2019-08-14 10:39:04 +00:00
}
2019-08-21 01:31:13 +00:00
pi := c . Account { header , "dashboard" , "convo" , c . ConvoViewPage { header , convo , pitems , users , c . Paginator { pageList , page , lastPage } } }
2019-07-26 23:29:42 +00:00
return renderTemplate ( "account" , w , r , header , pi )
}
2019-10-06 00:34:09 +00:00
func ConvosCreate ( w http . ResponseWriter , r * http . Request , user c . User , h * c . Header ) c . RouteError {
accountEditHead ( "create_convo" , w , r , & user , h )
h . AddNotice ( "convo_dev" )
2019-07-26 23:29:42 +00:00
recpName := ""
2019-10-06 00:34:09 +00:00
pi := c . Account { h , "dashboard" , "create_convo" , c . ConvoCreatePage { h , recpName } }
return renderTemplate ( "account" , w , r , h , pi )
2019-07-26 23:29:42 +00:00
}
func ConvosCreateSubmit ( w http . ResponseWriter , r * http . Request , user c . User ) c . RouteError {
_ , ferr := c . SimpleUserCheck ( w , r , & user )
if ferr != nil {
return ferr
}
2019-10-06 00:34:09 +00:00
if ! user . Perms . UseConvos {
2019-08-20 22:32:10 +00:00
return c . NoPermissions ( w , r , user )
2019-08-20 08:44:37 +00:00
}
2019-07-26 23:29:42 +00:00
recps := c . SanitiseSingleLine ( r . PostFormValue ( "recp" ) )
body := c . PreparseMessage ( r . PostFormValue ( "body" ) )
rlist := [ ] int { }
max := 10 // max number of recipients that can be added at once
for i , recp := range strings . Split ( recps , "," ) {
if i >= max {
break
}
2019-09-01 01:37:04 +00:00
u , err := c . Users . GetByName ( strings . TrimSpace ( recp ) )
2019-07-26 23:29:42 +00:00
if err == sql . ErrNoRows {
return c . LocalError ( "One of the recipients doesn't exist" , w , r , user )
} else if err != nil {
return c . InternalError ( err , w , r )
}
2019-10-06 00:34:09 +00:00
// TODO: Should we kick them out of existing conversations if they're moved into a group without permission or the permission is revoked from their group? We might want to give them a chance to delete their messages though to avoid privacy headaches here and it may only be temporarily to tackle a specific incident.
if ! u . Perms . UseConvos {
return c . LocalError ( "One of the recipients doesn't have permission to use the conversations system" , w , r , user )
}
2019-10-18 00:35:13 +00:00
blocked , err := c . UserBlocks . IsBlockedBy ( u . ID , user . ID )
if err != nil {
return c . InternalError ( err , w , r )
}
// Supermods can bypass blocks so they can tell people off when they do something stupid or have to convey important information
if blocked && ! user . IsSuperMod {
return c . LocalError ( "You don't have permission to send messages to one of these users." , w , r , user )
}
2019-07-26 23:29:42 +00:00
rlist = append ( rlist , u . ID )
}
cid , err := c . Convos . Create ( body , user . ID , rlist )
if err != nil {
return c . InternalError ( err , w , r )
}
http . Redirect ( w , r , "/user/convo/" + strconv . Itoa ( cid ) , http . StatusSeeOther )
return nil
}
2019-08-20 08:44:37 +00:00
/ * func ConvosDeleteSubmit ( w http . ResponseWriter , r * http . Request , user c . User , scid string ) c . RouteError {
2019-07-26 23:29:42 +00:00
_ , ferr := c . SimpleUserCheck ( w , r , & user )
if ferr != nil {
return ferr
}
cid , err := strconv . Atoi ( scid )
if err != nil {
2019-08-14 10:39:04 +00:00
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
2019-07-26 23:29:42 +00:00
}
2019-10-13 08:50:55 +00:00
if err := c . Convos . Delete ( cid ) ; err != nil {
2019-07-26 23:29:42 +00:00
return c . InternalError ( err , w , r )
}
http . Redirect ( w , r , "/user/convos/" , http . StatusSeeOther )
return nil
2019-08-20 08:44:37 +00:00
} * /
2019-07-26 23:29:42 +00:00
2019-08-20 08:44:37 +00:00
func ConvosCreateReplySubmit ( w http . ResponseWriter , r * http . Request , user c . User , scid string ) c . RouteError {
2019-07-26 23:29:42 +00:00
_ , ferr := c . SimpleUserCheck ( w , r , & user )
if ferr != nil {
return ferr
}
2019-10-06 00:34:09 +00:00
if ! user . Perms . UseConvos {
2019-08-20 22:32:10 +00:00
return c . NoPermissions ( w , r , user )
2019-08-20 08:44:37 +00:00
}
cid , err := strconv . Atoi ( scid )
if err != nil {
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
}
convo , err := c . Convos . Get ( cid )
if err == sql . ErrNoRows {
return c . NotFound ( w , r , nil )
} else if err != nil {
return c . InternalError ( err , w , r )
}
pcount := convo . PostsCount ( )
if pcount == 0 {
return c . NotFound ( w , r , nil )
}
if ! convo . Has ( user . ID ) {
2019-08-20 22:32:10 +00:00
return c . LocalError ( "You are not in this conversation." , w , r , user )
2019-08-20 08:44:37 +00:00
}
body := c . PreparseMessage ( r . PostFormValue ( "content" ) )
post := & c . ConversationPost { CID : cid , Body : body , CreatedBy : user . ID }
_ , err = post . Create ( )
if err != nil {
return c . InternalError ( err , w , r )
}
2019-08-20 22:32:10 +00:00
http . Redirect ( w , r , "/user/convo/" + strconv . Itoa ( convo . ID ) , http . StatusSeeOther )
2019-07-26 23:29:42 +00:00
return nil
}
2019-08-14 10:39:04 +00:00
func ConvosDeleteReplySubmit ( w http . ResponseWriter , r * http . Request , user c . User , scpid string ) c . RouteError {
_ , ferr := c . SimpleUserCheck ( w , r , & user )
if ferr != nil {
return ferr
}
cpid , err := strconv . Atoi ( scpid )
if err != nil {
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
}
post := & c . ConversationPost { ID : cpid }
err = post . Fetch ( )
if err == sql . ErrNoRows {
return c . NotFound ( w , r , nil )
} else if err != nil {
return c . InternalError ( err , w , r )
}
convo , err := c . Convos . Get ( post . CID )
if err == sql . ErrNoRows {
return c . NotFound ( w , r , nil )
} else if err != nil {
return c . InternalError ( err , w , r )
}
pcount := convo . PostsCount ( )
if pcount == 0 {
return c . NotFound ( w , r , nil )
}
2019-08-20 22:32:10 +00:00
if user . ID != post . CreatedBy && ! user . IsSuperMod {
return c . NoPermissions ( w , r , user )
2019-08-20 08:44:37 +00:00
}
2019-08-14 10:39:04 +00:00
posts , err := convo . Posts ( 0 , c . Config . ItemsPerPage )
// TODO: Report a better error for no posts
if err == sql . ErrNoRows {
return c . NotFound ( w , r , nil )
} else if err != nil {
return c . InternalError ( err , w , r )
}
if post . ID == posts [ 0 ] . ID {
err = c . Convos . Delete ( convo . ID )
} else {
err = post . Delete ( )
}
if err != nil {
return c . InternalError ( err , w , r )
}
http . Redirect ( w , r , "/user/convo/" + strconv . Itoa ( post . CID ) , http . StatusSeeOther )
return nil
}
func ConvosEditReplySubmit ( w http . ResponseWriter , r * http . Request , user c . User , scpid string ) c . RouteError {
2019-07-26 23:29:42 +00:00
_ , ferr := c . SimpleUserCheck ( w , r , & user )
if ferr != nil {
return ferr
}
2019-08-20 08:44:37 +00:00
cpid , err := strconv . Atoi ( scpid )
if err != nil {
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
}
2019-10-06 00:34:09 +00:00
if ! user . Perms . UseConvos {
return c . NoPermissions ( w , r , user )
}
2019-10-13 08:50:55 +00:00
js := r . PostFormValue ( "js" ) == "1"
2019-08-20 08:44:37 +00:00
post := & c . ConversationPost { ID : cpid }
err = post . Fetch ( )
if err == sql . ErrNoRows {
return c . NotFound ( w , r , nil )
} else if err != nil {
return c . InternalError ( err , w , r )
}
convo , err := c . Convos . Get ( post . CID )
if err == sql . ErrNoRows {
return c . NotFound ( w , r , nil )
} else if err != nil {
return c . InternalError ( err , w , r )
}
pcount := convo . PostsCount ( )
if pcount == 0 {
return c . NotFound ( w , r , nil )
}
2019-08-20 22:32:10 +00:00
if user . ID != post . CreatedBy && ! user . IsSuperMod {
return c . NoPermissions ( w , r , user )
}
if ! convo . Has ( user . ID ) {
return c . LocalError ( "You are not in this conversation." , w , r , user )
2019-08-20 08:44:37 +00:00
}
post . Body = c . PreparseMessage ( r . PostFormValue ( "edit_item" ) )
err = post . Update ( )
if err != nil {
return c . InternalError ( err , w , r )
}
2019-09-29 04:56:39 +00:00
if ! js {
2019-08-20 08:44:37 +00:00
http . Redirect ( w , r , "/user/convo/" + strconv . Itoa ( post . CID ) , http . StatusSeeOther )
} else {
w . Write ( successJSONBytes )
}
2019-07-26 23:29:42 +00:00
return nil
2019-08-14 10:39:04 +00:00
}
2019-10-13 08:50:55 +00:00
func RelationsBlockCreate ( w http . ResponseWriter , r * http . Request , user c . User , h * c . Header , spid string ) c . RouteError {
2019-10-18 00:35:13 +00:00
h . Title = p . GetTitlePhrase ( "create_block" )
2019-10-13 08:50:55 +00:00
pid , err := strconv . Atoi ( spid )
if err != nil {
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
}
puser , err := c . Users . Get ( pid )
if err == sql . ErrNoRows {
return c . LocalError ( "The user you're trying to block doesn't exist." , w , r , user )
} else if err != nil {
return c . InternalError ( err , w , r )
}
2019-10-18 00:35:13 +00:00
pi := c . Page { h , nil , c . AreYouSure { "/user/block/create/submit/" + strconv . Itoa ( puser . ID ) , p . GetTmplPhrase ( "create_block_msg" ) } }
return renderTemplate ( "are_you_sure" , w , r , h , pi )
}
func RelationsBlockCreateSubmit ( w http . ResponseWriter , r * http . Request , user c . User , spid string ) c . RouteError {
pid , err := strconv . Atoi ( spid )
if err != nil {
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
}
puser , err := c . Users . Get ( pid )
if err == sql . ErrNoRows {
return c . LocalError ( "The user you're trying to block doesn't exist." , w , r , user )
} else if err != nil {
return c . InternalError ( err , w , r )
}
if user . ID == puser . ID {
return c . LocalError ( "You can't block yourself." , w , r , user )
}
err = c . UserBlocks . Add ( user . ID , puser . ID )
if err != nil {
return c . InternalError ( err , w , r )
}
http . Redirect ( w , r , "/user/" + strconv . Itoa ( puser . ID ) , http . StatusSeeOther )
return nil
}
func RelationsBlockRemove ( w http . ResponseWriter , r * http . Request , user c . User , h * c . Header , spid string ) c . RouteError {
h . Title = p . GetTitlePhrase ( "remove_block" )
pid , err := strconv . Atoi ( spid )
if err != nil {
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
}
puser , err := c . Users . Get ( pid )
if err == sql . ErrNoRows {
return c . LocalError ( "The user you're trying to block doesn't exist." , w , r , user )
} else if err != nil {
return c . InternalError ( err , w , r )
}
pi := c . Page { h , nil , c . AreYouSure { "/user/block/remove/submit/" + strconv . Itoa ( puser . ID ) , p . GetTmplPhrase ( "remove_block_msg" ) } }
return renderTemplate ( "are_you_sure" , w , r , h , pi )
2019-10-13 08:50:55 +00:00
}
2019-10-18 00:35:13 +00:00
func RelationsBlockRemoveSubmit ( w http . ResponseWriter , r * http . Request , user c . User , spid string ) c . RouteError {
pid , err := strconv . Atoi ( spid )
if err != nil {
return c . LocalError ( p . GetErrorPhrase ( "id_must_be_integer" ) , w , r , user )
}
puser , err := c . Users . Get ( pid )
if err == sql . ErrNoRows {
return c . LocalError ( "The user you're trying to unblock doesn't exist." , w , r , user )
} else if err != nil {
return c . InternalError ( err , w , r )
}
err = c . UserBlocks . Remove ( user . ID , puser . ID )
if err != nil {
return c . InternalError ( err , w , r )
}
http . Redirect ( w , r , "/user/" + strconv . Itoa ( puser . ID ) , http . StatusSeeOther )
2019-10-13 08:50:55 +00:00
return nil
2019-10-18 00:35:13 +00:00
}