Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
cf350a8
cleanup officer delete
TheJolman Feb 28, 2026
e718a41
clean up officer get
TheJolman Feb 28, 2026
fdeef71
create resuable function
TheJolman Feb 28, 2026
2b9d53f
use reusable function once
TheJolman Feb 28, 2026
d3fe15e
more simplification
TheJolman Feb 28, 2026
a4f423c
use new function in announcements post
TheJolman Feb 28, 2026
811167e
add godoc comment
TheJolman Feb 28, 2026
78b59d8
update announcements put
TheJolman Feb 28, 2026
42e2830
use bytes.NewBuffer
TheJolman Feb 28, 2026
90c671b
fixup officers delete and get
TheJolman Feb 28, 2026
0d4bc93
rename officers.go to root.go
TheJolman Feb 28, 2026
4c0fdd1
remove top-level menu for now
TheJolman Feb 28, 2026
afe9e10
cleanup officer post
TheJolman Feb 28, 2026
6da3afc
implement officer post form
TheJolman Feb 28, 2026
c7efaa3
fixup officer put
TheJolman Feb 28, 2026
8917fe2
rm unused flags
TheJolman Feb 28, 2026
b1a12b6
restore auth to SendRequestAndReadResponse
TheJolman Feb 28, 2026
273f77f
change usage string
TheJolman Feb 28, 2026
3acf2c5
fixes
TheJolman Feb 28, 2026
6bf04fb
put old values in update form
TheJolman Feb 28, 2026
9b0bb7e
use default values in officer update
TheJolman Feb 28, 2026
e8fb875
fix bad route in officers get
TheJolman Feb 28, 2026
6ec4b51
rm default value for announnceAt
TheJolman Feb 28, 2026
636115b
fix but in announcemnet put form
TheJolman Feb 28, 2026
d7f5e59
ouput to stderr
TheJolman Mar 1, 2026
443e24b
error handling fixes
TheJolman Mar 1, 2026
72f0412
add logging message
TheJolman Mar 1, 2026
25a1c69
fixes after rebase
TheJolman Mar 7, 2026
65945a3
exit on unrecoverable errors in cli officer post
TheJolman Mar 9, 2026
938405e
fix typo in comment
TheJolman Mar 9, 2026
e70d892
print non-nil json body on err
TheJolman Mar 9, 2026
df98c02
fix: CheckErr can now detect if err is nil
TheJolman Mar 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions internal/api/handlers/announcement.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package handlers
import (
"database/sql"
"errors"
"fmt"
"log"
"net/http"

Expand Down Expand Up @@ -129,9 +128,9 @@ func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) {
DiscordMessageID: msgID,
}

fmt.Println("DTO ->", params, "\nDBMODEL->", dbParams)
// TODO: error out if required fields aren't provided
if err := h.announcementService.Create(ctx, dbParams); err != nil {
log.Printf("Failed to create announcement: %v\n", err)
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to create announcement",
})
Expand Down
35 changes: 9 additions & 26 deletions internal/cli/announcements/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package announcements

import (
"fmt"
"io"
"net/http"
"os"

"github.com/spf13/cobra"

"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/client"
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config"
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth"
"github.com/acmcsufoss/api.acmcsuf.com/utils"
)

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

// ----- Delete -----
request, err := oauth.NewRequestWithAuth(http.MethodDelete, deleteUrl.String(), nil)
if err != nil {
fmt.Println("Error: failed to construct delete request:", err)
return
if body, err := client.SendRequestAndReadResponse(deleteUrl, true, http.MethodDelete, nil); err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
if body != nil {
utils.PrettyPrintJSONErr(body)
}
} else {
utils.PrettyPrintJSON(body)
}

client := http.Client{}
response, err := client.Do(request)
if err != nil {
fmt.Println("Error: failed to send delete request:", err)
return
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK {
fmt.Println("Error: HTTP", response.Status)
return
}
body, err := io.ReadAll(response.Body)
if err != nil {
fmt.Println("Error: failed to read response body:", err)
return
}
utils.PrettyPrintJSON(body)
}
35 changes: 9 additions & 26 deletions internal/cli/announcements/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package announcements

