Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add regexTitle Filter #94

Merged
merged 13 commits into from
Nov 15, 2023
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