initial
This commit is contained in:
122
monitor/arlo.go
Executable file
122
monitor/arlo.go
Executable file
@@ -0,0 +1,122 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"local/logb"
|
||||
"local/sandbox/arlo-cleaner/arlo"
|
||||
"local/sandbox/arlo-cleaner/config"
|
||||
"local/sandbox/arlo-cleaner/rclone"
|
||||
"net/http"
|
||||
"path"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Arlo struct {
|
||||
arlo *arlo.Arlo
|
||||
rclone *rclone.RClone
|
||||
}
|
||||
|
||||
func NewArlo() (*Arlo, error) {
|
||||
rclone, err := rclone.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arlo, err := arlo.New()
|
||||
return &Arlo{
|
||||
arlo: arlo,
|
||||
rclone: rclone,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (a *Arlo) Start() <-chan error {
|
||||
ch := make(chan error)
|
||||
go a.watch(ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
func (a *Arlo) watch(ch chan<- error) {
|
||||
if err := a.Clean(); err != nil {
|
||||
ch <- err
|
||||
}
|
||||
ticker := time.NewTicker(config.MonitorInterval)
|
||||
for _ = range ticker.C {
|
||||
if err := a.Clean(); err != nil {
|
||||
ch <- err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Arlo) Clean() error {
|
||||
if ok, err := a.arlo.NeedsPruning(); err != nil {
|
||||
return err
|
||||
} else if !ok {
|
||||
logb.Infof("Arlo cleaning not needed")
|
||||
return nil
|
||||
}
|
||||
logb.Infof("Arlo clean commencing...")
|
||||
defer logb.Infof("Arlo clean done")
|
||||
prunes, err := a.pickPrunes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := a.archives(prunes); err != nil {
|
||||
return err
|
||||
}
|
||||
return a.arlo.DeleteVideos(prunes)
|
||||
}
|
||||
|
||||
func (a *Arlo) pickPrunes() ([]*arlo.Video, error) {
|
||||
videos, err := a.list()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a.pickRipe(videos), nil
|
||||
}
|
||||
|
||||
func (a *Arlo) list() ([]*arlo.Video, error) {
|
||||
return a.arlo.ListSince(time.Now().Add(time.Hour * -1 * 24 * 30))
|
||||
}
|
||||
|
||||
func (a *Arlo) pickRipe(videos []*arlo.Video) []*arlo.Video {
|
||||
sort.Slice(videos, func(i, j int) bool {
|
||||
return videos[i].Created.Before(videos[j].Created)
|
||||
})
|
||||
allowed := config.ArloCapacity
|
||||
retain := len(videos)
|
||||
for i := len(videos) - 1; i >= 0; i-- {
|
||||
sz := videos[i].Size()
|
||||
allowed -= sz
|
||||
if allowed >= 0 {
|
||||
retain = i
|
||||
}
|
||||
}
|
||||
logb.Debugf("found %v videos to purge of %v", retain, len(videos))
|
||||
return videos[:retain]
|
||||
}
|
||||
|
||||
func (a *Arlo) archives(videos []*arlo.Video) error {
|
||||
for _, video := range videos {
|
||||
if err := a.archive(video); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Arlo) archive(video *arlo.Video) error {
|
||||
resp, err := http.Get(video.Loc.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
target := path.Join(
|
||||
config.RCloneName,
|
||||
fmt.Sprintf("%02d", video.Created.Year()),
|
||||
fmt.Sprintf("%02d", video.Created.Month()),
|
||||
fmt.Sprintf("%02d", video.Created.Day()),
|
||||
video.Key(),
|
||||
)
|
||||
logb.Infof("archiving %v", target)
|
||||
return a.rclone.CopyTo(resp.Body, target)
|
||||
}
|
||||
Reference in New Issue
Block a user