package main import ( "context" "fmt" "log" "net/http" "net/url" "os" "strings" "github.com/AnthonyHewins/gotfy" ) type authdTransport struct { underlyingTransport http.RoundTripper } func (t *authdTransport) RoundTrip(req *http.Request) (*http.Response, error) { var ntfyToken string env := os.Environ() for _, keyVal := range env { keyValArr := strings.Split(keyVal, "=") if keyValArr[0] == "NTFY_TOKEN" { ntfyToken = keyValArr[1] } } req.Header.Add("Authorization", "Bearer "+ntfyToken) return t.underlyingTransport.RoundTrip(req) } type Ntfy struct { client *gotfy.Publisher } func SetupNtfyClient() *Ntfy { host := "" env := os.Environ() for _, keyVal := range env { keyValArr := strings.Split(keyVal, "=") if keyValArr[0] == "NTFY_HOST" { host = keyValArr[1] } } if host == "" { return nil } server, err := url.Parse(host) if err != nil { log.Fatal(err) } authdHttpClient := &http.Client{Transport: &authdTransport{underlyingTransport: http.DefaultTransport}} tp, err := gotfy.NewPublisher(server, authdHttpClient) if err != nil { log.Fatal(err) } if err != nil { log.Fatal(err) } return &Ntfy{client: tp} } func buildTitle(rsvp *Rsvp) string { builder := new(strings.Builder) if rsvp.Attending { peoplePerson := "people" if rsvp.PartySize == 1 { peoplePerson = "person" } fmt.Fprintf(builder, "%d %s confirmed!", rsvp.PartySize, peoplePerson) } else { fmt.Fprintf(builder, "Someone can't make it") } return builder.String() } func buildMessage(rsvp *Rsvp) string { builder := new(strings.Builder) if rsvp.Attending { builder.WriteString("Here's who is coming 👇") for _, mem := range rsvp.PartyMembers { age := "adult" if mem.Child { age = "👶" } else { age = "🧓" } dp := "n/a" if len(mem.DietaryPreferences) > 0 { dp = mem.DietaryPreferences } fmt.Fprintf(builder, "\n- %s %s, %s", age, mem.Name, dp) } } else { for _, mem := range rsvp.PartyMembers { fmt.Fprintf(builder, "%s\n", mem.Name) } builder.WriteString("can't make it") } return builder.String() } func numberToEmoji(num int64) string { switch num { case 0: return "zero" case 1: return "one" case 2: return "two" case 3: return "three" case 4: return "four" case 5: return "five" case 6: return "six" case 7: return "seven" case 8: return "eight" case 9: return "nine" default: return "question" } } func buildTags(rsvp *Rsvp) []string { if rsvp.Attending { return []string{"white_check_mark", numberToEmoji(rsvp.PartySize)} } else { return []string{"x"} } } func BuildNtfyMessage(topic string, rsvp *Rsvp) *gotfy.Message { return &gotfy.Message{ Topic: topic, Message: buildMessage(rsvp), Title: buildTitle(rsvp), Tags: buildTags(rsvp), Priority: gotfy.Default, } } func (n *Ntfy) PublishNewRsvpNotification(rsvp *Rsvp) (string, error) { resp, err := n.client.SendMessage(context.Background(), BuildNtfyMessage("collinenlucy_nl", rsvp)) if err != nil { return "", err } return resp.ID, nil }