123 lines
2.4 KiB
Go
Executable File
123 lines
2.4 KiB
Go
Executable File
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)
|
|
}
|