-
Notifications
You must be signed in to change notification settings - Fork 4
/
message.go
121 lines (105 loc) · 2.69 KB
/
message.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
package data
import (
"bytes"
"fmt"
html "html/template"
"sync"
text "text/template"
)
// Message is the data generated from a Feeder and it travels across Filters
type Message struct {
sync.RWMutex
fields map[string]interface{}
}
// NewMessage creates a new Message struct with only the "main" data
func NewMessage(msg interface{}) *Message {
return NewMessageWithExtra(msg, map[string]interface{}{})
}
// NewMessageWithExtra creates a Message struct with "main" and extra data
func NewMessageWithExtra(msg interface{}, extra map[string]interface{}) *Message {
extra["main"] = msg
return &Message{
fields: extra,
}
}
// SetMessage allows to change the "main" data in the Message struct
func (d *Message) SetMessage(msg interface{}) {
d.Lock()
defer d.Unlock()
d.fields["main"] = msg
}
// GetMessage returns the "main" data in the Message struct
func (d *Message) GetMessage() interface{} {
d.RLock()
defer d.RUnlock()
return d.fields["main"]
}
// SetExtra allows to change the "extra" data with key k and value v in the Message struct
func (d *Message) SetExtra(k string, v interface{}) {
d.Lock()
defer d.Unlock()
if k == "main" {
return
}
d.fields[k] = v
}
// GetExtra returns all the "extra" data in the Message struct
func (d *Message) GetExtra() map[string]interface{} {
d.Lock()
defer d.Unlock()
clone := make(map[string]interface{})
for key, value := range d.fields {
if key == "main" {
// Ignoring main content
continue
}
clone[key] = value
}
return clone
}
// SetTarget is like SetExtra but it can change also the "main" key
func (d *Message) SetTarget(name string, value interface{}) {
d.Lock()
defer d.Unlock()
d.fields[name] = value
}
// GetTarget returns the value of a key in the Message struct. It can return also the "main" data
func (d *Message) GetTarget(name string) interface{} {
d.RLock()
defer d.RUnlock()
if v, ok := d.fields[name]; ok {
return v
}
return nil
}
// Clone creates a deep copy of the Message struct
func (d *Message) Clone() *Message {
clone := &Message{
fields: make(map[string]interface{}, 0),
}
for k, v := range d.fields {
clone.fields[k] = v
}
return clone
}
// ApplyPlaceholder executes the template specified using the data in the Message struct
func (d *Message) ApplyPlaceholder(template interface{}) (string, error) {
d.RLock()
defer d.RUnlock()
var writer bytes.Buffer
switch t := template.(type) {
case *html.Template:
err := t.Execute(&writer, d.fields)
if err != nil {
return "", err
}
return writer.String(), nil
case *text.Template:
err := t.Execute(&writer, d.fields)
if err != nil {
return "", err
}
return writer.String(), nil
}
return "", fmt.Errorf("template type not supported")
}