feat: convert markdown to html

This commit is contained in:
Maas Lalani 2023-06-15 10:30:20 -04:00
parent d6f2498dbd
commit 616601a34a
No known key found for this signature in database
GPG key ID: 5A6ED5CBF1A0A000
5 changed files with 78 additions and 7 deletions

View file

@ -1,12 +1,17 @@
package main
import (
"bytes"
"os"
"strings"
tea "github.com/charmbracelet/bubbletea"
"github.com/resendlabs/resend-go"
"github.com/yuin/goldmark"
)
const TO_SEPARATOR = ","
// sendEmailSuccessMsg is the tea.Msg handled by Bubble Tea when the email has
// been sent successfully.
type sendEmailSuccessMsg struct{}
@ -26,7 +31,7 @@ func (m Model) sendEmailCmd() tea.Cmd {
}
attachments[i] = string(at)
}
err := sendEmail(m.From.Value(), m.To.Value(), m.Subject.Value(), m.Body.Value(), attachments)
err := sendEmail(strings.Split(m.To.Value(), TO_SEPARATOR), m.From.Value(), m.Subject.Value(), m.Body.Value(), attachments)
if err != nil {
return sendEmailFailureMsg(err)
}
@ -34,17 +39,24 @@ func (m Model) sendEmailCmd() tea.Cmd {
}
}
func sendEmail(from, to, subject, body string, attachments []string) error {
func sendEmail(to []string, from, subject, body string, attachments []string) error {
client := resend.NewClient(os.Getenv(RESEND_API_KEY))
var html, text = bytes.NewBufferString(""), bytes.NewBufferString("")
err := goldmark.Convert([]byte(body), html)
if err != nil {
text.WriteString(body)
}
request := &resend.SendEmailRequest{
From: from,
To: []string{to},
To: to,
Subject: subject,
Html: body,
Html: html.String(),
Text: text.String(),
}
_, err := client.Emails.Send(request)
_, err = client.Emails.Send(request)
if err != nil {
return err
}

1
go.mod
View file

@ -8,6 +8,7 @@ require (
github.com/charmbracelet/lipgloss v0.7.1
github.com/resendlabs/resend-go v1.6.0
github.com/spf13/cobra v1.7.0
github.com/yuin/goldmark v1.5.4
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
)

2
go.sum
View file

@ -48,6 +48,8 @@ github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRM
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=

50
main.go
View file

@ -2,20 +2,52 @@ package main
import (
"fmt"
"io"
"os"
tea "github.com/charmbracelet/bubbletea"
"github.com/resendlabs/resend-go"
"github.com/spf13/cobra"
)
const RESEND_API_KEY = "RESEND_API_KEY"
const RESEND_FROM = "RESEND_FROM"
var (
from string
to []string
subject string
body string
attachments []string
)
var rootCmd = &cobra.Command{
Use: "email",
Short: "email is a command line interface for sending emails.",
Long: `email is a command line interface for sending emails.`,
RunE: func(cmd *cobra.Command, args []string) error {
p := tea.NewProgram(NewModel())
if hasStdin() {
b, err := io.ReadAll(os.Stdin)
if err != nil {
return err
}
body = string(b)
}
if len(to) > 0 && from != "" && subject != "" && body != "" {
err := sendEmail(to, from, subject, body, attachments)
if err != nil {
return err
}
return nil
}
p := tea.NewProgram(NewModel(resend.SendEmailRequest{
From: from,
To: to,
Subject: subject,
Text: body,
}))
_, err := p.Run()
if err != nil {
return err
@ -24,6 +56,22 @@ var rootCmd = &cobra.Command{
},
}
// hasStdin returns whether there is data in stdin.
func hasStdin() bool {
stat, err := os.Stdin.Stat()
return err == nil && (stat.Mode()&os.ModeCharDevice) == 0
}
func init() {
rootCmd.Flags().StringSliceVar(&to, "bcc", []string{}, "Blind carbon copy recipients")
rootCmd.Flags().StringSliceVar(&to, "cc", []string{}, "Carbon copy recipients")
rootCmd.Flags().StringSliceVarP(&attachments, "attach", "a", []string{}, "Email's attachments")
rootCmd.Flags().StringSliceVarP(&to, "to", "t", []string{}, "Recipient emails")
rootCmd.Flags().StringVarP(&body, "body", "b", "", "Email's body (markdown)")
rootCmd.Flags().StringVarP(&from, "from", "f", os.Getenv(RESEND_FROM), "Email's sender ($RESEND_FROM)")
rootCmd.Flags().StringVarP(&subject, "subject", "s", "", "Email's subject")
}
func main() {
key := os.Getenv(RESEND_API_KEY)
if key == "" {

View file

@ -12,6 +12,7 @@ import (
"github.com/charmbracelet/bubbles/textarea"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/resendlabs/resend-go"
"golang.org/x/exp/constraints"
)
@ -54,7 +55,7 @@ type Model struct {
err error
}
func NewModel() Model {
func NewModel(defaults resend.SendEmailRequest) Model {
from := textinput.New()
from.Prompt = "From "
from.Placeholder = "me@example.com"
@ -63,6 +64,7 @@ func NewModel() Model {
from.TextStyle = activeTextStyle
from.Cursor.Style = cursorStyle
from.PlaceholderStyle = placeholderStyle
from.SetValue(defaults.From)
from.Focus()
to := textinput.New()
@ -70,14 +72,18 @@ func NewModel() Model {
to.PromptStyle = labelStyle.Copy()
to.Cursor.Style = cursorStyle
to.PlaceholderStyle = placeholderStyle
to.TextStyle = textStyle
to.Placeholder = "you@example.com"
to.SetValue(strings.Join(defaults.To, TO_SEPARATOR))
subject := textinput.New()
subject.Prompt = "Subject "
subject.PromptStyle = labelStyle.Copy()
subject.Cursor.Style = cursorStyle
subject.PlaceholderStyle = placeholderStyle
subject.TextStyle = textStyle
subject.Placeholder = "Hello!"
subject.SetValue(defaults.Subject)
body := textarea.New()
body.Placeholder = "# Email"
@ -91,6 +97,8 @@ func NewModel() Model {
body.BlurredStyle.Text = textStyle
body.BlurredStyle.Placeholder = placeholderStyle
body.Cursor.Style = cursorStyle
body.CharLimit = 4000
body.SetValue(defaults.Text)
body.Blur()
attachments := list.New([]list.Item{}, attachmentDelegate{}, 0, 3)