Skip to content

Commit

Permalink
Merge pull request #94 from inovex/regexTitleFilter
Browse files Browse the repository at this point in the history
Add regexTitle Filter
  • Loading branch information
MichaelEischer authored Nov 15, 2023
2 parents c0d2d8b + 29ee397 commit 8107b89
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 7 deletions.
6 changes: 5 additions & 1 deletion example.sync.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ source:
tenantId: "[UUID-format string here]"

# ZEP source adapter
#source:
#source:
# adapter:
# type: "zep"
# calendar: "absences"
Expand Down Expand Up @@ -60,6 +60,10 @@ filters:
- name: DeclinedEvents
# Events which cover the full day aren't synced
- name: AllDayEvents
# Exclude Events which match the following regular expression, syntax here: https://github.com/google/re2/wiki/Syntax
- name: RegexTitle
config:
ExcludeRegexp: ".*test"

# Perform multiple calendar updates concurrently
# Defaults to 1 if not set
Expand Down
39 changes: 39 additions & 0 deletions internal/filter/allDayEvents_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package filter_test

import (
"testing"

"github.com/inovex/CalendarSync/internal/filter"
"github.com/inovex/CalendarSync/internal/models"
)

// All Day Events should be filtered
func TestAllDayEventsFilter(t *testing.T) {
sourceEvents := []models.Event{
{
ICalUID: "testId",
ID: "testUid",
Title: "test",
Description: "bar",
AllDay: true,
},
{
ICalUID: "testId2",
ID: "testUid2",
Title: "Test 2",
Description: "bar",
AllDay: false,
},
{
ICalUID: "testId3",
ID: "testUid2",
Title: "foo",
Description: "bar",
},
}

expectedSinkEvents := []models.Event{sourceEvents[1], sourceEvents[2]}

eventFilter := filter.AllDayEvents{}
checkEventFilter(t, eventFilter, sourceEvents, expectedSinkEvents)
}
40 changes: 40 additions & 0 deletions internal/filter/declinedEvents_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package filter_test

import (
"testing"

"github.com/inovex/CalendarSync/internal/filter"
"github.com/inovex/CalendarSync/internal/models"
)

// Declined Events should be filtered
func TestDeclinedEventsFilter(t *testing.T) {
sourceEvents := []models.Event{
{
ICalUID: "testId",
ID: "testUid",
Title: "test",
Description: "bar",
Accepted: false,
},
{
ICalUID: "testId2",
ID: "testUid2",
Title: "Test 2",
Description: "bar",
Accepted: true,
},
{
ICalUID: "testId3",
ID: "testUid3",
Title: "foo",
Description: "bar",
Accepted: true,
},
}

expectedSinkEvents := []models.Event{sourceEvents[1], sourceEvents[2]}

eventFilter := filter.DeclinedEvents{}
checkEventFilter(t, eventFilter, sourceEvents, expectedSinkEvents)
}
40 changes: 40 additions & 0 deletions internal/filter/regexTitle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package filter

import (
"regexp"

"github.com/charmbracelet/log"

"github.com/inovex/CalendarSync/internal/models"
)

type RegexTitle struct {
ExcludeRegexp string
}

func (a RegexTitle) Name() string {
return "RegexTitle"
}

func (a RegexTitle) Filter(event models.Event) bool {

if len(a.ExcludeRegexp) == 0 {
log.Debugf("Regular Expression is empty, skipping Filter %s for event: %s", a.Name(), event.Title)
return true
}

log.Debugf("Running Regexp %s on event title: %s", a.ExcludeRegexp, event.Title)

r, err := regexp.Compile(a.ExcludeRegexp)
if err != nil {
log.Fatalf("Regular expression of Filter %s is not valid, please check", a.Name())
}

// if the title matches the Regexp, return false (filter the event)
if r.MatchString(event.Title) {
log.Debugf("Regular Expression %s matches the events title: %s, gets filtered", a.Name(), event.Title)
return false
}

return true
}
50 changes: 50 additions & 0 deletions internal/filter/regexTitle_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package filter_test

import (
"testing"

"github.com/inovex/CalendarSync/internal/filter"
"github.com/inovex/CalendarSync/internal/models"
)

