avatarrender

package
v1.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultCacheSize = 4096

DefaultCacheSize 是未配置时的 LRU 容量(条目数)。

注意:LRU 按**条目数**而非字节计 bound。当前所有渲染输出都是 200×200 的简单 PNG (数 KB 量级),故 4096 条目 ≈ 十几 MB,足够覆盖活跃用户集。若将来有调用方(如 #478 群头像)缓存尺寸差异很大的图,常驻内存会随 entries×单图尺寸增长,届时应改为 按字节预算的缓存或下调容量(PR#481 评审)。

View Source
const (
	// DefaultSize 是默认输出边长(与历史 generateDefaultAvatar 的 200 保持一致)。
	DefaultSize = 200
)

Variables

This section is empty.

Functions

func CacheKey added in v1.7.0

func CacheKey(parts ...string) string

CacheKey 从内容因子构造**单射**的共享缓存 key:长度分帧(<len>:<part>),保证不同 因子序列不会拼出同一个 key。所有头像端点(user/group/…)都应用本函数构造 GetOrRender 的 key,覆盖与各自 ETag 相同的因子。

注意:缓存 key **不能**用 ETag。ETag 是 32 位 CRC32 弱指纹,仅作 If-None-Match 验证符;作进程级共享缓存身份会碰撞 → 跨实体串图(且文字因子用户可控/可伪造)。

func ColorByIndex added in v1.7.0

func ColorByIndex(i int) (color.RGBA, bool)

ColorByIndex 返回色板第 i 个颜色(用户在二次弹窗显式选定的自定义色)。 i 越界时 ok=false,调用方应回退到 ColorForSeed。

func ColorForSeed

func ColorForSeed(seed string) color.RGBA

ColorForSeed 按 seed 稳定地从色板选一个背景色。seed 用 uid(不随昵称变化), 保证同一用户在任何页面颜色一致、且改名后颜色不变。

func ETag added in v1.7.0

func ETag(parts ...string) string

ETag 为服务端渲染的默认头像计算一个**弱 ETag**(W/ 前缀)。parts 应覆盖所有 决定图像内容的因子(渲染版本、seed→颜色、展示文字)——任一变化都会改变 ETag, 使共享缓存/浏览器在改名或换色后能 revalidate 拿到新图,而不是按 max-age 继续 返回旧图。这是弱验证符:指纹来自渲染输入而非响应字节,且渲染版本前缀已能在渲染 逻辑变更时使其失效;crc32 仅作轻量指纹(非安全用途)。

与 user 模块历史上的 avatarETag 行为一致;此处提升为共享实现供 group 等复用。

func GetOrRender added in v1.7.0

func GetOrRender(key string, render func() ([]byte, error)) ([]byte, error)

GetOrRender 用进程级共享缓存渲染 key 对应的头像;未设置默认缓存时直接渲染。 各端点 handler 应调用本函数,而不是各自持有 Cache。

func GroupAvatarLines added in v1.7.0

func GroupAvatarLines(text string) []string

GroupAvatarLines 决定群默认头像文字的排版行,对齐设计稿「群组头像颜色枚举」:

  • 含 CJK 等宽字符且 >= 3 字 → 两行,上少下多(floor/ceil 切分): "架构讨论"→["架构","讨论"](2+2)、"三个字"→["三","个字"](1+2);
  • 纯拉丁/窄字符,或 <= 2 字 → 单行(设计稿 abcd/efgh/开发 均单行)。

func GroupNameText added in v1.7.1

func GroupNameText(name string) string

GroupNameText derives a group's default-avatar text from its NAME: script-aware, leading 2 glyphs —— CJK(汉字/假名/谚文)前2 / 纯数字前2 / 纯拉丁等取首字母缩写 (≤2、大写) / 否则空(回退群组图标)。混排有 CJK 时只取 CJK(忽略拉丁/数字/符号)。

仅用于「群名自动取字」。用户显式设置的自定义头像文字走 GroupText(原样渲染、≤4), 不经过本规则。返回结果可能仍含本字体无字形的字符(罕见生僻字),调用方应配合 Renderable 判断,对不可渲染的结果回退到群组图标。

仅用于「改版前的存量老群(is_named=1)」的群名自动取字;新群(is_named=0)不调用本函数、 直接回退双人图标(见 modules/group writeGroupDefaultAvatar,2026-06-29 改版)。

func GroupText added in v1.7.0

func GroupText(name string) string

GroupText 规范化用户**显式设置**的自定义群头像文字:取可见字符前 4(PRD:中/英文 最多 4 字符)。空白/控制/零宽字符在计数前剔除。

注意:本函数用于「自定义 avatar_text」的清洗(写入校验 + 渲染原样),**不是**群名 自动取字 —— 后者走 GroupNameText(script 感知、前2)。返回结果可能仍含本字体无字形 的字符,调用方应配合 Renderable 判断,对不可渲染的结果回退到群组图标。

func IfNoneMatch added in v1.7.0

func IfNoneMatch(header, etag string) bool

IfNoneMatch 报告 If-None-Match 头是否匹配 etag(RFC 7232 §3.2 弱比较:忽略 W/ 前缀)。支持逗号分隔的多个验证符与通配 "*"。

func IndividualText

func IndividualText(nickname string) string

IndividualText 返回个人默认头像应显示的文字:script 感知、**后** 2 字 —— CJK(汉字/假名/谚文)取后2(混排时只取 CJK)、纯数字后2、纯拉丁等取首字母缩写 (≤2、大写)、否则空(调用方回退 ASCII 兜底)。

个人取**后**两字(区别于群名 GroupNameText 取前2):中文昵称后缀(名)更具辨识度 (张三丰→三丰、王小明→小明,同钉钉/飞书)。空白/控制/零宽字符在计数前剔除。结果可能 含本字体无字形的字符(如 emoji),调用方应配合 Renderable 判断并回退。

func PaletteSize added in v1.7.0

func PaletteSize() int

PaletteSize 返回固定色板的颜色数,供调用方校验自定义色板下标的取值范围。

func Render

func Render(opts Options) ([]byte, error)

Render 渲染一张「纯色圆 + 居中白色文字」的 PNG,返回编码后的字节。圆外**透明** (png.Encode 输出带 alpha 通道的 RGBA PNG),客户端在任意背景上合成时圆外不出白方块。 文字颜色固定为白色(与设计稿一致,不做对比度切换)。

func RenderGroup added in v1.7.0

func RenderGroup(text string, style GroupStyle, size int) ([]byte, error)

RenderGroup 渲染群默认头像「浅底描边圆 + 居中主题色文字」,圆外**透明**(输出带 alpha 通道的 RGBA PNG,客户端在任意背景上合成时圆外不出白方块),文字按 GroupAvatarLines 决定单行或两行(2×2)。个人头像继续走 Render(单行实心圆),本函数仅供群头像使用, 故可独立调整视觉而不影响个人头像。

func RenderIcon added in v1.7.0

func RenderIcon(style GroupStyle) ([]byte, error)

RenderIcon 渲染「浅底描边圆 + 双色群组图标」的 PNG,圆外**透明**,用于群名为空或 无法取字时的兜底。style 来自群头像专用色板,不影响个人头像 Render。

func Renderable

func Renderable(s string) bool

Renderable 报告 s 非空且其中每个字符在内嵌字体里都有字形(非 .notdef)。 截出的昵称文字若含本字体无字形的字符(典型是 emoji),渲染会出豆腐块, 调用方应据此回退到其它兜底图。sfnt.Buffer 为局部变量,本函数并发安全。

func SetDefaultCache added in v1.7.0

func SetDefaultCache(c *Cache)

SetDefaultCache 设置进程级共享头像缓存(组合根在启动时调用一次)。

func VisibleRuneCount added in v1.7.0

func VisibleRuneCount(s string) int

VisibleRuneCount 返回 s 去除不可见字符后的可见 rune 数,供调用方校验自定义头像 文字长度(PRD:最多 4 个中文/英文字符)。

Types

type Cache added in v1.7.0

type Cache struct {
	// contains filtered or unexported fields
}

Cache 是带 singleflight 与渲染信号量的头像 bytes 缓存。零值不可用,须经 NewCache 构造; 方法对 nil 接收者安全(直接渲染,无缓存),便于在未配置缓存时退化。

func DefaultCache added in v1.7.0

func DefaultCache() *Cache

DefaultCache 返回当前进程级共享缓存(未设置时为 nil)。

func NewCache added in v1.7.0

func NewCache(cfg Config) (*Cache, error)

NewCache 构造一个 Cache。

func (*Cache) GetOrRender added in v1.7.0

func (c *Cache) GetOrRender(key string, render func() ([]byte, error)) ([]byte, error)

GetOrRender 返回 key 对应的头像字节:命中 LRU 直接返回;否则经 singleflight 合并、 在渲染信号量约束下调用 render 生成一次,成功后写入 LRU。render 必须是确定性的 (相同 key → 相同字节),否则缓存会返回过期内容。

nil 接收者时直接调用 render(无缓存/合并/限流),用于缓存未配置的退化路径。

func (*Cache) Len added in v1.7.0

func (c *Cache) Len() int

Len 返回当前缓存的条目数(测试/诊断用)。nil 接收者返回 0。

type Config added in v1.7.0

type Config struct {
	// Size 是 LRU 最大条目数;<=0 用 DefaultCacheSize。
	Size int
	// MaxConcurrentRenders 是同时进行的真实渲染数上限(信号量容量);<=0 表示不限。
	// 取值应 < GOMAXPROCS,给非头像流量留核;配合缓存后,渲染只在冷 key 时发生,
	// 串行化冷渲染的代价是一次性的(之后命中缓存),换来洪峰下不饿死其它请求。
	MaxConcurrentRenders int
	// Hooks 是可观测性回调。
	Hooks Hooks
}

Config 配置 Cache。

func ConfigFromEnv added in v1.7.0

func ConfigFromEnv() Config

ConfigFromEnv 从环境变量读取共享缓存配置(不含 Hooks —— 观测点由组合根注入, 以免本包依赖 pkg/metrics):

  • DM_AVATAR_CACHE_SIZE: LRU 条目数,缺省/非法用 DefaultCacheSize;
  • DM_AVATAR_RENDER_MAX_CONCURRENCY: 最大并发真实渲染数,缺省 max(1, GOMAXPROCS-1)。

type GroupColorHex added in v1.8.0

type GroupColorHex struct {
	Index    int    // 色板下标 [0,PaletteSize),与 avatar_color 取值一致
	Main     string // 主题主色:圆描边 + 文字 + 图标前景人
	Fill     string // 圆填充浅色
	IconBack string // 图标兜底(双人剪影)后景人浅色
}

GroupColorHex 是一档群头像配色的十六进制(#RRGGBB)形式,供**客户端本地渲染** (如「修改头像」实时预览、色圈选择)使用:客户端用 Index 选色、用 Main/Fill/IconBack 复刻服务端 PNG 的视觉(主色描边/文字、浅底圆、图标后景人),保证预览与建群/改群后 服务端渲染出的真图一致。

func PaletteHex added in v1.8.0

func PaletteHex() []GroupColorHex

PaletteHex 返回整套群头像色板的十六进制形式(按下标 0..PaletteSize 顺序),作为 色板的**唯一数据源**对客户端暴露——前端不再硬编码色值,避免与服务端 palette.go 漂移。

type GroupStyle added in v1.7.0

type GroupStyle struct {
	Main     color.RGBA
	Fill     color.RGBA
	IconBack color.RGBA
}

GroupStyle 是群默认头像的一套配色:Main 为主题主色(圆描边 + 文字 + 图标前景人), Fill 为圆填充浅色,IconBack 为图标后景人浅色。三者来自设计稿同一色组。

func GroupStyleByIndex added in v1.7.0

func GroupStyleByIndex(i int) (GroupStyle, bool)

GroupStyleByIndex 返回群主在二次弹窗显式选定的自定义色组。i 越界时 ok=false, 调用方应回退到 GroupStyleForSeed。取值范围与 ColorByIndex/PaletteSize 一致。

func GroupStyleForSeed added in v1.7.0

func GroupStyleForSeed(seed string) GroupStyle

GroupStyleForSeed 按 seed(群号)稳定地解出一套群头像配色。下标算法与 ColorForSeed **完全一致**(crc32 % len(palette)),故 Main 等于历史 ColorForSeed(seed) —— 保证 「改名不变色」「与旧派生色一致」,已合成/历史群切到新风格后主色不跳变。

type Hooks added in v1.7.0

type Hooks struct {
	// OnHit / OnMiss:LRU 命中 / 未命中各记一次。
	OnHit  func()
	OnMiss func()
	// OnShared:本次渲染结果被并发调用方复用(singleflight 合并),记一次。
	OnShared func()
	// OnRender:一次真实渲染完成,带耗时与错误(用于渲染延迟直方图)。
	OnRender func(dur time.Duration, err error)
	// OnSemaphoreWait:获取渲染信号量的等待耗时(>0 说明渲染并发已饱和、在排队)。
	OnSemaphoreWait func(dur time.Duration)
	// OnInflight:正在进行的渲染数变化(+1 开始 / -1 结束),用于 inflight gauge。
	OnInflight func(delta float64)
}

Hooks 是可观测性回调,全部可选(nil 即 no-op)。刻意用函数字段而非接口,使本包 不依赖 pkg/metrics —— 由上层(modules/user)在构造时把 prometheus 观测点接进来。

type Options

type Options struct {
	// Text 是已截好的展示文字(如昵称后两字)。为空时返回错误,由调用方兜底。
	Text string
	// Bg 是背景圆颜色。
	Bg color.RGBA
	// Size 是输出 PNG 的边长(像素);<=0 时用 DefaultSize。
	Size int
}

Options 描述一次头像渲染。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL