Allow selecting animated face results and preserve received results in messages and history. Keep the default selection when no result is supplied.
Fixes#487
Decode every group in the third face panel and allow IDs absent from the catalog to use the small-face wire format. Keep animation resources dependent on authoritative catalog metadata.
Fixes#482
Send available face animations by default and accept large=false for the small representation. Preserve the sticker business type when encoding animated faces.
Fixes#483
Persist and validate the shared system face catalog, refresh it once when the first account connects, and coalesce concurrent loads. Resolve outgoing face metadata from the catalog so startup races, unknown IDs, and incomplete entries fail before sending.
A face was always built as a legacy FaceElem (face.index). QQ-NT only renders
classic small faces that way; newer 'super'/animated faces sent as face.index
are silently remapped by the server (e.g. 424→168) or shown as a placeholder.
Classify each face id off QQ's own system-face catalog (0x9154_1, ported from
SLE/Lagrange) and pick the matching wire form:
- super (animated, aniSticker pack ≠ (1,1)) → CommonElem 37 + QFaceExtra
- other id ≥ 260 → CommonElem 33 + QSmallFaceExtra
- classic id < 260 → legacy FaceElem
The catalog is fetched once (shared, lazy-warmed off the first face send) and
classify falls back to an id-range guess until it lands. Data-driven so all 66
non-(1,1) super faces encode correctly, not just a hardcoded few.
Verified on a live account: 424→424 (was 168), super 392→392, classic 14→14.