From 60eb0a89b5903527e247ed482a8385102160f32b Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Sat, 9 May 2026 20:47:16 +0100 Subject: [PATCH] refactor(api): typed enums for emoji-list fields (DiceEmoji, ReactionEmoji) 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 ".". - 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. --- api/emoji_enums_test.go | 96 +++++++++++++++++++++++++++++++++ api/enums.go | 104 +++++++++++++++++++++++++++++++++++ api/methods.gen.go | 2 +- api/types.gen.go | 2 +- cmd/genapi/emitter.go | 60 +++++++++++++++++++-- cmd/genapi/methods.tmpl | 6 +-- docs/reference/api.md | 117 +++++++++++++++++++++++++++++++++++++++- 7 files changed, 377 insertions(+), 10 deletions(-) create mode 100644 api/emoji_enums_test.go diff --git a/api/emoji_enums_test.go b/api/emoji_enums_test.go new file mode 100644 index 0000000..476c7ff --- /dev/null +++ b/api/emoji_enums_test.go @@ -0,0 +1,96 @@ +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) +} diff --git a/api/enums.go b/api/enums.go index a247cdb..003e32c 100644 --- a/api/enums.go +++ b/api/enums.go @@ -32,3 +32,107 @@ const ( UpdateChatBoost UpdateType = "chat_boost" UpdateRemovedChatBoost UpdateType = "removed_chat_boost" ) + +// DiceEmoji is the set of emoji values accepted by sendDice. Telegram's +// canonical list is "๐ŸŽฒ", "๐ŸŽฏ", "๐Ÿ€", "โšฝ", "๐ŸŽณ", "๐ŸŽฐ". The codegen +// scraper drops these values during regex extraction (multi-byte +// boundary issues with curly-quoted emoji), so this enum is hand- +// curated and wired into SendDiceParams.Emoji via the per-field type +// override in cmd/genapi/emitter.go. +type DiceEmoji string + +const ( + DiceEmojiDice DiceEmoji = "๐ŸŽฒ" + DiceEmojiDart DiceEmoji = "๐ŸŽฏ" + DiceEmojiBasketball DiceEmoji = "๐Ÿ€" + DiceEmojiFootball DiceEmoji = "โšฝ" + DiceEmojiBowling DiceEmoji = "๐ŸŽณ" + DiceEmojiSlotMachine DiceEmoji = "๐ŸŽฐ" +) + +// ReactionEmoji is the set of emoji Telegram allows in a +// ReactionTypeEmoji.Emoji value. Hand-curated from +// https://core.telegram.org/bots/api#reactiontypeemoji because the +// scraper's curly-quote regex strips the emoji literals (byte-boundary +// issue on multi-byte sequences). Names mirror the Unicode CLDR short +// name where one exists; otherwise a stable common-English label. +// Telegram occasionally extends this set โ€” passers of unrecognised +// strings still type-check (ReactionEmoji is a string alias) so this +// list need not block runtime use of newer values. +type ReactionEmoji string + +const ( + ReactionEmojiHeart ReactionEmoji = "โค" + ReactionEmojiThumbsUp ReactionEmoji = "๐Ÿ‘" + ReactionEmojiThumbsDown ReactionEmoji = "๐Ÿ‘Ž" + ReactionEmojiFire ReactionEmoji = "๐Ÿ”ฅ" + ReactionEmojiSmilingFaceWithHearts ReactionEmoji = "๐Ÿฅฐ" + ReactionEmojiClappingHands ReactionEmoji = "๐Ÿ‘" + ReactionEmojiBeamingFace ReactionEmoji = "๐Ÿ˜" + ReactionEmojiThinkingFace ReactionEmoji = "๐Ÿค”" + ReactionEmojiExplodingHead ReactionEmoji = "๐Ÿคฏ" + ReactionEmojiScreamingFace ReactionEmoji = "๐Ÿ˜ฑ" + ReactionEmojiCursingFace ReactionEmoji = "๐Ÿคฌ" + ReactionEmojiCryingFace ReactionEmoji = "๐Ÿ˜ข" + ReactionEmojiPartyPopper ReactionEmoji = "๐ŸŽ‰" + ReactionEmojiStarStruck ReactionEmoji = "๐Ÿคฉ" + ReactionEmojiVomiting ReactionEmoji = "๐Ÿคฎ" + ReactionEmojiPileOfPoo ReactionEmoji = "๐Ÿ’ฉ" + ReactionEmojiFoldedHands ReactionEmoji = "๐Ÿ™" + ReactionEmojiOKHand ReactionEmoji = "๐Ÿ‘Œ" + ReactionEmojiDove ReactionEmoji = "๐Ÿ•Š" + ReactionEmojiClown ReactionEmoji = "๐Ÿคก" + ReactionEmojiYawning ReactionEmoji = "๐Ÿฅฑ" + ReactionEmojiWoozyFace ReactionEmoji = "๐Ÿฅด" + ReactionEmojiHeartEyes ReactionEmoji = "๐Ÿ˜" + ReactionEmojiWhale ReactionEmoji = "๐Ÿณ" + ReactionEmojiHeartOnFire ReactionEmoji = "โคโ€๐Ÿ”ฅ" + ReactionEmojiNewMoonFace ReactionEmoji = "๐ŸŒš" + ReactionEmojiHotDog ReactionEmoji = "๐ŸŒญ" + ReactionEmojiHundredPoints ReactionEmoji = "๐Ÿ’ฏ" + ReactionEmojiRollingOnFloor ReactionEmoji = "๐Ÿคฃ" + ReactionEmojiLightning ReactionEmoji = "โšก" + ReactionEmojiBanana ReactionEmoji = "๐ŸŒ" + ReactionEmojiTrophy ReactionEmoji = "๐Ÿ†" + ReactionEmojiBrokenHeart ReactionEmoji = "๐Ÿ’”" + ReactionEmojiRaisedEyebrow ReactionEmoji = "๐Ÿคจ" + ReactionEmojiNeutralFace ReactionEmoji = "๐Ÿ˜" + ReactionEmojiStrawberry ReactionEmoji = "๐Ÿ“" + ReactionEmojiChampagne ReactionEmoji = "๐Ÿพ" + ReactionEmojiKissMark ReactionEmoji = "๐Ÿ’‹" + ReactionEmojiMiddleFinger ReactionEmoji = "๐Ÿ–•" + ReactionEmojiDevil ReactionEmoji = "๐Ÿ˜ˆ" + ReactionEmojiSleeping ReactionEmoji = "๐Ÿ˜ด" + ReactionEmojiLoudlyCrying ReactionEmoji = "๐Ÿ˜ญ" + ReactionEmojiNerd ReactionEmoji = "๐Ÿค“" + ReactionEmojiGhost ReactionEmoji = "๐Ÿ‘ป" + ReactionEmojiManTechnologist ReactionEmoji = "๐Ÿ‘จโ€๐Ÿ’ป" + ReactionEmojiEyes ReactionEmoji = "๐Ÿ‘€" + ReactionEmojiJackOLantern ReactionEmoji = "๐ŸŽƒ" + ReactionEmojiSeeNoEvil ReactionEmoji = "๐Ÿ™ˆ" + ReactionEmojiHalo ReactionEmoji = "๐Ÿ˜‡" + ReactionEmojiFearful ReactionEmoji = "๐Ÿ˜จ" + ReactionEmojiHandshake ReactionEmoji = "๐Ÿค" + ReactionEmojiWriting ReactionEmoji = "โœ" + ReactionEmojiHugging ReactionEmoji = "๐Ÿค—" + ReactionEmojiSaluting ReactionEmoji = "๐Ÿซก" + ReactionEmojiSantaClaus ReactionEmoji = "๐ŸŽ…" + ReactionEmojiChristmasTree ReactionEmoji = "๐ŸŽ„" + ReactionEmojiSnowman ReactionEmoji = "โ˜ƒ" + ReactionEmojiNailPolish ReactionEmoji = "๐Ÿ’…" + ReactionEmojiZanyFace ReactionEmoji = "๐Ÿคช" + ReactionEmojiMoai ReactionEmoji = "๐Ÿ—ฟ" + ReactionEmojiCool ReactionEmoji = "๐Ÿ†’" + ReactionEmojiHeartWithArrow ReactionEmoji = "๐Ÿ’˜" + ReactionEmojiHearNoEvil ReactionEmoji = "๐Ÿ™‰" + ReactionEmojiUnicorn ReactionEmoji = "๐Ÿฆ„" + ReactionEmojiKissingFace ReactionEmoji = "๐Ÿ˜˜" + ReactionEmojiPill ReactionEmoji = "๐Ÿ’Š" + ReactionEmojiSpeakNoEvil ReactionEmoji = "๐Ÿ™Š" + ReactionEmojiSmilingFaceWithSunglasses ReactionEmoji = "๐Ÿ˜Ž" + ReactionEmojiAlienMonster ReactionEmoji = "๐Ÿ‘พ" + ReactionEmojiManShrugging ReactionEmoji = "๐Ÿคทโ€โ™‚" + ReactionEmojiPersonShrugging ReactionEmoji = "๐Ÿคท" + ReactionEmojiWomanShrugging ReactionEmoji = "๐Ÿคทโ€โ™€" + ReactionEmojiPoutingFace ReactionEmoji = "๐Ÿ˜ก" +) diff --git a/api/methods.gen.go b/api/methods.gen.go index df48c20..bee9774 100644 --- a/api/methods.gen.go +++ b/api/methods.gen.go @@ -1953,7 +1953,7 @@ type SendDiceParams struct { // Identifier of the direct messages topic to which the message will be sent; required if the message is sent to a direct messages chat DirectMessagesTopicID *int64 `json:"direct_messages_topic_id,omitempty"` // Emoji on which the dice throw animation is based. Currently, must be one of โ€œโ€, โ€œโ€, โ€œโ€, โ€œโ€, โ€œโ€, or โ€œโ€. Dice can have values 1-6 for โ€œโ€, โ€œโ€ and โ€œโ€, values 1-5 for โ€œโ€ and โ€œโ€, and values 1-64 for โ€œโ€. Defaults to โ€œโ€ - Emoji string `json:"emoji,omitempty"` + Emoji DiceEmoji `json:"emoji,omitempty"` // Sends the message silently. Users will receive a notification with no sound. DisableNotification *bool `json:"disable_notification,omitempty"` // Protects the contents of the sent message from forwarding diff --git a/api/types.gen.go b/api/types.gen.go index cb6e782..649ffbb 100644 --- a/api/types.gen.go +++ b/api/types.gen.go @@ -3472,7 +3472,7 @@ type ReactionTypeEmoji struct { // Type of the reaction, always โ€œemojiโ€ Type ReactionTypeKind `json:"type"` // Reaction emoji. Currently, it can be one of "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" - Emoji string `json:"emoji"` + Emoji ReactionEmoji `json:"emoji"` } // MarshalJSON encodes ReactionTypeEmoji with the discriminator field diff --git a/cmd/genapi/emitter.go b/cmd/genapi/emitter.go index 34d0fa3..c61344a 100644 --- a/cmd/genapi/emitter.go +++ b/cmd/genapi/emitter.go @@ -46,6 +46,30 @@ var runtimeTypes = map[string]bool{ "MessageOrBool": true, } +// fieldTypeOverrides maps "." โ†’ Go type expression. +// Used for fields whose values are restricted but whose enum the scraper +// can't detect (Telegram's curly-quoted emoji literals are routinely +// stripped by the scraper's regex due to byte-boundary issues with +// multi-byte sequences). The hand-curated typed-string enum lives in +// api/enums.go (manual file); this override just retypes the field so +// callers get IDE completion and compile-time checks. Generated fields +// stay typed even after `make regen`. +var fieldTypeOverrides = map[string]string{ + "ReactionTypeEmoji.Emoji": "ReactionEmoji", + "SendDiceParams.Emoji": "DiceEmoji", +} + +// fieldTypeOverride returns the override type for a (parent, fieldName) +// pair, or "" if none. parent is the Go type name owning the field โ€” +// either a struct type (e.g. "ReactionTypeEmoji") or a method-params +// type (e.g. "SendDiceParams"). +func fieldTypeOverride(parent, fieldName string) string { + if parent == "" { + return "" + } + return fieldTypeOverrides[parent+"."+fieldName] +} + // discriminatorSpec describes how to decode a sealed-interface union by // peeking at a single JSON field. type discriminatorSpec struct { @@ -395,6 +419,9 @@ func funcs(plan *enumPlan) template.FuncMap { "goField": func(parent string, f spec.Field) string { return goField(plan, parent, f) }, + "goFieldP": func(methodName string, f spec.Field) string { + return goFieldX(plan, "", title(methodName)+"Params", f) + }, "docComment": docComment, "isOptional": func(f spec.Field) bool { return !f.Required }, "not": func(b bool) bool { return !b }, @@ -404,6 +431,9 @@ func funcs(plan *enumPlan) template.FuncMap { "multipartFieldEntry": func(parent string, f spec.Field) string { return multipartFieldEntry(plan, parent, f) }, + "multipartFieldEntryP": func(methodName string, f spec.Field) string { + return multipartFieldEntryX(plan, "", title(methodName)+"Params", f) + }, "multipartFileEntry": multipartFileEntry, "returnGoType": returnGoType, // enum helpers @@ -503,7 +533,17 @@ func multipartFileEntry(f spec.Field) string { // when non-zero/non-empty. Typed-string enum fields are cast to string // before assignment because the multipart map is map[string]string. func multipartFieldEntry(plan *enumPlan, parent string, f spec.Field) string { - enumName := plan.FieldEnum(parent, f.Name) + return multipartFieldEntryX(plan, parent, parent, f) +} + +// multipartFieldEntryX mirrors goFieldX: enumParent keys the enum plan, +// overrideParent keys fieldTypeOverrides. They differ only for method +// params. +func multipartFieldEntryX(plan *enumPlan, enumParent, overrideParent string, f spec.Field) string { + enumName := plan.FieldEnum(enumParent, f.Name) + if enumName == "" { + enumName = fieldTypeOverride(overrideParent, f.Name) + } switch f.Type.Kind { case spec.KindPrimitive: switch f.Type.Name { @@ -775,10 +815,24 @@ func matchesVariants(got []string, want ...string) bool { // has a planned enum name for (parent, field), the field's Go type is // the enum identifier. Typed-string enums use the zero string "" // behaviour for omitempty, so we do not pointer-wrap optional enum -// fields. Parent is "" for method parameters. +// fields. Parent is "" for method parameters; pass the params type +// name (e.g. "SendDiceParams") via overrideParent when calling from +// the methods template so fieldTypeOverrides can resolve. func goField(plan *enumPlan, parent string, f spec.Field) string { + return goFieldX(plan, parent, parent, f) +} + +// goFieldX is the underlying field-emitter. enumParent is used for the +// enum-plan lookup (which keys method params under ""); overrideParent +// is used for fieldTypeOverrides (which keys method params under the +// params type name). For struct types both are the same; for method +// params they differ. +func goFieldX(plan *enumPlan, enumParent, overrideParent string, f spec.Field) string { tag := fmt.Sprintf("`json:%q`", f.JSONName+omitempty(f)) - if name := plan.FieldEnum(parent, f.Name); name != "" { + if name := plan.FieldEnum(enumParent, f.Name); name != "" { + return fmt.Sprintf("%s %s %s", f.Name, name, tag) + } + if name := fieldTypeOverride(overrideParent, f.Name); name != "" { return fmt.Sprintf("%s %s %s", f.Name, name, tag) } return fmt.Sprintf("%s %s %s", f.Name, goType(f.Type, !f.Required), tag) diff --git a/cmd/genapi/methods.tmpl b/cmd/genapi/methods.tmpl index fef1f74..3266810 100644 --- a/cmd/genapi/methods.tmpl +++ b/cmd/genapi/methods.tmpl @@ -15,12 +15,12 @@ import ( var _ = strconv.Itoa // keep import for multipart helpers var _ = json.Marshal // keep import for complex multipart fields -{{range .Methods}} +{{range .Methods}}{{$methodName := .Name}} // {{title .Name}}Params is the parameter set for {{title .Name}}. // {{docComment .Doc -}} type {{title .Name}}Params struct { -{{range .Params}}{{docComment .Doc}} {{goField "" .}} +{{range .Params}}{{docComment .Doc}} {{goFieldP $methodName .}} {{end}}} {{if .HasFiles}} // HasFile reports whether a multipart upload is required. @@ -31,7 +31,7 @@ func (p *{{title .Name}}Params) HasFile() bool { // MultipartFields returns the non-file fields used in the multipart body. func (p *{{title .Name}}Params) MultipartFields() map[string]string { out := map[string]string{} -{{range .Params}}{{if not (isFileField .)}}{{multipartFieldEntry "" .}}{{end}}{{end}} return out +{{range .Params}}{{if not (isFileField .)}}{{multipartFieldEntryP $methodName .}}{{end}}{{end}} return out } // MultipartFiles returns the file parts. diff --git a/docs/reference/api.md b/docs/reference/api.md index c898f66..16fecd1 100644 --- a/docs/reference/api.md +++ b/docs/reference/api.md @@ -289,6 +289,7 @@ Package api contains the Telegram Bot API object types and method wrappers, gene - [type DeleteStoryParams](<#DeleteStoryParams>) - [type DeleteWebhookParams](<#DeleteWebhookParams>) - [type Dice](<#Dice>) +- [type DiceEmoji](<#DiceEmoji>) - [type DirectMessagePriceChanged](<#DirectMessagePriceChanged>) - [type DirectMessagesTopic](<#DirectMessagesTopic>) - [type Document](<#Document>) @@ -651,6 +652,7 @@ Package api contains the Telegram Bot API object types and method wrappers, gene - [type ProximityAlertTriggered](<#ProximityAlertTriggered>) - [type ReactionCount](<#ReactionCount>) - [func \(m \*ReactionCount\) UnmarshalJSON\(data \[\]byte\) error](<#ReactionCount.UnmarshalJSON>) +- [type ReactionEmoji](<#ReactionEmoji>) - [type ReactionType](<#ReactionType>) - [func UnmarshalReactionType\(data \[\]byte\) \(ReactionType, error\)](<#UnmarshalReactionType>) - [type ReactionTypeCustomEmoji](<#ReactionTypeCustomEmoji>) @@ -4884,6 +4886,28 @@ type Dice struct { } ``` + +## type [DiceEmoji]() + +DiceEmoji is the set of emoji values accepted by sendDice. Telegram's canonical list is "๐ŸŽฒ", "๐ŸŽฏ", "๐Ÿ€", "โšฝ", "๐ŸŽณ", "๐ŸŽฐ". The codegen scraper drops these values during regex extraction \(multi\-byte boundary issues with curly\-quoted emoji\), so this enum is hand\- curated and wired into SendDiceParams.Emoji via the per\-field type override in cmd/genapi/emitter.go. + +```go +type DiceEmoji string +``` + + + +```go +const ( + DiceEmojiDice DiceEmoji = "๐ŸŽฒ" + DiceEmojiDart DiceEmoji = "๐ŸŽฏ" + DiceEmojiBasketball DiceEmoji = "๐Ÿ€" + DiceEmojiFootball DiceEmoji = "โšฝ" + DiceEmojiBowling DiceEmoji = "๐ŸŽณ" + DiceEmojiSlotMachine DiceEmoji = "๐ŸŽฐ" +) +``` + ## type [DirectMessagePriceChanged]() @@ -11289,6 +11313,95 @@ func (m *ReactionCount) UnmarshalJSON(data []byte) error UnmarshalJSON decodes ReactionCount by dispatching union\-typed fields \(Type\) through their concrete UnmarshalXxx helpers. + +## type [ReactionEmoji]() + +ReactionEmoji is the set of emoji Telegram allows in a ReactionTypeEmoji.Emoji value. Hand\-curated from https://core.telegram.org/bots/api#reactiontypeemoji because the scraper's curly\-quote regex strips the emoji literals \(byte\-boundary issue on multi\-byte sequences\). Names mirror the Unicode CLDR short name where one exists; otherwise a stable common\-English label. Telegram occasionally extends this set โ€” passers of unrecognised strings still type\-check \(ReactionEmoji is a string alias\) so this list need not block runtime use of newer values. + +```go +type ReactionEmoji string +``` + + + +```go +const ( + ReactionEmojiHeart ReactionEmoji = "โค" + ReactionEmojiThumbsUp ReactionEmoji = "๐Ÿ‘" + ReactionEmojiThumbsDown ReactionEmoji = "๐Ÿ‘Ž" + ReactionEmojiFire ReactionEmoji = "๐Ÿ”ฅ" + ReactionEmojiSmilingFaceWithHearts ReactionEmoji = "๐Ÿฅฐ" + ReactionEmojiClappingHands ReactionEmoji = "๐Ÿ‘" + ReactionEmojiBeamingFace ReactionEmoji = "๐Ÿ˜" + ReactionEmojiThinkingFace ReactionEmoji = "๐Ÿค”" + ReactionEmojiExplodingHead ReactionEmoji = "๐Ÿคฏ" + ReactionEmojiScreamingFace ReactionEmoji = "๐Ÿ˜ฑ" + ReactionEmojiCursingFace ReactionEmoji = "๐Ÿคฌ" + ReactionEmojiCryingFace ReactionEmoji = "๐Ÿ˜ข" + ReactionEmojiPartyPopper ReactionEmoji = "๐ŸŽ‰" + ReactionEmojiStarStruck ReactionEmoji = "๐Ÿคฉ" + ReactionEmojiVomiting ReactionEmoji = "๐Ÿคฎ" + ReactionEmojiPileOfPoo ReactionEmoji = "๐Ÿ’ฉ" + ReactionEmojiFoldedHands ReactionEmoji = "๐Ÿ™" + ReactionEmojiOKHand ReactionEmoji = "๐Ÿ‘Œ" + ReactionEmojiDove ReactionEmoji = "๐Ÿ•Š" + ReactionEmojiClown ReactionEmoji = "๐Ÿคก" + ReactionEmojiYawning ReactionEmoji = "๐Ÿฅฑ" + ReactionEmojiWoozyFace ReactionEmoji = "๐Ÿฅด" + ReactionEmojiHeartEyes ReactionEmoji = "๐Ÿ˜" + ReactionEmojiWhale ReactionEmoji = "๐Ÿณ" + ReactionEmojiHeartOnFire ReactionEmoji = "โคโ€๐Ÿ”ฅ" + ReactionEmojiNewMoonFace ReactionEmoji = "๐ŸŒš" + ReactionEmojiHotDog ReactionEmoji = "๐ŸŒญ" + ReactionEmojiHundredPoints ReactionEmoji = "๐Ÿ’ฏ" + ReactionEmojiRollingOnFloor ReactionEmoji = "๐Ÿคฃ" + ReactionEmojiLightning ReactionEmoji = "โšก" + ReactionEmojiBanana ReactionEmoji = "๐ŸŒ" + ReactionEmojiTrophy ReactionEmoji = "๐Ÿ†" + ReactionEmojiBrokenHeart ReactionEmoji = "๐Ÿ’”" + ReactionEmojiRaisedEyebrow ReactionEmoji = "๐Ÿคจ" + ReactionEmojiNeutralFace ReactionEmoji = "๐Ÿ˜" + ReactionEmojiStrawberry ReactionEmoji = "๐Ÿ“" + ReactionEmojiChampagne ReactionEmoji = "๐Ÿพ" + ReactionEmojiKissMark ReactionEmoji = "๐Ÿ’‹" + ReactionEmojiMiddleFinger ReactionEmoji = "๐Ÿ–•" + ReactionEmojiDevil ReactionEmoji = "๐Ÿ˜ˆ" + ReactionEmojiSleeping ReactionEmoji = "๐Ÿ˜ด" + ReactionEmojiLoudlyCrying ReactionEmoji = "๐Ÿ˜ญ" + ReactionEmojiNerd ReactionEmoji = "๐Ÿค“" + ReactionEmojiGhost ReactionEmoji = "๐Ÿ‘ป" + ReactionEmojiManTechnologist ReactionEmoji = "๐Ÿ‘จโ€๐Ÿ’ป" + ReactionEmojiEyes ReactionEmoji = "๐Ÿ‘€" + ReactionEmojiJackOLantern ReactionEmoji = "๐ŸŽƒ" + ReactionEmojiSeeNoEvil ReactionEmoji = "๐Ÿ™ˆ" + ReactionEmojiHalo ReactionEmoji = "๐Ÿ˜‡" + ReactionEmojiFearful ReactionEmoji = "๐Ÿ˜จ" + ReactionEmojiHandshake ReactionEmoji = "๐Ÿค" + ReactionEmojiWriting ReactionEmoji = "โœ" + ReactionEmojiHugging ReactionEmoji = "๐Ÿค—" + ReactionEmojiSaluting ReactionEmoji = "๐Ÿซก" + ReactionEmojiSantaClaus ReactionEmoji = "๐ŸŽ…" + ReactionEmojiChristmasTree ReactionEmoji = "๐ŸŽ„" + ReactionEmojiSnowman ReactionEmoji = "โ˜ƒ" + ReactionEmojiNailPolish ReactionEmoji = "๐Ÿ’…" + ReactionEmojiZanyFace ReactionEmoji = "๐Ÿคช" + ReactionEmojiMoai ReactionEmoji = "๐Ÿ—ฟ" + ReactionEmojiCool ReactionEmoji = "๐Ÿ†’" + ReactionEmojiHeartWithArrow ReactionEmoji = "๐Ÿ’˜" + ReactionEmojiHearNoEvil ReactionEmoji = "๐Ÿ™‰" + ReactionEmojiUnicorn ReactionEmoji = "๐Ÿฆ„" + ReactionEmojiKissingFace ReactionEmoji = "๐Ÿ˜˜" + ReactionEmojiPill ReactionEmoji = "๐Ÿ’Š" + ReactionEmojiSpeakNoEvil ReactionEmoji = "๐Ÿ™Š" + ReactionEmojiSmilingFaceWithSunglasses ReactionEmoji = "๐Ÿ˜Ž" + ReactionEmojiAlienMonster ReactionEmoji = "๐Ÿ‘พ" + ReactionEmojiManShrugging ReactionEmoji = "๐Ÿคทโ€โ™‚" + ReactionEmojiPersonShrugging ReactionEmoji = "๐Ÿคท" + ReactionEmojiWomanShrugging ReactionEmoji = "๐Ÿคทโ€โ™€" + ReactionEmojiPoutingFace ReactionEmoji = "๐Ÿ˜ก" +) +``` + ## type [ReactionType]() @@ -11348,7 +11461,7 @@ type ReactionTypeEmoji struct { // Type of the reaction, always โ€œemojiโ€ Type ReactionTypeKind `json:"type"` // Reaction emoji. Currently, it can be one of "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" - Emoji string `json:"emoji"` + Emoji ReactionEmoji `json:"emoji"` } ``` @@ -12150,7 +12263,7 @@ type SendDiceParams struct { // Identifier of the direct messages topic to which the message will be sent; required if the message is sent to a direct messages chat DirectMessagesTopicID *int64 `json:"direct_messages_topic_id,omitempty"` // Emoji on which the dice throw animation is based. Currently, must be one of โ€œโ€, โ€œโ€, โ€œโ€, โ€œโ€, โ€œโ€, or โ€œโ€. Dice can have values 1-6 for โ€œโ€, โ€œโ€ and โ€œโ€, values 1-5 for โ€œโ€ and โ€œโ€, and values 1-64 for โ€œโ€. Defaults to โ€œโ€ - Emoji string `json:"emoji,omitempty"` + Emoji DiceEmoji `json:"emoji,omitempty"` // Sends the message silently. Users will receive a notification with no sound. DisableNotification *bool `json:"disable_notification,omitempty"` // Protects the contents of the sent message from forwarding