import (
"fmt"
"io"
"net/http"
"os"

"github.com/spf13/cobra"

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

// ----- Requesting Get -----
client := http.Client{}
req, err := http.NewRequest(http.MethodGet, getUrl.String(), nil)
if err != nil {
fmt.Println("error with request:", err)
return
if body, err := client.SendRequestAndReadResponse(getUrl, false, http.MethodGet, nil); err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
if body != nil {
utils.PrettyPrintJSONErr(body)
}
} else {
utils.PrettyPrintJSON(body)
}

res, err := client.Do(req)
if err != nil {
fmt.Println("error getting announcements:", err)
return
}
defer res.Body.Close()

if res.StatusCode != http.StatusOK {
fmt.Println("Error: HTTP", res.Status)
return
}

body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println("Error: failed to read response body:", err)
return
}
utils.PrettyPrintJSON(body)
}
50 changes: 17 additions & 33 deletions internal/cli/announcements/post.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package announcements

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"os"

"github.com/charmbracelet/huh"
"github.com/spf13/cobra"

"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/client"
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config"
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/forms"
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth"
"github.com/acmcsufoss/api.acmcsuf.com/internal/dto"
"github.com/acmcsufoss/api.acmcsuf.com/utils"
)
Expand All @@ -27,44 +27,28 @@ var PostAnnouncement = &cobra.Command{
}

func postAnnouncement(cfg *config.Config) {
payload, err := postForm()
if err != nil {
fmt.Println("Error:", err)
return
}

jsonPayload, err := json.Marshal(payload)
if err != nil {
fmt.Println("Error: could not marshal JSON:", err)
return
}
postUrl := config.GetBaseURL(cfg).JoinPath("v1", "announcements")

postURL := config.GetBaseURL(cfg).JoinPath("v1", "announcements")
client := http.Client{}
req, err := oauth.NewRequestWithAuth(http.MethodPost, postURL.String(), strings.NewReader(string(jsonPayload)))
payload, err := postForm()
if err != nil {
fmt.Println("Error: could not create request:", err)
fmt.Fprintln(os.Stderr, "Error:", err)
return
}

res, err := client.Do(req)
b, err := json.Marshal(payload)
if err != nil {
fmt.Println("Error: could not send request:", err)
fmt.Fprintln(os.Stderr, "Error: could not marshal JSON:", err)
return
}
defer res.Body.Close()

if res.StatusCode != http.StatusOK {
fmt.Println("Error: HTTP", res.Status)
return
}

body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println("Error: could not read response body:", err)
return
if body, err := client.SendRequestAndReadResponse(postUrl, true, http.MethodPost,
bytes.NewBuffer(b)); err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
if body != nil {
utils.PrettyPrintJSONErr(body)
}
} else {
utils.PrettyPrintJSON(body)
}
utils.PrettyPrintJSON(body)
}

func postForm() (*dto.Announcement, error) {
Expand Down Expand Up @@ -111,5 +95,5 @@ func postForm() (*dto.Announcement, error) {
payload.DiscordChannelID = &channelIDStr
payload.DiscordMessageID = &messageIDStr

return &payload, err
return &payload, nil
}
99 changes: 36 additions & 63 deletions internal/cli/announcements/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"

"github.com/charmbracelet/huh"
"github.com/spf13/cobra"

"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/client"
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config"
"github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth"
"github.com/acmcsufoss/api.acmcsuf.com/internal/dto"
"github.com/acmcsufoss/api.acmcsuf.com/utils"
)
Expand All @@ -32,81 +32,56 @@ func init() {
}

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

