* Update all import paths * Rename directory cmd/wpcomposer/ → cmd/wppackages/ * Rename import alias wpcomposergo → wppackagesgo in main.go and migrate_test.go * Makefile — binary name wpcomposer → wppackages * Update Air path * Global replace repo.wp-composer.com → repo.wp-packages.org * Global replace cdn.wp-composer.com → cdn.wp-packages.org * Global replace wp-composer.com → wp-packages.org (remaining) * Composer repo key in templates/docs: repositories.wp-composer → repositories.wp-packages * Rename columns on the existing schema * Update all Go code referencing these column names * Routes & SEO * Templates & front-end * Admin UI * Documentation * CI/CD * Config defaults * Rename role directory * Rename all systemd template files inside the role * Update contents of all .j2 templates — service names, binary paths, descriptions * Update tasks/main.yml and handlers/main.yml in the role * Update deploy/ansible/roles/app/tasks/main.yml and deploy.yml * Update deploy/ansible/group_vars/production/main.yml * Additional renames/fixes * Additional renames/fixes * Additional renames/fixes * not needed
87 lines
2.2 KiB
Go
87 lines
2.2 KiB
Go
package og
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
"github.com/aws/aws-sdk-go-v2/credentials"
|
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
|
"github.com/roots/wp-packages/internal/config"
|
|
)
|
|
|
|
// Uploader handles uploading OG images to R2 CDN or local disk.
|
|
type Uploader struct {
|
|
client *s3.Client
|
|
bucket string
|
|
publicURL string
|
|
localDir string
|
|
}
|
|
|
|
// NewUploader creates an Uploader. If R2 CDN is configured, it uploads to R2.
|
|
// Otherwise, it writes to localDir on disk.
|
|
func NewUploader(cfg config.R2Config) *Uploader {
|
|
u := &Uploader{
|
|
publicURL: cfg.CDNPublicURL,
|
|
}
|
|
|
|
if cfg.CDNBucket != "" && cfg.Endpoint != "" && cfg.AccessKeyID != "" {
|
|
u.client = s3.New(s3.Options{
|
|
Region: "auto",
|
|
Credentials: credentials.NewStaticCredentialsProvider(
|
|
cfg.AccessKeyID,
|
|
cfg.SecretAccessKey,
|
|
"",
|
|
),
|
|
BaseEndpoint: aws.String(cfg.Endpoint),
|
|
})
|
|
u.bucket = cfg.CDNBucket
|
|
} else {
|
|
u.localDir = filepath.Join("storage", "og")
|
|
}
|
|
|
|
return u
|
|
}
|
|
|
|
// Upload stores the PNG bytes at the given key (e.g. "social/plugin/akismet.png").
|
|
func (u *Uploader) Upload(ctx context.Context, key string, data []byte) error {
|
|
if u.client != nil {
|
|
_, err := u.client.PutObject(ctx, &s3.PutObjectInput{
|
|
Bucket: aws.String(u.bucket),
|
|
Key: aws.String(key),
|
|
Body: bytes.NewReader(data),
|
|
ContentType: aws.String("image/png"),
|
|
CacheControl: aws.String("public, max-age=86400"),
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("uploading %s to R2: %w", key, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Local disk fallback
|
|
path := filepath.Join(u.localDir, key)
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
return fmt.Errorf("creating directory for %s: %w", key, err)
|
|
}
|
|
if err := os.WriteFile(path, data, 0o644); err != nil {
|
|
return fmt.Errorf("writing %s: %w", key, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PublicURL returns the full public URL for an OG image key.
|
|
func (u *Uploader) PublicURL(key string) string {
|
|
if u.publicURL != "" {
|
|
return u.publicURL + "/" + key
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// IsR2 returns true if the uploader is configured for R2.
|
|
func (u *Uploader) IsR2() bool {
|
|
return u.client != nil
|
|
}
|