Skip to content
This repository was archived by the owner on Aug 3, 2024. It is now read-only.

Commit 5c1a580

Browse files
authored
feat(triggers): inotify (#38)
* feat(triggers): add inotify trigger * refactor(triggers/bernard): prefix paths with / and resolve issue with files in root of drive * docs: remove bernard mia status
1 parent 497ca67 commit 5c1a580

File tree

9 files changed

+426
-75
lines changed

9 files changed

+426
-75
lines changed

README.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,8 @@ In addition, this rewrite introduces a more modular approach and should be easy
2222

2323
## Early Access
2424

25-
**We are looking for technical writers! If you have ideas on how to improve Autoscan's documentation, please write [@m-rots](mailto:[email protected]?subject=Autoscan%20technical%20writer) an email.**
26-
2725
We have not finished all work on Autoscan yet, and are still working on some things.
2826

29-
The major feature which is currently MIA:
30-
31-
- Google Drive monitoring (Shared Drives exclusively)
32-
3327
Some small things we are still working on:
3428

3529
- Automating the testing of the processor's business logic
@@ -159,6 +153,7 @@ Daemons run in the background and continuously fetch new changes based on a [cro
159153
The following daemons are currently provided by Autoscan:
160154

161155
- Google Drive
156+
- inotify
162157

163158
#### Webhooks
164159

@@ -205,12 +200,29 @@ triggers:
205200
to: /mnt/unionfs/Media/$1
206201
207202
# filter with regular expressions
208-
include: # if set, then exclude is ignored
203+
include:
209204
- "^/mnt/unionfs/Media/*"
210-
211205
exclude:
212206
- "\.srt$"
213207
208+
inotify:
209+
- priority: 0
210+
211+
# filter with regular expressions
212+
include:
213+
- '/mnt/unionfs/Media/*'
214+
exclude:
215+
- '\.(srt|pdf)$'
216+
217+
# rewrite inotify path to unified filesystem
218+
rewrite:
219+
- from: ^/mnt/local/Media/*
220+
to: /mnt/unionfs/Media/$1
221+
222+
# local filesystem paths to monitor
223+
paths:
224+
- path: /mnt/local/Media
225+
214226
sonarr:
215227
- name: sonarr-docker # /triggers/sonarr-docker
216228
priority: 2

autoscan.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package autoscan
22

33
import (
44
"errors"
5+
"fmt"
56
"net/http"
67
"regexp"
78
"time"
@@ -83,3 +84,61 @@ func NewRewriter(rewriteRules []Rewrite) (Rewriter, error) {
8384

8485
return rewriter, nil
8586
}
87+
88+
type Filterer func(string) bool
89+
90+
func NewFilterer(includes []string, excludes []string) (Filterer, error) {
91+
reIncludes := make([]regexp.Regexp, 0)
92+
reExcludes := make([]regexp.Regexp, 0)
93+
94+
// compile patterns
95+
for _, pattern := range includes {
96+
re, err := regexp.Compile(pattern)
97+
if err != nil {
98+
return nil, fmt.Errorf("compiling include: %v: %w", pattern, err)
99+
}
100+
reIncludes = append(reIncludes, *re)
101+
}
102+
103+
for _, pattern := range excludes {
104+
re, err := regexp.Compile(pattern)
105+
if err != nil {
106+
return nil, fmt.Errorf("compiling exclude: %v: %w", pattern, err)
107+
}
108+
reExcludes = append(reExcludes, *re)
109+
}
110+
111+
incSize := len(reIncludes)
112+
excSize := len(reExcludes)
113+
114+
// create filterer
115+
var fn Filterer = func(string) bool { return true }
116+
117+
if incSize > 0 || excSize > 0 {
118+
fn = func(path string) bool {
119+
// check excludes
120+
for _, re := range reExcludes {
121+
if re.MatchString(path) {
122+
return false
123+
}
124+
}
125+
126+
// no includes (but excludes did not match)
127+
if incSize == 0 {
128+
return true
129+
}
130+
131+
// check includes
132+
for _, re := range reIncludes {
133+
if re.MatchString(path) {
134+
return true
135+
}
136+
}
137+
138+
// no includes passed
139+
return false
140+
}
141+
}
142+
143+
return fn, nil
144+
}

cmd/autoscan/main.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/cloudbox/autoscan/targets/plex"
2222
"github.com/cloudbox/autoscan/triggers"
2323
"github.com/cloudbox/autoscan/triggers/bernard"
24+
"github.com/cloudbox/autoscan/triggers/inotify"
2425
"github.com/cloudbox/autoscan/triggers/lidarr"
2526
"github.com/cloudbox/autoscan/triggers/radarr"
2627
"github.com/cloudbox/autoscan/triggers/sonarr"
@@ -42,6 +43,7 @@ type config struct {
4243
// autoscan.HTTPTrigger
4344
Triggers struct {
4445
Bernard []bernard.Config `yaml:"bernard"`
46+
Inotify []inotify.Config `yaml:"inotify"`
4547
Lidarr []lidarr.Config `yaml:"lidarr"`
4648
Radarr []radarr.Config `yaml:"radarr"`
4749
Sonarr []sonarr.Config `yaml:"sonarr"`
@@ -201,6 +203,18 @@ func main() {
201203
go trigger(proc.Add)
202204
}
203205

206+
for _, t := range c.Triggers.Inotify {
207+
trigger, err := inotify.New(t)
208+
if err != nil {
209+
log.Fatal().
210+
Err(err).
211+
Str("trigger", "inotify").
212+
Msg("Failed initialising trigger")
213+
}
214+
215+
go trigger(proc.Add)
216+
}
217+
204218
// HTTP Triggers
205219
for _, t := range c.Triggers.Lidarr {
206220
trigger, err := lidarr.New(t)
@@ -252,6 +266,7 @@ func main() {
252266

253267
log.Info().
254268
Int("bernard", len(c.Triggers.Bernard)).
269+
Int("inotify", len(c.Triggers.Inotify)).
255270
Int("lidarr", len(c.Triggers.Lidarr)).
256271
Int("sonarr", len(c.Triggers.Sonarr)).
257272
Int("radarr", len(c.Triggers.Radarr)).

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.14
55
require (
66
github.com/BurntSushi/toml v0.3.1 // indirect
77
github.com/alecthomas/kong v0.2.11
8+
github.com/fsnotify/fsnotify v1.4.9
89
github.com/justinas/alice v1.2.0
910
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
1011
github.com/m-rots/bernard v0.3.3-0.20200804121414-38394a889536

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ github.com/alecthomas/kong v0.2.11/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QL
66
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
77
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
88
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9+
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
10+
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
911
github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo=
1012
github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA=
1113
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f h1:dKccXx7xA56UNqOcFIbuqFjAWPVtP688j5QMgmo6OHU=
@@ -40,6 +42,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
4042
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
4143
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4244
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
45+
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
4346
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
4447
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
4548
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

triggers/bernard/bernard.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func New(c Config) (autoscan.Trigger, error) {
7373
return nil, err
7474
}
7575

76-
filterer, err := newFilterer(append(d.Include, c.Include...), append(d.Exclude, c.Exclude...))
76+
filterer, err := autoscan.NewFilterer(append(d.Include, c.Include...), append(d.Exclude, c.Exclude...))
7777
if err != nil {
7878
return nil, err
7979
}
@@ -106,7 +106,7 @@ func New(c Config) (autoscan.Trigger, error) {
106106
}
107107

108108
// start job(s)
109-
if err := d.StartAutoSync(); err != nil {
109+
if err := d.startAutoSync(); err != nil {
110110
l.Error().
111111
Err(err).
112112
Msg("Failed initialising cron jobs")
@@ -120,7 +120,7 @@ func New(c Config) (autoscan.Trigger, error) {
120120
type drive struct {
121121
ID string
122122
Rewriter autoscan.Rewriter
123-
Allowed filterer
123+
Allowed autoscan.Filterer
124124
ScanTime func() time.Time
125125
}
126126

@@ -207,7 +207,7 @@ func newSyncJob(c *cron.Cron, log zerolog.Logger, job func() error) *syncJob {
207207
}
208208
}
209209

210-
func (d daemon) StartAutoSync() error {
210+
func (d daemon) startAutoSync() error {
211211
c := cron.New()
212212

213213
for _, drive := range d.drives {

triggers/bernard/filters.go

Lines changed: 0 additions & 59 deletions
This file was deleted.

triggers/bernard/paths.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,18 @@ func getFolder(store *bds, driveId string, folderId string, folderMap map[string
164164
return &folder, nil
165165
}
166166

167+
if folderId == driveId {
168+
folder := datastore.Folder{
169+
ID: driveId,
170+
Name: "",
171+
Parent: "",
172+
Trashed: false,
173+
}
174+
175+
folderMap[driveId] = folder
176+
return &folder, nil
177+
}
178+
167179
// search datastore
168180
folder, err := store.GetFolder(driveId, folderId)
169181
if err != nil {
@@ -181,15 +193,15 @@ func getFolderPath(store *bds, driveId string, folderId string, folderMap map[st
181193

182194
// folderId == driveId
183195
if folderId == driveId {
184-
return path, nil
196+
return "/", nil
185197
}
186198

187199
// get top folder
188200
topFolder, ok := folderMap[folderId]
189201
if !ok {
190202
f, err := store.GetFolder(driveId, folderId)
191203
if err != nil {
192-
return path, fmt.Errorf("could not get folder %v: %w", folderId, err)
204+
return filepath.Join("/", path), fmt.Errorf("could not get folder %v: %w", folderId, err)
193205
}
194206

195207
topFolder = *f
@@ -205,7 +217,7 @@ func getFolderPath(store *bds, driveId string, folderId string, folderMap map[st
205217
if !ok {
206218
df, err := store.GetFolder(driveId, nextFolderId)
207219
if err != nil {
208-
return path, fmt.Errorf("could not get folder %v: %w", nextFolderId, err)
220+
return filepath.Join("/", path), fmt.Errorf("could not get folder %v: %w", nextFolderId, err)
209221
}
210222

211223
f = *df
@@ -216,5 +228,5 @@ func getFolderPath(store *bds, driveId string, folderId string, folderMap map[st
216228
nextFolderId = f.Parent
217229
}
218230

219-
return path, nil
231+
return filepath.Join("/", path), nil
220232
}

0 commit comments

Comments
 (0)