2024-06-02 07:53:13 +01:00
// SPDX-FileCopyrightText: 2024 Dan Anglin <d.n.i.anglin@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-or-later
2024-05-23 18:06:49 +01:00
package executor
2024-02-27 19:52:59 +00:00
import (
"flag"
"fmt"
2024-05-31 05:22:17 +01:00
"strconv"
2024-02-27 19:52:59 +00:00
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
2024-06-25 12:39:39 +01:00
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
2024-02-27 19:52:59 +00:00
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
2024-06-17 18:59:20 +01:00
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
2024-05-31 00:11:02 +01:00
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
2024-02-27 19:52:59 +00:00
)
2024-05-23 18:06:49 +01:00
type CreateExecutor struct {
2024-02-27 19:52:59 +00:00
* flag . FlagSet
2024-06-17 18:59:20 +01:00
printer * printer . Printer
2024-06-25 12:39:39 +01:00
config * config . Config
2024-06-17 18:59:20 +01:00
addPoll bool
boostable bool
federated bool
likeable bool
2024-06-15 18:40:13 +01:00
pollAllowsMultipleChoices bool
pollHidesVoteCounts bool
2024-06-17 18:59:20 +01:00
replyable bool
sensitive * bool
content string
contentType string
fromFile string
language string
resourceType string
listTitle string
listRepliesPolicy string
spoilerText string
visibility string
pollExpiresIn TimeDurationFlagValue
pollOptions MultiStringFlagValue
2024-02-27 19:52:59 +00:00
}
2024-06-25 12:39:39 +01:00
func NewCreateExecutor ( printer * printer . Printer , config * config . Config , name , summary string ) * CreateExecutor {
2024-05-23 18:06:49 +01:00
createExe := CreateExecutor {
2024-02-27 19:52:59 +00:00
FlagSet : flag . NewFlagSet ( name , flag . ExitOnError ) ,
2024-05-22 23:30:09 +01:00
2024-06-25 12:39:39 +01:00
printer : printer ,
config : config ,
2024-02-27 19:52:59 +00:00
}
2024-06-09 15:58:10 +01:00
createExe . BoolVar ( & createExe . boostable , flagEnableReposts , true , "Specify if the status can be reposted/boosted by others" )
createExe . BoolVar ( & createExe . federated , flagEnableFederation , true , "Specify if the status can be federated beyond the local timelines" )
createExe . BoolVar ( & createExe . likeable , flagEnableLikes , true , "Specify if the status can be liked/favourited" )
createExe . BoolVar ( & createExe . replyable , flagEnableReplies , true , "Specify if the status can be replied to" )
2024-06-15 18:40:13 +01:00
createExe . BoolVar ( & createExe . pollAllowsMultipleChoices , flagPollAllowsMultipleChoices , false , "The poll allows viewers to make multiple choices in the poll" )
createExe . BoolVar ( & createExe . pollHidesVoteCounts , flagPollHidesVoteCounts , false , "The poll will hide the vote count until it is closed" )
createExe . BoolVar ( & createExe . addPoll , flagAddPoll , false , "Add a poll to the status" )
2024-06-09 15:58:10 +01:00
createExe . StringVar ( & createExe . content , flagContent , "" , "The content of the status to create" )
createExe . StringVar ( & createExe . contentType , flagContentType , "plain" , "The type that the contents should be parsed from (valid values are plain and markdown)" )
createExe . StringVar ( & createExe . fromFile , flagFromFile , "" , "The file path where to read the contents from" )
createExe . StringVar ( & createExe . language , flagLanguage , "" , "The ISO 639 language code for this status" )
createExe . StringVar ( & createExe . spoilerText , flagSpoilerText , "" , "The text to display as the status' warning or subject" )
createExe . StringVar ( & createExe . visibility , flagVisibility , "" , "The visibility of the posted status" )
createExe . StringVar ( & createExe . resourceType , flagType , "" , "Specify the type of resource to create" )
createExe . StringVar ( & createExe . listTitle , flagListTitle , "" , "Specify the title of the list" )
createExe . StringVar ( & createExe . listRepliesPolicy , flagListRepliesPolicy , "list" , "Specify the policy of the replies for this list (valid values are followed, list and none)" )
2024-06-15 18:40:13 +01:00
createExe . Var ( & createExe . pollOptions , flagPollOption , "A poll option. Use this multiple times to set multiple options" )
createExe . Var ( & createExe . pollExpiresIn , flagPollExpiresIn , "The duration in which the poll is open for" )
2024-06-09 15:58:10 +01:00
createExe . BoolFunc ( flagSensitive , "Specify if the status should be marked as sensitive" , func ( value string ) error {
2024-05-31 05:22:17 +01:00
boolVal , err := strconv . ParseBool ( value )
if err != nil {
2024-06-02 11:35:43 +01:00
return fmt . Errorf ( "unable to parse %q as a boolean value: %w" , value , err )
2024-05-31 05:22:17 +01:00
}
createExe . sensitive = new ( bool )
* createExe . sensitive = boolVal
return nil
} )
2024-05-23 18:06:49 +01:00
createExe . Usage = commandUsageFunc ( name , summary , createExe . FlagSet )
2024-02-27 19:52:59 +00:00
2024-05-23 18:06:49 +01:00
return & createExe
2024-02-27 19:52:59 +00:00
}
2024-05-23 18:06:49 +01:00
func ( c * CreateExecutor ) Execute ( ) error {
2024-02-27 19:52:59 +00:00
if c . resourceType == "" {
2024-05-23 18:06:49 +01:00
return FlagNotSetError { flagText : flagType }
2024-02-27 19:52:59 +00:00
}
2024-06-25 12:39:39 +01:00
gtsClient , err := client . NewClientFromFile ( c . config . CredentialsFile )
2024-02-27 19:52:59 +00:00
if err != nil {
2024-06-02 11:35:43 +01:00
return fmt . Errorf ( "unable to create the GoToSocial client: %w" , err )
2024-02-27 19:52:59 +00:00
}
funcMap := map [ string ] func ( * client . Client ) error {
2024-05-30 18:46:33 +01:00
resourceList : c . createList ,
resourceStatus : c . createStatus ,
2024-02-27 19:52:59 +00:00
}
doFunc , ok := funcMap [ c . resourceType ]
if ! ok {
2024-05-23 18:06:49 +01:00
return UnsupportedTypeError { resourceType : c . resourceType }
2024-02-27 19:52:59 +00:00
}
return doFunc ( gtsClient )
}
2024-05-23 18:06:49 +01:00
func ( c * CreateExecutor ) createList ( gtsClient * client . Client ) error {
2024-02-27 19:52:59 +00:00
if c . listTitle == "" {
2024-05-23 18:06:49 +01:00
return FlagNotSetError { flagText : flagListTitle }
2024-02-27 19:52:59 +00:00
}
2024-06-02 11:35:43 +01:00
parsedListRepliesPolicy , err := model . ParseListRepliesPolicy ( c . listRepliesPolicy )
if err != nil {
return err
2024-02-27 19:52:59 +00:00
}
2024-05-30 20:04:55 +01:00
form := client . CreateListForm {
Title : c . listTitle ,
RepliesPolicy : parsedListRepliesPolicy ,
}
list , err := gtsClient . CreateList ( form )
2024-02-27 19:52:59 +00:00
if err != nil {
2024-06-02 11:35:43 +01:00
return fmt . Errorf ( "unable to create the list: %w" , err )
2024-02-27 19:52:59 +00:00
}
2024-06-17 18:59:20 +01:00
c . printer . PrintSuccess ( "Successfully created the following list:" )
c . printer . PrintList ( list )
2024-02-27 19:52:59 +00:00
return nil
}
2024-05-30 18:46:33 +01:00
func ( c * CreateExecutor ) createStatus ( gtsClient * client . Client ) error {
var (
2024-05-31 00:11:02 +01:00
err error
content string
2024-05-30 18:46:33 +01:00
language string
visibility string
2024-05-31 05:22:17 +01:00
sensitive bool
2024-05-30 18:46:33 +01:00
)
2024-05-31 00:11:02 +01:00
switch {
case c . content != "" :
content = c . content
case c . fromFile != "" :
content , err = utilities . ReadFile ( c . fromFile )
if err != nil {
2024-06-02 11:35:43 +01:00
return fmt . Errorf ( "unable to get the status contents from %q: %w" , c . fromFile , err )
2024-05-31 00:11:02 +01:00
}
default :
return EmptyContentError {
ResourceType : resourceStatus ,
Hint : "please use --" + flagContent + " or --" + flagFromFile ,
}
}
2024-05-30 18:46:33 +01:00
preferences , err := gtsClient . GetUserPreferences ( )
if err != nil {
2024-06-02 11:35:43 +01:00
fmt . Println ( "WARNING: Unable to get your posting preferences: %w" , err )
2024-05-30 18:46:33 +01:00
}
if c . language != "" {
language = c . language
} else {
language = preferences . PostingDefaultLanguage
}
if c . visibility != "" {
visibility = c . visibility
} else {
visibility = preferences . PostingDefaultVisibility
}
2024-05-31 05:22:17 +01:00
if c . sensitive != nil {
sensitive = * c . sensitive
} else {
sensitive = preferences . PostingDefaultSensitive
}
2024-06-02 11:35:43 +01:00
parsedVisibility , err := model . ParseStatusVisibility ( visibility )
if err != nil {
return err
2024-05-30 18:46:33 +01:00
}
2024-06-02 11:35:43 +01:00
parsedContentType , err := model . ParseStatusContentType ( c . contentType )
if err != nil {
return err
2024-05-30 18:46:33 +01:00
}
form := client . CreateStatusForm {
2024-05-31 00:11:02 +01:00
Content : content ,
2024-05-30 18:46:33 +01:00
ContentType : parsedContentType ,
Language : language ,
SpoilerText : c . spoilerText ,
Boostable : c . boostable ,
Federated : c . federated ,
Likeable : c . likeable ,
Replyable : c . replyable ,
2024-05-31 05:22:17 +01:00
Sensitive : sensitive ,
2024-05-30 18:46:33 +01:00
Visibility : parsedVisibility ,
2024-06-15 18:40:13 +01:00
Poll : nil ,
}
if c . addPoll {
if len ( c . pollOptions ) == 0 {
return NoPollOptionError { }
}
poll := client . CreateStatusPollForm {
Options : c . pollOptions ,
Multiple : c . pollAllowsMultipleChoices ,
HideTotals : c . pollHidesVoteCounts ,
ExpiresIn : int ( c . pollExpiresIn . Duration . Seconds ( ) ) ,
}
form . Poll = & poll
2024-05-30 18:46:33 +01:00
}
status , err := gtsClient . CreateStatus ( form )
if err != nil {
2024-06-02 11:35:43 +01:00
return fmt . Errorf ( "unable to create the status: %w" , err )
2024-05-30 18:46:33 +01:00
}
2024-06-17 18:59:20 +01:00
c . printer . PrintSuccess ( "Successfully created the following status:" )
c . printer . PrintStatus ( status )
2024-05-30 18:46:33 +01:00
return nil
}