github.com/decred/politeia@v1.4.0/politeiawww/cmd/shared/client.go (about) 1 // Copyright (c) 2017-2020 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 shared 6 7 import ( 8 "bytes" 9 "context" 10 "encoding/json" 11 "fmt" 12 "net/http" 13 "net/http/cookiejar" 14 "net/url" 15 "os" 16 "reflect" 17 "strings" 18 19 "decred.org/dcrwallet/rpc/walletrpc" 20 cms "github.com/decred/politeia/politeiawww/api/cms/v1" 21 www "github.com/decred/politeia/politeiawww/api/www/v1" 22 "github.com/decred/politeia/util" 23 "github.com/gorilla/schema" 24 "golang.org/x/net/publicsuffix" 25 "google.golang.org/grpc" 26 "google.golang.org/grpc/credentials" 27 ) 28 29 // Client is a politeiawww client. 30 type Client struct { 31 http *http.Client 32 cfg *Config 33 34 // wallet grpc 35 ctx context.Context 36 creds credentials.TransportCredentials 37 conn *grpc.ClientConn 38 wallet walletrpc.WalletServiceClient 39 } 40 41 func prettyPrintJSON(v interface{}) error { 42 b, err := json.MarshalIndent(v, "", " ") 43 if err != nil { 44 return fmt.Errorf("MarshalIndent: %v", err) 45 } 46 fmt.Fprintf(os.Stdout, "%s\n", b) 47 return nil 48 } 49 50 // userWWWErrorStatus retrieves the human readable error message for an error 51 // status code. The status code error message comes from the www api. 52 func userWWWErrorStatus(e www.ErrorStatusT) string { 53 s, ok := www.ErrorStatus[e] 54 if ok { 55 return s 56 } 57 s, ok = cms.ErrorStatus[e] 58 if ok { 59 return s 60 } 61 return "" 62 } 63 64 // wwwError unmarshals the response body from makeRequest, and handles any 65 // status code errors from the server. Parses the error code and error context 66 // from the www api, in case of user error. 67 func wwwError(body []byte, statusCode int) error { 68 switch statusCode { 69 case http.StatusBadRequest: 70 // User Error 71 var ue www.UserError 72 err := json.Unmarshal(body, &ue) 73 if err != nil { 74 return fmt.Errorf("unmarshal UserError: %v", err) 75 } 76 if ue.ErrorCode != 0 { 77 var e error 78 errMsg := userWWWErrorStatus(ue.ErrorCode) 79 if len(ue.ErrorContext) == 0 { 80 // Error format when an ErrorContext is not included 81 e = fmt.Errorf("%v, %v", statusCode, errMsg) 82 } else { 83 // Error format when an ErrorContext is included 84 e = fmt.Errorf("%v, %v: %v", statusCode, errMsg, 85 strings.Join(ue.ErrorContext, ", ")) 86 } 87 return e 88 } 89 case http.StatusInternalServerError: 90 // Server Error 91 var er www.ErrorReply 92 err := json.Unmarshal(body, &er) 93 if err != nil { 94 return fmt.Errorf("unmarshal Error: %v", err) 95 } 96 var e error 97 if len(er.ErrorContext) == 0 { 98 // Error format when an ErrorContext is not included 99 e = fmt.Errorf("ServerError timestamp: %v", er.ErrorCode) 100 } else { 101 // Error format when an ErrorContext is included 102 e = fmt.Errorf("ServerError timestamp: %v context: %v", 103 er.ErrorCode, er.ErrorContext) 104 } 105 return e 106 default: 107 // Default Status Code Error 108 return fmt.Errorf("%v", statusCode) 109 } 110 111 return nil 112 } 113 114 // makeRequest sends the provided request to the politeiawww backend specified 115 // by the Client config. This function handles verbose printing when specified 116 // by the Client config since verbose printing includes details such as the 117 // full route and http response codes. Caller functions handle status code 118 // validation and error checks. 119 func (c *Client) makeRequest(method, routeVersion, route string, body interface{}) (int, []byte, error) { 120 // Setup request 121 var requestBody []byte 122 var queryParams string 123 if body != nil { 124 switch { 125 case method == http.MethodGet: 126 // Use reflection in case the interface value is nil 127 // but the interface type is not. This can happen when 128 // query params exist but are not used. 129 if reflect.ValueOf(body).IsNil() { 130 break 131 } 132 133 // GET requests don't have a request body; instead we 134 // will populate the query params. 135 form := url.Values{} 136 if err := schema.NewEncoder().Encode(body, form); err != nil { 137 return 0, nil, err 138 } 139 queryParams = "?" + form.Encode() 140 141 case method == http.MethodPost || method == http.MethodPut: 142 var err error 143 requestBody, err = json.Marshal(body) 144 if err != nil { 145 return 0, nil, err 146 } 147 148 default: 149 return 0, nil, fmt.Errorf("unknown http method '%v'", method) 150 } 151 } 152 153 fullRoute := c.cfg.Host + routeVersion + route + queryParams 154 155 // Print request details 156 switch { 157 case c.cfg.Verbose && method == http.MethodGet: 158 fmt.Printf("Request: GET %v\n", fullRoute) 159 case c.cfg.Verbose && method == http.MethodPost: 160 fmt.Printf("Request: POST %v\n", fullRoute) 161 err := prettyPrintJSON(body) 162 if err != nil { 163 return 0, nil, err 164 } 165 case c.cfg.Verbose && method == http.MethodPut: 166 fmt.Printf("Request: PUT %v\n", fullRoute) 167 err := prettyPrintJSON(body) 168 if err != nil { 169 return 0, nil, err 170 } 171 } 172 173 // Create http request 174 req, err := http.NewRequest(method, fullRoute, bytes.NewReader(requestBody)) 175 if err != nil { 176 return 0, nil, err 177 } 178 req.Header.Add(www.CsrfToken, c.cfg.CSRF) 179 180 // Send request 181 r, err := c.http.Do(req) 182 if err != nil { 183 return 0, nil, err 184 } 185 defer func() { 186 r.Body.Close() 187 }() 188 189 responseBody := util.ConvertBodyToByteArray(r.Body, false) 190 191 // Print response details 192 if c.cfg.Verbose { 193 fmt.Printf("Response: %v\n", r.StatusCode) 194 } 195 196 return r.StatusCode, responseBody, nil 197 } 198 199 // Version returns the version information for the politeiawww instance. 200 func (c *Client) Version() (*www.VersionReply, error) { 201 fullRoute := c.cfg.Host + www.PoliteiaWWWAPIRoute + www.RouteVersion 202 203 // Print request details 204 if c.cfg.Verbose { 205 fmt.Printf("Request: GET %v\n", fullRoute) 206 } 207 208 // Create new http request instead of using makeRequest() 209 // so that we can save the CSRF tokens to disk. 210 req, err := http.NewRequest(http.MethodGet, fullRoute, nil) 211 if err != nil { 212 return nil, err 213 } 214 req.Header.Add(www.CsrfToken, c.cfg.CSRF) 215 216 // Send request 217 r, err := c.http.Do(req) 218 if err != nil { 219 return nil, err 220 } 221 defer func() { 222 r.Body.Close() 223 }() 224 225 respBody := util.ConvertBodyToByteArray(r.Body, false) 226 227 // Validate response status 228 if r.StatusCode != http.StatusOK { 229 var ue www.UserError 230 err = json.Unmarshal(respBody, &ue) 231 if err == nil { 232 return nil, fmt.Errorf("%v, %v %v", r.StatusCode, 233 userWWWErrorStatus(ue.ErrorCode), 234 strings.Join(ue.ErrorContext, ", ")) 235 } 236 237 return nil, fmt.Errorf("%v", r.StatusCode) 238 } 239 240 // Unmarshal response 241 var vr www.VersionReply 242 err = json.Unmarshal(respBody, &vr) 243 if err != nil { 244 return nil, fmt.Errorf("unmarshal VersionReply: %v", err) 245 } 246 247 // Print response details 248 if c.cfg.Verbose { 249 fmt.Printf("Response: %v\n", r.StatusCode) 250 err := prettyPrintJSON(vr) 251 if err != nil { 252 return nil, err 253 } 254 } 255 256 // CSRF protection works via the double-submit method. 257 // One token is sent in the cookie. A second token is 258 // sent in the header. Both tokens must be persisted 259 // between CLI commands. 260 261 // Persist CSRF header token 262 c.cfg.CSRF = r.Header.Get(www.CsrfToken) 263 err = c.cfg.SaveCSRF(c.cfg.CSRF) 264 if err != nil { 265 return nil, err 266 } 267 268 // Persist CSRF cookie token 269 err = c.cfg.SaveCookies(c.http.Jar.Cookies(req.URL)) 270 if err != nil { 271 return nil, err 272 } 273 274 return &vr, nil 275 } 276 277 // Login logs a user into politeiawww. 278 func (c *Client) Login(l *www.Login) (*www.LoginReply, error) { 279 // Setup request 280 requestBody, err := json.Marshal(l) 281 if err != nil { 282 return nil, err 283 } 284 285 fullRoute := c.cfg.Host + www.PoliteiaWWWAPIRoute + www.RouteLogin 286 287 // Print request details 288 if c.cfg.Verbose { 289 fmt.Printf("Request: POST %v\n", fullRoute) 290 err := prettyPrintJSON(l) 291 if err != nil { 292 return nil, err 293 } 294 } 295 296 // Create new http request instead of using makeRequest() 297 // so that we can save the session data for subsequent 298 // commands 299 req, err := http.NewRequest(http.MethodPost, fullRoute, 300 bytes.NewReader(requestBody)) 301 if err != nil { 302 return nil, err 303 } 304 req.Header.Add(www.CsrfToken, c.cfg.CSRF) 305 306 // Send request 307 r, err := c.http.Do(req) 308 if err != nil { 309 return nil, err 310 } 311 defer func() { 312 r.Body.Close() 313 }() 314 315 respBody := util.ConvertBodyToByteArray(r.Body, false) 316 317 // Validate response status 318 if r.StatusCode != http.StatusOK { 319 var ue www.UserError 320 err = json.Unmarshal(respBody, &ue) 321 if err == nil { 322 return nil, fmt.Errorf("%v, %v %v", r.StatusCode, 323 userWWWErrorStatus(ue.ErrorCode), 324 strings.Join(ue.ErrorContext, ", ")) 325 } 326 327 return nil, fmt.Errorf("%v", r.StatusCode) 328 } 329 330 // Unmarshal response 331 var lr www.LoginReply 332 err = json.Unmarshal(respBody, &lr) 333 if err != nil { 334 return nil, fmt.Errorf("unmarshal LoginReply: %v", err) 335 } 336 337 // Print response details 338 if c.cfg.Verbose { 339 fmt.Printf("Response: %v\n", r.StatusCode) 340 err := prettyPrintJSON(lr) 341 if err != nil { 342 return nil, err 343 } 344 } 345 346 // Persist session data 347 ck := c.http.Jar.Cookies(req.URL) 348 if err = c.cfg.SaveCookies(ck); err != nil { 349 return nil, err 350 } 351 352 return &lr, nil 353 } 354 355 // Logout logs out a user from politeiawww. 356 func (c *Client) Logout() (*www.LogoutReply, error) { 357 fullRoute := c.cfg.Host + www.PoliteiaWWWAPIRoute + www.RouteLogout 358 359 // Print request details 360 if c.cfg.Verbose { 361 fmt.Printf("Request: POST %v\n", fullRoute) 362 } 363 364 // Create new http request instead of using makeRequest() 365 // so that we can save the updated cookies to disk 366 req, err := http.NewRequest(http.MethodPost, fullRoute, nil) 367 if err != nil { 368 return nil, err 369 } 370 req.Header.Add(www.CsrfToken, c.cfg.CSRF) 371 372 // Send request 373 r, err := c.http.Do(req) 374 if err != nil { 375 return nil, err 376 } 377 defer func() { 378 r.Body.Close() 379 }() 380 381 respBody := util.ConvertBodyToByteArray(r.Body, false) 382 383 // Validate response status 384 if r.StatusCode != http.StatusOK { 385 var ue www.UserError 386 err = json.Unmarshal(respBody, &ue) 387 if err == nil { 388 return nil, fmt.Errorf("%v, %v %v", r.StatusCode, 389 userWWWErrorStatus(ue.ErrorCode), 390 strings.Join(ue.ErrorContext, ", ")) 391 } 392 393 return nil, fmt.Errorf("%v", r.StatusCode) 394 } 395 396 // Unmarshal response 397 var lr www.LogoutReply 398 err = json.Unmarshal(respBody, &lr) 399 if err != nil { 400 return nil, fmt.Errorf("unmarshal LogoutReply: %v", err) 401 } 402 403 // Print response details 404 if c.cfg.Verbose { 405 fmt.Printf("Response: %v\n", r.StatusCode) 406 err := prettyPrintJSON(lr) 407 if err != nil { 408 return nil, err 409 } 410 } 411 412 // Persist cookies 413 ck := c.http.Jar.Cookies(req.URL) 414 if err = c.cfg.SaveCookies(ck); err != nil { 415 return nil, err 416 } 417 418 return &lr, nil 419 } 420 421 // Policy returns the politeiawww policy information. 422 func (c *Client) Policy() (*www.PolicyReply, error) { 423 statusCode, respBody, err := c.makeRequest(http.MethodGet, 424 www.PoliteiaWWWAPIRoute, www.RoutePolicy, nil) 425 if err != nil { 426 return nil, err 427 } 428 429 if statusCode != http.StatusOK { 430 return nil, wwwError(respBody, statusCode) 431 } 432 433 var pr www.PolicyReply 434 err = json.Unmarshal(respBody, &pr) 435 if err != nil { 436 return nil, fmt.Errorf("unmarshal PolicyReply: %v", err) 437 } 438 439 if c.cfg.Verbose { 440 err := prettyPrintJSON(pr) 441 if err != nil { 442 return nil, err 443 } 444 } 445 446 return &pr, nil 447 } 448 449 // CMSPolicy returns the politeiawww policy information. 450 func (c *Client) CMSPolicy() (*cms.PolicyReply, error) { 451 statusCode, respBody, err := c.makeRequest(http.MethodGet, 452 www.PoliteiaWWWAPIRoute, www.RoutePolicy, nil) 453 if err != nil { 454 return nil, err 455 } 456 457 if statusCode != http.StatusOK { 458 return nil, wwwError(respBody, statusCode) 459 } 460 461 var pr cms.PolicyReply 462 err = json.Unmarshal(respBody, &pr) 463 if err != nil { 464 return nil, fmt.Errorf("unmarshal CMSPolicyReply: %v", err) 465 } 466 467 if c.cfg.Verbose { 468 err := prettyPrintJSON(pr) 469 if err != nil { 470 return nil, err 471 } 472 } 473 474 return &pr, nil 475 } 476 477 // InviteNewUser creates a new cmswww user. 478 func (c *Client) InviteNewUser(inu *cms.InviteNewUser) (*cms.InviteNewUserReply, error) { 479 statusCode, respBody, err := c.makeRequest(http.MethodPost, 480 cms.APIRoute, cms.RouteInviteNewUser, inu) 481 if err != nil { 482 return nil, err 483 } 484 485 if statusCode != http.StatusOK { 486 return nil, wwwError(respBody, statusCode) 487 } 488 489 var inur cms.InviteNewUserReply 490 err = json.Unmarshal(respBody, &inur) 491 if err != nil { 492 return nil, fmt.Errorf("unmarshal InviteNewUserReply: %v", err) 493 } 494 495 if c.cfg.Verbose { 496 err := prettyPrintJSON(inur) 497 if err != nil { 498 return nil, err 499 } 500 } 501 502 return &inur, nil 503 } 504 505 // RegisterUser finalizes the signup process for a new cmswww user. 506 func (c *Client) RegisterUser(ru *cms.RegisterUser) (*cms.RegisterUserReply, error) { 507 statusCode, respBody, err := c.makeRequest(http.MethodPost, 508 cms.APIRoute, cms.RouteRegisterUser, ru) 509 if err != nil { 510 return nil, err 511 } 512 513 if statusCode != http.StatusOK { 514 return nil, wwwError(respBody, statusCode) 515 } 516 517 var rur cms.RegisterUserReply 518 err = json.Unmarshal(respBody, &rur) 519 if err != nil { 520 return nil, fmt.Errorf("unmarshal RegisterUserReply: %v", err) 521 } 522 523 if c.cfg.Verbose { 524 err := prettyPrintJSON(rur) 525 if err != nil { 526 return nil, err 527 } 528 } 529 530 return &rur, nil 531 } 532 533 // NewUser creates a new politeiawww user. 534 func (c *Client) NewUser(nu *www.NewUser) (*www.NewUserReply, error) { 535 statusCode, respBody, err := c.makeRequest(http.MethodPost, 536 www.PoliteiaWWWAPIRoute, www.RouteNewUser, nu) 537 if err != nil { 538 return nil, err 539 } 540 541 if statusCode != http.StatusOK { 542 return nil, wwwError(respBody, statusCode) 543 } 544 545 var nur www.NewUserReply 546 err = json.Unmarshal(respBody, &nur) 547 if err != nil { 548 return nil, fmt.Errorf("unmarshal NewUserReply: %v", err) 549 } 550 551 if c.cfg.Verbose { 552 err := prettyPrintJSON(nur) 553 if err != nil { 554 return nil, err 555 } 556 } 557 558 return &nur, nil 559 } 560 561 // VerifyNewUser verifies a user's email address. 562 func (c *Client) VerifyNewUser(vnu *www.VerifyNewUser) (*www.VerifyNewUserReply, error) { 563 statusCode, respBody, err := c.makeRequest(http.MethodGet, 564 www.PoliteiaWWWAPIRoute, www.RouteVerifyNewUser, vnu) 565 if err != nil { 566 return nil, err 567 } 568 569 if statusCode != http.StatusOK { 570 return nil, wwwError(respBody, statusCode) 571 } 572 573 var vnur www.VerifyNewUserReply 574 err = json.Unmarshal(respBody, &vnur) 575 if err != nil { 576 return nil, fmt.Errorf("unmarshal VerifyNewUserReply: %v", err) 577 } 578 579 if c.cfg.Verbose { 580 err := prettyPrintJSON(vnur) 581 if err != nil { 582 return nil, err 583 } 584 } 585 586 return &vnur, nil 587 } 588 589 // Me returns user details for the logged in user. 590 func (c *Client) Me() (*www.LoginReply, error) { 591 statusCode, respBody, err := c.makeRequest(http.MethodGet, 592 www.PoliteiaWWWAPIRoute, www.RouteUserMe, nil) 593 if err != nil { 594 return nil, err 595 } 596 597 if statusCode != http.StatusOK { 598 return nil, wwwError(respBody, statusCode) 599 } 600 601 var lr www.LoginReply 602 err = json.Unmarshal(respBody, &lr) 603 if err != nil { 604 return nil, fmt.Errorf("unmarshal LoginReply: %v", err) 605 } 606 607 if c.cfg.Verbose { 608 err := prettyPrintJSON(lr) 609 if err != nil { 610 return nil, err 611 } 612 } 613 614 return &lr, nil 615 } 616 617 // Secret pings politeiawww. 618 func (c *Client) Secret() (*www.UserError, error) { 619 statusCode, respBody, err := c.makeRequest(http.MethodPost, 620 www.PoliteiaWWWAPIRoute, www.RouteSecret, nil) 621 if err != nil { 622 return nil, err 623 } 624 625 if statusCode != http.StatusOK { 626 return nil, wwwError(respBody, statusCode) 627 } 628 629 var ue www.UserError 630 err = json.Unmarshal(respBody, &ue) 631 if err != nil { 632 return nil, fmt.Errorf("unmarshal UserError: %v", err) 633 } 634 635 if c.cfg.Verbose { 636 err := prettyPrintJSON(ue) 637 if err != nil { 638 return nil, err 639 } 640 } 641 642 return &ue, nil 643 } 644 645 // ChangeUsername changes the username of the logged in user. 646 func (c *Client) ChangeUsername(cu *www.ChangeUsername) (*www.ChangeUsernameReply, error) { 647 statusCode, respBody, err := c.makeRequest(http.MethodPost, 648 www.PoliteiaWWWAPIRoute, www.RouteChangeUsername, cu) 649 if err != nil { 650 return nil, err 651 } 652 653 if statusCode != http.StatusOK { 654 return nil, wwwError(respBody, statusCode) 655 } 656 657 var cur www.ChangeUsernameReply 658 err = json.Unmarshal(respBody, &cur) 659 if err != nil { 660 return nil, fmt.Errorf("unmarshal ChangeUsernameReply: %v", err) 661 } 662 663 if c.cfg.Verbose { 664 err := prettyPrintJSON(cur) 665 if err != nil { 666 return nil, err 667 } 668 } 669 670 return &cur, nil 671 } 672 673 // ChangePassword changes the password for the logged in user. 674 func (c *Client) ChangePassword(cp *www.ChangePassword) (*www.ChangePasswordReply, error) { 675 statusCode, respBody, err := c.makeRequest(http.MethodPost, 676 www.PoliteiaWWWAPIRoute, www.RouteChangePassword, cp) 677 if err != nil { 678 return nil, err 679 } 680 681 if statusCode != http.StatusOK { 682 return nil, wwwError(respBody, statusCode) 683 } 684 685 var cpr www.ChangePasswordReply 686 err = json.Unmarshal(respBody, &cpr) 687 if err != nil { 688 return nil, fmt.Errorf("unmarshal ChangePasswordReply: %v", err) 689 } 690 691 if c.cfg.Verbose { 692 err := prettyPrintJSON(cpr) 693 if err != nil { 694 return nil, err 695 } 696 } 697 698 return &cpr, nil 699 } 700 701 // ResetPassword resets the password of the specified user. 702 func (c *Client) ResetPassword(rp *www.ResetPassword) (*www.ResetPasswordReply, error) { 703 statusCode, respBody, err := c.makeRequest(http.MethodPost, 704 www.PoliteiaWWWAPIRoute, www.RouteResetPassword, rp) 705 if err != nil { 706 return nil, err 707 } 708 709 if statusCode != http.StatusOK { 710 return nil, wwwError(respBody, statusCode) 711 } 712 713 var rpr www.ResetPasswordReply 714 err = json.Unmarshal(respBody, &rpr) 715 if err != nil { 716 return nil, fmt.Errorf("unmarshal ResetPasswordReply: %v", err) 717 } 718 719 if c.cfg.Verbose { 720 err := prettyPrintJSON(rpr) 721 if err != nil { 722 return nil, err 723 } 724 } 725 726 return &rpr, nil 727 } 728 729 // VerifyResetPassword sends the VerifyResetPassword command to politeiawww. 730 func (c *Client) VerifyResetPassword(vrp www.VerifyResetPassword) (*www.VerifyResetPasswordReply, error) { 731 statusCode, respBody, err := c.makeRequest(http.MethodPost, 732 www.PoliteiaWWWAPIRoute, www.RouteVerifyResetPassword, vrp) 733 if err != nil { 734 return nil, err 735 } 736 737 if statusCode != http.StatusOK { 738 return nil, wwwError(respBody, statusCode) 739 } 740 741 var reply www.VerifyResetPasswordReply 742 err = json.Unmarshal(respBody, &reply) 743 if err != nil { 744 return nil, fmt.Errorf("unmarshal VerifyResetPasswordReply: %v", err) 745 } 746 747 if c.cfg.Verbose { 748 err := prettyPrintJSON(reply) 749 if err != nil { 750 return nil, err 751 } 752 } 753 754 return &reply, nil 755 } 756 757 // UserProposalPaywall retrieves proposal credit paywall information for the 758 // logged in user. 759 func (c *Client) UserProposalPaywall() (*www.UserProposalPaywallReply, error) { 760 statusCode, respBody, err := c.makeRequest(http.MethodGet, 761 www.PoliteiaWWWAPIRoute, www.RouteUserProposalPaywall, nil) 762 if err != nil { 763 return nil, err 764 } 765 766 if statusCode != http.StatusOK { 767 return nil, wwwError(respBody, statusCode) 768 } 769 770 var ppdr www.UserProposalPaywallReply 771 err = json.Unmarshal(respBody, &ppdr) 772 if err != nil { 773 return nil, fmt.Errorf("unmarshal ProposalPaywalDetailsReply: %v", err) 774 } 775 776 if c.cfg.Verbose { 777 err := prettyPrintJSON(ppdr) 778 if err != nil { 779 return nil, err 780 } 781 } 782 783 return &ppdr, nil 784 } 785 786 // NewInvoice submits the specified invoice to politeiawww for the logged in 787 // user. 788 func (c *Client) NewInvoice(ni *cms.NewInvoice) (*cms.NewInvoiceReply, error) { 789 statusCode, respBody, err := c.makeRequest(http.MethodPost, 790 cms.APIRoute, cms.RouteNewInvoice, ni) 791 if err != nil { 792 return nil, err 793 } 794 795 if statusCode != http.StatusOK { 796 return nil, wwwError(respBody, statusCode) 797 } 798 799 var nir cms.NewInvoiceReply 800 err = json.Unmarshal(respBody, &nir) 801 if err != nil { 802 return nil, fmt.Errorf("unmarshal NewInvoiceReply: %v", err) 803 } 804 805 if c.cfg.Verbose { 806 err := prettyPrintJSON(nir) 807 if err != nil { 808 return nil, err 809 } 810 } 811 812 return &nir, nil 813 } 814 815 // EditInvoice edits the specified invoice with the logged in user. 816 func (c *Client) EditInvoice(ei *cms.EditInvoice) (*cms.EditInvoiceReply, error) { 817 statusCode, respBody, err := c.makeRequest(http.MethodPost, 818 cms.APIRoute, cms.RouteEditInvoice, ei) 819 if err != nil { 820 return nil, err 821 } 822 823 if statusCode != http.StatusOK { 824 return nil, wwwError(respBody, statusCode) 825 } 826 827 var eir cms.EditInvoiceReply 828 err = json.Unmarshal(respBody, &eir) 829 if err != nil { 830 return nil, fmt.Errorf("unmarshal EditInvoiceReply: %v", err) 831 } 832 833 if c.cfg.Verbose { 834 err := prettyPrintJSON(eir) 835 if err != nil { 836 return nil, err 837 } 838 } 839 840 return &eir, nil 841 } 842 843 // ProposalDetails retrieves the specified proposal. 844 func (c *Client) ProposalDetails(token string, pd *www.ProposalsDetails) (*www.ProposalDetailsReply, error) { 845 route := "/proposals/" + token 846 statusCode, respBody, err := c.makeRequest(http.MethodGet, 847 www.PoliteiaWWWAPIRoute, route, pd) 848 if err != nil { 849 return nil, err 850 } 851 852 if statusCode != http.StatusOK { 853 return nil, wwwError(respBody, statusCode) 854 } 855 856 var pr www.ProposalDetailsReply 857 err = json.Unmarshal(respBody, &pr) 858 if err != nil { 859 return nil, fmt.Errorf("unmarshal ProposalDetailsReply: %v", err) 860 } 861 862 if c.cfg.Verbose { 863 err := prettyPrintJSON(pr) 864 if err != nil { 865 return nil, err 866 } 867 } 868 869 return &pr, nil 870 } 871 872 // UserInvoices retrieves the proposals that have been submitted by the 873 // specified user. 874 func (c *Client) UserInvoices(up *cms.UserInvoices) (*cms.UserInvoicesReply, error) { 875 statusCode, respBody, err := c.makeRequest(http.MethodGet, 876 cms.APIRoute, cms.RouteUserInvoices, up) 877 if err != nil { 878 return nil, err 879 } 880 881 if statusCode != http.StatusOK { 882 return nil, wwwError(respBody, statusCode) 883 } 884 885 var upr cms.UserInvoicesReply 886 err = json.Unmarshal(respBody, &upr) 887 if err != nil { 888 return nil, fmt.Errorf("unmarshal UserInvoicesReply: %v", err) 889 } 890 891 if c.cfg.Verbose { 892 err := prettyPrintJSON(upr) 893 if err != nil { 894 return nil, err 895 } 896 } 897 898 return &upr, nil 899 } 900 901 // ProposalBilling retrieves the billing for the requested proposal 902 func (c *Client) ProposalBilling(pb *cms.ProposalBilling) (*cms.ProposalBillingReply, error) { 903 statusCode, respBody, err := c.makeRequest(http.MethodPost, 904 cms.APIRoute, cms.RouteProposalBilling, pb) 905 if err != nil { 906 return nil, err 907 } 908 909 if statusCode != http.StatusOK { 910 return nil, wwwError(respBody, statusCode) 911 } 912 913 var pbr cms.ProposalBillingReply 914 err = json.Unmarshal(respBody, &pbr) 915 if err != nil { 916 return nil, fmt.Errorf("unmarshal ProposalBillingReply: %v", err) 917 } 918 919 if c.cfg.Verbose { 920 err := prettyPrintJSON(pbr) 921 if err != nil { 922 return nil, err 923 } 924 } 925 926 return &pbr, nil 927 } 928 929 // ProposalBillingDetails retrieves the billing for the requested proposal 930 func (c *Client) ProposalBillingDetails(pbd *cms.ProposalBillingDetails) (*cms.ProposalBillingDetailsReply, error) { 931 statusCode, respBody, err := c.makeRequest(http.MethodPost, 932 cms.APIRoute, cms.RouteProposalBillingDetails, pbd) 933 if err != nil { 934 return nil, err 935 } 936 937 if statusCode != http.StatusOK { 938 return nil, wwwError(respBody, statusCode) 939 } 940 941 var pbdr cms.ProposalBillingDetailsReply 942 err = json.Unmarshal(respBody, &pbdr) 943 if err != nil { 944 return nil, fmt.Errorf("unmarshal ProposalBillingDetailsReply: %v", err) 945 } 946 947 if c.cfg.Verbose { 948 err := prettyPrintJSON(pbdr) 949 if err != nil { 950 return nil, err 951 } 952 } 953 954 return &pbdr, nil 955 } 956 957 // ProposalBillingSummary retrieves the billing for all approved proposals. 958 func (c *Client) ProposalBillingSummary(pbd *cms.ProposalBillingSummary) (*cms.ProposalBillingSummaryReply, error) { 959 statusCode, respBody, err := c.makeRequest(http.MethodGet, 960 cms.APIRoute, cms.RouteProposalBillingSummary, pbd) 961 if err != nil { 962 return nil, err 963 } 964 965 if statusCode != http.StatusOK { 966 return nil, wwwError(respBody, statusCode) 967 } 968 969 var pbdr cms.ProposalBillingSummaryReply 970 err = json.Unmarshal(respBody, &pbdr) 971 if err != nil { 972 return nil, fmt.Errorf("unmarshal ProposalBillingSummaryReply: %v", err) 973 } 974 975 if c.cfg.Verbose { 976 err := prettyPrintJSON(pbdr) 977 if err != nil { 978 return nil, err 979 } 980 } 981 982 return &pbdr, nil 983 } 984 985 // Invoices retrieves invoices base on possible field set in the request 986 // month/year and/or status 987 func (c *Client) Invoices(ai *cms.Invoices) (*cms.InvoicesReply, error) { 988 statusCode, respBody, err := c.makeRequest(http.MethodPost, 989 cms.APIRoute, cms.RouteInvoices, ai) 990 if err != nil { 991 return nil, err 992 } 993 994 if statusCode != http.StatusOK { 995 return nil, wwwError(respBody, statusCode) 996 } 997 998 var air cms.InvoicesReply 999 err = json.Unmarshal(respBody, &air) 1000 if err != nil { 1001 return nil, fmt.Errorf("unmarshal InvoicesReply: %v", err) 1002 } 1003 1004 if c.cfg.Verbose { 1005 err := prettyPrintJSON(air) 1006 if err != nil { 1007 return nil, err 1008 } 1009 } 1010 1011 return &air, nil 1012 } 1013 1014 // GeneratePayouts generates a list of payouts for all approved invoices that 1015 // contain an address and amount for an admin to the process 1016 func (c *Client) GeneratePayouts(gp *cms.GeneratePayouts) (*cms.GeneratePayoutsReply, error) { 1017 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1018 cms.APIRoute, cms.RouteGeneratePayouts, gp) 1019 if err != nil { 1020 return nil, err 1021 } 1022 1023 if statusCode != http.StatusOK { 1024 return nil, wwwError(respBody, statusCode) 1025 } 1026 1027 var gpr cms.GeneratePayoutsReply 1028 err = json.Unmarshal(respBody, &gpr) 1029 if err != nil { 1030 return nil, fmt.Errorf("unmarshal GeneratePayoutsReply: %v", err) 1031 } 1032 1033 if c.cfg.Verbose { 1034 err := prettyPrintJSON(gpr) 1035 if err != nil { 1036 return nil, err 1037 } 1038 } 1039 1040 return &gpr, nil 1041 } 1042 1043 // PayInvoices is a temporary command that allows an administrator to set all 1044 // approved invoices to the paid status. This will be removed once the 1045 // address watching for payment is complete and working. 1046 func (c *Client) PayInvoices(pi *cms.PayInvoices) (*cms.PayInvoicesReply, error) { 1047 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1048 cms.APIRoute, cms.RoutePayInvoices, pi) 1049 if err != nil { 1050 return nil, err 1051 } 1052 1053 if statusCode != http.StatusOK { 1054 return nil, wwwError(respBody, statusCode) 1055 } 1056 1057 var pir cms.PayInvoicesReply 1058 err = json.Unmarshal(respBody, &pir) 1059 if err != nil { 1060 return nil, fmt.Errorf("unmarshal PayInvoiceReply: %v", err) 1061 } 1062 1063 return &pir, nil 1064 } 1065 1066 // BatchProposals retrieves a list of proposals 1067 func (c *Client) BatchProposals(bp *www.BatchProposals) (*www.BatchProposalsReply, error) { 1068 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1069 www.PoliteiaWWWAPIRoute, www.RouteBatchProposals, bp) 1070 if err != nil { 1071 return nil, err 1072 } 1073 1074 if statusCode != http.StatusOK { 1075 return nil, wwwError(respBody, statusCode) 1076 } 1077 1078 var bpr www.BatchProposalsReply 1079 err = json.Unmarshal(respBody, &bpr) 1080 if err != nil { 1081 return nil, fmt.Errorf("unmarshal BatchProposals: %v", err) 1082 } 1083 1084 if c.cfg.Verbose { 1085 err := prettyPrintJSON(bpr) 1086 if err != nil { 1087 return nil, err 1088 } 1089 } 1090 1091 return &bpr, nil 1092 } 1093 1094 // GetAllVetted retrieves a page of vetted proposals. 1095 func (c *Client) GetAllVetted(gav *www.GetAllVetted) (*www.GetAllVettedReply, error) { 1096 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1097 www.PoliteiaWWWAPIRoute, www.RouteAllVetted, gav) 1098 if err != nil { 1099 return nil, err 1100 } 1101 1102 if statusCode != http.StatusOK { 1103 return nil, wwwError(respBody, statusCode) 1104 } 1105 1106 var gavr www.GetAllVettedReply 1107 err = json.Unmarshal(respBody, &gavr) 1108 if err != nil { 1109 return nil, fmt.Errorf("unmarshal GetAllVettedReply: %v", err) 1110 } 1111 1112 if c.cfg.Verbose { 1113 err := prettyPrintJSON(gavr) 1114 if err != nil { 1115 return nil, err 1116 } 1117 } 1118 1119 return &gavr, nil 1120 } 1121 1122 // WWWNewComment submits a new proposal comment for the logged in user. 1123 func (c *Client) WWWNewComment(nc *www.NewComment) (*www.NewCommentReply, error) { 1124 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1125 www.PoliteiaWWWAPIRoute, www.RouteNewComment, nc) 1126 if err != nil { 1127 return nil, err 1128 } 1129 1130 if statusCode != http.StatusOK { 1131 return nil, wwwError(respBody, statusCode) 1132 } 1133 1134 var ncr www.NewCommentReply 1135 err = json.Unmarshal(respBody, &ncr) 1136 if err != nil { 1137 return nil, fmt.Errorf("unmarshal NewCommentReply: %v", err) 1138 } 1139 1140 if c.cfg.Verbose { 1141 err := prettyPrintJSON(ncr) 1142 if err != nil { 1143 return nil, err 1144 } 1145 } 1146 1147 return &ncr, nil 1148 } 1149 1150 // InvoiceComments retrieves the comments for the specified proposal. 1151 func (c *Client) InvoiceComments(token string) (*www.GetCommentsReply, error) { 1152 route := "/invoices/" + token + "/comments" 1153 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1154 cms.APIRoute, route, nil) 1155 if err != nil { 1156 return nil, err 1157 } 1158 1159 if statusCode != http.StatusOK { 1160 return nil, wwwError(respBody, statusCode) 1161 } 1162 1163 var gcr www.GetCommentsReply 1164 err = json.Unmarshal(respBody, &gcr) 1165 if err != nil { 1166 return nil, fmt.Errorf("unmarshal InvoiceCommentsReply: %v", err) 1167 } 1168 1169 if c.cfg.Verbose { 1170 err := prettyPrintJSON(gcr) 1171 if err != nil { 1172 return nil, err 1173 } 1174 } 1175 1176 return &gcr, nil 1177 } 1178 1179 // WWWCensorComment censors the specified proposal comment. 1180 func (c *Client) WWWCensorComment(cc *www.CensorComment) (*www.CensorCommentReply, error) { 1181 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1182 www.PoliteiaWWWAPIRoute, www.RouteCensorComment, cc) 1183 if err != nil { 1184 return nil, err 1185 } 1186 1187 if statusCode != http.StatusOK { 1188 return nil, wwwError(respBody, statusCode) 1189 } 1190 1191 var ccr www.CensorCommentReply 1192 err = json.Unmarshal(respBody, &ccr) 1193 if err != nil { 1194 return nil, fmt.Errorf("unmarshal CensorCommentReply: %v", err) 1195 } 1196 1197 if c.cfg.Verbose { 1198 err := prettyPrintJSON(ccr) 1199 if err != nil { 1200 return nil, err 1201 } 1202 } 1203 1204 return &ccr, nil 1205 } 1206 1207 // UserRegistrationPayment checks whether the logged in user has paid their user 1208 // registration fee. 1209 func (c *Client) UserRegistrationPayment() (*www.UserRegistrationPaymentReply, error) { 1210 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1211 www.PoliteiaWWWAPIRoute, www.RouteUserRegistrationPayment, nil) 1212 if err != nil { 1213 return nil, err 1214 } 1215 1216 if statusCode != http.StatusOK { 1217 return nil, wwwError(respBody, statusCode) 1218 } 1219 1220 var urpr www.UserRegistrationPaymentReply 1221 err = json.Unmarshal(respBody, &urpr) 1222 if err != nil { 1223 return nil, fmt.Errorf("unmarshal UserRegistrationPaymentReply: %v", 1224 err) 1225 } 1226 1227 if c.cfg.Verbose { 1228 err := prettyPrintJSON(urpr) 1229 if err != nil { 1230 return nil, err 1231 } 1232 } 1233 1234 return &urpr, nil 1235 } 1236 1237 // UserDetails retrieves the user details for the specified user. 1238 func (c *Client) UserDetails(userID string) (*www.UserDetailsReply, error) { 1239 route := "/user/" + userID 1240 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1241 www.PoliteiaWWWAPIRoute, route, nil) 1242 if err != nil { 1243 return nil, err 1244 } 1245 1246 if statusCode != http.StatusOK { 1247 return nil, wwwError(respBody, statusCode) 1248 } 1249 1250 var udr www.UserDetailsReply 1251 err = json.Unmarshal(respBody, &udr) 1252 if err != nil { 1253 return nil, fmt.Errorf("unmarshal UserDetailsReply: %v", err) 1254 } 1255 1256 if c.cfg.Verbose { 1257 err := prettyPrintJSON(udr) 1258 if err != nil { 1259 return nil, err 1260 } 1261 } 1262 1263 return &udr, nil 1264 } 1265 1266 // Users retrieves a list of users that adhere to the specified filtering 1267 // parameters. 1268 func (c *Client) Users(u *www.Users) (*www.UsersReply, error) { 1269 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1270 www.PoliteiaWWWAPIRoute, www.RouteUsers, u) 1271 if err != nil { 1272 return nil, err 1273 } 1274 1275 if statusCode != http.StatusOK { 1276 return nil, wwwError(respBody, statusCode) 1277 } 1278 1279 var ur www.UsersReply 1280 err = json.Unmarshal(respBody, &ur) 1281 if err != nil { 1282 return nil, fmt.Errorf("unmarshal UsersReply: %v", err) 1283 } 1284 1285 if c.cfg.Verbose { 1286 err := prettyPrintJSON(ur) 1287 if err != nil { 1288 return nil, err 1289 } 1290 } 1291 1292 return &ur, nil 1293 } 1294 1295 // CMSUsers retrieves a list of cms users that adhere to the specified filtering 1296 // parameters. 1297 func (c *Client) CMSUsers(cu *cms.CMSUsers) (*cms.CMSUsersReply, error) { 1298 statusCode, respBody, err := c.makeRequest(http.MethodGet, cms.APIRoute, 1299 cms.RouteCMSUsers, cu) 1300 if err != nil { 1301 return nil, err 1302 } 1303 1304 if statusCode != http.StatusOK { 1305 return nil, wwwError(respBody, statusCode) 1306 } 1307 1308 var cur cms.CMSUsersReply 1309 err = json.Unmarshal(respBody, &cur) 1310 if err != nil { 1311 return nil, fmt.Errorf("unmarshal CMSUsersReply: %v", err) 1312 } 1313 1314 if c.cfg.Verbose { 1315 err := prettyPrintJSON(cur) 1316 if err != nil { 1317 return nil, err 1318 } 1319 } 1320 1321 return &cur, nil 1322 } 1323 1324 // ManageUser allows an admin to edit certain attributes of the specified user. 1325 func (c *Client) ManageUser(mu *www.ManageUser) (*www.ManageUserReply, error) { 1326 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1327 www.PoliteiaWWWAPIRoute, www.RouteManageUser, mu) 1328 if err != nil { 1329 return nil, err 1330 } 1331 1332 if statusCode != http.StatusOK { 1333 return nil, wwwError(respBody, statusCode) 1334 } 1335 1336 var mur www.ManageUserReply 1337 err = json.Unmarshal(respBody, &mur) 1338 if err != nil { 1339 return nil, fmt.Errorf("unmarshal ManageUserReply: %v", err) 1340 } 1341 1342 if c.cfg.Verbose { 1343 err := prettyPrintJSON(mur) 1344 if err != nil { 1345 return nil, err 1346 } 1347 } 1348 1349 return &mur, nil 1350 } 1351 1352 // EditUser allows the logged in user to update their user settings. 1353 func (c *Client) EditUser(eu *www.EditUser) (*www.EditUserReply, error) { 1354 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1355 www.PoliteiaWWWAPIRoute, www.RouteEditUser, eu) 1356 if err != nil { 1357 return nil, err 1358 } 1359 1360 if statusCode != http.StatusOK { 1361 return nil, wwwError(respBody, statusCode) 1362 } 1363 1364 var eur www.EditUserReply 1365 err = json.Unmarshal(respBody, &eur) 1366 if err != nil { 1367 return nil, fmt.Errorf("unmarshal EditUserReply: %v", err) 1368 } 1369 1370 if c.cfg.Verbose { 1371 err := prettyPrintJSON(eur) 1372 if err != nil { 1373 return nil, err 1374 } 1375 } 1376 1377 return &eur, nil 1378 } 1379 1380 // VoteStatus retrieves the vote status for the specified proposal. 1381 func (c *Client) VoteStatus(token string) (*www.VoteStatusReply, error) { 1382 route := "/proposals/" + token + "/votestatus" 1383 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1384 www.PoliteiaWWWAPIRoute, route, nil) 1385 if err != nil { 1386 return nil, err 1387 } 1388 1389 if statusCode != http.StatusOK { 1390 return nil, wwwError(respBody, statusCode) 1391 } 1392 1393 var vsr www.VoteStatusReply 1394 err = json.Unmarshal(respBody, &vsr) 1395 if err != nil { 1396 return nil, fmt.Errorf("unmarshal VoteStatusReply: %v", err) 1397 } 1398 1399 if c.cfg.Verbose { 1400 err := prettyPrintJSON(vsr) 1401 if err != nil { 1402 return nil, err 1403 } 1404 } 1405 1406 return &vsr, nil 1407 } 1408 1409 // VoteResults retrieves the vote results for a proposal. 1410 func (c *Client) VoteResults(token string) (*www.VoteResultsReply, error) { 1411 route := "/proposals/" + token + "/votes" 1412 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1413 www.PoliteiaWWWAPIRoute, route, nil) 1414 if err != nil { 1415 return nil, err 1416 } 1417 if statusCode != http.StatusOK { 1418 return nil, wwwError(respBody, statusCode) 1419 } 1420 1421 var vsr www.VoteResultsReply 1422 err = json.Unmarshal(respBody, &vsr) 1423 if err != nil { 1424 return nil, fmt.Errorf("unmarshal VoteResultsReply: %v", err) 1425 } 1426 1427 if c.cfg.Verbose { 1428 err := prettyPrintJSON(vsr) 1429 if err != nil { 1430 return nil, err 1431 } 1432 } 1433 1434 return &vsr, nil 1435 } 1436 1437 // GetAllVoteStatus retreives the vote status of all public proposals. 1438 func (c *Client) GetAllVoteStatus() (*www.GetAllVoteStatusReply, error) { 1439 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1440 www.PoliteiaWWWAPIRoute, www.RouteAllVoteStatus, nil) 1441 if err != nil { 1442 return nil, err 1443 } 1444 1445 if statusCode != http.StatusOK { 1446 return nil, wwwError(respBody, statusCode) 1447 } 1448 1449 var avsr www.GetAllVoteStatusReply 1450 err = json.Unmarshal(respBody, &avsr) 1451 if err != nil { 1452 return nil, fmt.Errorf("unmarshal GetAllVoteStatusReply: %v", err) 1453 } 1454 1455 if c.cfg.Verbose { 1456 err := prettyPrintJSON(avsr) 1457 if err != nil { 1458 return nil, fmt.Errorf("prettyPrintJSON: %v", err) 1459 } 1460 } 1461 1462 return &avsr, nil 1463 } 1464 1465 // ActiveVotes retreives the vote status of all public proposals. 1466 func (c *Client) ActiveVotes() (*www.ActiveVoteReply, error) { 1467 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1468 www.PoliteiaWWWAPIRoute, www.RouteActiveVote, nil) 1469 if err != nil { 1470 return nil, err 1471 } 1472 if statusCode != http.StatusOK { 1473 return nil, wwwError(respBody, statusCode) 1474 } 1475 1476 var avr www.ActiveVoteReply 1477 err = json.Unmarshal(respBody, &avr) 1478 if err != nil { 1479 return nil, err 1480 } 1481 1482 if c.cfg.Verbose { 1483 err := prettyPrintJSON(avr) 1484 if err != nil { 1485 return nil, err 1486 } 1487 } 1488 1489 return &avr, nil 1490 } 1491 1492 // ActiveVotesDCC retreives all dccs that are currently being voted on. 1493 func (c *Client) ActiveVotesDCC() (*cms.ActiveVoteReply, error) { 1494 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1495 www.PoliteiaWWWAPIRoute, cms.RouteActiveVotesDCC, nil) 1496 if err != nil { 1497 return nil, err 1498 } 1499 1500 if statusCode != http.StatusOK { 1501 return nil, wwwError(respBody, statusCode) 1502 } 1503 1504 var avr cms.ActiveVoteReply 1505 err = json.Unmarshal(respBody, &avr) 1506 if err != nil { 1507 return nil, fmt.Errorf("unmarshal ActiveVoteDCCReply: %v", err) 1508 } 1509 1510 if c.cfg.Verbose { 1511 err := prettyPrintJSON(avr) 1512 if err != nil { 1513 return nil, err 1514 } 1515 } 1516 1517 return &avr, nil 1518 } 1519 1520 // UpdateUserKey updates the identity of the logged in user. 1521 func (c *Client) UpdateUserKey(uuk *www.UpdateUserKey) (*www.UpdateUserKeyReply, error) { 1522 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1523 www.PoliteiaWWWAPIRoute, www.RouteUpdateUserKey, &uuk) 1524 if err != nil { 1525 return nil, err 1526 } 1527 1528 if statusCode != http.StatusOK { 1529 return nil, wwwError(respBody, statusCode) 1530 } 1531 1532 var uukr www.UpdateUserKeyReply 1533 err = json.Unmarshal(respBody, &uukr) 1534 if err != nil { 1535 return nil, fmt.Errorf("unmarshal UpdateUserKeyReply: %v", err) 1536 } 1537 1538 if c.cfg.Verbose { 1539 err := prettyPrintJSON(uukr) 1540 if err != nil { 1541 return nil, err 1542 } 1543 } 1544 1545 return &uukr, nil 1546 } 1547 1548 // VerifyUpdateUserKey is used to verify a new user identity. 1549 func (c *Client) VerifyUpdateUserKey(vuuk *www.VerifyUpdateUserKey) (*www.VerifyUpdateUserKeyReply, error) { 1550 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1551 www.PoliteiaWWWAPIRoute, www.RouteVerifyUpdateUserKey, &vuuk) 1552 if err != nil { 1553 return nil, err 1554 } 1555 1556 if statusCode != http.StatusOK { 1557 return nil, wwwError(respBody, statusCode) 1558 } 1559 1560 var vuukr www.VerifyUpdateUserKeyReply 1561 err = json.Unmarshal(respBody, &vuukr) 1562 if err != nil { 1563 return nil, fmt.Errorf("unmarshal VerifyUpdateUserKeyReply: %v", err) 1564 } 1565 1566 if c.cfg.Verbose { 1567 err := prettyPrintJSON(vuukr) 1568 if err != nil { 1569 return nil, err 1570 } 1571 } 1572 1573 return &vuukr, nil 1574 } 1575 1576 // UserProposalPaywallTx retrieves payment details of any pending proposal 1577 // credit payment from the logged in user. 1578 func (c *Client) UserProposalPaywallTx() (*www.UserProposalPaywallTxReply, error) { 1579 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1580 www.PoliteiaWWWAPIRoute, www.RouteUserProposalPaywallTx, nil) 1581 if err != nil { 1582 return nil, err 1583 } 1584 1585 if statusCode != http.StatusOK { 1586 return nil, wwwError(respBody, statusCode) 1587 } 1588 1589 var upptxr www.UserProposalPaywallTxReply 1590 err = json.Unmarshal(respBody, &upptxr) 1591 if err != nil { 1592 return nil, fmt.Errorf("unmarshal ProposalPaywallPaymentReply: %v", err) 1593 } 1594 1595 if c.cfg.Verbose { 1596 err := prettyPrintJSON(upptxr) 1597 if err != nil { 1598 return nil, err 1599 } 1600 } 1601 1602 return &upptxr, nil 1603 } 1604 1605 // UserPaymentsRescan scans the specified user's paywall address and makes sure 1606 // that the user's account has been properly credited with all payments. 1607 func (c *Client) UserPaymentsRescan(upr *www.UserPaymentsRescan) (*www.UserPaymentsRescanReply, error) { 1608 statusCode, respBody, err := c.makeRequest(http.MethodPut, 1609 www.PoliteiaWWWAPIRoute, www.RouteUserPaymentsRescan, upr) 1610 if err != nil { 1611 return nil, err 1612 } 1613 1614 if statusCode != http.StatusOK { 1615 return nil, wwwError(respBody, statusCode) 1616 } 1617 1618 var uprr www.UserPaymentsRescanReply 1619 err = json.Unmarshal(respBody, &uprr) 1620 if err != nil { 1621 return nil, fmt.Errorf("unmarshal UserPaymentsRescanReply: %v", err) 1622 } 1623 1624 if c.cfg.Verbose { 1625 err := prettyPrintJSON(uprr) 1626 if err != nil { 1627 return nil, err 1628 } 1629 } 1630 1631 return &uprr, nil 1632 } 1633 1634 // UserProposalCredits retrieves the proposal credit history for the logged 1635 // in user. 1636 func (c *Client) UserProposalCredits() (*www.UserProposalCreditsReply, error) { 1637 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1638 www.PoliteiaWWWAPIRoute, www.RouteUserProposalCredits, nil) 1639 if err != nil { 1640 return nil, err 1641 } 1642 1643 if statusCode != http.StatusOK { 1644 return nil, wwwError(respBody, statusCode) 1645 } 1646 1647 var upcr www.UserProposalCreditsReply 1648 err = json.Unmarshal(respBody, &upcr) 1649 if err != nil { 1650 return nil, fmt.Errorf("unmarshal UserProposalCreditsReply: %v", err) 1651 } 1652 1653 if c.cfg.Verbose { 1654 err := prettyPrintJSON(upcr) 1655 if err != nil { 1656 return nil, err 1657 } 1658 } 1659 1660 return &upcr, nil 1661 } 1662 1663 // ResendVerification re-sends the user verification email for an unverified 1664 // user. 1665 func (c *Client) ResendVerification(rv www.ResendVerification) (*www.ResendVerificationReply, error) { 1666 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1667 www.PoliteiaWWWAPIRoute, www.RouteResendVerification, rv) 1668 if err != nil { 1669 return nil, err 1670 } 1671 1672 if statusCode != http.StatusOK { 1673 return nil, wwwError(respBody, statusCode) 1674 } 1675 1676 var rvr www.ResendVerificationReply 1677 err = json.Unmarshal(respBody, &rvr) 1678 if err != nil { 1679 return nil, fmt.Errorf("unmarshal ResendVerificationReply: %v", err) 1680 } 1681 1682 if c.cfg.Verbose { 1683 err := prettyPrintJSON(rvr) 1684 if err != nil { 1685 return nil, err 1686 } 1687 } 1688 1689 return &rvr, nil 1690 } 1691 1692 // InvoiceDetails retrieves the specified invoice. 1693 func (c *Client) InvoiceDetails(token string, id *cms.InvoiceDetails) (*cms.InvoiceDetailsReply, error) { 1694 route := "/invoices/" + token 1695 statusCode, respBody, err := c.makeRequest(http.MethodGet, cms.APIRoute, 1696 route, id) 1697 if err != nil { 1698 return nil, err 1699 } 1700 1701 if statusCode != http.StatusOK { 1702 return nil, wwwError(respBody, statusCode) 1703 } 1704 1705 var idr cms.InvoiceDetailsReply 1706 err = json.Unmarshal(respBody, &idr) 1707 if err != nil { 1708 return nil, fmt.Errorf("unmarshal InvoiceDetailsReply: %v", err) 1709 } 1710 1711 if c.cfg.Verbose { 1712 err := prettyPrintJSON(idr) 1713 if err != nil { 1714 return nil, err 1715 } 1716 } 1717 1718 return &idr, nil 1719 } 1720 1721 // SetInvoiceStatus changes the status of the specified invoice. 1722 func (c *Client) SetInvoiceStatus(sis *cms.SetInvoiceStatus) (*cms.SetInvoiceStatusReply, error) { 1723 route := "/invoices/" + sis.Token + "/status" 1724 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1725 cms.APIRoute, route, sis) 1726 if err != nil { 1727 return nil, err 1728 } 1729 1730 if statusCode != http.StatusOK { 1731 return nil, wwwError(respBody, statusCode) 1732 } 1733 1734 var sisr cms.SetInvoiceStatusReply 1735 err = json.Unmarshal(respBody, &sisr) 1736 if err != nil { 1737 return nil, fmt.Errorf("unmarshal SetInvoiceStatusReply: %v", err) 1738 } 1739 1740 if c.cfg.Verbose { 1741 err := prettyPrintJSON(sisr) 1742 if err != nil { 1743 return nil, err 1744 } 1745 } 1746 1747 return &sisr, nil 1748 } 1749 1750 // TokenInventory retrieves the censorship record tokens of all proposals in 1751 // the inventory. 1752 func (c *Client) TokenInventory() (*www.TokenInventoryReply, error) { 1753 statusCode, respBody, err := c.makeRequest(http.MethodGet, 1754 www.PoliteiaWWWAPIRoute, www.RouteTokenInventory, nil) 1755 if err != nil { 1756 return nil, err 1757 } 1758 1759 if statusCode != http.StatusOK { 1760 return nil, wwwError(respBody, statusCode) 1761 } 1762 1763 var tir www.TokenInventoryReply 1764 err = json.Unmarshal(respBody, &tir) 1765 if err != nil { 1766 return nil, fmt.Errorf("unmarshal TokenInventoryReply: %v", err) 1767 } 1768 1769 if c.cfg.Verbose { 1770 err := prettyPrintJSON(tir) 1771 if err != nil { 1772 return nil, err 1773 } 1774 } 1775 1776 return &tir, nil 1777 } 1778 1779 // InvoiceExchangeRate changes the status of the specified invoice. 1780 func (c *Client) InvoiceExchangeRate(ier *cms.InvoiceExchangeRate) (*cms.InvoiceExchangeRateReply, error) { 1781 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1782 cms.APIRoute, cms.RouteInvoiceExchangeRate, ier) 1783 if err != nil { 1784 return nil, err 1785 } 1786 1787 if statusCode != http.StatusOK { 1788 return nil, wwwError(respBody, statusCode) 1789 } 1790 1791 var ierr cms.InvoiceExchangeRateReply 1792 err = json.Unmarshal(respBody, &ierr) 1793 if err != nil { 1794 return nil, fmt.Errorf("unmarshal SetInvoiceStatusReply: %v", err) 1795 } 1796 1797 if c.cfg.Verbose { 1798 err := prettyPrintJSON(ierr) 1799 if err != nil { 1800 return nil, err 1801 } 1802 } 1803 return &ierr, nil 1804 } 1805 1806 // InvoicePayouts retrieves invoices base on possible field set in the request 1807 // month/year and/or status 1808 func (c *Client) InvoicePayouts(lip *cms.InvoicePayouts) (*cms.InvoicePayoutsReply, error) { 1809 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1810 cms.APIRoute, cms.RouteInvoicePayouts, lip) 1811 if err != nil { 1812 return nil, err 1813 } 1814 1815 if statusCode != http.StatusOK { 1816 return nil, wwwError(respBody, statusCode) 1817 } 1818 1819 var lipr cms.InvoicePayoutsReply 1820 err = json.Unmarshal(respBody, &lipr) 1821 if err != nil { 1822 return nil, fmt.Errorf("unmarshal InvoicePayouts: %v", err) 1823 } 1824 1825 if c.cfg.Verbose { 1826 err := prettyPrintJSON(lipr) 1827 if err != nil { 1828 return nil, err 1829 } 1830 } 1831 return &lipr, nil 1832 } 1833 1834 // CMSUserDetails returns the current cms user's information. 1835 func (c *Client) CMSUserDetails(userID string) (*cms.UserDetailsReply, error) { 1836 route := "/user/" + userID 1837 statusCode, respBody, err := c.makeRequest(http.MethodGet, cms.APIRoute, 1838 route, nil) 1839 if err != nil { 1840 return nil, err 1841 } 1842 1843 if statusCode != http.StatusOK { 1844 return nil, wwwError(respBody, statusCode) 1845 } 1846 1847 var uir cms.UserDetailsReply 1848 err = json.Unmarshal(respBody, &uir) 1849 if err != nil { 1850 return nil, fmt.Errorf("unmarshal CMSUserDetailsReply: %v", err) 1851 } 1852 1853 if c.cfg.Verbose { 1854 err := prettyPrintJSON(uir) 1855 if err != nil { 1856 return nil, err 1857 } 1858 } 1859 1860 return &uir, nil 1861 } 1862 1863 // CodeStats returns the given cms user's code statistics. 1864 func (c *Client) CodeStats(usc cms.UserCodeStats) (*cms.UserCodeStatsReply, error) { 1865 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1866 cms.APIRoute, cms.RouteUserCodeStats, usc) 1867 if err != nil { 1868 return nil, err 1869 } 1870 1871 if statusCode != http.StatusOK { 1872 return nil, wwwError(respBody, statusCode) 1873 } 1874 1875 var csr cms.UserCodeStatsReply 1876 err = json.Unmarshal(respBody, &csr) 1877 if err != nil { 1878 return nil, fmt.Errorf("unmarshal UserCodeStatsReply: %v", err) 1879 } 1880 1881 if c.cfg.Verbose { 1882 err := prettyPrintJSON(csr) 1883 if err != nil { 1884 return nil, err 1885 } 1886 } 1887 1888 return &csr, nil 1889 } 1890 1891 // CMSEditUser edits the current user's information. 1892 func (c *Client) CMSEditUser(uui cms.EditUser) (*cms.EditUserReply, error) { 1893 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1894 cms.APIRoute, www.RouteEditUser, uui) 1895 if err != nil { 1896 return nil, err 1897 } 1898 1899 if statusCode != http.StatusOK { 1900 return nil, wwwError(respBody, statusCode) 1901 } 1902 1903 var eur cms.EditUserReply 1904 err = json.Unmarshal(respBody, &eur) 1905 if err != nil { 1906 return nil, fmt.Errorf("unmarshal CMSEditUserReply: %v", err) 1907 } 1908 1909 if c.cfg.Verbose { 1910 err := prettyPrintJSON(eur) 1911 if err != nil { 1912 return nil, err 1913 } 1914 } 1915 1916 return &eur, nil 1917 } 1918 1919 // CMSManageUser updates the given user's information. 1920 func (c *Client) CMSManageUser(uui cms.CMSManageUser) (*cms.CMSManageUserReply, error) { 1921 statusCode, respBody, err := c.makeRequest(http.MethodPost, cms.APIRoute, 1922 cms.RouteManageCMSUser, uui) 1923 if err != nil { 1924 return nil, err 1925 } 1926 1927 if statusCode != http.StatusOK { 1928 return nil, wwwError(respBody, statusCode) 1929 } 1930 1931 var eur cms.CMSManageUserReply 1932 err = json.Unmarshal(respBody, &eur) 1933 if err != nil { 1934 return nil, fmt.Errorf("unmarshal CMSManageUserReply: %v", err) 1935 } 1936 1937 if c.cfg.Verbose { 1938 err := prettyPrintJSON(eur) 1939 if err != nil { 1940 return nil, err 1941 } 1942 } 1943 1944 return &eur, nil 1945 } 1946 1947 // NewDCC creates a new dcc proposal. 1948 func (c *Client) NewDCC(nd cms.NewDCC) (*cms.NewDCCReply, error) { 1949 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1950 cms.APIRoute, cms.RouteNewDCC, nd) 1951 if err != nil { 1952 return nil, err 1953 } 1954 1955 if statusCode != http.StatusOK { 1956 return nil, wwwError(respBody, statusCode) 1957 } 1958 1959 var ndr cms.NewDCCReply 1960 err = json.Unmarshal(respBody, &ndr) 1961 if err != nil { 1962 return nil, fmt.Errorf("unmarshal NewDCCReply: %v", err) 1963 } 1964 1965 if c.cfg.Verbose { 1966 err := prettyPrintJSON(ndr) 1967 if err != nil { 1968 return nil, err 1969 } 1970 } 1971 1972 return &ndr, nil 1973 } 1974 1975 // SupportOpposeDCC issues support for a given DCC proposal. 1976 func (c *Client) SupportOpposeDCC(sd cms.SupportOpposeDCC) (*cms.SupportOpposeDCCReply, error) { 1977 statusCode, respBody, err := c.makeRequest(http.MethodPost, 1978 cms.APIRoute, cms.RouteSupportOpposeDCC, sd) 1979 if err != nil { 1980 return nil, err 1981 } 1982 1983 if statusCode != http.StatusOK { 1984 return nil, wwwError(respBody, statusCode) 1985 } 1986 1987 var sdr cms.SupportOpposeDCCReply 1988 err = json.Unmarshal(respBody, &sdr) 1989 if err != nil { 1990 return nil, fmt.Errorf("unmarshal SupportOpposeDCCReply: %v", err) 1991 } 1992 1993 if c.cfg.Verbose { 1994 err := prettyPrintJSON(sdr) 1995 if err != nil { 1996 return nil, err 1997 } 1998 } 1999 2000 return &sdr, nil 2001 } 2002 2003 // NewDCCComment submits a new dcc comment for the logged in user. 2004 func (c *Client) NewDCCComment(nc *www.NewComment) (*www.NewCommentReply, error) { 2005 statusCode, respBody, err := c.makeRequest(http.MethodPost, 2006 cms.APIRoute, cms.RouteNewCommentDCC, nc) 2007 if err != nil { 2008 return nil, err 2009 } 2010 2011 if statusCode != http.StatusOK { 2012 return nil, wwwError(respBody, statusCode) 2013 } 2014 2015 var ncr www.NewCommentReply 2016 err = json.Unmarshal(respBody, &ncr) 2017 if err != nil { 2018 return nil, fmt.Errorf("unmarshal NewDCCCommentReply: %v", err) 2019 } 2020 2021 if c.cfg.Verbose { 2022 err := prettyPrintJSON(ncr) 2023 if err != nil { 2024 return nil, err 2025 } 2026 } 2027 2028 return &ncr, nil 2029 } 2030 2031 // DCCComments retrieves the comments for the specified proposal. 2032 func (c *Client) DCCComments(token string) (*www.GetCommentsReply, error) { 2033 route := "/dcc/" + token + "/comments" 2034 statusCode, respBody, err := c.makeRequest(http.MethodGet, cms.APIRoute, 2035 route, nil) 2036 if err != nil { 2037 return nil, err 2038 } 2039 2040 if statusCode != http.StatusOK { 2041 return nil, wwwError(respBody, statusCode) 2042 } 2043 2044 var gcr www.GetCommentsReply 2045 err = json.Unmarshal(respBody, &gcr) 2046 if err != nil { 2047 return nil, fmt.Errorf("unmarshal DCCCommentsReply: %v", err) 2048 } 2049 2050 if c.cfg.Verbose { 2051 err := prettyPrintJSON(gcr) 2052 if err != nil { 2053 return nil, err 2054 } 2055 } 2056 2057 return &gcr, nil 2058 } 2059 2060 // DCCDetails retrieves the specified dcc. 2061 func (c *Client) DCCDetails(token string) (*cms.DCCDetailsReply, error) { 2062 route := "/dcc/" + token 2063 statusCode, respBody, err := c.makeRequest(http.MethodGet, cms.APIRoute, 2064 route, nil) 2065 if err != nil { 2066 return nil, err 2067 } 2068 2069 if statusCode != http.StatusOK { 2070 return nil, wwwError(respBody, statusCode) 2071 } 2072 2073 var ddr cms.DCCDetailsReply 2074 err = json.Unmarshal(respBody, &ddr) 2075 if err != nil { 2076 return nil, fmt.Errorf("unmarshal DCCDetailsReply: %v", err) 2077 } 2078 2079 if c.cfg.Verbose { 2080 err := prettyPrintJSON(ddr) 2081 if err != nil { 2082 return nil, err 2083 } 2084 } 2085 2086 return &ddr, nil 2087 } 2088 2089 // GetDCCs retrieves invoices base on possible field set in the request 2090 // month/year and/or status 2091 func (c *Client) GetDCCs(gd *cms.GetDCCs) (*cms.GetDCCsReply, error) { 2092 statusCode, respBody, err := c.makeRequest(http.MethodPost, 2093 cms.APIRoute, cms.RouteGetDCCs, gd) 2094 if err != nil { 2095 return nil, err 2096 } 2097 2098 if statusCode != http.StatusOK { 2099 return nil, wwwError(respBody, statusCode) 2100 } 2101 2102 var gdr cms.GetDCCsReply 2103 err = json.Unmarshal(respBody, &gdr) 2104 if err != nil { 2105 return nil, fmt.Errorf("unmarshal GetDCCsReply: %v", err) 2106 } 2107 2108 if c.cfg.Verbose { 2109 err := prettyPrintJSON(gdr) 2110 if err != nil { 2111 return nil, err 2112 } 2113 } 2114 2115 return &gdr, nil 2116 } 2117 2118 // SetDCCStatus issues an status update for a given DCC proposal. 2119 func (c *Client) SetDCCStatus(sd *cms.SetDCCStatus) (*cms.SetDCCStatusReply, error) { 2120 route := "/dcc/" + sd.Token + "/status" 2121 statusCode, respBody, err := c.makeRequest(http.MethodPost, cms.APIRoute, 2122 route, sd) 2123 if err != nil { 2124 return nil, err 2125 } 2126 2127 if statusCode != http.StatusOK { 2128 return nil, wwwError(respBody, statusCode) 2129 } 2130 2131 var sdr cms.SetDCCStatusReply 2132 err = json.Unmarshal(respBody, &sdr) 2133 if err != nil { 2134 return nil, fmt.Errorf("unmarshal SetDCCStatusReply: %v", err) 2135 } 2136 2137 if c.cfg.Verbose { 2138 err := prettyPrintJSON(sdr) 2139 if err != nil { 2140 return nil, err 2141 } 2142 } 2143 2144 return &sdr, nil 2145 } 2146 2147 // UserSubContractors retrieves the subcontractors that are linked to the requesting user 2148 func (c *Client) UserSubContractors(usc *cms.UserSubContractors) (*cms.UserSubContractorsReply, error) { 2149 statusCode, respBody, err := c.makeRequest(http.MethodGet, 2150 cms.APIRoute, cms.RouteUserSubContractors, usc) 2151 if err != nil { 2152 return nil, err 2153 } 2154 2155 if statusCode != http.StatusOK { 2156 return nil, wwwError(respBody, statusCode) 2157 } 2158 2159 var uscr cms.UserSubContractorsReply 2160 err = json.Unmarshal(respBody, &uscr) 2161 if err != nil { 2162 return nil, fmt.Errorf("unmarshal UserSubContractorsReply: %v", err) 2163 } 2164 2165 if c.cfg.Verbose { 2166 err := prettyPrintJSON(uscr) 2167 if err != nil { 2168 return nil, err 2169 } 2170 } 2171 return &uscr, nil 2172 } 2173 2174 // ProposalOwner retrieves the subcontractors that are linked to the requesting user 2175 func (c *Client) ProposalOwner(po *cms.ProposalOwner) (*cms.ProposalOwnerReply, error) { 2176 statusCode, respBody, err := c.makeRequest(http.MethodGet, 2177 cms.APIRoute, cms.RouteProposalOwner, po) 2178 if err != nil { 2179 return nil, err 2180 } 2181 2182 if statusCode != http.StatusOK { 2183 return nil, wwwError(respBody, statusCode) 2184 } 2185 2186 var por cms.ProposalOwnerReply 2187 err = json.Unmarshal(respBody, &por) 2188 if err != nil { 2189 return nil, fmt.Errorf("unmarshal ProposalOwnerReply: %v", err) 2190 } 2191 2192 if c.cfg.Verbose { 2193 err := prettyPrintJSON(por) 2194 if err != nil { 2195 return nil, err 2196 } 2197 } 2198 2199 return &por, nil 2200 } 2201 2202 // CastVoteDCC issues a signed vote for a given DCC proposal. approval 2203 func (c *Client) CastVoteDCC(cv cms.CastVote) (*cms.CastVoteReply, error) { 2204 statusCode, respBody, err := c.makeRequest("POST", cms.APIRoute, 2205 cms.RouteCastVoteDCC, cv) 2206 if err != nil { 2207 return nil, err 2208 } 2209 2210 if statusCode != http.StatusOK { 2211 return nil, wwwError(respBody, statusCode) 2212 } 2213 2214 var cvr cms.CastVoteReply 2215 err = json.Unmarshal(respBody, &cvr) 2216 if err != nil { 2217 return nil, fmt.Errorf("unmarshal VoteDCCReply: %v", err) 2218 } 2219 2220 if c.cfg.Verbose { 2221 err := prettyPrintJSON(cvr) 2222 if err != nil { 2223 return nil, err 2224 } 2225 } 2226 2227 return &cvr, nil 2228 } 2229 2230 // VoteDetailsDCC returns all the needed information about a given vote for a 2231 // DCC proposal. 2232 func (c *Client) VoteDetailsDCC(cv cms.VoteDetails) (*cms.VoteDetailsReply, error) { 2233 statusCode, respBody, err := c.makeRequest("POST", cms.APIRoute, 2234 cms.RouteVoteDetailsDCC, cv) 2235 if err != nil { 2236 return nil, err 2237 } 2238 2239 if statusCode != http.StatusOK { 2240 return nil, wwwError(respBody, statusCode) 2241 } 2242 2243 var vdr cms.VoteDetailsReply 2244 err = json.Unmarshal(respBody, &vdr) 2245 if err != nil { 2246 return nil, fmt.Errorf("unmarshal VoteDCCReply: %v", err) 2247 } 2248 2249 if c.cfg.Verbose { 2250 err := prettyPrintJSON(vdr) 2251 if err != nil { 2252 return nil, err 2253 } 2254 } 2255 2256 return &vdr, nil 2257 } 2258 2259 // StartVoteDCC sends the provided StartVoteDCC to the politeiawww backend. 2260 func (c *Client) StartVoteDCC(sv cms.StartVote) (*cms.StartVoteReply, error) { 2261 statusCode, respBody, err := c.makeRequest(http.MethodPost, 2262 cms.APIRoute, cms.RouteStartVoteDCC, sv) 2263 if err != nil { 2264 return nil, err 2265 } 2266 2267 if statusCode != http.StatusOK { 2268 return nil, wwwError(respBody, statusCode) 2269 } 2270 2271 var svr cms.StartVoteReply 2272 err = json.Unmarshal(respBody, &svr) 2273 if err != nil { 2274 return nil, fmt.Errorf("unmarshal StartVoteReply: %v", err) 2275 } 2276 2277 if c.cfg.Verbose { 2278 svr.UserWeights = []string{"removed by piwww for readability"} 2279 err := prettyPrintJSON(svr) 2280 if err != nil { 2281 return nil, err 2282 } 2283 } 2284 2285 return &svr, nil 2286 } 2287 2288 // SetTOTP sets the logged in user's TOTP Key. 2289 func (c *Client) SetTOTP(st *www.SetTOTP) (*www.SetTOTPReply, error) { 2290 statusCode, respBody, err := c.makeRequest(http.MethodPost, 2291 cms.APIRoute, www.RouteSetTOTP, st) 2292 if err != nil { 2293 return nil, err 2294 } 2295 2296 if statusCode != http.StatusOK { 2297 return nil, wwwError(respBody, statusCode) 2298 } 2299 2300 var str www.SetTOTPReply 2301 err = json.Unmarshal(respBody, &str) 2302 if err != nil { 2303 return nil, fmt.Errorf("unmarshal SetTOTPReply: %v", err) 2304 } 2305 2306 if c.cfg.Verbose { 2307 err := prettyPrintJSON(str) 2308 if err != nil { 2309 return nil, err 2310 } 2311 } 2312 2313 return &str, nil 2314 } 2315 2316 // VerifyTOTP comfirms the logged in user's TOTP Key. 2317 func (c *Client) VerifyTOTP(vt *www.VerifyTOTP) (*www.VerifyTOTPReply, error) { 2318 statusCode, respBody, err := c.makeRequest(http.MethodPost, 2319 cms.APIRoute, www.RouteVerifyTOTP, vt) 2320 if err != nil { 2321 return nil, err 2322 } 2323 2324 if statusCode != http.StatusOK { 2325 return nil, wwwError(respBody, statusCode) 2326 } 2327 2328 var vtr www.VerifyTOTPReply 2329 err = json.Unmarshal(respBody, &vtr) 2330 if err != nil { 2331 return nil, fmt.Errorf("unmarshal VerifyTOTPReply: %v", err) 2332 } 2333 2334 if c.cfg.Verbose { 2335 err := prettyPrintJSON(vtr) 2336 if err != nil { 2337 return nil, err 2338 } 2339 } 2340 2341 return &vtr, nil 2342 } 2343 2344 // NewClient returns a new politeiawww client. 2345 func NewClient(cfg *Config) (*Client, error) { 2346 // Setup http client 2347 httpClient, err := util.NewHTTPClient(cfg.SkipVerify, cfg.HTTPSCert) 2348 if err != nil { 2349 return nil, err 2350 } 2351 2352 // Setup cookies 2353 jar, err := cookiejar.New(&cookiejar.Options{ 2354 PublicSuffixList: publicsuffix.List, 2355 }) 2356 if err != nil { 2357 return nil, err 2358 } 2359 u, err := url.Parse(cfg.Host) 2360 if err != nil { 2361 return nil, err 2362 } 2363 jar.SetCookies(u, cfg.Cookies) 2364 httpClient.Jar = jar 2365 2366 return &Client{ 2367 http: httpClient, 2368 cfg: cfg, 2369 }, nil 2370 }