github.com/decred/politeia@v1.4.0/politeiawww/cmd/pictl/cmdproposalsetbillingstatus.go (about)

     1  // Copyright (c) 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  	"fmt"
    10  	"strconv"
    11  
    12  	piv1 "github.com/decred/politeia/politeiawww/api/pi/v1"
    13  	pclient "github.com/decred/politeia/politeiawww/client"
    14  	"github.com/decred/politeia/politeiawww/cmd/shared"
    15  )
    16  
    17  // cmdProposalSetBillingStatus sets the status of a proposal.
    18  type cmdProposalSetBillingStatus struct {
    19  	Args struct {
    20  		Token  string `positional-arg-name:"token" required:"true"`
    21  		Status string `positional-arg-name:"status" required:"true"`
    22  		Reason string `positional-arg-name:"reason"`
    23  	} `positional-args:"true"`
    24  }
    25  
    26  // Execute executes the cmdProposalSetBillingStatus command.
    27  //
    28  // This function satisfies the go-flags Commander interface.
    29  func (c *cmdProposalSetBillingStatus) Execute(args []string) error {
    30  	// Verify user identity. This will be needed to sign the status
    31  	// change.
    32  	if cfg.Identity == nil {
    33  		return shared.ErrUserIdentityNotFound
    34  	}
    35  
    36  	// Setup client
    37  	opts := pclient.Opts{
    38  		HTTPSCert:  cfg.HTTPSCert,
    39  		Cookies:    cfg.Cookies,
    40  		HeaderCSRF: cfg.CSRF,
    41  		Verbose:    cfg.Verbose,
    42  		RawJSON:    cfg.RawJSON,
    43  	}
    44  	pc, err := pclient.New(cfg.Host, opts)
    45  	if err != nil {
    46  		return err
    47  	}
    48  
    49  	// Parse billing status. This can be either the numeric status code or the
    50  	// human readable equivalent.
    51  	status, err := parseBillingStatus(c.Args.Status)
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	// Setup request
    57  	msg := c.Args.Token + strconv.Itoa(int(status)) + c.Args.Reason
    58  	sig := cfg.Identity.SignMessage([]byte(msg))
    59  	sbs := piv1.SetBillingStatus{
    60  		Token:     c.Args.Token,
    61  		Status:    status,
    62  		Reason:    c.Args.Reason,
    63  		PublicKey: cfg.Identity.Public.String(),
    64  		Signature: hex.EncodeToString(sig[:]),
    65  	}
    66  
    67  	// Send request
    68  	sbsr, err := pc.PiSetBillingStatus(sbs)
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	// Print receipt
    74  	printf("Token    : %v\n", sbs.Token)
    75  	printf("Status   : %v\n", piv1.BillingStatuses[sbs.Status])
    76  	printf("Timestamp: %v\n", dateAndTimeFromUnix(sbsr.Timestamp))
    77  	printf("Receipt  : %v\n", sbsr.Receipt)
    78  	return nil
    79  }
    80  
    81  func parseBillingStatus(status string) (piv1.BillingStatusT, error) {
    82  	// Parse billing status. This can be either the numeric status code or the
    83  	// human readable equivalent.
    84  	var (
    85  		bs piv1.BillingStatusT
    86  
    87  		statuses = map[string]piv1.BillingStatusT{
    88  			"active":    piv1.BillingStatusActive,
    89  			"close":     piv1.BillingStatusClosed,
    90  			"closed":    piv1.BillingStatusClosed,
    91  			"complete":  piv1.BillingStatusCompleted,
    92  			"completed": piv1.BillingStatusCompleted,
    93  		}
    94  	)
    95  	u, err := strconv.ParseUint(status, 10, 32)
    96  	if err == nil {
    97  		// Numeric status code found
    98  		bs = piv1.BillingStatusT(u)
    99  	} else if s, ok := statuses[status]; ok {
   100  		// Human readable status code found
   101  		bs = s
   102  	} else {
   103  		return bs, fmt.Errorf("invalid status '%v'", status)
   104  	}
   105  
   106  	return bs, nil
   107  }
   108  
   109  // proposalSetBillingStatusHelpMsg is printed to stdout by the help command.
   110  const proposalSetBillingStatusHelpMsg = `proposalsetbillingstatus "token" "status" "reason"
   111  
   112  Set the billing status of a proposal.
   113  
   114  Valid statuses:
   115    (1) active
   116    (2) close
   117    (3) complete
   118  
   119  The following statuses require a billing status change reason to be included:
   120    close
   121  
   122  Arguments:
   123  1. token   (string, required)   Proposal censorship token
   124  2. status  (string, required)   New billing status
   125  3. reason  (string, optional)   Billing status change reason
   126  `