Skip to content

Commit 7ab1acd

Browse files
ernadoclaude
andcommitted
feat(types): add core Bot API types and incoming unions
Hand-written primitive types and the discriminated incoming unions: - types_user_chat.go: User, Chat. - types_media.go: PhotoSize, Animation, Audio, Document, Video, VideoNote, Voice, Sticker, File, UserProfilePhotos. - types_message.go: MessageEntity, Contact, Dice, Location, Venue, Poll, PollOption, PollAnswer, and Message. - types_query.go: CallbackQuery, InlineQuery, ChosenInlineResult. - update.go: Update (the aggregate incoming envelope). - message_origin.go: MessageOrigin union (user/hidden/chat/channel). - chat_member.go: ChatMember union + ChatMemberUpdated, ChatInviteLink. - input_media.go: InputMedia union (photo/video/animation/audio/document). All fields carry snake_case JSON tags for the future HTTP compatibility shim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent bd641e8 commit 7ab1acd

9 files changed

Lines changed: 614 additions & 0 deletions

chat_member.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package botapi
2+
3+
// ChatMember is a sealed union describing one member of a chat. The concrete
4+
// type corresponds to the member's status.
5+
//
6+
// Concrete variants: *ChatMemberOwner, *ChatMemberAdministrator,
7+
// *ChatMemberMember, *ChatMemberRestricted, *ChatMemberLeft, *ChatMemberBanned.
8+
type ChatMember interface {
9+
isChatMember()
10+
}
11+
12+
// ChatMemberOwner is the chat creator.
13+
type ChatMemberOwner struct {
14+
Status ChatMemberStatus `json:"status"`
15+
User User `json:"user"`
16+
IsAnonymous bool `json:"is_anonymous,omitempty"`
17+
CustomTitle string `json:"custom_title,omitempty"`
18+
}
19+
20+
// ChatMemberAdministrator is a chat administrator with granted privileges.
21+
type ChatMemberAdministrator struct {
22+
Status ChatMemberStatus `json:"status"`
23+
User User `json:"user"`
24+
CanBeEdited bool `json:"can_be_edited,omitempty"`
25+
IsAnonymous bool `json:"is_anonymous,omitempty"`
26+
CanManageChat bool `json:"can_manage_chat,omitempty"`
27+
CanDeleteMessages bool `json:"can_delete_messages,omitempty"`
28+
CanManageVideoChats bool `json:"can_manage_video_chats,omitempty"`
29+
CanRestrictMembers bool `json:"can_restrict_members,omitempty"`
30+
CanPromoteMembers bool `json:"can_promote_members,omitempty"`
31+
CanChangeInfo bool `json:"can_change_info,omitempty"`
32+
CanInviteUsers bool `json:"can_invite_users,omitempty"`
33+
CanPostMessages bool `json:"can_post_messages,omitempty"`
34+
CanEditMessages bool `json:"can_edit_messages,omitempty"`
35+
CanPinMessages bool `json:"can_pin_messages,omitempty"`
36+
CustomTitle string `json:"custom_title,omitempty"`
37+
}
38+
39+
// ChatMemberMember is an ordinary member with no special restrictions.
40+
type ChatMemberMember struct {
41+
Status ChatMemberStatus `json:"status"`
42+
User User `json:"user"`
43+
UntilDate int `json:"until_date,omitempty"`
44+
}
45+
46+
// ChatMemberRestricted is a member subject to restrictions.
47+
type ChatMemberRestricted struct {
48+
Status ChatMemberStatus `json:"status"`
49+
User User `json:"user"`
50+
IsMember bool `json:"is_member,omitempty"`
51+
CanSendMessages bool `json:"can_send_messages,omitempty"`
52+
CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"`
53+
CanSendPolls bool `json:"can_send_polls,omitempty"`
54+
CanSendOtherMessages bool `json:"can_send_other_messages,omitempty"`
55+
CanAddWebPagePreviews bool `json:"can_add_web_page_previews,omitempty"`
56+
CanChangeInfo bool `json:"can_change_info,omitempty"`
57+
CanInviteUsers bool `json:"can_invite_users,omitempty"`
58+
CanPinMessages bool `json:"can_pin_messages,omitempty"`
59+
UntilDate int `json:"until_date,omitempty"`
60+
}
61+
62+
// ChatMemberLeft is a user who is not and was not a member of the chat.
63+
type ChatMemberLeft struct {
64+
Status ChatMemberStatus `json:"status"`
65+
User User `json:"user"`
66+
}
67+
68+
// ChatMemberBanned is a user banned from the chat.
69+
type ChatMemberBanned struct {
70+
Status ChatMemberStatus `json:"status"`
71+
User User `json:"user"`
72+
UntilDate int `json:"until_date,omitempty"`
73+
}
74+
75+
func (*ChatMemberOwner) isChatMember() {}
76+
func (*ChatMemberAdministrator) isChatMember() {}
77+
func (*ChatMemberMember) isChatMember() {}
78+
func (*ChatMemberRestricted) isChatMember() {}
79+
func (*ChatMemberLeft) isChatMember() {}
80+
func (*ChatMemberBanned) isChatMember() {}
81+
82+
// ChatInviteLink represents an invite link for a chat.
83+
type ChatInviteLink struct {
84+
InviteLink string `json:"invite_link"`
85+
Creator User `json:"creator"`
86+
CreatesJoinRequest bool `json:"creates_join_request,omitempty"`
87+
IsPrimary bool `json:"is_primary,omitempty"`
88+
IsRevoked bool `json:"is_revoked,omitempty"`
89+
Name string `json:"name,omitempty"`
90+
ExpireDate int `json:"expire_date,omitempty"`
91+
MemberLimit int `json:"member_limit,omitempty"`
92+
PendingJoinRequestCount int `json:"pending_join_request_count,omitempty"`
93+
}
94+
95+
// ChatMemberUpdated represents a change in the status of a chat member.
96+
type ChatMemberUpdated struct {
97+
Chat Chat `json:"chat"`
98+
From User `json:"from"`
99+
Date int `json:"date"`
100+
OldChatMember ChatMember `json:"old_chat_member"`
101+
NewChatMember ChatMember `json:"new_chat_member"`
102+
InviteLink *ChatInviteLink `json:"invite_link,omitempty"`
103+
}