var sourceEvents = []models.Event{
{
ICalUID: "testId",
ID: "testUid",
Title: "test",
Description: "bar",
},
{
ICalUID: "testId2",
ID: "testUid2",
Title: "Test 2",
Description: "bar",
},
{
ICalUID: "testId3",
ID: "testUid2",
Title: "foo",
Description: "bar",
},
}

// Some events should be filtered
func TestRegexTitleFilter(t *testing.T) {

expectedSinkEvents := []models.Event{sourceEvents[1], sourceEvents[2]}

eventFilter := filter.RegexTitle{
ExcludeRegexp: ".*test",
}
checkEventFilter(t, eventFilter, sourceEvents, expectedSinkEvents)
}

// All Events should be there
func TestRegexTitleFilterEmptyRegex(t *testing.T) {
expectedSinkEvents := sourceEvents

eventFilter := filter.RegexTitle{
ExcludeRegexp: "",
}
checkEventFilter(t, eventFilter, sourceEvents, expectedSinkEvents)
}
23 changes: 23 additions & 0 deletions internal/filter/util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package filter_test

import (
"github.com/inovex/CalendarSync/internal/models"
"github.com/inovex/CalendarSync/internal/sync"
"github.com/stretchr/testify/assert"
)

// FilterEvents takes an array of events and a filter and executes the .Filter Method on each of the sourceEvents
// Not excluded events get returned in the filteredEvents
func FilterEvents(sourceEvents []models.Event, filter sync.Filter) (filteredEvents []models.Event) {
for _, event := range sourceEvents {
if filter.Filter(event) {
filteredEvents = append(filteredEvents, event)
}
}
return filteredEvents
}

func checkEventFilter(t assert.TestingT, filter sync.Filter, sourceEvents []models.Event, expectedEvents []models.Event) {
filteredEvents := FilterEvents(sourceEvents, filter)
assert.Equal(t, expectedEvents, filteredEvents)
}
9 changes: 6 additions & 3 deletions internal/sync/filter.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package sync

import (
"fmt"
"strings"

"github.com/charmbracelet/log"

"github.com/inovex/CalendarSync/internal/config"
"github.com/inovex/CalendarSync/internal/filter"
"github.com/inovex/CalendarSync/internal/models"
Expand Down Expand Up @@ -31,19 +32,21 @@ var (
filterConfigMapping = map[string]Filter{
"DeclinedEvents": &filter.DeclinedEvents{},
"AllDayEvents": &filter.AllDayEvents{},
"RegexTitle": &filter.RegexTitle{},
}

filterOrder = []string{
"DeclinedEvents",
"AllDayEvents",
"RegexTitle",
}
)

func FilterFactory(configuredFilters []config.Filter) (loadedFilters []Filter) {
for _, configuredFilter := range configuredFilters {
if _, nameExists := filterConfigMapping[configuredFilter.Name]; !nameExists {
// todo: handle properly
panic(fmt.Sprintf("unknown filter: %s", configuredFilter.Name))
log.Warnf("unknown filter: %s, skipping...", configuredFilter.Name)
continue
}
// load the default Transformer for the configured name and initialize it based on the config
filterDefault := filterConfigMapping[configuredFilter.Name]
Expand Down
7 changes: 4 additions & 3 deletions internal/sync/transformer.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package sync

import (
"fmt"
"strings"

"github.com/charmbracelet/log"

"github.com/inovex/CalendarSync/internal/config"
"github.com/inovex/CalendarSync/internal/models"
"github.com/inovex/CalendarSync/internal/transformation"
Expand Down Expand Up @@ -58,8 +59,8 @@ var (
func TransformerFactory(configuredTransformers []config.Transformer) (loadedTransformers []Transformer) {
for _, configuredTransformer := range configuredTransformers {
if _, nameExists := transformerConfigMapping[configuredTransformer.Name]; !nameExists {
// todo: handle properly
panic(fmt.Sprintf("unknown transformer: %s", configuredTransformer.Name))
log.Warnf("unknown transformer: %s, skipping...", configuredTransformer.Name)
continue
}
// load the default Transformer for the configured name and initialize it based on the config
transformerDefault := transformerConfigMapping[configuredTransformer.Name]
Expand Down

0 comments on commit 8107b89

Please sign in to comment.