v0.5.0

Saving Media

Last updated

Each platform's Save method downloads a received file to a directory and returns the saved path.

Signatures

// core/telegram — fileID from Input.Photo[i].FileID or Input.Document.FileID
func (b *Bot) Save(ctx context.Context, fileID, dir string) (string, error)

// core/discord — one entry of Input.Attachments
func (b *Bot) Save(ctx context.Context, att *discordgo.MessageAttachment, dir string) (string, error)

// core/line — Input.MessageID of an image, video, audio, or file message
func (b *Bot) Save(ctx context.Context, messageID, dir string) (string, error)

Per-platform behavior

Telegram Discord LINE
Size cap 20 MiB (Bot API getFile limit) 25 MiB 50 MiB (library limit)
Size known before download GetFile → FileSize att.Size ContentLength
Download FileDownloadLink over http.DefaultClient att.URL over http.DefaultClient GetMessageContent stream
Extension From Telegram's file_path From att.Filename From the response Content-Type

Shared steps

  1. Reject empty arguments (fileID / att / att.URL / messageID, and dir).
  2. Reject the file when the reported size exceeds the cap, before downloading.
  3. On a non-200 HTTP status (Telegram, Discord), return http <code>: <body> with at most 8 KiB of the body.
  4. Create dir with os.MkdirAll(dir, 0755).
  5. Stream into a temporary file <uuid>.*.tmp inside dir, reading at most cap + 1 bytes. If more than the cap arrives (the reported size was missing or wrong), delete the temp file and return an error. Oversized files are never truncated.
  6. Rename the temp file to <uuid><ext> and return the full path.

The file name is a v4 UUID from go-pkg/utils; an empty UUID (random source failure) is returned as an error. The original Telegram/Discord file name is not kept; for LINE file messages the original name is in Input.FileName.

LINE extension mapping

image/jpeg → .jpg, image/png → .png, image/gif → .gif, image/webp → .webp, video/mp4 → .mp4, audio/mp4 and audio/x-m4a → .m4a, audio/aac → .aac, application/pdf → .pdf. Other types use the first extension from mime.ExtensionsByType; unknown types get no extension.

Example

bot.Reply(func(ctx context.Context, in discord.Input) string {
    for _, att := range in.Attachments {
        path, err := bot.Save(ctx, att, "./uploads")
        if err != nil {
            return "save failed: " + err.Error()
        }
        log.Println("saved", path)
    }
    return ""
})
中文