Switch to multipart upload of PDF to lob, move backend to using that.
This commit is contained in:
parent
2c0aa980e7
commit
dc3cce0b8a
5 changed files with 64 additions and 51 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
|
|
@ -25,12 +26,21 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *file == "" {
|
||||||
|
log.Printf("you must specify a file with -file")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
content, err := os.ReadFile(*file)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("read file: %v", err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
client := lob.NewLob(key)
|
client := lob.NewLob(key)
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
req := lob.RequestLetterCreate{
|
req := lob.RequestLetterCreate{
|
||||||
To: *to,
|
To: *to,
|
||||||
From: *from,
|
From: *from,
|
||||||
File: *file,
|
File: bytes.NewReader(content),
|
||||||
Color: *color,
|
Color: *color,
|
||||||
UseType: *use_type,
|
UseType: *use_type,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
lob/lob.go
29
lob/lob.go
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
@ -102,11 +103,11 @@ type RequestAddressCreate struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
type RequestLetterCreate struct {
|
type RequestLetterCreate struct {
|
||||||
Color bool `json:"color"`
|
Color bool
|
||||||
From string `json:"from"`
|
From string
|
||||||
File string `json:"file"`
|
File io.Reader
|
||||||
To string `json:"to"`
|
To string
|
||||||
UseType string `json:"use_type"`
|
UseType string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Lob) AddressCreate(ctx context.Context, req RequestAddressCreate) (Address, error) {
|
func (l *Lob) AddressCreate(ctx context.Context, req RequestAddressCreate) (Address, error) {
|
||||||
|
|
@ -146,10 +147,24 @@ func (l *Lob) AddressList(ctx context.Context) ([]Address, error) {
|
||||||
|
|
||||||
func (l *Lob) LetterCreate(ctx context.Context, req RequestLetterCreate) (Letter, error) {
|
func (l *Lob) LetterCreate(ctx context.Context, req RequestLetterCreate) (Letter, error) {
|
||||||
var result Letter
|
var result Letter
|
||||||
|
color_str := "false"
|
||||||
|
if req.Color {
|
||||||
|
color_str = "true"
|
||||||
|
}
|
||||||
resp, err := l.client.R().
|
resp, err := l.client.R().
|
||||||
SetBody(req).
|
SetMultipartField(
|
||||||
|
"file",
|
||||||
|
"content.pdf",
|
||||||
|
"application/pdf",
|
||||||
|
req.File,
|
||||||
|
).
|
||||||
|
SetMultipartFormData(map[string]string{
|
||||||
|
"color": color_str,
|
||||||
|
"from": req.From,
|
||||||
|
"to": req.To,
|
||||||
|
"use_type": req.UseType,
|
||||||
|
}).
|
||||||
SetContext(ctx).
|
SetContext(ctx).
|
||||||
SetContentType("application/json").
|
|
||||||
SetResult(&result).
|
SetResult(&result).
|
||||||
SetPathParam("urlBase", l.urlBaseApi).
|
SetPathParam("urlBase", l.urlBaseApi).
|
||||||
Post("https://{urlBase}/v1/letters")
|
Post("https://{urlBase}/v1/letters")
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,16 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Gleipnir-Technology/bob"
|
"github.com/Gleipnir-Technology/bob"
|
||||||
"github.com/Gleipnir-Technology/nidus-sync/config"
|
"github.com/Gleipnir-Technology/nidus-sync/config"
|
||||||
"github.com/Gleipnir-Technology/nidus-sync/db/models"
|
"github.com/Gleipnir-Technology/nidus-sync/db/models"
|
||||||
|
"github.com/Gleipnir-Technology/nidus-sync/lob"
|
||||||
"github.com/Gleipnir-Technology/nidus-sync/platform/file"
|
"github.com/Gleipnir-Technology/nidus-sync/platform/file"
|
||||||
"github.com/Gleipnir-Technology/nidus-sync/platform/pdf"
|
"github.com/Gleipnir-Technology/nidus-sync/platform/pdf"
|
||||||
"github.com/aarondl/opt/omit"
|
"github.com/aarondl/opt/omit"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
lob "github.com/lob/lob-go"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -71,7 +70,7 @@ func ComplianceSend(ctx context.Context, txn bob.Executor, row_id int32) error {
|
||||||
return fmt.Errorf("lob address for %d is null", organization.ID)
|
return fmt.Errorf("lob address for %d is null", organization.ID)
|
||||||
}
|
}
|
||||||
lob_address := organization.LobAddressID.MustGet()
|
lob_address := organization.LobAddressID.MustGet()
|
||||||
letter, err := sendMail(ctx, lob_address, compliance_req.PublicID, site, address)
|
letter, err := sendMail(ctx, lob_address, compliance_req.PublicID, site, address, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("send mail: %w", err)
|
return fmt.Errorf("send mail: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +82,7 @@ func ComplianceSend(ctx context.Context, txn bob.Executor, row_id int32) error {
|
||||||
mailer, err := models.CommsMailers.Insert(&models.CommsMailerSetter{
|
mailer, err := models.CommsMailers.Insert(&models.CommsMailerSetter{
|
||||||
AddressID: omit.From(address.ID),
|
AddressID: omit.From(address.ID),
|
||||||
Created: omit.From(time.Now()),
|
Created: omit.From(time.Now()),
|
||||||
ExternalID: omit.From(letter.Id),
|
ExternalID: omit.From(letter.ID),
|
||||||
// ID
|
// ID
|
||||||
Recipient: omit.From(site.OwnerName),
|
Recipient: omit.From(site.OwnerName),
|
||||||
UUID: omit.From(mailer_uuid),
|
UUID: omit.From(mailer_uuid),
|
||||||
|
|
@ -104,44 +103,33 @@ func ComplianceSend(ctx context.Context, txn bob.Executor, row_id int32) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendMail(ctx context.Context, org_address_id string, public_id string, site *models.Site, address *models.Address) (*lob.Letter, error) {
|
func sendMail(ctx context.Context, org_address_id string, public_id string, site *models.Site, address *models.Address, content []byte) (*lob.Letter, error) {
|
||||||
ctx_lob := context.WithValue(ctx, lob.ContextBasicAuth, lob.BasicAuth{UserName: config.LobAPIKey})
|
key := config.LobAPIKey
|
||||||
config := lob.NewConfiguration()
|
client := lob.NewLob(key)
|
||||||
client := lob.NewAPIClient(config)
|
|
||||||
|
|
||||||
from_addr, _, err := client.AddressesApi.Get(ctx_lob, org_address_id).Execute()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get from address '%s': %w", org_address_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
var to_addr = *lob.NewAddressEditable()
|
|
||||||
line1 := address.Number + " " + address.Street
|
line1 := address.Number + " " + address.Street
|
||||||
to_addr.SetAddressLine1(line1)
|
addr_req := lob.RequestAddressCreate{
|
||||||
to_addr.SetAddressLine2("")
|
AddressLine1: line1,
|
||||||
to_addr.SetAddressCity(address.Locality)
|
AddressCity: address.Locality,
|
||||||
to_addr.SetAddressState(address.Region)
|
AddressState: address.Region,
|
||||||
to_addr.SetAddressZip(address.PostalCode)
|
AddressZip: address.PostalCode,
|
||||||
to_addr.SetAddressCountry(lob.COUNTRYEXTENDED_US)
|
Name: site.OwnerName,
|
||||||
addr_desc := fmt.Sprintf("site %d - %s", site.ID, site.OwnerName)
|
|
||||||
to_addr.SetDescription(addr_desc)
|
|
||||||
to_addr.SetName(site.OwnerName)
|
|
||||||
|
|
||||||
var use_type lob.LtrUseType = lob.LTRUSETYPE_OPERATIONAL
|
|
||||||
|
|
||||||
content_path := file.MailerPath(public_id)
|
|
||||||
var ltr = lob.NewLetterEditable(true, to_addr, from_addr, content_path, *lob.NewNullableLtrUseType(&use_type))
|
|
||||||
desc := fmt.Sprintf("Compliance request %s", public_id)
|
|
||||||
ltr.SetDescription(desc)
|
|
||||||
result, resp, err := client.LettersApi.Create(ctx_lob).LetterEditable(*ltr).Execute()
|
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("read lob response")
|
|
||||||
}
|
}
|
||||||
log.Debug().Str("status", resp.Status).Bytes("body", body).Msg("response from lob")
|
addr_to, err := client.AddressCreate(ctx, addr_req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("create letter: %w", err)
|
return nil, fmt.Errorf("create to addr: %w", err)
|
||||||
}
|
}
|
||||||
log.Info().Str("id", result.Id).Msg("Created Lob letter")
|
|
||||||
return result, nil
|
req := lob.RequestLetterCreate{
|
||||||
|
To: addr_to.ID,
|
||||||
|
From: org_address_id,
|
||||||
|
File: bytes.NewReader(content),
|
||||||
|
Color: true,
|
||||||
|
UseType: "operational",
|
||||||
|
}
|
||||||
|
letter, err := client.LetterCreate(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("letter create: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &letter, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ func GeneratePDF(ctx context.Context, path string) ([]byte, error) {
|
||||||
|
|
||||||
// capture pdf
|
// capture pdf
|
||||||
var buf []byte
|
var buf []byte
|
||||||
url := fmt.Sprintf("http://%s%s", config.Bind, path)
|
url := fmt.Sprintf("https://%s%s", config.DomainNidus, path)
|
||||||
log.Info().Str("url", url).Msg("Getting with headless chrome")
|
log.Info().Str("url", url).Msg("Getting with headless chrome")
|
||||||
if err := chromedp.Run(chrome_ctx, printToPDF(url, &buf)); err != nil {
|
if err := chromedp.Run(chrome_ctx, printToPDF(url, &buf)); err != nil {
|
||||||
return nil, fmt.Errorf("print to pdf: %w", err)
|
return nil, fmt.Errorf("print to pdf: %w", err)
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,8 @@ func getMailer3(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, "empty code", http.StatusBadRequest)
|
http.Error(w, "empty code", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
path := fmt.Sprintf("/mailer/mode-3/%s/preview", code)
|
||||||
content, err := pdf.GeneratePDF(r.Context(), code)
|
content, err := pdf.GeneratePDF(r.Context(), path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, "generate pdf failure", err, http.StatusInternalServerError)
|
respondError(w, "generate pdf failure", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue