feat: better document sending handling with more general io.Reader interface to get the data.
This commit is contained in:
parent
23a34b0ed3
commit
e62ccf5780
6 changed files with 102 additions and 46 deletions
|
@ -337,10 +337,27 @@ var beh = tg.NewBehaviour().
|
|||
c.Sendf2("You typed `%s`", str)
|
||||
}),
|
||||
),
|
||||
tg.NewCommand("image", "sends a sample image").
|
||||
tg.NewCommand("cat", "sends a sample image of cat").
|
||||
ActionFunc(func(c *tg.Context) {
|
||||
img := tg.NewFile("media/cat.jpg").Image().Caption("A cat!")
|
||||
c.Send(img)
|
||||
f, err := os.Open("media/cat.jpg")
|
||||
if err != nil {
|
||||
c.Sendf("err: %s", err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
photo := tg.NewFile(f).Photo().Name("cat.jpg").Caption("A cat!")
|
||||
c.Send(photo)
|
||||
}),
|
||||
tg.NewCommand("document", "sends a sample text document").
|
||||
ActionFunc(func(c *tg.Context) {
|
||||
f, err := os.Open("media/hello.txt")
|
||||
if err != nil {
|
||||
c.Sendf("err: %s", err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
doc := tg.NewFile(f).Document().Name("hello.txt").Caption("The document")
|
||||
c.Send(doc)
|
||||
}),
|
||||
tg.NewCommand("botname", "get the bot name").
|
||||
WithAction(tg.Func(func(c *tg.Context) {
|
||||
|
|
23
context.go
23
context.go
|
@ -156,7 +156,7 @@ func (c *Context) Send(v Sendable) (*Message, error) {
|
|||
// Sends the formatted with fmt.Sprintf message to the user
|
||||
// using default Markdown parsing format.
|
||||
func (c *Context) Sendf(format string, v ...any) (*Message, error) {
|
||||
return c.Send(NewMessage(fmt.Sprintf(format, v...)))
|
||||
return c.Send(NewMessage(format, v...))
|
||||
}
|
||||
|
||||
// Same as Sendf but uses Markdown 2 format for parsing.
|
||||
|
@ -372,10 +372,11 @@ func (c *Context) ReadString(pref string, args ...any) string {
|
|||
return text
|
||||
}
|
||||
|
||||
func (c *Context) GetFile(fileId FileId) (io.ReadCloser, error) {
|
||||
// Returns the reader for specified file ID and path.
|
||||
func (c *Context) GetFile(fileId FileId) (io.ReadCloser, string, error) {
|
||||
file, err := c.Bot.Api.GetFile(tgbotapi.FileConfig{FileID:string(fileId)})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
r, err := http.Get(fmt.Sprintf(
|
||||
"https://api.telegram.org/file/bot%s/%s",
|
||||
|
@ -383,27 +384,27 @@ func (c *Context) GetFile(fileId FileId) (io.ReadCloser, error) {
|
|||
file.FilePath,
|
||||
))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
if r.StatusCode != 200 {
|
||||
return nil, StatusCodeErr
|
||||
return nil, "", StatusCodeErr
|
||||
}
|
||||
|
||||
return r.Body, nil
|
||||
return r.Body, file.FilePath, nil
|
||||
}
|
||||
|
||||
func (c *Context) ReadFile(fileId FileId) ([]byte, error) {
|
||||
file, err := c.GetFile(fileId)
|
||||
func (c *Context) ReadFile(fileId FileId) ([]byte, string, error) {
|
||||
file, pth, err := c.GetFile(fileId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
bts, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return bts, nil
|
||||
return bts, pth, nil
|
||||
}
|
||||
|
||||
|
|
75
file.go
75
file.go
|
@ -4,8 +4,8 @@ import (
|
|||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
//"os"
|
||||
//"path/filepath"
|
||||
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
)
|
||||
|
@ -16,67 +16,96 @@ type FileType int
|
|||
|
||||
const (
|
||||
NoFileType FileType = iota
|
||||
ImageFileType
|
||||
PhotoFileType
|
||||
DocumentFileType
|
||||
)
|
||||
|
||||
var (
|
||||
UnknownFileTypeErr = errors.New("unknown file type")
|
||||
)
|
||||
|
||||
// The type implements the structure to easily send
|
||||
// files to the client.
|
||||
type File struct {
|
||||
*MessageCompo
|
||||
path string
|
||||
name string
|
||||
reader io.Reader
|
||||
upload bool
|
||||
typ FileType
|
||||
caption string
|
||||
data, caption string
|
||||
}
|
||||
|
||||
func NewFile(path string) *File {
|
||||
// Create the new file with the specified reader.
|
||||
// By default it NeedsUpload is set to true.
|
||||
func NewFile(reader io.Reader) *File {
|
||||
ret := &File{}
|
||||
|
||||
ret.MessageCompo = NewMessage("")
|
||||
ret.path = path
|
||||
ret.reader = reader
|
||||
ret.upload = true
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (f *File) Name(name string) *File {
|
||||
f.name = name
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *File) withType(typ FileType) *File {
|
||||
f.typ = typ
|
||||
return f
|
||||
}
|
||||
|
||||
// Get the file type.
|
||||
func (f *File) Type() FileType {
|
||||
return f.typ
|
||||
}
|
||||
|
||||
func (f *File) Image() *File {
|
||||
return f.withType(ImageFileType)
|
||||
// Set the file type to PhotoFileType.
|
||||
func (f *File) Photo() *File {
|
||||
return f.withType(PhotoFileType)
|
||||
}
|
||||
|
||||
func (f *File) Document() *File {
|
||||
return f.withType(DocumentFileType)
|
||||
}
|
||||
|
||||
// Set the file caption.
|
||||
func (f *File) Caption(caption string) *File {
|
||||
f.caption = caption
|
||||
return f
|
||||
}
|
||||
|
||||
// Specifiy whether the file needs to be uploaded to Telegram.
|
||||
func (f *File) Upload(upload bool) *File {
|
||||
f.upload = upload
|
||||
return f
|
||||
}
|
||||
|
||||
// Set the data to return via SendData()
|
||||
func (f *File) Data(data string) *File {
|
||||
f.data = data
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *File) NeedsUpload() bool {
|
||||
return true
|
||||
return f.upload
|
||||
}
|
||||
|
||||
func (f *File) UploadData() (string, io.Reader, error) {
|
||||
rd, err := os.Open(f.path)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
bufRd := bufio.NewReader(rd)
|
||||
|
||||
fileName := filepath.Base(f.path)
|
||||
// Bufferizing the reader
|
||||
// to make it faster.
|
||||
bufRd := bufio.NewReader(f.reader)
|
||||
fileName := f.name
|
||||
|
||||
return fileName, bufRd, nil
|
||||
}
|
||||
|
||||
func (f *File) SendData() string {
|
||||
return ""
|
||||
return f.data
|
||||
}
|
||||
|
||||
func (f *File) SendConfig(
|
||||
sid SessionId, bot *Bot,
|
||||
) (*SendConfig) {
|
||||
|
@ -84,11 +113,15 @@ func (f *File) SendConfig(
|
|||
cid := sid.ToApi()
|
||||
|
||||
switch f.Type() {
|
||||
case ImageFileType:
|
||||
case PhotoFileType:
|
||||
photo := tgbotapi.NewPhoto(cid, f)
|
||||
photo.Caption = f.caption
|
||||
|
||||
config.Image = &photo
|
||||
config.Photo = &photo
|
||||
case DocumentFileType:
|
||||
doc := tgbotapi.NewDocument(sid.ToApi(), f)
|
||||
doc.Caption = f.caption
|
||||
config.Document = &doc
|
||||
default:
|
||||
panic(UnknownFileTypeErr)
|
||||
}
|
||||
|
|
3
media/hello.txt
Normal file
3
media/hello.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Hello, World!
|
||||
This is the text document!
|
||||
|
16
send.go
16
send.go
|
@ -21,22 +21,16 @@ type Errorer interface {
|
|||
// The type is used as an endpoint to send messages
|
||||
// via bot.Send .
|
||||
type SendConfig struct {
|
||||
// The name will be used to store
|
||||
// the message in the map.
|
||||
Name string
|
||||
// Message with text and keyboard.
|
||||
Message *tgbotapi.MessageConfig
|
||||
|
||||
// The image to be sent.
|
||||
Image *tgbotapi.PhotoConfig
|
||||
Photo *tgbotapi.PhotoConfig
|
||||
Document *tgbotapi.DocumentConfig
|
||||
Location *tgbotapi.LocationConfig
|
||||
Error error
|
||||
}
|
||||
|
||||
func (cfg *SendConfig) WithName(name string) *SendConfig {
|
||||
cfg.Name = name
|
||||
return cfg
|
||||
}
|
||||
|
||||
type MessageMap map[string] *Message
|
||||
|
||||
|
@ -45,10 +39,12 @@ func (config *SendConfig) ToApi() tgbotapi.Chattable {
|
|||
switch {
|
||||
case config.Message != nil :
|
||||
return *(config.Message)
|
||||
case config.Image != nil :
|
||||
return *(config.Image)
|
||||
case config.Photo != nil :
|
||||
return *(config.Photo)
|
||||
case config.Location != nil :
|
||||
return *(config.Location)
|
||||
case config.Document != nil :
|
||||
return *(config.Document)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -61,13 +61,19 @@ func (updates *UpdateChan) Close() {
|
|||
}
|
||||
|
||||
func (u *Update) HasDocument() bool {
|
||||
return u.Message != nil && u.Message.Document != nil
|
||||
return u != nil &&
|
||||
u.Message != nil &&
|
||||
u.Message.Document != nil
|
||||
}
|
||||
|
||||
func (u *Update) DocumentId() FileId {
|
||||
return FileId(u.Update.Message.Document.FileID)
|
||||
}
|
||||
|
||||
func (u *Update) DocumentName() string {
|
||||
return u.Message.Document.FileName
|
||||
}
|
||||
|
||||
func (u *Update) HasPhotos() bool {
|
||||
return u.Message != nil && u.Message.Photo != nil &&
|
||||
len(u.Message.Photo) != 0
|
||||
|
|
Loading…
Reference in a new issue