Skip to content

Commit bc112ea

Browse files
authored
Refactor: update officers to use new huh logic (#166)
* cleanup officer delete * clean up officer get * create resuable function * use reusable function once * more simplification * use new function in announcements post * add godoc comment * update announcements put * use bytes.NewBuffer * fixup officers delete and get * rename officers.go to root.go * remove top-level menu for now * cleanup officer post * implement officer post form * fixup officer put * rm unused flags * restore auth to SendRequestAndReadResponse * change usage string * fixes * put old values in update form * use default values in officer update * fix bad route in officers get * rm default value for announnceAt * fix but in announcemnet put form * ouput to stderr * error handling fixes * add logging message * fixes after rebase * exit on unrecoverable errors in cli officer post * fix typo in comment * print non-nil json body on err * fix: CheckErr can now detect if err is nil
1 parent 1b185b1 commit bc112ea

14 files changed

Lines changed: 280 additions & 899 deletions

File tree

internal/api/handlers/announcement.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package handlers
55
import (
66
"database/sql"
77
"errors"
8-
"fmt"
98
"log"
109
"net/http"
1110

@@ -129,9 +128,9 @@ func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) {
129128
DiscordMessageID: msgID,
130129
}
131130

132-
fmt.Println("DTO ->", params, "\nDBMODEL->", dbParams)
133131
// TODO: error out if required fields aren't provided
134132
if err := h.announcementService.Create(ctx, dbParams); err != nil {
133+
log.Printf("Failed to create announcement: %v\n", err)
135134
c.JSON(http.StatusInternalServerError, gin.H{
136135
"error": "Failed to create announcement",
137136
})

internal/cli/announcements/delete.go

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ package announcements
22

33
import (
44
"fmt"
5-
"io"
65
"net/http"
6+
"os"
77

88
"github.com/spf13/cobra"
99

10+
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/client"
1011
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config"
11-
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth"
1212
"github.com/acmcsufoss/api.acmcsuf.com/utils"
1313
)
1414

@@ -31,29 +31,12 @@ func init() {
3131
func deleteAnnouncement(id string, cfg *config.Config) {
3232
deleteUrl := config.GetBaseURL(cfg).JoinPath("v1", "announcements", id)
3333

34-
// ----- Delete -----
35-
request, err := oauth.NewRequestWithAuth(http.MethodDelete, deleteUrl.String(), nil)
36-
if err != nil {
37-
fmt.Println("Error: failed to construct delete request:", err)
38-
return
34+
if body, err := client.SendRequestAndReadResponse(deleteUrl, true, http.MethodDelete, nil); err != nil {
35+
fmt.Fprintln(os.Stderr, "Error:", err)
36+
if body != nil {
37+
utils.PrettyPrintJSONErr(body)
38+
}
39+
} else {
40+
utils.PrettyPrintJSON(body)
3941
}
40-
41-
client := http.Client{}
42-
response, err := client.Do(request)
43-
if err != nil {
44-
fmt.Println("Error: failed to send delete request:", err)
45-
return
46-
}
47-
defer response.Body.Close()
48-
49-
if response.StatusCode != http.StatusOK {
50-
fmt.Println("Error: HTTP", response.Status)
51-
return
52-
}
53-
body, err := io.ReadAll(response.Body)
54-
if err != nil {
55-
fmt.Println("Error: failed to read response body:", err)
56-
return
57-
}
58-
utils.PrettyPrintJSON(body)
5942
}

internal/cli/announcements/get.go

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package announcements
22

33
import (
44
"fmt"
5-
"io"
65
"net/http"
6+
"os"
77

88
"github.com/spf13/cobra"
99

10+
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/client"
1011
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config"
1112
"github.com/acmcsufoss/api.acmcsuf.com/utils"
1213
)
@@ -29,30 +30,12 @@ func init() {
2930
func getAnnouncement(uuid string, cfg *config.Config) {
3031
getUrl := config.GetBaseURL(cfg).JoinPath("v1", "announcements", uuid)
3132

32-
// ----- Requesting Get -----
33-
client := http.Client{}
34-
req, err := http.NewRequest(http.MethodGet, getUrl.String(), nil)
35-
if err != nil {
36-
fmt.Println("error with request:", err)
37-
return
33+
if body, err := client.SendRequestAndReadResponse(getUrl, false, http.MethodGet, nil); err != nil {
34+
fmt.Fprintln(os.Stderr, "Error:", err)
35+
if body != nil {
36+
utils.PrettyPrintJSONErr(body)
37+
}
38+
} else {
39+
utils.PrettyPrintJSON(body)
3840
}
39-
40-
res, err := client.Do(req)
41-
if err != nil {
42-
fmt.Println("error getting announcements:", err)
43-
return
44-
}
45-
defer res.Body.Close()
46-
47-
if res.StatusCode != http.StatusOK {
48-
fmt.Println("Error: HTTP", res.Status)
49-
return
50-
}
51-
52-
body, err := io.ReadAll(res.Body)
53-
if err != nil {
54-
fmt.Println("Error: failed to read response body:", err)
55-
return
56-
}
57-
utils.PrettyPrintJSON(body)
5841
}

internal/cli/announcements/post.go

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
package announcements
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"fmt"
6-
"io"
77
"net/http"
8-
"strings"
8+
"os"
99

1010
"github.com/charmbracelet/huh"
1111
"github.com/spf13/cobra"
1212

13+
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/client"
1314
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config"
1415
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/forms"
15-
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth"
1616
"github.com/acmcsufoss/api.acmcsuf.com/internal/dto"
1717
"github.com/acmcsufoss/api.acmcsuf.com/utils"
1818
)
@@ -27,44 +27,28 @@ var PostAnnouncement = &cobra.Command{
2727
}
2828

2929
func postAnnouncement(cfg *config.Config) {
30-
payload, err := postForm()
31-
if err != nil {
32-
fmt.Println("Error:", err)
33-
return
34-
}
35-
36-
jsonPayload, err := json.Marshal(payload)
37-
if err != nil {
38-
fmt.Println("Error: could not marshal JSON:", err)
39-
return
40-
}
30+
postUrl := config.GetBaseURL(cfg).JoinPath("v1", "announcements")
4131

42-
postURL := config.GetBaseURL(cfg).JoinPath("v1", "announcements")
43-
client := http.Client{}
44-
req, err := oauth.NewRequestWithAuth(http.MethodPost, postURL.String(), strings.NewReader(string(jsonPayload)))
32+
payload, err := postForm()
4533
if err != nil {
46-
fmt.Println("Error: could not create request:", err)
34+
fmt.Fprintln(os.Stderr, "Error:", err)
4735
return
4836
}
49-
50-
res, err := client.Do(req)
37+
b, err := json.Marshal(payload)
5138
if err != nil {
52-
fmt.Println("Error: could not send request:", err)
39+
fmt.Fprintln(os.Stderr, "Error: could not marshal JSON:", err)
5340
return
5441
}
55-
defer res.Body.Close()
5642

57-
if res.StatusCode != http.StatusOK {
58-
fmt.Println("Error: HTTP", res.Status)
59-
return
60-
}
61-
62-
body, err := io.ReadAll(res.Body)
63-
if err != nil {
64-
fmt.Println("Error: could not read response body:", err)
65-
return
43+
if body, err := client.SendRequestAndReadResponse(postUrl, true, http.MethodPost,
44+
bytes.NewBuffer(b)); err != nil {
45+
fmt.Fprintln(os.Stderr, "Error:", err)
46+
if body != nil {
47+
utils.PrettyPrintJSONErr(body)
48+
}
49+
} else {
50+
utils.PrettyPrintJSON(body)
6651
}
67-
utils.PrettyPrintJSON(body)
6852
}
6953

7054
func postForm() (*dto.Announcement, error) {
@@ -111,5 +95,5 @@ func postForm() (*dto.Announcement, error) {
11195
payload.DiscordChannelID = &channelIDStr
11296
payload.DiscordMessageID = &messageIDStr
11397

114-
return &payload, err
98+
return &payload, nil
11599
}

internal/cli/announcements/put.go

Lines changed: 36 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import (
44
"bytes"
55
"encoding/json"
66
"fmt"
7-
"io"
87
"net/http"
8+
"os"
99

1010
"github.com/charmbracelet/huh"
1111
"github.com/spf13/cobra"
1212

13+
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/client"
1314
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config"
14-
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth"
1515
"github.com/acmcsufoss/api.acmcsuf.com/internal/dto"
1616
"github.com/acmcsufoss/api.acmcsuf.com/utils"
1717
)
@@ -32,81 +32,56 @@ func init() {
3232
}
3333

3434
func putAnnouncements(id string, cfg *config.Config) {
35-
resourceURL := config.GetBaseURL(cfg).JoinPath("v1", "announcements", id)
35+
resourceUrl := config.GetBaseURL(cfg).JoinPath("v1", "announcements", id)
3636

37-
// ----- Get the Announcement We Want to Update -----
38-
client := http.Client{}
39-
getReq, err := oauth.NewRequestWithAuth(http.MethodGet, resourceURL.String(), nil)
40-
if err != nil {
41-
fmt.Printf("Error: couldn't retrieve resource %s: %s", id, err)
42-
return
43-
}
44-
getRes, err := client.Do(getReq)
45-
if err != nil {
46-
fmt.Println("Error: failed to send request:", err)
47-
return
48-
}
49-
defer getRes.Body.Close()
50-
if getRes.StatusCode != http.StatusOK {
51-
fmt.Println("Error: HTTP", getRes.Status)
52-
return
53-
}
54-
body, err := io.ReadAll(getRes.Body)
55-
if err != nil {
56-
fmt.Println("Error: failed to read response body:", err)
37+
// ----- Get announcement we want to update -----
38+
var oldPayload dto.Announcement
39+
if body, err := client.SendRequestAndReadResponse(resourceUrl, false, http.MethodGet, nil); err != nil {
40+
fmt.Fprintln(os.Stderr, "Error:", err)
41+
if body != nil {
42+
utils.PrettyPrintJSON(body)
43+
}
5744
return
45+
} else {
46+
err = json.Unmarshal(body, &oldPayload)
47+
if err != nil {
48+
fmt.Fprintln(os.Stderr, "Error: failed to unmarshal response body:", err)
49+
return
50+
}
5851
}
5952

60-
// ----- Update found announceement -----
61-
var oldPayload dto.UpdateAnnouncement
62-
err = json.Unmarshal(body, &oldPayload)
53+
// ----- Update found announcement -----
54+
newPayload, err := putForm(&oldPayload)
6355
if err != nil {
64-
fmt.Println("Error: failed to unmarshal response body:", err)
56+
fmt.Fprintln(os.Stderr, "Error:", err)
6557
return
6658
}
67-
newPayload, err := putForm(id)
59+
b, err := json.Marshal(newPayload)
6860
if err != nil {
69-
fmt.Println("Error:", err)
61+
fmt.Fprintln(os.Stderr, "Error: failed to marshal data:", err)
7062
return
7163
}
72-
jsonPayload, err := json.Marshal(newPayload)
73-
if err != nil {
74-
fmt.Println("Error: failed to marshal data:", err)
75-
return
76-
}
77-
putRequest, err := oauth.NewRequestWithAuth(http.MethodPut, resourceURL.String(), bytes.NewBuffer(jsonPayload))
78-
if err != nil {
79-
fmt.Println("Error: failed to contruct request:", err)
80-
return
81-
}
82-
putResponse, err := client.Do(putRequest)
83-
if err != nil {
84-
fmt.Println("Error: failed to send request: ", err)
85-
return
86-
}
87-
defer putResponse.Body.Close()
8864

89-
if putResponse.StatusCode != http.StatusOK {
90-
fmt.Println("Error: HTTP", putResponse.Status)
91-
return
92-
}
93-
body, err = io.ReadAll(putResponse.Body)
94-
if err != nil {
95-
fmt.Println("Error: failed to read response body", err)
96-
return
65+
// Update remote resource with new data
66+
if body, err := client.SendRequestAndReadResponse(resourceUrl, true, http.MethodPut,
67+
bytes.NewBuffer(b)); err != nil {
68+
fmt.Fprintln(os.Stderr, "Error:", err)
69+
if body != nil {
70+
utils.PrettyPrintJSONErr(body)
71+
}
72+
} else {
73+
utils.PrettyPrintJSON(body)
9774
}
98-
utils.PrettyPrintJSON(body)
9975
}
10076

101-
// TODO: Use DTO models instaad of dbmodels
102-
func putForm(uuid string) (*dto.UpdateAnnouncement, error) {
77+
func putForm(oldPayload *dto.Announcement) (*dto.UpdateAnnouncement, error) {
10378
var payload dto.UpdateAnnouncement
10479
var err error
10580
var (
106-
visibilityStr string
107-
announceAtStr string
108-
channelIDStr string
109-
messageIDStr string
81+
visibilityStr string = oldPayload.Visibility
82+
announceAtStr string // no default for now bc its stored as a raw timestamp
83+
channelIDStr string = *oldPayload.DiscordChannelID
84+
messageIDStr string = *oldPayload.DiscordMessageID
11085
)
11186
form := huh.NewForm(
11287
huh.NewGroup(
@@ -131,8 +106,7 @@ func putForm(uuid string) (*dto.UpdateAnnouncement, error) {
131106
return nil, err
132107
}
133108

134-
payload.Uuid = uuid
135-
// HACK: These conversions won't be necessary once we start using DTO models here
109+
payload.Uuid = oldPayload.Uuid
136110
payload.Visibility = &visibilityStr
137111
if announceAtStr != "" {
138112
timestamp, err := utils.ByteSlicetoUnix([]byte(announceAtStr))
@@ -141,7 +115,6 @@ func putForm(uuid string) (*dto.UpdateAnnouncement, error) {
141115
}
142116
payload.AnnounceAt = &timestamp
143117
}
144-
145118
payload.DiscordChannelID = &channelIDStr
146119
payload.DiscordMessageID = &messageIDStr
147120

0 commit comments

Comments
 (0)