mirror of
https://github.com/databasus/databasus.git
synced 2026-04-06 00:32:03 +02:00
118 lines
2.7 KiB
Go
118 lines
2.7 KiB
Go
package telegram_notifier
|
|
|
|
import (
|
|
"databasus-backend/internal/util/encryption"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type TelegramNotifier struct {
|
|
NotifierID uuid.UUID `json:"notifierId" gorm:"primaryKey;column:notifier_id"`
|
|
BotToken string `json:"botToken" gorm:"not null;column:bot_token"`
|
|
TargetChatID string `json:"targetChatId" gorm:"not null;column:target_chat_id"`
|
|
ThreadID *int64 `json:"threadId" gorm:"column:thread_id"`
|
|
}
|
|
|
|
func (t *TelegramNotifier) TableName() string {
|
|
return "telegram_notifiers"
|
|
}
|
|
|
|
func (t *TelegramNotifier) Validate(encryptor encryption.FieldEncryptor) error {
|
|
if t.BotToken == "" {
|
|
return errors.New("bot token is required")
|
|
}
|
|
|
|
if t.TargetChatID == "" {
|
|
return errors.New("target chat ID is required")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TelegramNotifier) Send(
|
|
encryptor encryption.FieldEncryptor,
|
|
logger *slog.Logger,
|
|
heading string,
|
|
message string,
|
|
) error {
|
|
botToken, err := encryptor.Decrypt(t.NotifierID, t.BotToken)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to decrypt bot token: %w", err)
|
|
}
|
|
|
|
fullMessage := heading
|
|
if message != "" {
|
|
fullMessage = fmt.Sprintf("%s\n\n%s", heading, message)
|
|
}
|
|
|
|
apiURL := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", botToken)
|
|
|
|
data := url.Values{}
|
|
data.Set("chat_id", t.TargetChatID)
|
|
data.Set("text", fullMessage)
|
|
data.Set("parse_mode", "HTML")
|
|
|
|
if t.ThreadID != nil && *t.ThreadID != 0 {
|
|
data.Set("message_thread_id", strconv.FormatInt(*t.ThreadID, 10))
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", apiURL, strings.NewReader(data.Encode()))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create request: %w", err)
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
|
|
client := &http.Client{}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to send telegram message: %w", err)
|
|
}
|
|
defer func() {
|
|
_ = resp.Body.Close()
|
|
}()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
return fmt.Errorf(
|
|
"telegram API returned non-OK status: %s. Error: %s",
|
|
resp.Status,
|
|
string(bodyBytes),
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TelegramNotifier) HideSensitiveData() {
|
|
t.BotToken = ""
|
|
}
|
|
|
|
func (t *TelegramNotifier) Update(incoming *TelegramNotifier) {
|
|
t.TargetChatID = incoming.TargetChatID
|
|
t.ThreadID = incoming.ThreadID
|
|
|
|
if incoming.BotToken != "" {
|
|
t.BotToken = incoming.BotToken
|
|
}
|
|
}
|
|
|
|
func (t *TelegramNotifier) EncryptSensitiveData(encryptor encryption.FieldEncryptor) error {
|
|
if t.BotToken != "" {
|
|
encrypted, err := encryptor.Encrypt(t.NotifierID, t.BotToken)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to encrypt bot token: %w", err)
|
|
}
|
|
t.BotToken = encrypted
|
|
}
|
|
return nil
|
|
}
|