github.com/decred/politeia@v1.4.0/politeiawww/cmd/pictl/cmdcommenttimestamps.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 cmv1 "github.com/decred/politeia/politeiawww/api/comments/v1" 9 pclient "github.com/decred/politeia/politeiawww/client" 10 ) 11 12 // cmdCommentTimestamps retrieves the timestamps for a record's comments. 13 type cmdCommentTimestamps struct { 14 Args struct { 15 Token string `positional-arg-name:"token" required:"true"` 16 CommentIDs []uint32 `positional-arg-name:"commentids" optional:"true"` 17 } `positional-args:"true"` 18 } 19 20 // Execute executes the cmdCommentTimestamps command. 21 // 22 // This function satisfies the go-flags Commander interface. 23 func (c *cmdCommentTimestamps) Execute(args []string) error { 24 // Setup client 25 opts := pclient.Opts{ 26 HTTPSCert: cfg.HTTPSCert, 27 Cookies: cfg.Cookies, 28 HeaderCSRF: cfg.CSRF, 29 Verbose: cfg.Verbose, 30 RawJSON: cfg.RawJSON, 31 } 32 pc, err := pclient.New(cfg.Host, opts) 33 if err != nil { 34 return err 35 } 36 37 // If given comment IDs is empty fetch all IDs and request timestamps 38 // page by page. 39 commentIDs := c.Args.CommentIDs 40 if len(commentIDs) == 0 { 41 // Fetch all comments 42 cm := cmv1.Comments{ 43 Token: c.Args.Token, 44 } 45 cmr, err := pc.Comments(cm) 46 if err != nil { 47 return err 48 } 49 50 // Collect comment IDs 51 for _, c := range cmr.Comments { 52 commentIDs = append(commentIDs, c.CommentID) 53 } 54 } 55 56 // If the proposal has no comments yet, nothing to do. 57 if len(commentIDs) == 0 { 58 printf("Proposal has no comments \n") 59 return nil 60 } 61 62 // Get timestamps page size 63 pr, err := pc.CommentPolicy() 64 if err != nil { 65 return err 66 } 67 pageSize := pr.TimestampsPageSize 68 69 // Timestamps route is paginated, request timestamps page by page. 70 var ( 71 pageStartIdx int 72 fetched int 73 totalNotTimestamped int 74 ) 75 for pageStartIdx < len(commentIDs) { 76 pageEndIdx := pageStartIdx + int(pageSize) 77 if pageEndIdx > len(commentIDs) { 78 // We've reached the end of the slice 79 pageEndIdx = len(commentIDs) 80 } 81 82 // pageStartIdx is included. pageEndIdx is excluded. 83 page := commentIDs[pageStartIdx:pageEndIdx] 84 85 // Get timestamps 86 t := cmv1.Timestamps{ 87 Token: c.Args.Token, 88 CommentIDs: page, 89 } 90 tr, err := pc.CommentTimestamps(t) 91 if err != nil { 92 return err 93 } 94 fetched = fetched + len(page) 95 96 // Verify timestamps 97 notTimestamped, err := pclient.CommentTimestampsVerify(*tr) 98 if err != nil { 99 return err 100 } 101 if len(notTimestamped) > 0 { 102 totalNotTimestamped = totalNotTimestamped + len(notTimestamped) 103 } 104 105 printf("Total number of comments: %v, fetched: %v, timestamped: %v, "+ 106 "not timestamped: %v \n", len(commentIDs), fetched, 107 fetched-totalNotTimestamped, totalNotTimestamped) 108 109 // Next page start index 110 pageStartIdx = pageEndIdx 111 } 112 113 return nil 114 } 115 116 // commentTimestampsHelpMsg is printed to stdout by the help command. 117 const commentTimestampsHelpMsg = `commenttimestamps [flags] "token" commentIDs 118 119 Fetch the timestamps for a record's comments. The timestamp contains all 120 necessary data to verify that user submitted comment data has been timestamped 121 onto the decred blockchain. 122 123 If comment IDs are not provided then the timestamps for all comments will be 124 returned. If the record is unvetted, the --unvetted flag must be used. 125 126 Arguments: 127 1. token (string, required) Proposal token 128 2. commentIDs ([]uint32, optional) Proposal version 129 130 Example: Fetch all record comment timestamps 131 $ pictl commenttimestamps 0a265dd93e9bae6d 132 133 Example: Fetch comment timestamps for comment IDs 1, 6, and 7 134 $ pictl commenttimestamps 0a265dd93e9bae6d 1 6 7`