-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
133 lines (112 loc) · 2.94 KB
/
main.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
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"strings"
"time"
"github.com/PuerkitoBio/goquery"
"github.com/spf13/viper"
)
type SlackRequestBody struct {
Text string `json:"text"`
}
type Configuration struct {
Frequency int
WebhookUrl string
SearchUrl string
SearchText string
DomSearch string
FoundMsg string
NotFoundMsg string
}
// Author: Edd Turtle
// https://golangcode.com/send-slack-messages-without-a-library/
// SendSlackNotification will post to an 'Incoming Webook' url setup in
// Slack Apps. It accepts some text and the slack channel is saved within Slack.
func SendSlackNotification(webhookUrl string, msg string) error {
slackBody, _ := json.Marshal(SlackRequestBody{Text: msg})
req, err := http.NewRequest(http.MethodPost, webhookUrl, bytes.NewBuffer(slackBody))
if err != nil {
return err
}
req.Header.Add("Content-Type", "application/json")
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
}
buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
if buf.String() != "ok" {
return errors.New("Non-ok response returned from Slack")
}
return nil
}
func retrievePage(searchUrl string) *goquery.Document {
// make client
client := &http.Client{
Timeout: 30 * time.Second,
}
// make request
response, err := client.Get("https://jobs.dev.to/")
if err != nil {
log.Fatal(err)
}
defer response.Body.Close()
document, err := goquery.NewDocumentFromReader(response.Body)
if err != nil {
log.Fatal("Error loading HTTP response body. ", err)
}
return document
}
func SendNotification(searchUrl string) {
webhookUrl := viper.GetString("webhookUrl")
changeMessage := viper.GetString("changeDetectedMsg") + " " + searchUrl
SendSlackNotification(webhookUrl, changeMessage)
log.Println(changeMessage)
}
func checkForListings(configuration Configuration, foundChange bool) bool {
searchUrl := configuration.SearchUrl
document := retrievePage(searchUrl)
changeDetected := foundChange
openings := document.Find(configuration.DomSearch)
if strings.TrimSpace(openings.Text()) == configuration.SearchText {
log.Println("No changes detected.")
changeDetected = false
} else {
if foundChange == false {
SendNotification(searchUrl)
changeDetected = true
}
}
return changeDetected
}
func configSetup() {
viper.SetConfigName("config")
viper.AddConfigPath("/etc/page-watcher/")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
}
func main() {
var configuration Configuration
configSetup()
err := viper.Unmarshal(&configuration)
if err != nil {
log.Fatalf("unable to decode into struct, %v", err)
}
foundChange := false
for {
foundChange = checkForListings(configuration, foundChange)
if configuration.Frequency < 1 {
configuration.Frequency = 1
}
time.Sleep(time.Duration(configuration.Frequency) * time.Minute)
}
}