input_media.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package botapi
2+
3+
// InputMedia is a sealed union describing the content of a media message to be
4+
// sent (e.g. in a media group or via an edit).
5+
//
6+
// Concrete variants: *InputMediaPhoto, *InputMediaVideo, *InputMediaAnimation,
7+
// *InputMediaAudio, *InputMediaDocument.
8+
//
9+
// The Media (and Thumbnail) fields hold an InputFile; the send path (Phase 3)
10+
// resolves each to a file_id, URL or upload.
11+
type InputMedia interface {
12+
isInputMedia()
13+
}
14+
15+
// InputMediaPhoto is a photo to be sent.
16+
type InputMediaPhoto struct {
17+
Type InputMediaType `json:"type"`
18+
Media InputFile `json:"-"`
19+
Caption string `json:"caption,omitempty"`
20+
ParseMode ParseMode `json:"parse_mode,omitempty"`
21+
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
22+
HasSpoiler bool `json:"has_spoiler,omitempty"`
23+
}
24+
25+
// InputMediaVideo is a video to be sent.
26+
type InputMediaVideo struct {
27+
Type InputMediaType `json:"type"`
28+
Media InputFile `json:"-"`
29+
Thumbnail InputFile `json:"-"`
30+
Caption string `json:"caption,omitempty"`
31+
ParseMode ParseMode `json:"parse_mode,omitempty"`
32+
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
33+
Width int `json:"width,omitempty"`
34+
Height int `json:"height,omitempty"`
35+
Duration int `json:"duration,omitempty"`
36+
SupportsStreaming bool `json:"supports_streaming,omitempty"`
37+
HasSpoiler bool `json:"has_spoiler,omitempty"`
38+
}
39+
40+
// InputMediaAnimation is an animation (GIF or silent H.264/MPEG-4 AVC) to be sent.
41+
type InputMediaAnimation struct {
42+
Type InputMediaType `json:"type"`
43+
Media InputFile `json:"-"`
44+
Thumbnail InputFile `json:"-"`
45+
Caption string `json:"caption,omitempty"`
46+
ParseMode ParseMode `json:"parse_mode,omitempty"`
47+
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
48+
Width int `json:"width,omitempty"`
49+
Height int `json:"height,omitempty"`
50+
Duration int `json:"duration,omitempty"`
51+
HasSpoiler bool `json:"has_spoiler,omitempty"`
52+
}
53+
54+
// InputMediaAudio is an audio file to be sent.
55+
type InputMediaAudio struct {
56+
Type InputMediaType `json:"type"`
57+
Media InputFile `json:"-"`
58+
Thumbnail InputFile `json:"-"`
59+
Caption string `json:"caption,omitempty"`
60+
ParseMode ParseMode `json:"parse_mode,omitempty"`
61+
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
62+
Duration int `json:"duration,omitempty"`
63+
Performer string `json:"performer,omitempty"`
64+
Title string `json:"title,omitempty"`
65+
}
66+
67+
// InputMediaDocument is a general file to be sent.
68+
type InputMediaDocument struct {
69+
Type InputMediaType `json:"type"`
70+
Media InputFile `json:"-"`
71+
Thumbnail InputFile `json:"-"`
72+
Caption string `json:"caption,omitempty"`
73+
ParseMode ParseMode `json:"parse_mode,omitempty"`
74+
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
75+
DisableContentTypeDetection bool `json:"disable_content_type_detection,omitempty"`
76+
}
77+
78+
func (*InputMediaPhoto) isInputMedia() {}
79+
func (*InputMediaVideo) isInputMedia() {}
80+
func (*InputMediaAnimation) isInputMedia() {}
81+
func (*InputMediaAudio) isInputMedia() {}
82+
func (*InputMediaDocument) isInputMedia() {}

