-
Notifications
You must be signed in to change notification settings - Fork 0
/
listeners.go
157 lines (140 loc) · 4.79 KB
/
listeners.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package papaBot
// Full message handling routines.
import (
"fmt"
"github.com/pawelszydlo/papa-bot/events"
"github.com/pawelszydlo/papa-bot/utils"
"log"
"mvdan.cc/xurls/v2"
"os"
"regexp"
"time"
)
var titleRe = regexp.MustCompile("(?is)<title.*?>(.+?)</title>")
var metaRe = regexp.MustCompile(`(?is)<\s*?meta.*?content\s*?=\s*?"(.*?)".*?>`)
var descRe = regexp.MustCompile(`(?is)(property|name)\s*?=.*?description`)
// messageListener looks for commands in messages.
func (bot *Bot) messageListener(message events.EventMessage) {
// Increase lines count for all announcements.
for k := range bot.lastURLAnnouncedLinesPassed {
bot.lastURLAnnouncedLinesPassed[k] += 1
// After 100 lines pass, forget it ever happened.
if bot.lastURLAnnouncedLinesPassed[k] > 100 {
delete(bot.lastURLAnnouncedLinesPassed, k)
delete(bot.lastURLAnnouncedTime, k)
}
}
// Handles the commands.
if message.AtBot {
bot.handleBotCommand(&message)
}
}
// handleURLsListener finds all URLs in the message and fires URL events on them.
func (bot *Bot) handleURLsListener(message events.EventMessage) {
// Find all URLs in the message.
links := xurls.Strict().FindAllString(message.Message, -1)
// Remove multiple same links from one message.
links = utils.RemoveDuplicates(links)
for i := range links {
// Validate the url.
bot.Log.Infof("Got link %s", links[i])
link := utils.StandardizeURL(links[i])
bot.Log.Debugf("Standardized to: %s", link)
// Try to get the body of the page.
err, finalLink, body := bot.GetPageBody(link, map[string]string{})
if err != nil {
bot.Log.Warningf("Could't fetch the body: %s", err)
}
// Update link if needed.
if finalLink != "" {
link = finalLink
}
// Iterate over meta tags to get the description
description := ""
metas := metaRe.FindAllStringSubmatch(string(body), -1)
for i := range metas {
if len(metas[i]) > 1 {
isDesc := descRe.FindString(metas[i][0])
if isDesc != "" && (len(metas[i][1]) > len(description)) {
description = utils.CleanString(metas[i][1], true)
}
}
}
// Get the title
title := ""
match := titleRe.FindStringSubmatch(string(body))
if len(match) > 1 {
title = utils.CleanString(match[1], true)
}
// Insert URL into the db.
bot.Log.Debugf("Storing URL info for: %s", link)
if _, err := bot.Db.Exec(`INSERT INTO urls(transport, channel, nick, link, quote, title) VALUES(?, ?, ?, ?, ?, ?)`,
message.TransportName, message.Channel, message.Nick, link, message.Message, title); err != nil {
bot.Log.Warningf("Can't add url to database: %s", err)
}
// Trigger url found message.
bot.EventDispatcher.Trigger(events.EventMessage{
message.TransportName,
message.TransportFormatting,
events.EventURLFound,
message.Nick,
message.UserId,
message.Channel,
link,
message.Context,
message.AtBot,
})
linkKey := link + message.Channel
// If we can't announce yet, skip this link.
if time.Since(bot.lastURLAnnouncedTime[linkKey]) < bot.Config.UrlAnnounceIntervalMinutes*time.Minute {
continue
}
if lines, exists := bot.lastURLAnnouncedLinesPassed[linkKey]; exists && lines < bot.Config.UrlAnnounceIntervalLines {
continue
}
// On mattermost we can skip all link info display.
if message.TransportName == "mattermost" {
return
}
// Announce the title, save the description.
if title != "" {
if description != "" {
bot.SendNotice(&message, title+" …")
} else {
bot.SendNotice(&message, title)
}
bot.lastURLAnnouncedTime[linkKey] = time.Now()
bot.lastURLAnnouncedLinesPassed[linkKey] = 0
// Keep the long info for later.
bot.AddMoreInfo(message.TransportName, message.Channel, description)
}
}
}
// scribe saves the message into appropriate channel log file.
func (bot *Bot) scribeListener(message events.EventMessage) {
if !bot.Config.ChatLogging {
return
}
go func() {
logFileName := fmt.Sprintf(
"logs/%s_%s_%s.txt", message.TransportName, message.Channel, time.Now().Format("2006-01-02"))
f, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
bot.Log.Errorf("Error opening log file: %s", err)
return
}
defer f.Close()
scribe := log.New(f, "", log.Ldate|log.Ltime)
if message.EventCode == events.EventChatMessage {
scribe.Println(fmt.Sprintf("%s: %s", message.Nick, message.Message))
} else if message.EventCode == events.EventChatNotice {
scribe.Println(fmt.Sprintf("Notice from %s: %s", message.Nick, message.Message))
} else if message.EventCode == events.EventJoinedChannel {
scribe.Println(fmt.Sprintf("* %s joined.", message.Nick))
} else if message.EventCode == events.EventPartChannel {
scribe.Println(fmt.Sprintf("* %s left.", message.Nick))
} else { // Must be channel activity.
scribe.Println(fmt.Sprintf("* %s %s", message.Nick, message.Message))
}
}()
}