-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.go
133 lines (112 loc) · 3.59 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 (
"flag"
"fmt"
"github.com/darkhelmet/twitterstream"
"github.com/njern/gogmail"
"log"
"sort"
"time"
)
const (
RECONNECT_TIME = time.Duration(30 * time.Second)
LINK_SEND_INTERVAL = time.Duration(24 * time.Hour)
)
var (
topics = flag.String("topics", "", "The topics Hutch should be tracking.")
numberOfLinks = flag.Int("num_links", 5, "The number of unique links to track (daily)")
trackedLinks = make(map[string]int)
lastLinksSentTime = time.Now()
gmail *gogmail.GMail
)
var config struct {
ConsumerKey string
ConsumerSecret string
AccessToken string
AccessSecret string
GmailUser string
GmailPassword string
Sendto string
}
func parseFlags() {
flag.Parse()
if *topics == "" {
log.Fatalln("Please specify --topics \"some topics here\"(according to https://dev.twitter.com/docs/streaming-apis/parameters#track)")
}
}
func handleIncomingTweet(tweet *twitterstream.Tweet) {
if len(tweet.Entities.Urls) == 0 {
//log.Printf("Skipping tweet: '%s', written by %s - It does not contain any URL's!\n", tweet.Text, tweet.User.ScreenName)
return
}
for _, url := range tweet.Entities.Urls {
finalURL, err := resolveFinalURL(url.Url)
if err != nil {
log.Printf("Error resolving URL %s: Error was: %s\n", url, err)
return
}
// Store the number of times we've seen this particular, unique URL
_, ok := trackedLinks[finalURL]
if !ok {
trackedLinks[finalURL] = 1
} else {
trackedLinks[finalURL] += 1
}
}
// Send the most popular links and clear the list every twenty-four hours.
if time.Since(lastLinksSentTime).Seconds() > LINK_SEND_INTERVAL.Seconds() {
// Refresh the lastLinksSentTime
lastLinksSentTime = time.Now()
// Extract the list of unique links
var linkScores []LinkScore
for link, score := range trackedLinks {
linkScores = append(linkScores, LinkScore{link, score})
}
// Sort in descending order
sort.Sort(sort.Reverse(ByScore(linkScores)))
// Send the top links (in order) via e-mail (TODO: HTML template)
list := fmt.Sprintf("Hi there %s, here are your links for the last 24 hours:\n\n\n", config.GmailUser)
for i := 0; i < min(*numberOfLinks, len(linkScores)); i++ {
list += fmt.Sprintf("\t* %s - %d mentions\n", linkScores[i].link, linkScores[i].score)
}
list += "\nKind regards,\n\nHutch"
subject := fmt.Sprintf("Your daily tracked links from Twitter")
err := gmail.SendMail([]string{config.Sendto}, subject, list, false)
if err != nil {
log.Fatalf("Something went horribly wrong sending your daily e-mail! Error was: %s\n", err)
}
// Empty the list and begin the dance all over again.
trackedLinks = make(map[string]int)
}
}
func init() {
parseFlags() // Parse flags
}
func main() {
// Load credentials
loadCredentials()
// Initialize Twitter streaming client.
twitterStream := twitterstream.NewClient(config.ConsumerKey, config.ConsumerSecret, config.AccessToken, config.AccessSecret)
// Initialize e-mail "client"
gmail = gogmail.GmailConnection(config.GmailUser, config.GmailPassword)
for {
stream, err := twitterStream.Track(*topics)
if err != nil {
log.Printf("Connecting to the streaming API failed, reconnecting in %s...\n", RECONNECT_TIME)
time.Sleep(RECONNECT_TIME)
continue
}
for {
tweet, err := stream.Next()
if err != nil {
log.Println("Connection died with error:", err)
log.Printf("Reconnecting in %s...\n", RECONNECT_TIME)
break
}
// Handle the Tweet that just came in
handleIncomingTweet(tweet)
}
// We sleep a while before reconnecting to keep Twitter happy.
time.Sleep(RECONNECT_TIME)
}
}