message_origin.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package botapi
2+
3+
// MessageOrigin is a sealed union describing the original sender of a forwarded
4+
// message.
5+
//
6+
// Concrete variants: *MessageOriginUser, *MessageOriginHiddenUser,
7+
// *MessageOriginChat, *MessageOriginChannel.
8+
type MessageOrigin interface {
9+
isMessageOrigin()
10+
}
11+
12+
// MessageOriginUser is a message originally sent by a known user.
13+
type MessageOriginUser struct {
14+
Type MessageOriginType `json:"type"`
15+
Date int `json:"date"`
16+
SenderUser User `json:"sender_user"`
17+
}
18+
19+
// MessageOriginHiddenUser is a message originally sent by a user who hid their
20+
// account.
21+
type MessageOriginHiddenUser struct {
22+
Type MessageOriginType `json:"type"`
23+
Date int `json:"date"`
24+
SenderUserName string `json:"sender_user_name"`
25+
}
26+
27+
// MessageOriginChat is a message originally sent on behalf of a chat.
28+
type MessageOriginChat struct {
29+
Type MessageOriginType `json:"type"`
30+
Date int `json:"date"`
31+
SenderChat Chat `json:"sender_chat"`
32+
AuthorSignature string `json:"author_signature,omitempty"`
33+
}
34+
35+
// MessageOriginChannel is a message originally sent to a channel.
36+
type MessageOriginChannel struct {
37+
Type MessageOriginType `json:"type"`
38+
Date int `json:"date"`
39+
Chat Chat `json:"chat"`
40+
MessageID int `json:"message_id"`
41+
AuthorSignature string `json:"author_signature,omitempty"`
42+
}
43+
44+
func (*MessageOriginUser) isMessageOrigin() {}
45+
func (*MessageOriginHiddenUser) isMessageOrigin() {}
46+
func (*MessageOriginChat) isMessageOrigin() {}
47+
func (*MessageOriginChannel) isMessageOrigin() {}

