Skip to content

Commit

Permalink
V7.6 (#102)
Browse files Browse the repository at this point in the history
* add models.ParseModeMarkdownV1 const

* fix typo in readme

* add method SendPaidMedia

* add field PaidMedia

* add InvoicePayload to TransactionPartnerUser

* add PaidMedia

* remove comments from example

* add refunded_payment

* changelog, readme
  • Loading branch information
negasus authored Jul 18, 2024
1 parent 9b4caac commit 8984ecd
Show file tree
Hide file tree
Showing 16 changed files with 390 additions and 12 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## v1.6.0 (2024-07-18)

- support API v7.6, 7.7
- add const `models.ParseModeMarkdownV1`

## v1.5.0 (2024-06-24)

- support API v7.5
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

> [Telegram Group](https://t.me/gotelegrambotui)
> Supports Bot API version: [7.5](https://core.telegram.org/bots/api#june-18-2024) from June 18, 2024
> Supports Bot API version: [7.7](https://core.telegram.org/bots/api#july-7-2024) from July 7, 2024
It's a Go zero-dependencies telegram bot framework

Expand Down Expand Up @@ -343,7 +343,7 @@ b.SendPoll(ctx, p)

Return file download link after call method `GetFile`

See [documentation(https://core.telegram.org/bots/api#getfile)
See [documentation](https://core.telegram.org/bots/api#getfile)

## Errors

Expand Down
28 changes: 22 additions & 6 deletions build_request_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ import (
"github.com/go-telegram/bot/models"
)

type inputMedia interface {
MarshalInputMedia() ([]byte, error)
Attachment() io.Reader
GetMedia() string
}

type customMarshal interface {
MarshalCustom() ([]byte, error)
}

var customMarshalInterface = reflect.TypeOf(new(customMarshal)).Elem()
var inputMediaInterface = reflect.TypeOf(new(models.InputMedia)).Elem()
var inputMediaInterface = reflect.TypeOf(new(inputMedia)).Elem()

// buildRequestForm builds form-data for request
// if params contains InputFile of type InputFileUpload, it will be added to form-data ad upload file. Also, for InputMedia attachments
Expand Down Expand Up @@ -46,7 +52,7 @@ func buildRequestForm(form *multipart.Writer, params any) (int, error) {
continue
}
if v.Field(i).Type().Implements(inputMediaInterface) {
err := addFormFieldInputMedia(form, fieldName, v.Field(i).Interface().(models.InputMedia))
err := addFormFieldInputMedia(form, fieldName, v.Field(i).Interface().(inputMedia))
if err != nil {
return 0, err
}
Expand All @@ -64,7 +70,17 @@ func buildRequestForm(form *multipart.Writer, params any) (int, error) {
case *models.InputFileString:
err = addFormFieldString(form, fieldName, vv.Data)
case []models.InputMedia:
err = addFormFieldInputMediaSlice(form, fieldName, vv)
var ss []inputMedia
for _, m := range vv {
ss = append(ss, m)
}
err = addFormFieldInputMediaSlice(form, fieldName, ss)
case []models.InputPaidMedia:
var ss []inputMedia
for _, m := range vv {
ss = append(ss, m)
}
err = addFormFieldInputMediaSlice(form, fieldName, ss)
case []models.InlineQueryResult:
err = addFormFieldInlineQueryResultSlice(form, fieldName, vv)
default:
Expand All @@ -89,7 +105,7 @@ func addFormFieldInputFileUpload(form *multipart.Writer, fieldName string, value
return errCopy
}

func addFormFieldInputMediaItem(form *multipart.Writer, value models.InputMedia) ([]byte, error) {
func addFormFieldInputMediaItem(form *multipart.Writer, value inputMedia) ([]byte, error) {
if strings.HasPrefix(value.GetMedia(), "attach://") {
filename := strings.TrimPrefix(value.GetMedia(), "attach://")
mediaAttachmentField, errCreateMediaAttachmentField := form.CreateFormFile(filename, filename)
Expand Down Expand Up @@ -117,7 +133,7 @@ func addFormFieldCustomMarshal(form *multipart.Writer, fieldName string, value c
return errCopy
}

func addFormFieldInputMedia(form *multipart.Writer, fieldName string, value models.InputMedia) error {
func addFormFieldInputMedia(form *multipart.Writer, fieldName string, value inputMedia) error {
line, err := addFormFieldInputMediaItem(form, value)
if err != nil {
return err
Expand All @@ -131,7 +147,7 @@ func addFormFieldInputMedia(form *multipart.Writer, fieldName string, value mode
return errCopy
}

func addFormFieldInputMediaSlice(form *multipart.Writer, fieldName string, value []models.InputMedia) error {
func addFormFieldInputMediaSlice(form *multipart.Writer, fieldName string, value []inputMedia) error {
var lines []string
for _, media := range value {
line, err := addFormFieldInputMediaItem(form, media)
Expand Down
Binary file added examples/send_paid_media/images/facebook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/send_paid_media/images/youtube.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 75 additions & 0 deletions examples/send_paid_media/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"bytes"
"context"
"embed"
"fmt"
"os"
"os/signal"

"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
)

func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()

opts := []bot.Option{
bot.WithDefaultHandler(handler),
}

b, err := bot.New(os.Getenv("EXAMPLE_TELEGRAM_BOT_TOKEN"), opts...)
if nil != err {
// panics for the sake of simplicity.
// you should handle this error properly in your code.
panic(err)
}

b.Start(ctx)
}

//go:embed images
var images embed.FS

func handler(ctx context.Context, b *bot.Bot, update *models.Update) {
fileDataFacebook, _ := images.ReadFile("images/facebook.png")
fileDataYoutube, _ := images.ReadFile("images/youtube.png")

if update.ChannelPost == nil {
fmt.Printf("expect channel post\n")
return
}

chatID := update.ChannelPost.Chat.ID

media1 := &models.InputPaidMediaPhoto{
Media: "https://telegram.org/img/t_logo.png",
}

media2 := &models.InputPaidMediaPhoto{
Media: "attach://facebook.png",
MediaAttachment: bytes.NewReader(fileDataFacebook),
}

media3 := &models.InputPaidMediaPhoto{
Media: "attach://youtube.png",
MediaAttachment: bytes.NewReader(fileDataYoutube),
}

params := &bot.SendPaidMediaParams{
ChatID: chatID,
StarCount: 10,
Media: []models.InputPaidMedia{
media1,
media2,
media3,
},
}

_, err := b.SendPaidMedia(ctx, params)
if err != nil {
fmt.Printf("%+v\n", err)
}
}
7 changes: 7 additions & 0 deletions methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ func (b *Bot) SendVideoNote(ctx context.Context, params *SendVideoNoteParams) (*
return result, err
}

// SendPaidMedia https://core.telegram.org/bots/api#sendpaidmedia
func (b *Bot) SendPaidMedia(ctx context.Context, params *SendPaidMediaParams) (*models.Message, error) {
var result models.Message
err := b.rawRequest(ctx, "sendPaidMedia", params, &result)
return &result, err
}

// SendMediaGroup https://core.telegram.org/bots/api#sendmediagroup
func (b *Bot) SendMediaGroup(ctx context.Context, params *SendMediaGroupParams) ([]*models.Message, error) {
var result []*models.Message
Expand Down
15 changes: 15 additions & 0 deletions methods_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,21 @@ type SendVideoNoteParams struct {
ReplyMarkup models.ReplyMarkup `json:"reply_markup,omitempty"`
}

// SendPaidMediaParams https://core.telegram.org/bots/api#sendpaidmedia
type SendPaidMediaParams struct {
ChatID any `json:"chat_id"`
StarCount int `json:"star_count"`
Media []models.InputPaidMedia `json:"media"`
Caption string `json:"caption,omitempty"`
ParseMode models.ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []models.MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
ReplyParameters *models.ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup models.ReplyMarkup `json:"reply_markup,omitempty"`
}

// SendMediaGroupParams https://core.telegram.org/bots/api#sendmediagroup
type SendMediaGroupParams struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions models/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ type ChatFullInfo struct {
InviteLink string `json:"invite_link,omitempty"`
PinnedMessage *Message `json:"pinned_message,omitempty"`
Permissions *ChatPermissions `json:"permissions,omitempty"`
CanSendPaidMedia bool `json:"can_send_paid_media,omitempty"`
SlowModeDelay int `json:"slow_mode_delay,omitempty"`
UnrestrictBoostCount int `json:"unrestrict_boost_count,omitempty"`
MessageAutoDeleteTime int `json:"message_auto_delete_time,omitempty"`
Expand Down
2 changes: 2 additions & 0 deletions models/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type Message struct {
Animation *Animation `json:"animation,omitempty"`
Audio *Audio `json:"audio,omitempty"`
Document *Document `json:"document,omitempty"`
PaidMedia *PaidMediaInfo `json:"paid_media,omitempty"`
Photo []PhotoSize `json:"photo,omitempty"`
Sticker *Sticker `json:"sticker,omitempty"`
Story *Story `json:"story,omitempty"`
Expand Down Expand Up @@ -129,6 +130,7 @@ type Message struct {
PinnedMessage MaybeInaccessibleMessage `json:"pinned_message,omitempty"`
Invoice *Invoice `json:"invoice,omitempty"`
SuccessfulPayment *SuccessfulPayment `json:"successful_payment,omitempty"`
RefundedPayment *RefundedPayment `json:"refunded_payment,omitempty"`
UsersShared *UsersShared `json:"users_shared,omitempty"`
ChatShared *ChatShared `json:"chat_shared,omitempty"`
ConnectedWebsite string `json:"connected_website,omitempty"`
Expand Down
150 changes: 150 additions & 0 deletions models/paid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package models

import (
"encoding/json"
"fmt"
"io"
)

type InputPaidMedia interface {
inputPaidMediaTag()

MarshalInputMedia() ([]byte, error)
Attachment() io.Reader
GetMedia() string
}

// InputPaidMediaPhoto https://core.telegram.org/bots/api#inputpaidmediaphoto
type InputPaidMediaPhoto struct {
Media string `json:"media"`

MediaAttachment io.Reader `json:"-"`
}

func (m *InputPaidMediaPhoto) inputPaidMediaTag() {}

func (m *InputPaidMediaPhoto) Attachment() io.Reader {
return m.MediaAttachment
}

func (m *InputPaidMediaPhoto) GetMedia() string {
return m.Media
}

func (m *InputPaidMediaPhoto) MarshalInputMedia() ([]byte, error) {
ret := struct {
Type string `json:"type"`
*InputPaidMediaPhoto
}{
Type: "photo",
InputPaidMediaPhoto: m,
}

return json.Marshal(&ret)
}

// InputPaidMediaVideo https://core.telegram.org/bots/api#inputpaidmediavideo
type InputPaidMediaVideo struct {
Media string `json:"media"`
Thumbnail InputFile `json:"thumbnail,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
SupportsStreaming bool `json:"supports_streaming,omitempty"`

MediaAttachment io.Reader `json:"-"`
}

func (m *InputPaidMediaVideo) inputPaidMediaTag() {}

func (m *InputPaidMediaVideo) Attachment() io.Reader {
return m.MediaAttachment
}

func (m *InputPaidMediaVideo) GetMedia() string {
return m.Media
}

func (m *InputPaidMediaVideo) MarshalInputMedia() ([]byte, error) {
ret := struct {
Type string `json:"type"`
*InputPaidMediaVideo
}{
Type: "video",
InputPaidMediaVideo: m,
}

return json.Marshal(&ret)
}

type PaidMediaType string

const (
PaidMediaTypePreview PaidMediaType = "preview"
PaidMediaTypePhoto PaidMediaType = "photo"
PaidMediaTypeVideo PaidMediaType = "video"
)

// PaidMedia https://core.telegram.org/bots/api#paidmedia
type PaidMedia struct {
Type PaidMediaType

Preview *PaidMediaPreview
Photo *PaidMediaPhoto
Video *PaidMediaVideo
}

func (p *PaidMedia) UnmarshalJSON(data []byte) error {
v := struct {
Type PaidMediaType `json:"type"`
}{}
err := json.Unmarshal(data, &v)
if err != nil {
return err
}

p.Type = v.Type

switch v.Type {
case PaidMediaTypePreview:
p.Preview = &PaidMediaPreview{}
return json.Unmarshal(data, p.Preview)
case PaidMediaTypePhoto:
p.Photo = &PaidMediaPhoto{}
return json.Unmarshal(data, p.Photo)
case PaidMediaTypeVideo:
p.Video = &PaidMediaVideo{}
return json.Unmarshal(data, p.Video)
default:
return fmt.Errorf("unsupported PaidMedia type, %v", v.Type)
}
}

// PaidMediaPreview https://core.telegram.org/bots/api#paidmediapreview
type PaidMediaPreview struct {
Type PaidMediaType

Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
}

// PaidMediaPhoto https://core.telegram.org/bots/api#paidmediaphoto
type PaidMediaPhoto struct {
Type PaidMediaType

Photo []PhotoSize `json:"photo"`
}

// PaidMediaVideo https://core.telegram.org/bots/api#paidmediavideo
type PaidMediaVideo struct {
Type PaidMediaType

Video Video `json:"video"`
}

// PaidMediaInfo https://core.telegram.org/bots/api#paidmediainfo
type PaidMediaInfo struct {
StarCount int `json:"star_count"`
PaidMedia []PaidMedia `json:"paid_media"`
}
Loading

0 comments on commit 8984ecd

Please sign in to comment.