-
Notifications
You must be signed in to change notification settings - Fork 699
/
events.go
149 lines (130 loc) · 4.83 KB
/
events.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
package config
import (
"errors"
"fmt"
"strings"
validator "github.com/asaskevich/govalidator"
)
// VASTEventElement indicates valid VAST event element
type VASTEventElement string
const (
ImpressionVASTElement VASTEventElement = "impression"
TrackingVASTElement VASTEventElement = "tracking"
ClickTrackingVASTElement VASTEventElement = "clicktracking"
CompanionClickThroughVASTElement VASTEventElement = "companionclickthrough"
ErrorVASTElement VASTEventElement = "error"
NonLinearClickTrackingVASTElement VASTEventElement = "nonlinearclicktracking"
)
var vastEventElementMap = map[VASTEventElement]struct{}{
ImpressionVASTElement: {},
TrackingVASTElement: {},
ClickTrackingVASTElement: {},
CompanionClickThroughVASTElement: {},
ErrorVASTElement: {},
NonLinearClickTrackingVASTElement: {},
}
// TrackingEventType indicates quartile events
type TrackingEventType string
const (
Start TrackingEventType = "start"
FirstQuartile TrackingEventType = "firstQuartile"
MidPoint TrackingEventType = "midPoint"
ThirdQuartile TrackingEventType = "thirdQuartile"
Complete TrackingEventType = "complete"
)
var trackingEventTypeMap = map[TrackingEventType]struct{}{
Start: {},
FirstQuartile: {},
MidPoint: {},
ThirdQuartile: {},
Complete: {},
}
// VASTEvent indicates the configurations required for injecting VAST event trackers within
// VAST XML
type VASTEvent struct {
CreateElement VASTEventElement `mapstructure:"create_element" json:"create_element"`
Type TrackingEventType `mapstructure:"type" json:"type"`
ExcludeDefaultURL bool `mapstructure:"exclude_default_url" json:"exclude_default_url"`
URLs []string `mapstructure:"urls" json:"urls"`
}
// Events indicates the various types of events to be captured typically for injecting tracker URLs
// within the VAST XML
// Don't enable this feature. It is still under developmment. Please follow https://github.com/prebid/prebid-server/issues/1725 for more updates
type Events struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
DefaultURL string `mapstructure:"default_url" json:"default_url"`
VASTEvents []VASTEvent `mapstructure:"vast_events" json:"vast_events,omitempty"`
}
// validate verifies the events object and returns error if at least one is invalid.
func (e Events) validate(errs []error) []error {
if e.Enabled {
if !isValidURL(e.DefaultURL) {
return append(errs, errors.New("Invalid events.default_url"))
}
err := validateVASTEvents(e.VASTEvents)
if err != nil {
return append(errs, err)
}
}
return errs
}
// validateVASTEvents verifies the all VASTEvent objects and returns error if at least one is invalid.
func validateVASTEvents(events []VASTEvent) error {
if events != nil {
for i, event := range events {
if err := event.validate(); err != nil {
return fmt.Errorf(err.Error(), i, i)
}
}
}
return nil
}
// validate validates event object and returns error if at least one is invalid
func (e VASTEvent) validate() error {
if !e.CreateElement.isValid() {
return fmt.Errorf("Invalid events.vast_events[%s].create_element", "%d")
}
validType := e.Type.isValid()
if e.isTrackingEvent() && !validType {
var ele []string
for k := range vastEventElementMap {
ele = append(ele, string(k))
}
return fmt.Errorf("Missing or Invalid events.vast_events[%s].type. Valid values are %v", "%d", strings.Join(ele, ", "))
}
if validType && !e.isTrackingEvent() {
return fmt.Errorf("events.vast_events[%s].type is not applicable for create element '%s'", "%d", e.CreateElement)
}
for i, url := range e.URLs {
if !isValidURL(url) {
return fmt.Errorf("Invalid events.vast_events[%s].urls[%d]", "%d", i)
}
}
// ensure at least one valid url exists when default URL to be excluded
if e.ExcludeDefaultURL && len(e.URLs) == 0 {
return fmt.Errorf("Please provide at least one valid URL in events.vast_events[%s].urls or set events.vast_events[%s].exclude_default_url=false", "%d", "%d")
}
return nil // no errors
}
// isValid checks create_element has valid value
// if value is value returns true, otherwise false
func (element VASTEventElement) isValid() bool {
// validate create element
if _, ok := vastEventElementMap[element]; ok {
return true
}
return false
}
// isValid checks if valid type is provided (case-sensitive)
func (t TrackingEventType) isValid() bool {
_, valid := trackingEventTypeMap[t]
return valid
}
// isValidURL validates the event URL
func isValidURL(eventURL string) bool {
return validator.IsURL(eventURL) && validator.IsRequestURL(eventURL)
}
// isTrackingEvent returns true if event object contains event.CreateElement == "tracking"
func (e VASTEvent) isTrackingEvent() bool {
return e.CreateElement == TrackingVASTElement
}