types_media.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package botapi
2+
3+
// PhotoSize represents one size of a photo or a file/sticker thumbnail.
4+
type PhotoSize struct {
5+
FileID string `json:"file_id"`
6+
FileUniqueID string `json:"file_unique_id"`
7+
Width int `json:"width"`
8+
Height int `json:"height"`
9+
FileSize int `json:"file_size,omitempty"`
10+
}
11+
12+
// Animation represents an animation file (GIF or H.264/MPEG-4 AVC without sound).
13+
type Animation struct {
14+
FileID string `json:"file_id"`
15+
FileUniqueID string `json:"file_unique_id"`
16+
Width int `json:"width"`
17+
Height int `json:"height"`
18+
Duration int `json:"duration"`
19+
Thumbnail *PhotoSize `json:"thumbnail,omitempty"`
20+
FileName string `json:"file_name,omitempty"`
21+
MIMEType string `json:"mime_type,omitempty"`
22+
FileSize int64 `json:"file_size,omitempty"`
23+
}
24+
25+
// Audio represents an audio file to be treated as music.
26+
type Audio struct {
27+
FileID string `json:"file_id"`
28+
FileUniqueID string `json:"file_unique_id"`
29+
Duration int `json:"duration"`
30+
Performer string `json:"performer,omitempty"`
31+
Title string `json:"title,omitempty"`
32+
FileName string `json:"file_name,omitempty"`
33+
MIMEType string `json:"mime_type,omitempty"`
34+
FileSize int64 `json:"file_size,omitempty"`
35+
Thumbnail *PhotoSize `json:"thumbnail,omitempty"`
36+
}
37+
38+
// Document represents a general file (other than photos, voice or audio).
39+
type Document struct {
40+
FileID string `json:"file_id"`
41+
FileUniqueID string `json:"file_unique_id"`
42+
Thumbnail *PhotoSize `json:"thumbnail,omitempty"`
43+
FileName string `json:"file_name,omitempty"`
44+
MIMEType string `json:"mime_type,omitempty"`
45+
FileSize int64 `json:"file_size,omitempty"`
46+
}
47+
48+
// Video represents a video file.
49+
type Video struct {
50+
FileID string `json:"file_id"`
51+
FileUniqueID string `json:"file_unique_id"`
52+
Width int `json:"width"`
53+
Height int `json:"height"`
54+
Duration int `json:"duration"`
55+
Thumbnail *PhotoSize `json:"thumbnail,omitempty"`
56+
FileName string `json:"file_name,omitempty"`
57+
MIMEType string `json:"mime_type,omitempty"`
58+
FileSize int64 `json:"file_size,omitempty"`
59+
}
60+
61+
// VideoNote represents a rounded, square video message.
62+
type VideoNote struct {
63+
FileID string `json:"file_id"`
64+
FileUniqueID string `json:"file_unique_id"`
65+
Length int `json:"length"`
66+
Duration int `json:"duration"`
67+
Thumbnail *PhotoSize `json:"thumbnail,omitempty"`
68+
FileSize int `json:"file_size,omitempty"`
69+
}
70+
71+
// Voice represents a voice note.
72+
type Voice struct {
73+
FileID string `json:"file_id"`
74+
FileUniqueID string `json:"file_unique_id"`
75+
Duration int `json:"duration"`
76+
MIMEType string `json:"mime_type,omitempty"`
77+
FileSize int64 `json:"file_size,omitempty"`
78+
}
79+
80+
// Sticker represents a sticker.
81+
type Sticker struct {
82+
FileID string `json:"file_id"`
83+
FileUniqueID string `json:"file_unique_id"`
84+
Type StickerType `json:"type"`
85+
Width int `json:"width"`
86+
Height int `json:"height"`
87+
IsAnimated bool `json:"is_animated,omitempty"`
88+
IsVideo bool `json:"is_video,omitempty"`
89+
Thumbnail *PhotoSize `json:"thumbnail,omitempty"`
90+
Emoji string `json:"emoji,omitempty"`
91+
SetName string `json:"set_name,omitempty"`
92+
FileSize int `json:"file_size,omitempty"`
93+
}
94+
95+
// File represents a file ready to be downloaded.
96+
type File struct {
97+
FileID string `json:"file_id"`
98+
FileUniqueID string `json:"file_unique_id"`
99+
FileSize int64 `json:"file_size,omitempty"`
100+
FilePath string `json:"file_path,omitempty"`
101+
}
102+
103+
// UserProfilePhotos represents a user's profile pictures.
104+
type UserProfilePhotos struct {
105+
TotalCount int `json:"total_count"`
106+
Photos [][]PhotoSize `json:"photos"`
107+
}

0 commit comments

Comments
 (0)