79 lines
2.6 KiB
Go
79 lines
2.6 KiB
Go
package admin
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/base64"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// برخی ابزارها (مثلِ خروجیِ AI) یک PNG را داخلِ یک <svg> با base64 قرار میدهند.
|
|
// flutter_svg نمیتواند این «SVGِ رستری» را رندر کند، پس آن را به PNG واقعی تبدیل
|
|
// میکنیم.
|
|
var rasterInSVG = regexp.MustCompile(`data:image/(png|jpe?g);base64,([A-Za-z0-9+/=\s]+)`)
|
|
|
|
// extractEmbeddedRaster اگر محتوای SVG صرفاً یک تصویرِ رستریِ base64 باشد، آن را
|
|
// استخراج میکند (بایتهای خام + پسوند). برای SVGهای واقعیِ برداری false برمیگرداند.
|
|
func extractEmbeddedRaster(svg []byte) (data []byte, ext string, ok bool) {
|
|
m := rasterInSVG.FindSubmatch(svg)
|
|
if m == nil {
|
|
return nil, "", false
|
|
}
|
|
ext = "png"
|
|
if strings.HasPrefix(string(m[1]), "jp") {
|
|
ext = "jpg"
|
|
}
|
|
b64 := regexp.MustCompile(`\s`).ReplaceAll(m[2], nil)
|
|
raw, err := base64.StdEncoding.DecodeString(string(b64))
|
|
if err != nil || len(raw) == 0 {
|
|
return nil, "", false
|
|
}
|
|
return raw, ext, true
|
|
}
|
|
|
|
// convertRasterAvatars فایلهای آواتارِ svg را که در واقع رستر هستند به png/jpg
|
|
// تبدیل میکند و img_ext را در DB بهروزرسانی میکند. یکبار در startup اجرا میشود
|
|
// (idempotent). برای رفعِ آواتارهایی که قبلاً بهصورتِ «svgِ رستری» آپلود شدهاند.
|
|
func convertRasterAvatars(ctx context.Context, db *sql.DB, dir string) {
|
|
if dir == "" {
|
|
return
|
|
}
|
|
rows, err := db.QueryContext(ctx, `SELECT id FROM avatars WHERE img_ext = 'svg'`)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var ids []string
|
|
for rows.Next() {
|
|
var id string
|
|
if rows.Scan(&id) == nil {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
rows.Close()
|
|
|
|
for _, id := range ids {
|
|
svgPath := filepath.Join(dir, id+".svg")
|
|
content, err := os.ReadFile(svgPath)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
raw, ext, ok := extractEmbeddedRaster(content)
|
|
if !ok {
|
|
continue // SVGِ واقعیِ برداری — دست نزن.
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dir, id+"."+ext), raw, 0o644); err != nil {
|
|
continue
|
|
}
|
|
_ = os.Remove(svgPath)
|
|
_, _ = db.ExecContext(ctx, `UPDATE avatars SET img_ext = ? WHERE id = ?`, ext, id)
|
|
}
|
|
}
|
|
|
|
// ConvertRasterAvatars نسخهی عمومی برای فراخوانی از main در startup.
|
|
func ConvertRasterAvatars(ctx context.Context, db *sql.DB, dir string) {
|
|
convertRasterAvatars(ctx, db, dir)
|
|
}
|