// ----- Get the Announcement We Want to Update -----
client := http.Client{}
getReq, err := oauth.NewRequestWithAuth(http.MethodGet, resourceURL.String(), nil)
if err != nil {
fmt.Printf("Error: couldn't retrieve resource %s: %s", id, err)
return
}
getRes, err := client.Do(getReq)
if err != nil {
fmt.Println("Error: failed to send request:", err)
return
}
defer getRes.Body.Close()
if getRes.StatusCode != http.StatusOK {
fmt.Println("Error: HTTP", getRes.Status)
return
}
body, err := io.ReadAll(getRes.Body)
if err != nil {
fmt.Println("Error: failed to read response body:", err)
// ----- Get announcement we want to update -----
var oldPayload dto.Announcement
if body, err := client.SendRequestAndReadResponse(resourceUrl, false, http.MethodGet, nil); err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
if body != nil {
utils.PrettyPrintJSON(body)
}
return
} else {
err = json.Unmarshal(body, &oldPayload)
if err != nil {
fmt.Fprintln(os.Stderr, "Error: failed to unmarshal response body:", err)
return
}
}

// ----- Update found announceement -----
var oldPayload dto.UpdateAnnouncement
err = json.Unmarshal(body, &oldPayload)
// ----- Update found announcement -----
newPayload, err := putForm(&oldPayload)
if err != nil {
fmt.Println("Error: failed to unmarshal response body:", err)
fmt.Fprintln(os.Stderr, "Error:", err)
return
}
newPayload, err := putForm(id)
b, err := json.Marshal(newPayload)
if err != nil {
fmt.Println("Error:", err)
fmt.Fprintln(os.Stderr, "Error: failed to marshal data:", err)
return
}
jsonPayload, err := json.Marshal(newPayload)
if err != nil {
fmt.Println("Error: failed to marshal data:", err)
return
}
putRequest, err := oauth.NewRequestWithAuth(http.MethodPut, resourceURL.String(), bytes.NewBuffer(jsonPayload))
if err != nil {
fmt.Println("Error: failed to contruct request:", err)
return
}
putResponse, err := client.Do(putRequest)
if err != nil {
fmt.Println("Error: failed to send request: ", err)
return
}
defer putResponse.Body.Close()

if putResponse.StatusCode != http.StatusOK {
fmt.Println("Error: HTTP", putResponse.Status)
return
}
body, err = io.ReadAll(putResponse.Body)
if err != nil {
fmt.Println("Error: failed to read response body", err)
return
// Update remote resource with new data
if body, err := client.SendRequestAndReadResponse(resourceUrl, true, http.MethodPut,
bytes.NewBuffer(b)); err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
if body != nil {
utils.PrettyPrintJSONErr(body)
}
} else {
utils.PrettyPrintJSON(body)
}
utils.PrettyPrintJSON(body)
}

// TODO: Use DTO models instaad of dbmodels
func putForm(uuid string) (*dto.UpdateAnnouncement, error) {
func putForm(oldPayload *dto.Announcement) (*dto.UpdateAnnouncement, error) {
var payload dto.UpdateAnnouncement
var err error
var (
visibilityStr string
announceAtStr string
channelIDStr string
messageIDStr string
visibilityStr string = oldPayload.Visibility
announceAtStr string // no default for now bc its stored as a raw timestamp
channelIDStr string = *oldPayload.DiscordChannelID
messageIDStr string = *oldPayload.DiscordMessageID
)
form := huh.NewForm(
huh.NewGroup(
Expand All @@ -131,8 +106,7 @@ func putForm(uuid string) (*dto.UpdateAnnouncement, error) {
return nil, err
}

payload.Uuid = uuid
// HACK: These conversions won't be necessary once we start using DTO models here
payload.Uuid = oldPayload.Uuid
payload.Visibility = &visibilityStr
if announceAtStr != "" {
timestamp, err := utils.ByteSlicetoUnix([]byte(announceAtStr))
Expand All @@ -141,7 +115,6 @@ func putForm(uuid string) (*dto.UpdateAnnouncement, error) {
}
payload.AnnounceAt = &timestamp
}

payload.DiscordChannelID = &channelIDStr
payload.DiscordMessageID = &messageIDStr

Expand Down
Loading