Skip to content
This repository was archived by the owner on May 29, 2024. It is now read-only.

Commit c960e5b

Browse files
committed
Implement Telegram alert client
1 parent a692c87 commit c960e5b

File tree

2 files changed

+113
-1
lines changed

2 files changed

+113
-1
lines changed

internal/client/slack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ type slackClient struct {
4343
// NewSlackClient ... Initializer
4444
func NewSlackClient(cfg *SlackConfig, name string) SlackClient {
4545
if cfg.URL == "" {
46-
logging.NoContext().Warn("No Slack webhook URL not provided")
46+
logging.NoContext().Warn("No Slack webhook URL provided")
4747
}
4848

4949
return &slackClient{

internal/client/telegram.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package client
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"fmt"
8+
"io"
9+
"net/http"
10+
11+
"github.com/base-org/pessimism/internal/core"
12+
"github.com/base-org/pessimism/internal/logging"
13+
)
14+
15+
// TelegramConfig stores configuration for the Telegram bot
16+
type TelegramConfig struct {
17+
Token string // Bot token received from BotFather
18+
ChatID string // Chat ID where messages will be sent
19+
}
20+
21+
// TelegramClient interface for sending alerts
22+
type TelegramClient interface {
23+
AlertClient
24+
}
25+
26+
// telegramClient implementation of TelegramClient
27+
type telegramClient struct {
28+
token string
29+
chatID string
30+
client *http.Client
31+
}
32+
33+
// NewTelegramClient initializes a new Telegram client with given config
34+
func NewTelegramClient(cfg *TelegramConfig) TelegramClient {
35+
if cfg.Token == "" {
36+
logging.NoContext().Warn("No Telegram token provided")
37+
}
38+
39+
return &telegramClient{
40+
token: cfg.Token,
41+
chatID: cfg.ChatID,
42+
client: &http.Client{},
43+
}
44+
}
45+
46+
// TelegramPayload structure for the message payload
47+
type TelegramPayload struct {
48+
ChatID string `json:"chat_id"`
49+
Text string `json:"text"`
50+
}
51+
52+
// PostEvent sends an alert message to the specified Telegram chat
53+
func (tc *telegramClient) PostEvent(ctx context.Context, data *AlertEventTrigger) (*AlertAPIResponse, error) {
54+
payload := TelegramPayload{
55+
ChatID: tc.chatID,
56+
Text: data.Message,
57+
}
58+
59+
payloadBytes, err := json.Marshal(payload)
60+
if err != nil {
61+
return nil, err
62+
}
63+
64+
url := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", tc.token)
65+
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(payloadBytes))
66+
if err != nil {
67+
return nil, err
68+
}
69+
req.Header.Set("Content-Type", "application/json")
70+
71+
resp, err := tc.client.Do(req)
72+
if err != nil {
73+
return nil, err
74+
}
75+
defer resp.Body.Close()
76+
77+
respBytes, err := io.ReadAll(resp.Body)
78+
if err != nil {
79+
return nil, err
80+
}
81+
82+
if resp.StatusCode != http.StatusOK {
83+
return nil, fmt.Errorf("telegram API returned bad status code %d: %s", resp.StatusCode, string(respBytes))
84+
}
85+
86+
// Simplified handling
87+
var apiResp struct {
88+
Ok bool `json:"ok"`
89+
Result json.RawMessage `json:"result"`
90+
Error string `json:"description"`
91+
}
92+
if err = json.Unmarshal(respBytes, &apiResp); err != nil {
93+
return nil, fmt.Errorf("could not unmarshal telegram response: %w", err)
94+
}
95+
96+
if !apiResp.Ok {
97+
return &AlertAPIResponse{
98+
Status: core.FailureStatus,
99+
Message: apiResp.Error,
100+
}, nil
101+
}
102+
103+
return &AlertAPIResponse{
104+
Status: core.SuccessStatus,
105+
Message: "Message sent successfully",
106+
}, nil
107+
}
108+
109+
// GetName returns the name of the Telegram client
110+
func (tc telegramClient) GetName() string {
111+
return "TelegramClient"
112+
}

0 commit comments

Comments
 (0)