This repository has been archived by the owner on Nov 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
notifier_telegram.go
138 lines (120 loc) · 4.11 KB
/
notifier_telegram.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package main
import (
"fmt"
"time"
telegram "github.com/go-telegram-bot-api/telegram-bot-api/v5"
log "github.com/sirupsen/logrus"
"gorm.io/gorm"
)
// TelegramMessage to store relationship between a Product and a Telegram notification
type TelegramMessage struct {
gorm.Model
MessageID int `gorm:"not null;unique"`
ProductURL string
Product Product `gorm:"not null;references:URL;constraint:OnDelete:CASCADE"`
}
// TelegramNotifier to manage notifications to Twitter
type TelegramNotifier struct {
db *gorm.DB
bot *telegram.BotAPI
chatID int64
channelName string
enableReplies bool
}
// NewTelegramNotifier to create a Notifier with Telegram capabilities
func NewTelegramNotifier(config *TelegramConfig, db *gorm.DB) (*TelegramNotifier, error) {
// create table
err := db.AutoMigrate(&TelegramMessage{})
if err != nil {
return nil, err
}
// create client
bot, err := telegram.NewBotAPI(config.Token)
if err != nil {
return nil, err
}
log.Debugf("connected to telegram as %s", bot.Self.UserName)
return &TelegramNotifier{
db: db,
bot: bot,
chatID: config.ChatID,
channelName: config.ChannelName,
enableReplies: config.EnableReplies,
}, nil
}
// NotifyWhenAvailable create a Telegram message for announcing that a product is available
// implements the Notifier interface
func (n *TelegramNotifier) NotifyWhenAvailable(shopName string, productName string, productPrice float64, productCurrency string, productURL string) error {
// TODO: check if message exists in the database to avoid flood
// send message to telegram
formattedPrice := formatPrice(productPrice, productCurrency)
rawMessage := `*Name:* %s
*Retailer:* %s
*Price:* %s
*URL*: [go to website](%s)
*Date/Time:* %s`
message := fmt.Sprintf(rawMessage, productName, shopName, formattedPrice, productURL, time.Now().UTC().Format("2006-01-02 15:04:05 (-0700)"))
messageID, err := n.sendMessage(message, 0)
if err != nil {
return err
}
// save telegram message to database
m := TelegramMessage{MessageID: messageID, ProductURL: productURL}
trx := n.db.Create(&m)
if trx.Error != nil {
return fmt.Errorf("failed to save telegram message %d to database: %s", m.MessageID, trx.Error)
}
log.Debugf("telegram message %d saved to database", m.MessageID)
return nil
}
// NotifyWhenNotAvailable create a Telegram message replying to the NotifyWhenAvailable message to say it's gone
// implements the Notifier interface
func (n *TelegramNotifier) NotifyWhenNotAvailable(productURL string, duration time.Duration) error {
// find message in the database
var m TelegramMessage
trx := n.db.Where(TelegramMessage{ProductURL: productURL}).First(&m)
if trx.Error != nil {
return fmt.Errorf("failed to find telegram message in database for product with url %s: %s", productURL, trx.Error)
}
if m.MessageID == 0 {
log.Warnf("telegram message for product with url %s not found, skipping close notification", productURL)
return nil
}
if n.enableReplies {
// format message
text := fmt.Sprintf("And it's gone (%s)", duration)
// send reply on telegram
_, err := n.sendMessage(text, m.MessageID)
if err != nil {
return fmt.Errorf("failed to reply on telegram: %s", err)
}
log.Infof("reply to telegram message %d sent", m.MessageID)
}
// remove message from database
trx = n.db.Unscoped().Delete(&m)
if trx.Error != nil {
return fmt.Errorf("failed to remove message %d from database: %s", m.MessageID, trx.Error)
}
log.Debugf("telegram message removed from database")
return nil
}
func (n *TelegramNotifier) sendMessage(text string, reply int) (int, error) {
log.Debugf("sending message %s to telegram", text)
var request telegram.MessageConfig
if n.chatID != 0 {
request = telegram.NewMessage(n.chatID, text)
} else {
request = telegram.NewMessageToChannel(n.channelName, text)
}
request.DisableWebPagePreview = true
request.ParseMode = telegram.ModeMarkdown
if reply != 0 {
request.ReplyToMessageID = reply
}
response, err := n.bot.Send(request)
if err != nil {
return 0, err
}
log.Infof("message %d sent to telegram", response.MessageID)
return response.MessageID, nil
}