feat(publish): add baijiahao and jianshu desktop adapters
Wires up Baijiahao (百家号) and Jianshu (简书) as first-class desktop publish targets, with risk-control prompts surfaced in the runtime controller and a normalized error message in publish records. Adds external-link buttons in the publish management table, an asset format conversion endpoint for cover image compatibility, and reorders publish-status display priority so failures take precedence over partial successes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "golang.org/x/image/webp"
|
||||
|
||||
"github.com/geo-platform/tenant-api/internal/bootstrap"
|
||||
)
|
||||
@@ -43,6 +48,14 @@ func (h *AssetHandler) Serve(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if converted, contentType, ok := convertPublicAssetFormat(content, c.Query("format")); ok {
|
||||
c.Header("Cache-Control", "public, max-age=31536000, immutable")
|
||||
c.Header("Content-Type", contentType)
|
||||
c.Writer.WriteHeader(http.StatusOK)
|
||||
_, _ = c.Writer.Write(converted)
|
||||
return
|
||||
}
|
||||
|
||||
contentType := http.DetectContentType(content)
|
||||
c.Header("Cache-Control", "public, max-age=31536000, immutable")
|
||||
c.Header("Content-Type", contentType)
|
||||
@@ -50,6 +63,34 @@ func (h *AssetHandler) Serve(c *gin.Context) {
|
||||
_, _ = c.Writer.Write(content)
|
||||
}
|
||||
|
||||
func convertPublicAssetFormat(content []byte, format string) ([]byte, string, bool) {
|
||||
normalized := strings.ToLower(strings.TrimSpace(format))
|
||||
if normalized == "" {
|
||||
return nil, "", false
|
||||
}
|
||||
if normalized != "png" && normalized != "jpg" && normalized != "jpeg" {
|
||||
return nil, "", false
|
||||
}
|
||||
|
||||
decoded, _, err := image.Decode(bytes.NewReader(content))
|
||||
if err != nil {
|
||||
return nil, "", false
|
||||
}
|
||||
|
||||
var output bytes.Buffer
|
||||
if normalized == "png" {
|
||||
if err := png.Encode(&output, decoded); err != nil {
|
||||
return nil, "", false
|
||||
}
|
||||
return output.Bytes(), "image/png", true
|
||||
}
|
||||
|
||||
if err := jpeg.Encode(&output, decoded, &jpeg.Options{Quality: 92}); err != nil {
|
||||
return nil, "", false
|
||||
}
|
||||
return output.Bytes(), "image/jpeg", true
|
||||
}
|
||||
|
||||
func (h *AssetHandler) signObjectKey(objectKey string) string {
|
||||
encodedKey := base64.RawURLEncoding.EncodeToString([]byte(objectKey))
|
||||
mac := hmac.New(sha256.New, []byte(h.secret))
|
||||
|
||||
Reference in New Issue
Block a user