-
Notifications
You must be signed in to change notification settings - Fork 0
/
function.go
129 lines (109 loc) · 3.21 KB
/
function.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
package AppleProductMonitor
import (
"context"
_ "embed"
"fmt"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
"gopkg.in/yaml.v3"
"io/ioutil"
"log"
"time"
)
//go:embed resources/newitem_explanation.txt
var NewItemExplanation string
// PubSubMessage is the payload of a Pub/Sub event. Please refer to the docs for
// additional information regarding Pub/Sub events.
type PubSubMessage struct {
Data []byte `json:"data"`
}
type Configuration struct {
BotToken string `yaml:"botToken"`
ChannelId int64 `yaml:"channelId"`
FetchTarget string `yaml:"fetchTarget"`
FetchIntervalSec int `yaml:"fetchIntervalSec"`
DebugLevel int `yaml:"debugLevel"`
Bucket string `yaml:"bucket"`
Prefix string `yaml:"prefix"`
}
func CrawlAndAnalyze(ctx context.Context, m PubSubMessage) error {
log.Printf("received event %+v\n", m)
confByte, err := ioutil.ReadFile("/secrets/AppleTwNccBotConfig.yml")
if err != nil {
return err
}
log.Printf("config : %s", string(confByte))
config := Configuration{}
err = yaml.Unmarshal(confByte, &config)
if err != nil {
return err
}
//Initialize bot
bot, err := tgbotapi.NewBotAPI(config.BotToken)
if err != nil {
return fmt.Errorf("bot initialization failed, bot ID is %s, err = %v", config.BotToken, err)
}
//Initialize Storage
dataAccess, err := NewGcsDataAccess(ctx, config.Bucket, config.Prefix)
if err != nil {
return fmt.Errorf("GCS initialization failed, err = %v", err)
}
crawler := Crawler{
DataAccess: dataAccess,
FetchTarget: "https://www.apple.com/tw/nccid",
}
event, err := crawler.FetchAndCompare(ctx)
if err != nil {
return err
}
if len(event.Added) > 0 {
sendToChannel(bot, config.ChannelId, "偵測到新加入產品:")
addList := prettyPrintProducts(event.Added, "(+)")
for _, v := range addList {
sendToChannel(bot, config.ChannelId, v)
}
sendToChannel(bot, config.ChannelId, NewItemExplanation)
}
if len(event.Removed) > 0 {
sendToChannel(bot, config.ChannelId, "偵測到移除產品:")
removeList := prettyPrintProducts(event.Removed, "(-)")
for _, v := range removeList {
sendToChannel(bot, config.ChannelId, v)
}
}
if len(event.Removed) != 0 || len(event.Added) != 0 {
//Serialize into gcs
err = dataAccess.SaveDiff(ctx, event)
if err != nil {
return fmt.Errorf("unable write diff file : %v", err)
}
}
return nil
}
func sendToChannel(bot *tgbotapi.BotAPI, channelId int64, message string) {
log.Println("Sending : ", message)
msg := tgbotapi.NewMessage(channelId, message)
_, _ = bot.Send(msg)
time.Sleep(1 * time.Second)
}
func prettyPrintProducts(source []Product, prefix string) (ret []string) {
log.Printf("Trying to print : %+v", source)
productMap := make(map[string][]Product)
for _, r := range source {
if v, exist := productMap[r.Group]; !exist {
productMap[r.Group] = []Product{r}
} else {
productMap[r.Group] = append(v, r)
}
}
log.Printf("Product Map : %+v", productMap)
ret = make([]string, 0)
for k, v := range productMap {
var buffer string
buffer += fmt.Sprintf("產品 : %s\n", k)
for _, p := range v {
buffer += fmt.Sprintf("%s%s, %s, %s\n", prefix, p.Model, p.NCC, p.Product)
}
ret = append(ret, buffer)
}
return
}