github.com/decred/politeia@v1.4.0/politeiawww/cmd/pictl/cmdcommentnew.go (about) 1 // Copyright (c) 2020-2021 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "encoding/hex" 9 "encoding/json" 10 "strconv" 11 12 cmv1 "github.com/decred/politeia/politeiawww/api/comments/v1" 13 piv1 "github.com/decred/politeia/politeiawww/api/pi/v1" 14 pclient "github.com/decred/politeia/politeiawww/client" 15 "github.com/decred/politeia/politeiawww/cmd/shared" 16 ) 17 18 // cmdCommentNew submits a new comment. 19 type cmdCommentNew struct { 20 Args struct { 21 Token string `positional-arg-name:"token" required:"true"` 22 Comment string `positional-arg-name:"comment" required:"true"` 23 ParentID uint32 `positional-arg-name:"parentid"` 24 } `positional-args:"true"` 25 26 // Unvetted is used to comment on an unvetted record. If this flag 27 // is not used the command assumes the record is vetted. 28 Unvetted bool `long:"unvetted" optional:"true"` 29 30 // UpdateTitle is used to post a new author update. 31 UpdateTitle string `long:"updatetitle" optional:"true"` 32 } 33 34 // Execute executes the cmdCommentNew command. 35 // 36 // This function satisfies the go-flags Commander interface. 37 func (c *cmdCommentNew) Execute(args []string) error { 38 // Unpack args 39 var ( 40 token = c.Args.Token 41 comment = c.Args.Comment 42 parentID = c.Args.ParentID 43 ) 44 45 // Check for user identity. A user identity is required to sign 46 // the comment. 47 if cfg.Identity == nil { 48 return shared.ErrUserIdentityNotFound 49 } 50 51 // Setup client 52 opts := pclient.Opts{ 53 HTTPSCert: cfg.HTTPSCert, 54 Cookies: cfg.Cookies, 55 HeaderCSRF: cfg.CSRF, 56 Verbose: cfg.Verbose, 57 RawJSON: cfg.RawJSON, 58 } 59 pc, err := pclient.New(cfg.Host, opts) 60 if err != nil { 61 return err 62 } 63 64 // Setup state 65 var state cmv1.RecordStateT 66 switch { 67 case c.Unvetted: 68 state = cmv1.RecordStateUnvetted 69 default: 70 state = cmv1.RecordStateVetted 71 } 72 73 // Prepare extra data if it's a new author update 74 var ( 75 extraData, 76 extraDataHint string 77 ) 78 if c.UpdateTitle != "" { 79 extraDataHint = piv1.ProposalUpdateHint 80 pum := piv1.ProposalUpdateMetadata{ 81 Title: c.UpdateTitle, 82 } 83 b, err := json.Marshal(pum) 84 if err != nil { 85 return err 86 } 87 extraData = string(b) 88 } 89 90 // Setup request 91 msg := strconv.FormatUint(uint64(state), 10) + token + 92 strconv.FormatUint(uint64(parentID), 10) + comment + 93 extraData + extraDataHint 94 sig := cfg.Identity.SignMessage([]byte(msg)) 95 n := cmv1.New{ 96 State: state, 97 Token: token, 98 ParentID: parentID, 99 Comment: comment, 100 Signature: hex.EncodeToString(sig[:]), 101 PublicKey: cfg.Identity.Public.String(), 102 ExtraDataHint: extraDataHint, 103 ExtraData: extraData, 104 } 105 106 // Send request 107 nr, err := pc.CommentNew(n) 108 if err != nil { 109 return err 110 } 111 112 // Verify receipt 113 vr, err := client.Version() 114 if err != nil { 115 return err 116 } 117 err = pclient.CommentVerify(nr.Comment, vr.PubKey) 118 if err != nil { 119 return err 120 } 121 122 // Print receipt 123 printComment(nr.Comment) 124 125 return nil 126 } 127 128 // commentNewHelpMsg is printed to stdout by the help command. 129 const commentNewHelpMsg = `commentnew "token" "comment" parentid 130 131 Comment on a record. Requires the user to be logged in. 132 133 This command assumes the record is a vetted record. 134 135 If the record is unvetted, the --unvetted flag must be used. Commenting on 136 unvetted records requires admin priviledges. 137 138 Proposal's author may post author update using the --updatetitle flag. Author 139 updates are allowed only on a proposal which finished voting and it's 140 vote was approved. User can reply only on the latest author update. When a 141 proposal billing status is set to closed or completed it's not possible to 142 post author updates or to reply on them. 143 144 Arguments: 145 1. token (string, required) Proposal censorship token. 146 2. comment (string, required) Comment text. 147 3. parentid (uint32, optional) ID of parent commment. Including a parent ID 148 indicates that the comment is a reply. 149 150 Flags: 151 --unvetted (bool, optional) Record is unvetted. 152 --updatetitle (string, optional) Authour update title. 153 `