mirror of
https://github.com/lukaszraczylo/go-telegram.git
synced 2026-06-05 22:43:59 +00:00
60eb0a89b5
Two API fields carry restricted emoji-value sets that the scraper's
curly-quote regex strips during IR extraction (multi-byte boundary
issue): ReactionTypeEmoji.Emoji and sendDice.Emoji. They previously
typed as plain string with no compile-time guarantee on values.
Add hand-curated typed-string enums in api/enums.go (the manual file,
not enums.gen.go):
- DiceEmoji: 6 constants (Dice, Dart, Basketball, Football, Bowling,
SlotMachine) covering Telegram's full set for sendDice.
- ReactionEmoji: 73 constants covering the canonical reaction set
from https://core.telegram.org/bots/api#reactiontypeemoji. Names
follow Unicode CLDR short names where one exists, otherwise stable
common-English labels (e.g. ThumbsUp, Heart, Clown, ManTechnologist).
Wire the field-type override via cmd/genapi/emitter.go:
- fieldTypeOverrides map keyed "<TypeOrParamsName>.<FieldName>".
- goField/multipartFieldEntry consult the override after the enum-plan
lookup; falls through to the default goType when nothing matches.
- methods.tmpl gains goFieldP/multipartFieldEntryP helpers that pass
the params type name as override-parent (the params struct doesn't
share a Go type with the field, so the existing parent="" enum-key
convention is preserved).
Regenerated api/types.gen.go and api/methods.gen.go now type the two
fields as ReactionEmoji and DiceEmoji respectively. No other Emoji
field is affected (override is scoped per parent type). regen-from-
fixture is byte-deterministic across runs.
Add api/emoji_enums_test.go covering const wire values, reflection
checks on field types, and a marshal/unmarshal round-trip for
ReactionTypeEmoji.
97 lines
3.3 KiB
Go
97 lines
3.3 KiB
Go
package api
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/goccy/go-json"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestDiceEmoji_Constants pins the canonical six dice-emoji values so a
|
|
// regen, refactor, or accidental rename can't silently break the wire
|
|
// contract.
|
|
func TestDiceEmoji_Constants(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
got DiceEmoji
|
|
want string
|
|
}{
|
|
{"Dice", DiceEmojiDice, "🎲"},
|
|
{"Dart", DiceEmojiDart, "🎯"},
|
|
{"Basketball", DiceEmojiBasketball, "🏀"},
|
|
{"Football", DiceEmojiFootball, "⚽"},
|
|
{"Bowling", DiceEmojiBowling, "🎳"},
|
|
{"SlotMachine", DiceEmojiSlotMachine, "🎰"},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
require.Equal(t, c.want, string(c.got))
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestSendDiceParams_EmojiFieldType asserts the codegen override wired
|
|
// SendDiceParams.Emoji to the typed enum (not plain string). Reflection
|
|
// catches a regression even if the file compiles via implicit string
|
|
// conversion of an untyped literal.
|
|
func TestSendDiceParams_EmojiFieldType(t *testing.T) {
|
|
rt := reflect.TypeOf(SendDiceParams{})
|
|
f, ok := rt.FieldByName("Emoji")
|
|
require.True(t, ok, "SendDiceParams.Emoji not present")
|
|
require.Equal(t, "DiceEmoji", f.Type.Name())
|
|
}
|
|
|
|
// TestSendDiceParams_MarshalJSON exercises the marshalled wire form to
|
|
// prove the typed enum still serialises as a JSON string holding the
|
|
// raw emoji bytes — i.e. the type override doesn't accidentally
|
|
// double-encode.
|
|
func TestSendDiceParams_MarshalJSON(t *testing.T) {
|
|
p := &SendDiceParams{
|
|
ChatID: ChatIDFromInt(1),
|
|
Emoji: DiceEmojiBasketball,
|
|
}
|
|
data, err := json.Marshal(p)
|
|
require.NoError(t, err)
|
|
require.Contains(t, string(data), `"emoji":"🏀"`)
|
|
}
|
|
|
|
// TestReactionEmoji_Constants spot-checks a representative slice of the
|
|
// 73-value enum. A full enumeration would be redundant — the test is
|
|
// here to lock the wire form, not to retest the const-block.
|
|
func TestReactionEmoji_Constants(t *testing.T) {
|
|
require.Equal(t, "👍", string(ReactionEmojiThumbsUp))
|
|
require.Equal(t, "👎", string(ReactionEmojiThumbsDown))
|
|
require.Equal(t, "❤", string(ReactionEmojiHeart))
|
|
require.Equal(t, "🔥", string(ReactionEmojiFire))
|
|
require.Equal(t, "💯", string(ReactionEmojiHundredPoints))
|
|
require.Equal(t, "🤡", string(ReactionEmojiClown))
|
|
}
|
|
|
|
// TestReactionTypeEmoji_FieldType asserts the codegen override wired
|
|
// ReactionTypeEmoji.Emoji to the typed enum.
|
|
func TestReactionTypeEmoji_FieldType(t *testing.T) {
|
|
rt := reflect.TypeOf(ReactionTypeEmoji{})
|
|
f, ok := rt.FieldByName("Emoji")
|
|
require.True(t, ok, "ReactionTypeEmoji.Emoji not present")
|
|
require.Equal(t, "ReactionEmoji", f.Type.Name())
|
|
}
|
|
|
|
// TestReactionTypeEmoji_RoundTrip proves a typed-enum value survives
|
|
// JSON marshal → unmarshal cycle without losing fidelity. The
|
|
// discriminator MarshalJSON on ReactionTypeEmoji forces type="emoji",
|
|
// so we set it explicitly here for symmetry with the unmarshal path.
|
|
func TestReactionTypeEmoji_RoundTrip(t *testing.T) {
|
|
in := &ReactionTypeEmoji{
|
|
Type: ReactionTypeKindEmoji,
|
|
Emoji: ReactionEmojiThumbsUp,
|
|
}
|
|
data, err := json.Marshal(in)
|
|
require.NoError(t, err)
|
|
require.Contains(t, string(data), `"emoji":"👍"`)
|
|
|
|
var out ReactionTypeEmoji
|
|
require.NoError(t, json.Unmarshal(data, &out))
|
|
require.Equal(t, ReactionEmojiThumbsUp, out.Emoji)
|
|
}
|