- Add Telegram integration support by introducing a dispatcher for handling Telegram events and messages. - Implement event notifications for robot configuration changes (creation, update, deletion) to facilitate integration with external services. - Refactor the robot initialization process to load robots into cache and start the dispatcher, improving the overall system setup. - Update the delivery event structure to include additional metadata for better context during message handling. - Enhance logging capabilities for better observability during robot execution and event processing.
81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
package telegram
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/go-telegram/bot/models"
|
|
)
|
|
|
|
// GetUpdates fetches new updates via long polling and returns them as
|
|
// ConvertedMessages ready for consumption. Non-message updates (e.g.
|
|
// callback_query without a message) are silently skipped.
|
|
// When groups is non-nil, media attachments are automatically downloaded
|
|
// and stored via DownloadAndStore, filling each MediaItem.Wrapper.
|
|
func (b *Bot) GetUpdates(ctx context.Context, offset int64, timeout int, groups []string) ([]*ConvertedMessage, error) {
|
|
raw, err := b.GetRawUpdates(ctx, offset, timeout)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var msgs []*ConvertedMessage
|
|
for i := range raw {
|
|
if cm := ConvertUpdate(&raw[i]); cm != nil {
|
|
if groups != nil && cm.HasMedia() {
|
|
b.ResolveMedia(ctx, cm, groups)
|
|
}
|
|
msgs = append(msgs, cm)
|
|
}
|
|
}
|
|
return msgs, nil
|
|
}
|
|
|
|
// GetRawUpdates fetches raw Telegram updates without conversion.
|
|
// Use this when you need access to the original models.Update (e.g. for
|
|
// offset tracking). Uses raw HTTP because the SDK keeps getUpdates private.
|
|
func (b *Bot) GetRawUpdates(ctx context.Context, offset int64, timeout int) ([]models.Update, error) {
|
|
params := map[string]interface{}{
|
|
"offset": offset,
|
|
"timeout": timeout,
|
|
"limit": 100,
|
|
}
|
|
body, err := json.Marshal(params)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("marshal params: %w", err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "POST", b.botURL()+"/getUpdates", bytes.NewReader(body))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("create request: %w", err)
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := b.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
respBody, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read response: %w", err)
|
|
}
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("telegram API error status=%d body=%s", resp.StatusCode, string(respBody))
|
|
}
|
|
|
|
var result struct {
|
|
OK bool `json:"ok"`
|
|
Result []models.Update `json:"result"`
|
|
}
|
|
if err := json.Unmarshal(respBody, &result); err != nil {
|
|
return nil, fmt.Errorf("unmarshal response: %w", err)
|
|
}
|
|
if !result.OK {
|
|
return nil, fmt.Errorf("telegram API returned ok=false")
|
|
}
|
|
return result.Result, nil
|
|
}
|