OvyFlash / telegram-bot-api

Golang bindings for the Telegram Bot API
https://go-telegram-bot-api.dev
MIT License
100 stars 48 forks source link

Large Files & custom endpoint #46

Closed soaska closed 4 minutes ago

soaska commented 2 days ago

Hi~ I want to download large files from telegram. Telegram api docs says that I need own bot api. So:

telegram-bot-api:
    image: aiogram/telegram-bot-api:latest
    hostname: tgapi
    env_file:
      - .env
    volumes:
      - ./data/telegram-bot-api:/var/lib/telegram-bot-api
    ports:
      - "8081:8081"
      - "8082:8082" # statistics

In my code I define bot like this:

    // start the bot
    bot, err := tgbotapi.NewBotAPIWithAPIEndpoint(BOT_TOKEN, BOT_ENDPOINT+`/bot%s/%s`)
    if err != nil {
        panic(err)
    } else {
        log.Printf("Authorized on account %s", bot.Self.UserName)
    }
    if BOT_DEBUG {
        bot.Debug = true
        log.Print("bot in DEBUG mode")
    }

And I'm trying to download files like this:

        file, err := bot.GetFile(tgbotapi.FileConfig{FileID: fileID})
    if err != nil {
        return fmt.Errorf("replace with fancy err text: %v", err)
    }

    fileURL := fmt.Sprintf("%s/file/bot%s/%s", api_endpint, bot.Token, file.FilePath)

    // Download request
    resp, err := http.Get(fileURL)
    if err != nil {
        return fmt.Errorf("replace wit text: %v", err)
    }
    defer resp.Body.Close()

This function gives error "Bad Request: file is too big" when calling bot.GetFile. Is there a proper way to do that?

soaska commented 2 days ago

Ig I need to override var named FileEndpoint But how

soaska commented 2 days ago

I think you can add FileEndpoint to FileConfig structure, but it will change endpint globally

soaska commented 4 minutes ago

Using local Telegram API, don't forget to set TELEGRAM_LOCAL=1. Now all files will be stored at /var/lib/telegram-bot-api. Then if you make a GetFile request, the API will return the path to the file in that location. So you need to mount /var/lib/telegram-bot-api to your program when you need to use the local Telegram API and get the path like this:


func getTelegramFile(bot *tgbotapi.BotAPI, fileID string) (string, error) {
    //file, err := bot.GetFile(tgbotapi.FileConfig{FileID: fileID})
    CallUrl := fmt.Sprintf("%s/bot%s/getFile?file_id=%s", api_endpoint, bot.Token, fileID)
    resp, err := http.Get(CallUrl)
    if err != nil {
        return "", fmt.Errorf("http error: %v", err)
    }
    defer resp.Body.Close()

    responseBody, err := io.ReadAll(resp.Body)
    if err != nil {
        return "", fmt.Errorf(“response interpretation error: %v", err)
    }

    fileResponse := &FileResponse{}
    err = json.Unmarshal(responseBody, fileResponse)
    if err != nil {
        return "", fmt.Errorf("JSON interpretation error: %v", err)
    }

    if fileResponse.OK {
        filePath, ok := fileResponse.Result["file_path"]
        if !ok || filePath == "" {
            return "", fmt.Errorf("path not found")
        }
        return filePath.(string), nil
    } else {
        return "", fmt.Errorf("error getting path: %v", resp.StatusCode)
    }
}