diff --git a/hfcs.go b/hfcs.go index 50b4301..e21233d 100644 --- a/hfcs.go +++ b/hfcs.go @@ -43,6 +43,7 @@ type Filter struct { Rewrite string `json:",omitempty"` re_rewrite *regexp.Regexp Replace string `json:",omitempty"` + Expiration time.Time } type filtType uint @@ -65,7 +66,14 @@ func (ft filtType) String() string { type afiltermap map[filtType][]*Filter -var filtcache = cache.New(cache.Options{Filler: func(userid int64) (afiltermap, bool) { +var filtcache *cache.Cache + +func init() { + // resolve init loop + filtcache = cache.New(cache.Options{Filler: filtcachefiller}) +} + +func filtcachefiller(userid int64) (afiltermap, bool) { rows, err := stmtGetFilters.Query(userid) if err != nil { log.Printf("error querying filters: %s", err) @@ -73,6 +81,10 @@ var filtcache = cache.New(cache.Options{Filler: func(userid int64) (afiltermap, } defer rows.Close() + now := time.Now() + + var expflush time.Time + filtmap := make(afiltermap) for rows.Next() { filt := new(Filter) @@ -86,6 +98,14 @@ var filtcache = cache.New(cache.Options{Filler: func(userid int64) (afiltermap, log.Printf("error scanning filter: %s", err) continue } + if !filt.Expiration.IsZero() { + if filt.Expiration.Before(now) { + continue + } + if expflush.IsZero() || filt.Expiration.Before(expflush) { + expflush = filt.Expiration + } + } if filt.Text != "" { filt.re_text, err = regexp.Compile("\\b(?i:" + filt.Text + ")\\b") if err != nil { @@ -127,8 +147,17 @@ var filtcache = cache.New(cache.Options{Filler: func(userid int64) (afiltermap, sort.Slice(filtmap[filtAny], func(i, j int) bool { return sorting[i].Name < sorting[j].Name }) + if !expflush.IsZero() { + dur := expflush.Sub(now) + go filtcacheclear(userid, dur) + } return filtmap, true -}}) +} + +func filtcacheclear(userid int64, dur time.Duration) { + time.Sleep(dur + time.Second) + filtcache.Clear(userid) +} func getfilters(userid int64, scope filtType) []*Filter { var filtmap afiltermap diff --git a/honk.go b/honk.go index b7be1ca..96f949e 100644 --- a/honk.go +++ b/honk.go @@ -20,6 +20,7 @@ import ( "html/template" "log" "os" + "strconv" "strings" "time" ) @@ -119,6 +120,17 @@ func (d Duration) String() string { return s } +func parseDuration(s string) time.Duration { + didx := strings.IndexByte(s, 'd') + if didx != -1 { + days, _ := strconv.ParseInt(s[:didx], 10, 0) + dur, _ := time.ParseDuration(s[didx:]) + return dur + 24*time.Hour*time.Duration(days) + } + dur, _ := time.ParseDuration(s) + return dur +} + type Time struct { StartTime time.Time EndTime time.Time diff --git a/views/hfcs.html b/views/hfcs.html index d840fad..1cfa721 100644 --- a/views/hfcs.html +++ b/views/hfcs.html @@ -36,6 +36,10 @@ Honk Filtering and Censorship System



+

expiration

+


+ +


@@ -49,6 +53,7 @@ Honk Filtering and Censorship System

Actions: {{ range .Actions }} {{ . }} {{ end }} {{ with .Rewrite }}

Rewrite: {{ . }}{{ end }} {{ with .Replace }}

Replace: {{ . }}{{ end }} +{{ if not .Expiration.IsZero }}

Expiration: {{ .Expiration.Format "2006-01-02 03:04" }}{{ end }}

diff --git a/web.go b/web.go index 79adeaf..7450c94 100644 --- a/web.go +++ b/web.go @@ -1217,8 +1217,8 @@ func submithonk(w http.ResponseWriter, r *http.Request) { } } timeend := r.FormValue("timeend") - dur, err := time.ParseDuration(timeend) - if err == nil { + dur := parseDuration(timeend) + if dur != 0 { t.Duration = Duration(dur) } if !t.StartTime.IsZero() { @@ -1460,6 +1460,9 @@ func savehfcs(w http.ResponseWriter, r *http.Request) { filt.Collapse = r.FormValue("docollapse") == "yes" filt.Rewrite = strings.TrimSpace(r.FormValue("filtrewrite")) filt.Replace = strings.TrimSpace(r.FormValue("filtreplace")) + if dur := parseDuration(r.FormValue("filtduration")); dur > 0 { + filt.Expiration = time.Now().UTC().Add(dur) + } if filt.Actor == "" && filt.Text == "" { log.Printf("blank filter")